Merge branch 'stable-6.10' into stable-7.0

* stable-6.10:
  Do not always refresh packed-refs during ref updates

Change-Id: I4cdc1b80841481f83b64b800ef54da0b8ef8753a
diff --git a/.bazelrc b/.bazelrc
index 7c71c4a..74601dc 100644
--- a/.bazelrc
+++ b/.bazelrc
@@ -2,30 +2,17 @@
 # https://issues.gerritcodereview.com/issues/303819949
 common --noenable_bzlmod
 
-build --workspace_status_command="python ./tools/workspace_status.py"
+build --workspace_status_command="python3 ./tools/workspace_status.py"
 build --repository_cache=~/.gerritcodereview/bazel-cache/repository
 build --incompatible_strict_action_env
 build --action_env=PATH
 build --disk_cache=~/.gerritcodereview/bazel-cache/cas
 
-# Builds using remote_jdk11, executes using remote_jdk11 or local_jdk
-build --java_language_version=11
-build --java_runtime_version=remotejdk_11
-build --tool_java_language_version=11
-build --tool_java_runtime_version=remotejdk_11
-
-# Builds and executes on RBE using remotejdk_11
-build:remote11 --java_language_version=11
-build:remote11 --java_runtime_version=remotejdk_11
-build:remote11 --tool_java_language_version=11
-build:remote11 --tool_java_runtime_version=remotejdk_11
-build:remote11 --config=remote
-
 # Builds using remote_jdk17, executes using remote_jdk17 or local_jdk
-build:java17 --java_language_version=17
-build:java17 --java_runtime_version=remotejdk_17
-build:java17 --tool_java_language_version=17
-build:java17 --tool_java_runtime_version=remotejdk_17
+build --java_language_version=17
+build --java_runtime_version=remotejdk_17
+build --tool_java_language_version=17
+build --tool_java_runtime_version=remotejdk_17
 
 # Builds and executes on RBE using remotejdk_17
 build:remote17 --java_language_version=17
@@ -52,4 +39,3 @@
 test --flaky_test_attempts=3
 
 import %workspace%/tools/remote-bazelrc
-
diff --git a/WORKSPACE b/WORKSPACE
index ecaa82a..34caf9d 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -32,8 +32,6 @@
     ],
 )
 
-register_toolchains("//tools:error_prone_warnings_toolchain_java11_definition")
-
 register_toolchains("//tools:error_prone_warnings_toolchain_java17_definition")
 
 register_toolchains("//tools:error_prone_warnings_toolchain_java21_definition")
@@ -140,14 +138,14 @@
 
 maven_jar(
     name = "commons-codec",
-    artifact = "commons-codec:commons-codec:1.17.0",
-    sha1 = "0dbe8eef6e14460e73da07f7b11bf994d6626355",
+    artifact = "commons-codec:commons-codec:1.17.1",
+    sha1 = "973638b7149d333563584137ebf13a691bb60579",
 )
 
 maven_jar(
     name = "commons-logging",
-    artifact = "commons-logging:commons-logging:1.3.2",
-    sha1 = "3dc966156ef19d23c839715165435e582fafa753",
+    artifact = "commons-logging:commons-logging:1.3.4",
+    sha1 = "b9fc14968d63a8b8a8a2c1885fe3e90564239708",
 )
 
 maven_jar(
@@ -164,20 +162,20 @@
 
 maven_jar(
     name = "servlet-api",
-    artifact = "jakarta.servlet:jakarta.servlet-api:4.0.4",
-    sha1 = "b8a1142e04838fe54194049c6e7a18dae8f9b960",
+    artifact = "jakarta.servlet:jakarta.servlet-api:6.1.0",
+    sha1 = "1169a246913fe3823782af7943e7a103634867c5",
 )
 
 maven_jar(
     name = "commons-compress",
-    artifact = "org.apache.commons:commons-compress:1.26.2",
-    sha1 = "eb1f823447af685208e684fce84783b43517960c",
+    artifact = "org.apache.commons:commons-compress:1.27.1",
+    sha1 = "a19151084758e2fbb6b41eddaa88e7b8ff4e6599",
 )
 
 maven_jar(
     name = "commons-lang3",
-    artifact = "org.apache.commons:commons-lang3:3.14.0",
-    sha1 = "1ed471194b02f2c6cb734a0cd6f6f107c673afae",
+    artifact = "org.apache.commons:commons-lang3:3.16.0",
+    sha1 = "3eb54effe40946dfb06dc5cd6c7ce4116cd51ea4",
 )
 
 maven_jar(
@@ -188,8 +186,8 @@
 
 maven_jar(
     name = "tukaani-xz",
-    artifact = "org.tukaani:xz:1.9",
-    sha1 = "1ea4bec1a921180164852c65006d928617bd2caf",
+    artifact = "org.tukaani:xz:1.10",
+    sha1 = "1be8166f89e035a56c6bfc67dbc423996fe577e2",
 )
 
 maven_jar(
@@ -218,22 +216,22 @@
 
 maven_jar(
     name = "assertj-core",
-    artifact = "org.assertj:assertj-core:3.26.0",
-    sha1 = "fc4a3d051da838946f9dffe725efbd06cd7d1eec",
+    artifact = "org.assertj:assertj-core:3.26.3",
+    sha1 = "0d26263eb7524252d98e602fc6942996a3195e29",
 )
 
-BYTE_BUDDY_VERSION = "1.14.16"
+BYTE_BUDDY_VERSION = "1.15.0"
 
 maven_jar(
     name = "bytebuddy",
     artifact = "net.bytebuddy:byte-buddy:" + BYTE_BUDDY_VERSION,
-    sha1 = "e1b9a06e131b7d5b183c8ccc7c29b9e5a8dba077",
+    sha1 = "a5b1159b91c5334015de0f22ab4b1188cd42bbff",
 )
 
 maven_jar(
     name = "bytebuddy-agent",
     artifact = "net.bytebuddy:byte-buddy-agent:" + BYTE_BUDDY_VERSION,
-    sha1 = "4a451ee6484abac3a498df0f3b33ed00a6fced4d",
+    sha1 = "e32740c43acebaac9d55b86399ecf6a5df3c17fb",
 )
 
 maven_jar(
@@ -248,55 +246,62 @@
     sha1 = "527175ca6d81050b53bdd4c457a6d6e017626b0e",
 )
 
-JETTY_VER = "10.0.21"
+JETTY_VER = "12.0.12"
 
 maven_jar(
     name = "jetty-servlet",
-    artifact = "org.eclipse.jetty:jetty-servlet:" + JETTY_VER,
-    sha1 = "6de2f73e1edbd368b14c485597d555d1190e6221",
-    src_sha1 = "6a82804a625a730a13dfcb9fbd3c9d09016bae92",
+    artifact = "org.eclipse.jetty.ee10:jetty-ee10-servlet:" + JETTY_VER,
+    sha1 = "12f25f260a8f9fb519b6d3058260564277e618cd",
+    src_sha1 = "16a22f6ed585c6dcab07d111de290301373db1c7",
 )
 
 maven_jar(
     name = "jetty-security",
     artifact = "org.eclipse.jetty:jetty-security:" + JETTY_VER,
-    sha1 = "fec31c853de43a15a5a75f2e1492e930366d4595",
-    src_sha1 = "ef7660113cae5cfbf4fb24c6c8d832a74d4fd800",
+    sha1 = "962d2c5748f750aae667399481915bd02a9746e0",
+    src_sha1 = "e953d0e19e6e420f5e7c1f62424c4bbe0d385d15",
 )
 
 maven_jar(
     name = "jetty-server",
     artifact = "org.eclipse.jetty:jetty-server:" + JETTY_VER,
-    sha1 = "1e49b8b6d0ce2f8e484e4eec3d8b0a55c4cc599c",
-    src_sha1 = "a6b18935ddbe227a717bea6343603a8cf2629e0c",
+    sha1 = "77591ab10113d7de7eb8a01bb4d9d23b234aebd1",
+    src_sha1 = "952873398a59bc5a964d9d2d130227af807559e9",
+)
+
+maven_jar(
+    name = "jetty-session",
+    artifact = "org.eclipse.jetty:jetty-session:" + JETTY_VER,
+    sha1 = "fceae460fb4677a6cec80d3b70b1fc3ae2a114a7",
+    src_sha1 = "ba95d5e17a3d7f09ca908d4c0773e913f3612425",
 )
 
 maven_jar(
     name = "jetty-http",
     artifact = "org.eclipse.jetty:jetty-http:" + JETTY_VER,
-    sha1 = "26c21d1d16f2929c8f58f177a246687444217cbe",
-    src_sha1 = "fa315f1a44b11759c14373c5bafe4014c837d3a6",
+    sha1 = "549fe58ae50b9c061d09803fb0d2659a93ce0ecd",
+    src_sha1 = "c7afad980b9eade12b473172a9d069d96d016677",
 )
 
 maven_jar(
     name = "jetty-io",
     artifact = "org.eclipse.jetty:jetty-io:" + JETTY_VER,
-    sha1 = "21bb67ceae5fa145ee86ce88a5609c908b880bf8",
-    src_sha1 = "44afc9e83169cc40b6b13ab49789693da1298860",
+    sha1 = "4e2cd5c23e8ba550238f35c361c22ffb1e7bf00c",
+    src_sha1 = "42397797c496a51520900a529ba7e1b315aba768",
 )
 
 maven_jar(
     name = "jetty-util",
     artifact = "org.eclipse.jetty:jetty-util:" + JETTY_VER,
-    sha1 = "141f604e6ae732bf2c5e7488ddf82697eb7d8b86",
-    src_sha1 = "91da8bf1f086a98dbb11c8ef63f79dd9f0f66c33",
+    sha1 = "f7b1e4f835c38d12668b426d327118e767d2f1d4",
+    src_sha1 = "0fdb95a123cc50f6adf4154edc5316cabca05f58",
 )
 
 maven_jar(
     name = "jetty-util-ajax",
     artifact = "org.eclipse.jetty:jetty-util-ajax:" + JETTY_VER,
-    sha1 = "8bc368c8619dee1e30de0ca57189569ba17bd86e",
-    src_sha1 = "17c7eb1571d944cee942d43d160cb6547afa6e07",
+    sha1 = "330e692032c82c305cd52c6a8e9bfba0f1da2555",
+    src_sha1 = "d6b9274b3ef0419a6ba869c828fd0c59c570cd9d",
 )
 
 BOUNCYCASTLE_VER = "1.78.1"
diff --git a/lib/BUILD b/lib/BUILD
index 8918df8..d26ccae 100644
--- a/lib/BUILD
+++ b/lib/BUILD
@@ -163,6 +163,13 @@
 )
 
 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"],
+)
+
+java_library(
     name = "jetty-server",
     # TODO: This should be testonly but org.eclipse.jgit.pgm depends on it.
     visibility = ["//visibility:public"],
diff --git a/org.eclipse.jgit.ant.test/.classpath b/org.eclipse.jgit.ant.test/.classpath
index 73d6894..427e49b 100644
--- a/org.eclipse.jgit.ant.test/.classpath
+++ b/org.eclipse.jgit.ant.test/.classpath
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17">
 		<attributes>
 			<attribute name="module" value="true"/>
 		</attributes>
diff --git a/org.eclipse.jgit.ant.test/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit.ant.test/.settings/org.eclipse.jdt.core.prefs
index 69e9221..362915d 100644
--- a/org.eclipse.jgit.ant.test/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit.ant.test/.settings/org.eclipse.jdt.core.prefs
@@ -7,9 +7,9 @@
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=11
+org.eclipse.jdt.core.compiler.compliance=17
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -115,7 +115,7 @@
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
 org.eclipse.jdt.core.compiler.release=enabled
-org.eclipse.jdt.core.compiler.source=11
+org.eclipse.jdt.core.compiler.source=17
 org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
 org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
diff --git a/org.eclipse.jgit.ant.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.ant.test/META-INF/MANIFEST.MF
index 5c5c48d..251a2f7 100644
--- a/org.eclipse.jgit.ant.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.ant.test/META-INF/MANIFEST.MF
@@ -5,13 +5,13 @@
 Automatic-Module-Name: org.eclipse.jgit.ant.test
 Bundle-SymbolicName: org.eclipse.jgit.ant.test
 Bundle-Vendor: %Bundle-Vendor
-Bundle-Version: 6.10.2.qualifier
+Bundle-Version: 7.0.2.qualifier
 Bundle-ActivationPolicy: lazy
-Bundle-RequiredExecutionEnvironment: JavaSE-11
+Bundle-RequiredExecutionEnvironment: JavaSE-17
 Import-Package: org.apache.tools.ant,
- org.eclipse.jgit.ant.tasks;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.junit;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.lib;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.util;version="[6.10.2,6.11.0)",
+ org.eclipse.jgit.ant.tasks;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.junit;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.lib;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.util;version="[7.0.2,7.1.0)",
  org.hamcrest.core;version="[1.1.0,3.0.0)",
  org.junit;version="[4.13,5.0.0)"
diff --git a/org.eclipse.jgit.ant.test/build.properties b/org.eclipse.jgit.ant.test/build.properties
index 019f659..507f045 100644
--- a/org.eclipse.jgit.ant.test/build.properties
+++ b/org.eclipse.jgit.ant.test/build.properties
@@ -3,5 +3,5 @@
 bin.includes = plugin.properties,\
 			   META-INF/,\
 			   .
-jre.compilation.profile = JavaSE-11
+jre.compilation.profile = JavaSE-17
 additional.bundles = org.eclipse.jgit
diff --git a/org.eclipse.jgit.ant.test/pom.xml b/org.eclipse.jgit.ant.test/pom.xml
index a370b90..e32e54f 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>6.10.2-SNAPSHOT</version>
+    <version>7.0.2-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.ant.test</artifactId>
diff --git a/org.eclipse.jgit.ant/.classpath b/org.eclipse.jgit.ant/.classpath
index 1fde318..efeb803 100644
--- a/org.eclipse.jgit.ant/.classpath
+++ b/org.eclipse.jgit.ant/.classpath
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17">
 		<attributes>
 			<attribute name="module" value="true"/>
 		</attributes>
diff --git a/org.eclipse.jgit.ant/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit.ant/.settings/org.eclipse.jdt.core.prefs
index a08ba7b..844a02f 100644
--- a/org.eclipse.jgit.ant/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit.ant/.settings/org.eclipse.jdt.core.prefs
@@ -7,9 +7,9 @@
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=11
+org.eclipse.jdt.core.compiler.compliance=17
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -115,7 +115,7 @@
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
 org.eclipse.jdt.core.compiler.release=enabled
-org.eclipse.jdt.core.compiler.source=11
+org.eclipse.jdt.core.compiler.source=17
 org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
 org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
diff --git a/org.eclipse.jgit.ant/META-INF/MANIFEST.MF b/org.eclipse.jgit.ant/META-INF/MANIFEST.MF
index 90aadf0..b59b2be 100644
--- a/org.eclipse.jgit.ant/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.ant/META-INF/MANIFEST.MF
@@ -3,13 +3,13 @@
 Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.ant
 Bundle-SymbolicName: org.eclipse.jgit.ant
-Bundle-Version: 6.10.2.qualifier
-Bundle-RequiredExecutionEnvironment: JavaSE-11
+Bundle-Version: 7.0.2.qualifier
+Bundle-RequiredExecutionEnvironment: JavaSE-17
 Import-Package: org.apache.tools.ant,
-  org.eclipse.jgit.storage.file;version="[6.10.2,6.11.0)"
+  org.eclipse.jgit.storage.file;version="[7.0.2,7.1.0)"
 Bundle-Localization: OSGI-INF/l10n/plugin
 Bundle-Vendor: %Bundle-Vendor
-Export-Package: org.eclipse.jgit.ant;version="6.10.2",
- org.eclipse.jgit.ant.tasks;version="6.10.2";
+Export-Package: org.eclipse.jgit.ant;version="7.0.2",
+ org.eclipse.jgit.ant.tasks;version="7.0.2";
   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 98a3f1f..2a78006 100644
--- a/org.eclipse.jgit.ant/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.ant/META-INF/SOURCE-MANIFEST.MF
@@ -3,5 +3,5 @@
 Bundle-Name: org.eclipse.jgit.ant - Sources
 Bundle-SymbolicName: org.eclipse.jgit.ant.source
 Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 6.10.2.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit.ant;version="6.10.2.qualifier";roots="."
+Bundle-Version: 7.0.2.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit.ant;version="7.0.2.qualifier";roots="."
diff --git a/org.eclipse.jgit.ant/pom.xml b/org.eclipse.jgit.ant/pom.xml
index fab0891..b60743d 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>6.10.2-SNAPSHOT</version>
+    <version>7.0.2-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.ant</artifactId>
diff --git a/org.eclipse.jgit.archive/.classpath b/org.eclipse.jgit.archive/.classpath
index f0d0c73..e3378d0 100644
--- a/org.eclipse.jgit.archive/.classpath
+++ b/org.eclipse.jgit.archive/.classpath
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
 	<classpathentry kind="src" path="src"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17">
 		<attributes>
 			<attribute name="module" value="true"/>
 		</attributes>
diff --git a/org.eclipse.jgit.archive/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit.archive/.settings/org.eclipse.jdt.core.prefs
index b27b6c3..c4dc76f 100644
--- a/org.eclipse.jgit.archive/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit.archive/.settings/org.eclipse.jdt.core.prefs
@@ -7,9 +7,9 @@
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=11
+org.eclipse.jdt.core.compiler.compliance=17
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -115,7 +115,7 @@
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
 org.eclipse.jdt.core.compiler.release=enabled
-org.eclipse.jdt.core.compiler.source=11
+org.eclipse.jdt.core.compiler.source=17
 org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
 org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
diff --git a/org.eclipse.jgit.archive/META-INF/MANIFEST.MF b/org.eclipse.jgit.archive/META-INF/MANIFEST.MF
index 9d164d1..1318c44 100644
--- a/org.eclipse.jgit.archive/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.archive/META-INF/MANIFEST.MF
@@ -3,27 +3,28 @@
 Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.archive
 Bundle-SymbolicName: org.eclipse.jgit.archive
-Bundle-Version: 6.10.2.qualifier
+Bundle-Version: 7.0.2.qualifier
 Bundle-Vendor: %Bundle-Vendor
 Bundle-Localization: OSGI-INF/l10n/plugin
-Bundle-RequiredExecutionEnvironment: JavaSE-11
+Bundle-RequiredExecutionEnvironment: JavaSE-17
 Import-Package: org.apache.commons.compress.archivers;version="[1.4,2.0)",
  org.apache.commons.compress.archivers.tar;version="[1.4,2.0)",
  org.apache.commons.compress.archivers.zip;version="[1.4,2.0)",
  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="[6.10.2,6.11.0)",
- org.eclipse.jgit.lib;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.nls;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.revwalk;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.util;version="[6.10.2,6.11.0)",
- org.osgi.framework;version="[1.3.0,2.0.0)"
+ org.eclipse.jgit.api;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.lib;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.nls;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.revwalk;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.util;version="[7.0.2,7.1.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="6.10.2";
-  uses:="org.eclipse.jgit.lib,
+Export-Package: org.eclipse.jgit.archive;version="7.0.2";
+  uses:="org.apache.commons.compress.archivers,
+   org.osgi.framework,
    org.eclipse.jgit.api,
-   org.apache.commons.compress.archivers,
-   org.osgi.framework",
- org.eclipse.jgit.archive.internal;version="6.10.2";x-internal:=true
+   org.eclipse.jgit.lib",
+ org.eclipse.jgit.archive.internal;version="7.0.2";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 89e5df0..95915c2 100644
--- a/org.eclipse.jgit.archive/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.archive/META-INF/SOURCE-MANIFEST.MF
@@ -3,5 +3,5 @@
 Bundle-Name: org.eclipse.jgit.archive - Sources
 Bundle-SymbolicName: org.eclipse.jgit.archive.source
 Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 6.10.2.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit.archive;version="6.10.2.qualifier";roots="."
+Bundle-Version: 7.0.2.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit.archive;version="7.0.2.qualifier";roots="."
diff --git a/org.eclipse.jgit.archive/pom.xml b/org.eclipse.jgit.archive/pom.xml
index e6a2411..aa1e770 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>6.10.2-SNAPSHOT</version>
+    <version>7.0.2-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.archive</artifactId>
@@ -41,6 +41,11 @@
     </dependency>
 
     <dependency>
+      <groupId>org.tukaani</groupId>
+      <artifactId>xz</artifactId>
+    </dependency>
+
+    <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit</artifactId>
       <version>${project.version}</version>
diff --git a/org.eclipse.jgit.benchmarks/.classpath b/org.eclipse.jgit.benchmarks/.classpath
index 01d7161..51158bf 100644
--- a/org.eclipse.jgit.benchmarks/.classpath
+++ b/org.eclipse.jgit.benchmarks/.classpath
@@ -6,7 +6,7 @@
 			<attribute name="maven.pomderived" value="true"/>
 		</attributes>
 	</classpathentry>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17">
 		<attributes>
 			<attribute name="maven.pomderived" value="true"/>
 		</attributes>
diff --git a/org.eclipse.jgit.benchmarks/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit.benchmarks/.settings/org.eclipse.jdt.core.prefs
index c7a9985..1fe550b 100644
--- a/org.eclipse.jgit.benchmarks/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit.benchmarks/.settings/org.eclipse.jdt.core.prefs
@@ -10,9 +10,9 @@
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=11
+org.eclipse.jdt.core.compiler.compliance=17
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -127,7 +127,7 @@
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
 org.eclipse.jdt.core.compiler.processAnnotations=enabled
 org.eclipse.jdt.core.compiler.release=enabled
-org.eclipse.jdt.core.compiler.source=11
+org.eclipse.jdt.core.compiler.source=17
 org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
 org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
diff --git a/org.eclipse.jgit.benchmarks/pom.xml b/org.eclipse.jgit.benchmarks/pom.xml
index 03c78ca..dbf35a3 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>6.10.2-SNAPSHOT</version>
+    <version>7.0.2-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.benchmarks</artifactId>
@@ -25,7 +25,7 @@
   <name>JGit - JMH based benchmarks</name>
 
   <properties>
-    <java.version>11</java.version>
+    <java.version>17</java.version>
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
     <jmh.version>1.37</jmh.version>
     <uberjar.name>benchmarks</uberjar.name>
diff --git a/org.eclipse.jgit.coverage/.classpath b/org.eclipse.jgit.coverage/.classpath
index a454e3e..50d80ed 100644
--- a/org.eclipse.jgit.coverage/.classpath
+++ b/org.eclipse.jgit.coverage/.classpath
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17">
 		<attributes>
 			<attribute name="maven.pomderived" value="true"/>
 		</attributes>
diff --git a/org.eclipse.jgit.coverage/pom.xml b/org.eclipse.jgit.coverage/pom.xml
index 3ed641c..499c0de 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>6.10.2-SNAPSHOT</version>
+    <version>7.0.2-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
 
@@ -27,88 +27,88 @@
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit</artifactId>
-      <version>6.10.2-SNAPSHOT</version>
+      <version>7.0.2-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit.ant</artifactId>
-      <version>6.10.2-SNAPSHOT</version>
+      <version>7.0.2-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit.archive</artifactId>
-      <version>6.10.2-SNAPSHOT</version>
+      <version>7.0.2-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit.http.apache</artifactId>
-      <version>6.10.2-SNAPSHOT</version>
+      <version>7.0.2-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit.http.server</artifactId>
-      <version>6.10.2-SNAPSHOT</version>
+      <version>7.0.2-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit.lfs</artifactId>
-      <version>6.10.2-SNAPSHOT</version>
+      <version>7.0.2-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit.lfs.server</artifactId>
-      <version>6.10.2-SNAPSHOT</version>
+      <version>7.0.2-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit.pgm</artifactId>
-      <version>6.10.2-SNAPSHOT</version>
+      <version>7.0.2-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit.ui</artifactId>
-      <version>6.10.2-SNAPSHOT</version>
+      <version>7.0.2-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit.ssh.apache</artifactId>
-      <version>6.10.2-SNAPSHOT</version>
+      <version>7.0.2-SNAPSHOT</version>
     </dependency>
 
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit.test</artifactId>
-      <version>6.10.2-SNAPSHOT</version>
+      <version>7.0.2-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit.ant.test</artifactId>
-      <version>6.10.2-SNAPSHOT</version>
+      <version>7.0.2-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit.http.test</artifactId>
-      <version>6.10.2-SNAPSHOT</version>
+      <version>7.0.2-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit.pgm.test</artifactId>
-      <version>6.10.2-SNAPSHOT</version>
+      <version>7.0.2-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit.lfs.test</artifactId>
-      <version>6.10.2-SNAPSHOT</version>
+      <version>7.0.2-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit.lfs.server.test</artifactId>
-      <version>6.10.2-SNAPSHOT</version>
+      <version>7.0.2-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit.ssh.apache.test</artifactId>
-      <version>6.10.2-SNAPSHOT</version>
+      <version>7.0.2-SNAPSHOT</version>
     </dependency>
   </dependencies>
 
diff --git a/org.eclipse.jgit.gpg.bc.test/.classpath b/org.eclipse.jgit.gpg.bc.test/.classpath
index 2a1645a..bb10f81 100644
--- a/org.eclipse.jgit.gpg.bc.test/.classpath
+++ b/org.eclipse.jgit.gpg.bc.test/.classpath
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17">
 		<attributes>
 			<attribute name="module" value="true"/>
 		</attributes>
diff --git a/org.eclipse.jgit.gpg.bc.test/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit.gpg.bc.test/.settings/org.eclipse.jdt.core.prefs
index 76f48d8..489fd95 100644
--- a/org.eclipse.jgit.gpg.bc.test/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit.gpg.bc.test/.settings/org.eclipse.jdt.core.prefs
@@ -7,9 +7,9 @@
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=11
+org.eclipse.jdt.core.compiler.compliance=17
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -115,7 +115,7 @@
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
 org.eclipse.jdt.core.compiler.release=enabled
-org.eclipse.jdt.core.compiler.source=11
+org.eclipse.jdt.core.compiler.source=17
 org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
 org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
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 5bcd749..707c55b 100644
--- a/org.eclipse.jgit.gpg.bc.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.gpg.bc.test/META-INF/MANIFEST.MF
@@ -3,19 +3,19 @@
 Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.gpg.bc.test
 Bundle-SymbolicName: org.eclipse.jgit.gpg.bc.test
-Bundle-Version: 6.10.2.qualifier
+Bundle-Version: 7.0.2.qualifier
 Bundle-Vendor: %Bundle-Vendor
 Bundle-Localization: plugin
-Bundle-RequiredExecutionEnvironment: JavaSE-11
+Bundle-RequiredExecutionEnvironment: JavaSE-17
 Require-Bundle: org.hamcrest.core;bundle-version="[1.3.0,2.0.0)"
 Import-Package: org.bouncycastle.jce.provider;version="[1.65.0,2.0.0)",
  org.bouncycastle.openpgp;version="[1.65.0,2.0.0)",
  org.bouncycastle.openpgp.operator;version="[1.65.0,2.0.0)",
  org.bouncycastle.openpgp.operator.jcajce;version="[1.65.0,2.0.0)",
  org.bouncycastle.util.encoders;version="[1.65.0,2.0.0)",
- org.eclipse.jgit.gpg.bc.internal;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.gpg.bc.internal.keys;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.util.sha1;version="[6.10.2,6.11.0)",
+ org.eclipse.jgit.gpg.bc.internal;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.gpg.bc.internal.keys;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.util.sha1;version="[7.0.2,7.1.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)"
diff --git a/org.eclipse.jgit.gpg.bc.test/pom.xml b/org.eclipse.jgit.gpg.bc.test/pom.xml
index f674ded..2310b6f 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>6.10.2-SNAPSHOT</version>
+    <version>7.0.2-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.gpg.bc.test</artifactId>
diff --git a/org.eclipse.jgit.gpg.bc/.classpath b/org.eclipse.jgit.gpg.bc/.classpath
index 1fde318..efeb803 100644
--- a/org.eclipse.jgit.gpg.bc/.classpath
+++ b/org.eclipse.jgit.gpg.bc/.classpath
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17">
 		<attributes>
 			<attribute name="module" value="true"/>
 		</attributes>
diff --git a/org.eclipse.jgit.gpg.bc/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit.gpg.bc/.settings/org.eclipse.jdt.core.prefs
index d5c0e6c..270fc64 100644
--- a/org.eclipse.jgit.gpg.bc/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit.gpg.bc/.settings/org.eclipse.jdt.core.prefs
@@ -7,9 +7,9 @@
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=11
+org.eclipse.jdt.core.compiler.compliance=17
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -115,7 +115,7 @@
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
 org.eclipse.jdt.core.compiler.release=enabled
-org.eclipse.jdt.core.compiler.source=11
+org.eclipse.jdt.core.compiler.source=17
 org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
 org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
diff --git a/org.eclipse.jgit.gpg.bc/META-INF/MANIFEST.MF b/org.eclipse.jgit.gpg.bc/META-INF/MANIFEST.MF
index 8d72ff2..6bed05d 100644
--- a/org.eclipse.jgit.gpg.bc/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.gpg.bc/META-INF/MANIFEST.MF
@@ -3,11 +3,11 @@
 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="[6.10.2,6.11.0)"
+Fragment-Host: org.eclipse.jgit;bundle-version="[7.0.2,7.1.0)"
 Bundle-Vendor: %Bundle-Vendor
 Bundle-Localization: OSGI-INF/l10n/gpg_bc
-Bundle-Version: 6.10.2.qualifier
-Bundle-RequiredExecutionEnvironment: JavaSE-11
+Bundle-Version: 7.0.2.qualifier
+Bundle-RequiredExecutionEnvironment: JavaSE-17
 Import-Package: org.bouncycastle.asn1;version="[1.69.0,2.0.0)",
  org.bouncycastle.asn1.x9;version="[1.69.0,2.0.0)",
  org.bouncycastle.bcpg;version="[1.69.0,2.0.0)",
@@ -28,9 +28,6 @@
  org.bouncycastle.util;version="[1.69.0,2.0.0)",
  org.bouncycastle.util.encoders;version="[1.69.0,2.0.0)",
  org.bouncycastle.util.io;version="[1.69.0,2.0.0)",
- org.eclipse.jgit.annotations;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.api.errors;version="[6.10.2,6.11.0)",
  org.slf4j;version="[1.7.0,3.0.0)"
-Export-Package: org.eclipse.jgit.gpg.bc;version="6.10.2",
- org.eclipse.jgit.gpg.bc.internal;version="6.10.2";x-friends:="org.eclipse.jgit.gpg.bc.test",
- org.eclipse.jgit.gpg.bc.internal.keys;version="6.10.2";x-friends:="org.eclipse.jgit.gpg.bc.test"
+Export-Package: org.eclipse.jgit.gpg.bc.internal;version="7.0.2";x-friends:="org.eclipse.jgit.gpg.bc.test",
+ org.eclipse.jgit.gpg.bc.internal.keys;version="7.0.2";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 b440342..9dc9a9f 100644
--- a/org.eclipse.jgit.gpg.bc/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.gpg.bc/META-INF/SOURCE-MANIFEST.MF
@@ -3,5 +3,5 @@
 Bundle-Name: org.eclipse.jgit.gpg.bc - Sources
 Bundle-SymbolicName: org.eclipse.jgit.gpg.bc.source
 Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 6.10.2.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit.gpg.bc;version="6.10.2.qualifier";roots="."
+Bundle-Version: 7.0.2.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit.gpg.bc;version="7.0.2.qualifier";roots="."
diff --git a/org.eclipse.jgit.gpg.bc/pom.xml b/org.eclipse.jgit.gpg.bc/pom.xml
index 6f4d5af..f51b978 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>6.10.2-SNAPSHOT</version>
+    <version>7.0.2-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.gpg.bc</artifactId>
@@ -160,7 +160,7 @@
                   <breakBuildOnBinaryIncompatibleModifications>false</breakBuildOnBinaryIncompatibleModifications>
                   <onlyBinaryIncompatible>false</onlyBinaryIncompatible>
                   <includeSynthetic>false</includeSynthetic>
-                  <ignoreMissingClasses>false</ignoreMissingClasses>
+                  <ignoreMissingClasses>true</ignoreMissingClasses>
                   <skipPomModules>true</skipPomModules>
               </parameter>
               <skip>false</skip>
diff --git a/org.eclipse.jgit.gpg.bc/resources/META-INF/services/org.eclipse.jgit.lib.GpgSigner b/org.eclipse.jgit.gpg.bc/resources/META-INF/services/org.eclipse.jgit.lib.GpgSigner
deleted file mode 100644
index 6752b64..0000000
--- a/org.eclipse.jgit.gpg.bc/resources/META-INF/services/org.eclipse.jgit.lib.GpgSigner
+++ /dev/null
@@ -1 +0,0 @@
-org.eclipse.jgit.gpg.bc.internal.BouncyCastleGpgSigner
diff --git a/org.eclipse.jgit.gpg.bc/resources/META-INF/services/org.eclipse.jgit.lib.GpgSignatureVerifierFactory b/org.eclipse.jgit.gpg.bc/resources/META-INF/services/org.eclipse.jgit.lib.SignatureVerifierFactory
similarity index 100%
rename from org.eclipse.jgit.gpg.bc/resources/META-INF/services/org.eclipse.jgit.lib.GpgSignatureVerifierFactory
rename to org.eclipse.jgit.gpg.bc/resources/META-INF/services/org.eclipse.jgit.lib.SignatureVerifierFactory
diff --git a/org.eclipse.jgit.gpg.bc/resources/META-INF/services/org.eclipse.jgit.lib.SignerFactory b/org.eclipse.jgit.gpg.bc/resources/META-INF/services/org.eclipse.jgit.lib.SignerFactory
new file mode 100644
index 0000000..c0b214d
--- /dev/null
+++ b/org.eclipse.jgit.gpg.bc/resources/META-INF/services/org.eclipse.jgit.lib.SignerFactory
@@ -0,0 +1 @@
+org.eclipse.jgit.gpg.bc.internal.BouncyCastleGpgSignerFactory
diff --git a/org.eclipse.jgit.gpg.bc/src/org/eclipse/jgit/gpg/bc/BouncyCastleGpgSignerFactory.java b/org.eclipse.jgit.gpg.bc/src/org/eclipse/jgit/gpg/bc/BouncyCastleGpgSignerFactory.java
deleted file mode 100644
index fdd1a2b..0000000
--- a/org.eclipse.jgit.gpg.bc/src/org/eclipse/jgit/gpg/bc/BouncyCastleGpgSignerFactory.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2021 Thomas Wolf <thomas.wolf@paranor.ch> and others
- *
- * 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.gpg.bc;
-
-import org.eclipse.jgit.gpg.bc.internal.BouncyCastleGpgSigner;
-import org.eclipse.jgit.lib.GpgSigner;
-
-/**
- * Factory for creating a {@link GpgSigner} based on Bouncy Castle.
- *
- * @since 5.11
- */
-public final class BouncyCastleGpgSignerFactory {
-
-	private BouncyCastleGpgSignerFactory() {
-		// No instantiation
-	}
-
-	/**
-	 * Creates a new {@link GpgSigner}.
-	 *
-	 * @return the {@link GpgSigner}
-	 */
-	public static GpgSigner create() {
-		return new BouncyCastleGpgSigner();
-	}
-}
diff --git a/org.eclipse.jgit.gpg.bc/src/org/eclipse/jgit/gpg/bc/internal/BouncyCastleGpgPublicKey.java b/org.eclipse.jgit.gpg.bc/src/org/eclipse/jgit/gpg/bc/internal/BouncyCastleGpgPublicKey.java
index d736536..9ec5b45 100644
--- a/org.eclipse.jgit.gpg.bc/src/org/eclipse/jgit/gpg/bc/internal/BouncyCastleGpgPublicKey.java
+++ b/org.eclipse.jgit.gpg.bc/src/org/eclipse/jgit/gpg/bc/internal/BouncyCastleGpgPublicKey.java
@@ -1,3 +1,12 @@
+/*
+ * Copyright (C) 2024 Thomas Wolf <twolf@apache.org> and others
+ *
+ * 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.gpg.bc.internal;
 
 import java.util.List;
diff --git a/org.eclipse.jgit.gpg.bc/src/org/eclipse/jgit/gpg/bc/internal/BouncyCastleGpgSignatureVerifier.java b/org.eclipse.jgit.gpg.bc/src/org/eclipse/jgit/gpg/bc/internal/BouncyCastleGpgSignatureVerifier.java
index 3378bb3..5a3d43b 100644
--- a/org.eclipse.jgit.gpg.bc/src/org/eclipse/jgit/gpg/bc/internal/BouncyCastleGpgSignatureVerifier.java
+++ b/org.eclipse.jgit.gpg.bc/src/org/eclipse/jgit/gpg/bc/internal/BouncyCastleGpgSignatureVerifier.java
@@ -12,7 +12,6 @@
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.security.Security;
 import java.text.MessageFormat;
 import java.time.Instant;
 import java.util.Date;
@@ -20,7 +19,6 @@
 import java.util.Locale;
 
 import org.bouncycastle.bcpg.sig.IssuerFingerprint;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
 import org.bouncycastle.openpgp.PGPCompressedData;
 import org.bouncycastle.openpgp.PGPException;
 import org.bouncycastle.openpgp.PGPPublicKey;
@@ -31,33 +29,20 @@
 import org.bouncycastle.openpgp.jcajce.JcaPGPObjectFactory;
 import org.bouncycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider;
 import org.bouncycastle.util.encoders.Hex;
-import org.eclipse.jgit.annotations.NonNull;
 import org.eclipse.jgit.api.errors.JGitInternalException;
-import org.eclipse.jgit.lib.AbstractGpgSignatureVerifier;
 import org.eclipse.jgit.lib.GpgConfig;
-import org.eclipse.jgit.lib.GpgSignatureVerifier;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.SignatureVerifier;
 import org.eclipse.jgit.util.LRUMap;
 import org.eclipse.jgit.util.StringUtils;
 
 /**
- * A {@link GpgSignatureVerifier} to verify GPG signatures using BouncyCastle.
+ * A {@link SignatureVerifier} to verify GPG signatures using BouncyCastle.
  */
 public class BouncyCastleGpgSignatureVerifier
-		extends AbstractGpgSignatureVerifier {
+		implements SignatureVerifier {
 
-	private static void registerBouncyCastleProviderIfNecessary() {
-		if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
-			Security.addProvider(new BouncyCastleProvider());
-		}
-	}
-
-	/**
-	 * Creates a new instance and registers the BouncyCastle security provider
-	 * if needed.
-	 */
-	public BouncyCastleGpgSignatureVerifier() {
-		registerBouncyCastleProviderIfNecessary();
-	}
+	private static final String NAME = "bc"; //$NON-NLS-1$
 
 	// To support more efficient signature verification of multiple objects we
 	// cache public keys once found in a LRU cache.
@@ -70,7 +55,7 @@ public BouncyCastleGpgSignatureVerifier() {
 
 	@Override
 	public String getName() {
-		return "bc"; //$NON-NLS-1$
+		return NAME;
 	}
 
 	static PGPSignature parseSignature(InputStream in)
@@ -90,9 +75,8 @@ static PGPSignature parseSignature(InputStream in)
 	}
 
 	@Override
-	public SignatureVerification verify(@NonNull GpgConfig config, byte[] data,
-			byte[] signatureData)
-			throws IOException {
+	public SignatureVerification verify(Repository repository, GpgConfig config,
+			byte[] data, byte[] signatureData) throws IOException {
 		PGPSignature signature = null;
 		String fingerprint = null;
 		String signer = null;
@@ -127,14 +111,15 @@ public SignatureVerification verify(@NonNull GpgConfig config, byte[] data,
 		}
 		Date signatureCreatedAt = signature.getCreationTime();
 		if (fingerprint == null && signer == null && keyId == null) {
-			return new VerificationResult(signatureCreatedAt, null, null, null,
-					false, false, TrustLevel.UNKNOWN,
+			return new SignatureVerification(NAME, signatureCreatedAt,
+					null, null, null, false, false, TrustLevel.UNKNOWN,
 					BCText.get().signatureNoKeyInfo);
 		}
 		if (fingerprint != null && keyId != null
 				&& !fingerprint.endsWith(keyId)) {
-			return new VerificationResult(signatureCreatedAt, signer, fingerprint,
-					signer, false, false, TrustLevel.UNKNOWN,
+			return new SignatureVerification(NAME, signatureCreatedAt,
+					signer, fingerprint, signer, false, false,
+					TrustLevel.UNKNOWN,
 					MessageFormat.format(BCText.get().signatureInconsistent,
 							keyId, fingerprint));
 		}
@@ -175,15 +160,16 @@ public SignatureVerification verify(@NonNull GpgConfig config, byte[] data,
 					bySigner.put(signer, NO_KEY);
 				}
 			}
-			return new VerificationResult(signatureCreatedAt, signer,
-					fingerprint, signer, false, false, TrustLevel.UNKNOWN,
-					BCText.get().signatureNoPublicKey);
+			return new SignatureVerification(NAME, signatureCreatedAt,
+					signer, fingerprint, signer, false, false,
+					TrustLevel.UNKNOWN, BCText.get().signatureNoPublicKey);
 		}
 		if (fingerprint != null && !publicKey.isExactMatch()) {
 			// We did find _some_ signing key for the signer, but it doesn't
 			// match the given fingerprint.
-			return new VerificationResult(signatureCreatedAt, signer,
-					fingerprint, signer, false, false, TrustLevel.UNKNOWN,
+			return new SignatureVerification(NAME, signatureCreatedAt,
+					signer, fingerprint, signer, false, false,
+					TrustLevel.UNKNOWN,
 					MessageFormat.format(BCText.get().signatureNoSigningKey,
 							fingerprint));
 		}
@@ -229,8 +215,7 @@ public SignatureVerification verify(@NonNull GpgConfig config, byte[] data,
 		boolean verified = false;
 		try {
 			signature.init(
-					new JcaPGPContentVerifierBuilderProvider()
-							.setProvider(BouncyCastleProvider.PROVIDER_NAME),
+					new JcaPGPContentVerifierBuilderProvider(),
 					pubKey);
 			signature.update(data);
 			verified = signature.verify();
@@ -238,15 +223,8 @@ public SignatureVerification verify(@NonNull GpgConfig config, byte[] data,
 			throw new JGitInternalException(
 					BCText.get().signatureVerificationError, e);
 		}
-		return new VerificationResult(signatureCreatedAt, signer, fingerprint, user,
-				verified, expired, trust, null);
-	}
-
-	@Override
-	public SignatureVerification verify(byte[] data, byte[] signatureData)
-			throws IOException {
-		throw new UnsupportedOperationException(
-				"Call verify(GpgConfig, byte[], byte[]) instead."); //$NON-NLS-1$
+		return new SignatureVerification(NAME, signatureCreatedAt, signer,
+				fingerprint, user, verified, expired, trust, null);
 	}
 
 	private TrustLevel parseGpgTrustPacket(byte[] packet) {
@@ -282,76 +260,4 @@ public void clear() {
 		byFingerprint.clear();
 		bySigner.clear();
 	}
-
-	private static class VerificationResult implements SignatureVerification {
-
-		private final Date creationDate;
-
-		private final String signer;
-
-		private final String keyUser;
-
-		private final String fingerprint;
-
-		private final boolean verified;
-
-		private final boolean expired;
-
-		private final @NonNull TrustLevel trustLevel;
-
-		private final String message;
-
-		public VerificationResult(Date creationDate, String signer,
-				String fingerprint, String user, boolean verified,
-				boolean expired, @NonNull TrustLevel trust, String message) {
-			this.creationDate = creationDate;
-			this.signer = signer;
-			this.fingerprint = fingerprint;
-			this.keyUser = user;
-			this.verified = verified;
-			this.expired = expired;
-			this.trustLevel = trust;
-			this.message = message;
-		}
-
-		@Override
-		public Date getCreationDate() {
-			return creationDate;
-		}
-
-		@Override
-		public String getSigner() {
-			return signer;
-		}
-
-		@Override
-		public String getKeyUser() {
-			return keyUser;
-		}
-
-		@Override
-		public String getKeyFingerprint() {
-			return fingerprint;
-		}
-
-		@Override
-		public boolean isExpired() {
-			return expired;
-		}
-
-		@Override
-		public TrustLevel getTrustLevel() {
-			return trustLevel;
-		}
-
-		@Override
-		public String getMessage() {
-			return message;
-		}
-
-		@Override
-		public boolean getVerified() {
-			return verified;
-		}
-	}
 }
diff --git a/org.eclipse.jgit.gpg.bc/src/org/eclipse/jgit/gpg/bc/internal/BouncyCastleGpgSignatureVerifierFactory.java b/org.eclipse.jgit.gpg.bc/src/org/eclipse/jgit/gpg/bc/internal/BouncyCastleGpgSignatureVerifierFactory.java
index ae82b75..566ad1b 100644
--- a/org.eclipse.jgit.gpg.bc/src/org/eclipse/jgit/gpg/bc/internal/BouncyCastleGpgSignatureVerifierFactory.java
+++ b/org.eclipse.jgit.gpg.bc/src/org/eclipse/jgit/gpg/bc/internal/BouncyCastleGpgSignatureVerifierFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021, Thomas Wolf <thomas.wolf@paranor.ch> and others
+ * Copyright (C) 2021, 2024 Thomas Wolf <twolf@apache.org> and others
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Distribution License v. 1.0 which is available at
@@ -9,20 +9,27 @@
  */
 package org.eclipse.jgit.gpg.bc.internal;
 
-import org.eclipse.jgit.lib.GpgSignatureVerifier;
-import org.eclipse.jgit.lib.GpgSignatureVerifierFactory;
+import org.eclipse.jgit.lib.GpgConfig.GpgFormat;
+import org.eclipse.jgit.lib.SignatureVerifier;
+import org.eclipse.jgit.lib.SignatureVerifierFactory;
 
 /**
- * A {@link GpgSignatureVerifierFactory} that creates
- * {@link GpgSignatureVerifier} instances that verify GPG signatures using
- * BouncyCastle and that do cache public keys.
+ * A {@link SignatureVerifierFactory} that creates {@link SignatureVerifier}
+ * instances that verify GPG signatures using BouncyCastle and that do cache
+ * public keys.
  */
 public final class BouncyCastleGpgSignatureVerifierFactory
-		extends GpgSignatureVerifierFactory {
+		implements SignatureVerifierFactory {
 
 	@Override
-	public GpgSignatureVerifier getVerifier() {
+	public GpgFormat getType() {
+		return GpgFormat.OPENPGP;
+	}
+
+	@Override
+	public SignatureVerifier create() {
 		return new BouncyCastleGpgSignatureVerifier();
 	}
 
+
 }
diff --git a/org.eclipse.jgit.gpg.bc/src/org/eclipse/jgit/gpg/bc/internal/BouncyCastleGpgSigner.java b/org.eclipse.jgit.gpg.bc/src/org/eclipse/jgit/gpg/bc/internal/BouncyCastleGpgSigner.java
index 763b7f7..1d187a5 100644
--- a/org.eclipse.jgit.gpg.bc/src/org/eclipse/jgit/gpg/bc/internal/BouncyCastleGpgSigner.java
+++ b/org.eclipse.jgit.gpg.bc/src/org/eclipse/jgit/gpg/bc/internal/BouncyCastleGpgSigner.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018, 2021, Salesforce and others
+ * Copyright (C) 2018, 2024, Salesforce and others
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Distribution License v. 1.0 which is available at
@@ -14,13 +14,11 @@
 import java.net.URISyntaxException;
 import java.security.NoSuchAlgorithmException;
 import java.security.NoSuchProviderException;
-import java.security.Security;
 import java.util.Iterator;
 
 import org.bouncycastle.bcpg.ArmoredOutputStream;
 import org.bouncycastle.bcpg.BCPGOutputStream;
 import org.bouncycastle.bcpg.HashAlgorithmTags;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
 import org.bouncycastle.openpgp.PGPException;
 import org.bouncycastle.openpgp.PGPPrivateKey;
 import org.bouncycastle.openpgp.PGPPublicKey;
@@ -30,79 +28,23 @@
 import org.bouncycastle.openpgp.PGPSignatureSubpacketGenerator;
 import org.bouncycastle.openpgp.operator.jcajce.JcaPGPContentSignerBuilder;
 import org.bouncycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;
-import org.eclipse.jgit.annotations.NonNull;
 import org.eclipse.jgit.annotations.Nullable;
 import org.eclipse.jgit.api.errors.CanceledException;
 import org.eclipse.jgit.api.errors.JGitInternalException;
 import org.eclipse.jgit.api.errors.UnsupportedSigningFormatException;
 import org.eclipse.jgit.errors.UnsupportedCredentialItem;
-import org.eclipse.jgit.internal.JGitText;
-import org.eclipse.jgit.lib.CommitBuilder;
 import org.eclipse.jgit.lib.GpgConfig;
-import org.eclipse.jgit.lib.GpgObjectSigner;
 import org.eclipse.jgit.lib.GpgSignature;
-import org.eclipse.jgit.lib.GpgSigner;
-import org.eclipse.jgit.lib.ObjectBuilder;
 import org.eclipse.jgit.lib.PersonIdent;
-import org.eclipse.jgit.lib.GpgConfig.GpgFormat;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.Signer;
 import org.eclipse.jgit.transport.CredentialsProvider;
 import org.eclipse.jgit.util.StringUtils;
 
 /**
  * GPG Signer using the BouncyCastle library.
  */
-public class BouncyCastleGpgSigner extends GpgSigner
-		implements GpgObjectSigner {
-
-	private static void registerBouncyCastleProviderIfNecessary() {
-		if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
-			Security.addProvider(new BouncyCastleProvider());
-		}
-	}
-
-	/**
-	 * Create a new instance.
-	 * <p>
-	 * The BounceCastleProvider will be registered if necessary.
-	 * </p>
-	 */
-	public BouncyCastleGpgSigner() {
-		registerBouncyCastleProviderIfNecessary();
-	}
-
-	@Override
-	public boolean canLocateSigningKey(@Nullable String gpgSigningKey,
-			PersonIdent committer, CredentialsProvider credentialsProvider)
-			throws CanceledException {
-		try {
-			return canLocateSigningKey(gpgSigningKey, committer,
-					credentialsProvider, null);
-		} catch (UnsupportedSigningFormatException e) {
-			// Cannot occur with a null config
-			return false;
-		}
-	}
-
-	@Override
-	public boolean canLocateSigningKey(@Nullable String gpgSigningKey,
-			PersonIdent committer, CredentialsProvider credentialsProvider,
-			GpgConfig config)
-			throws CanceledException, UnsupportedSigningFormatException {
-		if (config != null && config.getKeyFormat() != GpgFormat.OPENPGP) {
-			throw new UnsupportedSigningFormatException(
-					JGitText.get().onlyOpenPgpSupportedForSigning);
-		}
-		try (BouncyCastleGpgKeyPassphrasePrompt passphrasePrompt = new BouncyCastleGpgKeyPassphrasePrompt(
-				credentialsProvider)) {
-			BouncyCastleGpgKey gpgKey = locateSigningKey(gpgSigningKey,
-					committer, passphrasePrompt);
-			return gpgKey != null;
-		} catch (CanceledException e) {
-			throw e;
-		} catch (Exception e) {
-			return false;
-		}
-	}
+public class BouncyCastleGpgSigner implements Signer {
 
 	private BouncyCastleGpgKey locateSigningKey(@Nullable String gpgSigningKey,
 			PersonIdent committer,
@@ -121,38 +63,24 @@ private BouncyCastleGpgKey locateSigningKey(@Nullable String gpgSigningKey,
 	}
 
 	@Override
-	public void sign(@NonNull CommitBuilder commit,
-			@Nullable String gpgSigningKey, @NonNull PersonIdent committer,
-			CredentialsProvider credentialsProvider) throws CanceledException {
-		try {
-			signObject(commit, gpgSigningKey, committer, credentialsProvider,
-					null);
-		} catch (UnsupportedSigningFormatException e) {
-			// Cannot occur with a null config
-		}
-	}
-
-	@Override
-	public void signObject(@NonNull ObjectBuilder object,
-			@Nullable String gpgSigningKey, @NonNull PersonIdent committer,
-			CredentialsProvider credentialsProvider, GpgConfig config)
-			throws CanceledException, UnsupportedSigningFormatException {
-		if (config != null && config.getKeyFormat() != GpgFormat.OPENPGP) {
-			throw new UnsupportedSigningFormatException(
-					JGitText.get().onlyOpenPgpSupportedForSigning);
+	public GpgSignature sign(Repository repository, GpgConfig config,
+			byte[] data, PersonIdent committer, String signingKey,
+			CredentialsProvider credentialsProvider) throws CanceledException,
+			IOException, UnsupportedSigningFormatException {
+		String gpgSigningKey = signingKey;
+		if (gpgSigningKey == null) {
+			gpgSigningKey = config.getSigningKey();
 		}
 		try (BouncyCastleGpgKeyPassphrasePrompt passphrasePrompt = new BouncyCastleGpgKeyPassphrasePrompt(
 				credentialsProvider)) {
 			BouncyCastleGpgKey gpgKey = locateSigningKey(gpgSigningKey,
-					committer,
-						passphrasePrompt);
+					committer, passphrasePrompt);
 			PGPSecretKey secretKey = gpgKey.getSecretKey();
 			if (secretKey == null) {
 				throw new JGitInternalException(
 						BCText.get().unableToSignCommitNoSecretKey);
 			}
-			JcePBESecretKeyDecryptorBuilder decryptorBuilder = new JcePBESecretKeyDecryptorBuilder()
-					.setProvider(BouncyCastleProvider.PROVIDER_NAME);
+			JcePBESecretKeyDecryptorBuilder decryptorBuilder = new JcePBESecretKeyDecryptorBuilder();
 			PGPPrivateKey privateKey = null;
 			if (!passphrasePrompt.hasPassphrase()) {
 				// Either the key is not encrypted, or it was read from the
@@ -177,8 +105,7 @@ public void signObject(@NonNull ObjectBuilder object,
 			PGPSignatureGenerator signatureGenerator = new PGPSignatureGenerator(
 					new JcaPGPContentSignerBuilder(
 							publicKey.getAlgorithm(),
-							HashAlgorithmTags.SHA256).setProvider(
-									BouncyCastleProvider.PROVIDER_NAME));
+							HashAlgorithmTags.SHA256));
 			signatureGenerator.init(PGPSignature.BINARY_DOCUMENT, privateKey);
 			PGPSignatureSubpacketGenerator subpackets = new PGPSignatureSubpacketGenerator();
 			subpackets.setIssuerFingerprint(false, publicKey);
@@ -202,16 +129,36 @@ public void signObject(@NonNull ObjectBuilder object,
 			ByteArrayOutputStream buffer = new ByteArrayOutputStream();
 			try (BCPGOutputStream out = new BCPGOutputStream(
 					new ArmoredOutputStream(buffer))) {
-				signatureGenerator.update(object.build());
+				signatureGenerator.update(data);
 				signatureGenerator.generate().encode(out);
 			}
-			object.setGpgSignature(new GpgSignature(buffer.toByteArray()));
-		} catch (PGPException | IOException | NoSuchAlgorithmException
+			return new GpgSignature(buffer.toByteArray());
+		} catch (PGPException | NoSuchAlgorithmException
 				| NoSuchProviderException | URISyntaxException e) {
 			throw new JGitInternalException(e.getMessage(), e);
 		}
 	}
 
+	@Override
+	public boolean canLocateSigningKey(Repository repository, GpgConfig config,
+			PersonIdent committer, String signingKey,
+			CredentialsProvider credentialsProvider) throws CanceledException {
+		String gpgSigningKey = signingKey;
+		if (gpgSigningKey == null) {
+			gpgSigningKey = config.getSigningKey();
+		}
+		try (BouncyCastleGpgKeyPassphrasePrompt passphrasePrompt = new BouncyCastleGpgKeyPassphrasePrompt(
+				credentialsProvider)) {
+			BouncyCastleGpgKey gpgKey = locateSigningKey(gpgSigningKey,
+					committer, passphrasePrompt);
+			return gpgKey != null;
+		} catch (CanceledException e) {
+			throw e;
+		} catch (Exception e) {
+			return false;
+		}
+	}
+
 	static String extractSignerId(String pgpUserId) {
 		int from = pgpUserId.indexOf('<');
 		if (from >= 0) {
diff --git a/org.eclipse.jgit.gpg.bc/src/org/eclipse/jgit/gpg/bc/internal/BouncyCastleGpgSignerFactory.java b/org.eclipse.jgit.gpg.bc/src/org/eclipse/jgit/gpg/bc/internal/BouncyCastleGpgSignerFactory.java
new file mode 100644
index 0000000..92ab65d
--- /dev/null
+++ b/org.eclipse.jgit.gpg.bc/src/org/eclipse/jgit/gpg/bc/internal/BouncyCastleGpgSignerFactory.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2021, 2024 Thomas Wolf <twolf@apache.org> and others
+ *
+ * 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.gpg.bc.internal;
+
+import org.eclipse.jgit.lib.GpgConfig.GpgFormat;
+import org.eclipse.jgit.lib.Signer;
+import org.eclipse.jgit.lib.SignerFactory;
+
+/**
+ * Factory for creating a {@link Signer} for OPENPGP signatures based on Bouncy
+ * Castle.
+ */
+public final class BouncyCastleGpgSignerFactory implements SignerFactory {
+
+	@Override
+	public GpgFormat getType() {
+		return GpgFormat.OPENPGP;
+	}
+
+	@Override
+	public Signer create() {
+		return new BouncyCastleGpgSigner();
+	}
+}
diff --git a/org.eclipse.jgit.http.apache/.classpath b/org.eclipse.jgit.http.apache/.classpath
index 1fde318..efeb803 100644
--- a/org.eclipse.jgit.http.apache/.classpath
+++ b/org.eclipse.jgit.http.apache/.classpath
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17">
 		<attributes>
 			<attribute name="module" value="true"/>
 		</attributes>
diff --git a/org.eclipse.jgit.http.apache/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit.http.apache/.settings/org.eclipse.jdt.core.prefs
index a08ba7b..844a02f 100644
--- a/org.eclipse.jgit.http.apache/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit.http.apache/.settings/org.eclipse.jdt.core.prefs
@@ -7,9 +7,9 @@
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=11
+org.eclipse.jdt.core.compiler.compliance=17
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -115,7 +115,7 @@
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
 org.eclipse.jdt.core.compiler.release=enabled
-org.eclipse.jdt.core.compiler.source=11
+org.eclipse.jdt.core.compiler.source=17
 org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
 org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
diff --git a/org.eclipse.jgit.http.apache/META-INF/MANIFEST.MF b/org.eclipse.jgit.http.apache/META-INF/MANIFEST.MF
index f54350d..18238b5 100644
--- a/org.eclipse.jgit.http.apache/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.http.apache/META-INF/MANIFEST.MF
@@ -3,8 +3,8 @@
 Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.http.apache
 Bundle-SymbolicName: org.eclipse.jgit.http.apache
-Bundle-Version: 6.10.2.qualifier
-Bundle-RequiredExecutionEnvironment: JavaSE-11
+Bundle-Version: 7.0.2.qualifier
+Bundle-RequiredExecutionEnvironment: JavaSE-17
 Bundle-Localization: OSGI-INF/l10n/plugin
 Bundle-Vendor: %Bundle-Vendor
 Bundle-ActivationPolicy: lazy
@@ -26,11 +26,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="[6.10.2,6.11.0)",
- org.eclipse.jgit.nls;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.transport.http;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.util;version="[6.10.2,6.11.0)"
-Export-Package: org.eclipse.jgit.transport.http.apache;version="6.10.2";
+ org.eclipse.jgit.annotations;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.nls;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.transport.http;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.util;version="[7.0.2,7.1.0)"
+Export-Package: org.eclipse.jgit.transport.http.apache;version="7.0.2";
   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 00bf64e..89b7db1 100644
--- a/org.eclipse.jgit.http.apache/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.http.apache/META-INF/SOURCE-MANIFEST.MF
@@ -3,5 +3,5 @@
 Bundle-Name: org.eclipse.jgit.http.apache - Sources
 Bundle-SymbolicName: org.eclipse.jgit.http.apache.source
 Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 6.10.2.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit.http.apache;version="6.10.2.qualifier";roots="."
+Bundle-Version: 7.0.2.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit.http.apache;version="7.0.2.qualifier";roots="."
diff --git a/org.eclipse.jgit.http.apache/pom.xml b/org.eclipse.jgit.http.apache/pom.xml
index eb714a3..ec29cbd 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>6.10.2-SNAPSHOT</version>
+    <version>7.0.2-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.http.apache</artifactId>
diff --git a/org.eclipse.jgit.http.server/.classpath b/org.eclipse.jgit.http.server/.classpath
index 139a059..dde8e3f 100644
--- a/org.eclipse.jgit.http.server/.classpath
+++ b/org.eclipse.jgit.http.server/.classpath
@@ -2,7 +2,7 @@
 <classpath>
 	<classpathentry kind="src" path="src"/>
 	<classpathentry kind="src" path="resources"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17">
 		<attributes>
 			<attribute name="module" value="true"/>
 		</attributes>
diff --git a/org.eclipse.jgit.http.server/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit.http.server/.settings/org.eclipse.jdt.core.prefs
index a08ba7b..844a02f 100644
--- a/org.eclipse.jgit.http.server/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit.http.server/.settings/org.eclipse.jdt.core.prefs
@@ -7,9 +7,9 @@
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=11
+org.eclipse.jdt.core.compiler.compliance=17
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -115,7 +115,7 @@
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
 org.eclipse.jdt.core.compiler.release=enabled
-org.eclipse.jdt.core.compiler.source=11
+org.eclipse.jdt.core.compiler.source=17
 org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
 org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
diff --git a/org.eclipse.jgit.http.server/META-INF/MANIFEST.MF b/org.eclipse.jgit.http.server/META-INF/MANIFEST.MF
index 7192432..b0b1ae1 100644
--- a/org.eclipse.jgit.http.server/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.http.server/META-INF/MANIFEST.MF
@@ -3,29 +3,30 @@
 Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.http.server
 Bundle-SymbolicName: org.eclipse.jgit.http.server
-Bundle-Version: 6.10.2.qualifier
+Bundle-Version: 7.0.2.qualifier
 Bundle-Localization: OSGI-INF/l10n/plugin
 Bundle-Vendor: %Bundle-Vendor
-Export-Package: org.eclipse.jgit.http.server;version="6.10.2",
- org.eclipse.jgit.http.server.glue;version="6.10.2";
-  uses:="javax.servlet,javax.servlet.http",
- org.eclipse.jgit.http.server.resolver;version="6.10.2";
-  uses:="org.eclipse.jgit.transport.resolver,
+Export-Package: org.eclipse.jgit.http.server;version="7.0.2",
+ org.eclipse.jgit.http.server.glue;version="7.0.2";
+  uses:="jakarta.servlet,
+  	jakarta.servlet.http",
+ org.eclipse.jgit.http.server.resolver;version="7.0.2";
+  uses:="jakarta.servlet.http
+   org.eclipse.jgit.transport.resolver,
    org.eclipse.jgit.lib,
    org.eclipse.jgit.transport,
-   javax.servlet.http"
 Bundle-ActivationPolicy: lazy
-Bundle-RequiredExecutionEnvironment: JavaSE-11
-Import-Package: javax.servlet;version="[2.5.0,5.0.0)",
- javax.servlet.http;version="[2.5.0,5.0.0)",
- org.eclipse.jgit.annotations;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.errors;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.internal.storage.dfs;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.internal.storage.file;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.internal.transport.parser;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.lib;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.nls;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.revwalk;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.transport;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.transport.resolver;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.util;version="[6.10.2,6.11.0)"
+Bundle-RequiredExecutionEnvironment: JavaSE-17
+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.0.2,7.1.0)",
+ org.eclipse.jgit.errors;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.internal.storage.dfs;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.internal.storage.file;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.internal.transport.parser;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.lib;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.nls;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.revwalk;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.transport;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.transport.resolver;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.util;version="[7.0.2,7.1.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 2630ad2..4239578 100644
--- a/org.eclipse.jgit.http.server/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.http.server/META-INF/SOURCE-MANIFEST.MF
@@ -3,5 +3,5 @@
 Bundle-Name: org.eclipse.jgit.http.server - Sources
 Bundle-SymbolicName: org.eclipse.jgit.http.server.source
 Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 6.10.2.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit.http.server;version="6.10.2.qualifier";roots="."
+Bundle-Version: 7.0.2.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit.http.server;version="7.0.2.qualifier";roots="."
diff --git a/org.eclipse.jgit.http.server/pom.xml b/org.eclipse.jgit.http.server/pom.xml
index 5be0847..e13c39e 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>6.10.2-SNAPSHOT</version>
+    <version>7.0.2-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.http.server</artifactId>
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/AsIsFileFilter.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/AsIsFileFilter.java
index fb74dc7..add5353 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/AsIsFileFilter.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/AsIsFileFilter.java
@@ -10,20 +10,20 @@
 
 package org.eclipse.jgit.http.server;
 
-import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN;
-import static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;
+import static jakarta.servlet.http.HttpServletResponse.SC_FORBIDDEN;
+import static jakarta.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;
 import static org.eclipse.jgit.http.server.ServletUtils.getRepository;
 
 import java.io.IOException;
 
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.Filter;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.FilterConfig;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.ServletResponse;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 
 import org.eclipse.jgit.http.server.resolver.AsIsFileService;
 import org.eclipse.jgit.lib.Repository;
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/ClientVersionUtil.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/ClientVersionUtil.java
index 99ff653..22fa345 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/ClientVersionUtil.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/ClientVersionUtil.java
@@ -10,7 +10,7 @@
 
 package org.eclipse.jgit.http.server;
 
-import javax.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletRequest;
 
 /**
  * Parses Git client User-Agent strings.
@@ -154,6 +154,7 @@ public static boolean hasPushStatusBug(int[] version) {
 	 *            incoming HTTP request.
 	 * @return true if the client has the chunked encoding bug.
 	 * @deprecated no widely used Git versions need this any more
+	 * @since 7.0
 	 */
 	@Deprecated
 	public static boolean hasChunkedEncodingRequestBug(
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/FileSender.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/FileSender.java
index ec53182..941e8ad 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/FileSender.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/FileSender.java
@@ -10,8 +10,8 @@
 
 package org.eclipse.jgit.http.server;
 
-import static javax.servlet.http.HttpServletResponse.SC_PARTIAL_CONTENT;
-import static javax.servlet.http.HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE;
+import static jakarta.servlet.http.HttpServletResponse.SC_PARTIAL_CONTENT;
+import static jakarta.servlet.http.HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE;
 import static org.eclipse.jgit.util.HttpSupport.HDR_ACCEPT_RANGES;
 import static org.eclipse.jgit.util.HttpSupport.HDR_CONTENT_LENGTH;
 import static org.eclipse.jgit.util.HttpSupport.HDR_CONTENT_RANGE;
@@ -28,8 +28,8 @@
 import java.time.Instant;
 import java.util.Enumeration;
 
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.util.FS;
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/GitFilter.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/GitFilter.java
index 703c0be..8adeddd 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/GitFilter.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/GitFilter.java
@@ -15,11 +15,11 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import javax.servlet.Filter;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.Filter;
+import jakarta.servlet.FilterConfig;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 
 import org.eclipse.jgit.http.server.glue.ErrorServlet;
 import org.eclipse.jgit.http.server.glue.MetaFilter;
@@ -139,6 +139,7 @@ public void setUploadPackErrorHandler(UploadPackErrorHandler h) {
 	 *            filter to apply before any of the UploadPack operations. The
 	 *            UploadPack instance is available in the request attribute
 	 *            {@link org.eclipse.jgit.http.server.ServletUtils#ATTRIBUTE_HANDLER}.
+	 * @since 7.0
 	 */
 	public void addUploadPackFilter(Filter filter) {
 		assertNotInitialized();
@@ -178,6 +179,7 @@ public void setReceivePackErrorHandler(ReceivePackErrorHandler h) {
 	 *            filter to apply before any of the ReceivePack operations. The
 	 *            ReceivePack instance is available in the request attribute
 	 *            {@link org.eclipse.jgit.http.server.ServletUtils#ATTRIBUTE_HANDLER}.
+	 * @since 7.0
 	 */
 	public void addReceivePackFilter(Filter filter) {
 		assertNotInitialized();
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/GitServlet.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/GitServlet.java
index 0157dff..eadab21 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/GitServlet.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/GitServlet.java
@@ -12,12 +12,12 @@
 
 import java.util.Enumeration;
 
-import javax.servlet.Filter;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletConfig;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
+import jakarta.servlet.Filter;
+import jakarta.servlet.FilterConfig;
+import jakarta.servlet.ServletConfig;
+import jakarta.servlet.ServletContext;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServletRequest;
 
 import org.eclipse.jgit.http.server.glue.MetaServlet;
 import org.eclipse.jgit.http.server.resolver.AsIsFileService;
@@ -130,6 +130,7 @@ public void setUploadPackErrorHandler(UploadPackErrorHandler h) {
 	 *            filter to apply before any of the UploadPack operations. The
 	 *            UploadPack instance is available in the request attribute
 	 *            {@link org.eclipse.jgit.http.server.ServletUtils#ATTRIBUTE_HANDLER}.
+	 * @since 7.0
 	 */
 	public void addUploadPackFilter(Filter filter) {
 		gitFilter.addUploadPackFilter(filter);
@@ -165,6 +166,7 @@ public void setReceivePackErrorHandler(ReceivePackErrorHandler h) {
 	 *            filter to apply before any of the ReceivePack operations. The
 	 *            ReceivePack instance is available in the request attribute
 	 *            {@link org.eclipse.jgit.http.server.ServletUtils#ATTRIBUTE_HANDLER}.
+	 * @since 7.0
 	 */
 	public void addReceivePackFilter(Filter filter) {
 		gitFilter.addReceivePackFilter(filter);
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/GitSmartHttpTools.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/GitSmartHttpTools.java
index 078b22a..bf3da4b 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/GitSmartHttpTools.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/GitSmartHttpTools.java
@@ -10,9 +10,9 @@
 
 package org.eclipse.jgit.http.server;
 
-import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN;
-import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
-import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND;
+import static jakarta.servlet.http.HttpServletResponse.SC_FORBIDDEN;
+import static jakarta.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
+import static jakarta.servlet.http.HttpServletResponse.SC_NOT_FOUND;
 import static org.eclipse.jgit.http.server.ServletUtils.ATTRIBUTE_HANDLER;
 import static org.eclipse.jgit.transport.GitProtocolConstants.CAPABILITY_SIDE_BAND_64K;
 import static org.eclipse.jgit.transport.SideBandOutputStream.CH_ERROR;
@@ -25,8 +25,8 @@
 import java.util.Collections;
 import java.util.List;
 
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 
 import org.eclipse.jgit.internal.transport.parser.FirstCommand;
 import org.eclipse.jgit.lib.Constants;
@@ -83,6 +83,7 @@ public class GitSmartHttpTools {
 	 * @param req
 	 *            the current HTTP request that may have been made by Git.
 	 * @return true if the request is likely made by a Git client program.
+	 * @since 7.0
 	 */
 	public static boolean isGitClient(HttpServletRequest req) {
 		return isInfoRefs(req) || isUploadPack(req) || isReceivePack(req);
@@ -104,6 +105,7 @@ public static boolean isGitClient(HttpServletRequest req) {
 	 *            HTTP status code to set if the client is not a Git client.
 	 * @throws IOException
 	 *             the response cannot be sent.
+	 * @since 7.0
 	 */
 	public static void sendError(HttpServletRequest req,
 			HttpServletResponse res, int httpStatus) throws IOException {
@@ -136,6 +138,7 @@ public static void sendError(HttpServletRequest req,
 	 *            response code.
 	 * @throws IOException
 	 *             the response cannot be sent.
+	 * @since 7.0
 	 */
 	public static void sendError(HttpServletRequest req,
 			HttpServletResponse res, int httpStatus, String textForGit)
@@ -252,9 +255,11 @@ private static void writePacket(PacketLineOut pckOut, String textForGit)
 	private static void send(HttpServletRequest req, HttpServletResponse res,
 			String type, byte[] buf, int httpStatus) throws IOException {
 		ServletUtils.consumeRequestBody(req);
-		res.setStatus(httpStatus);
-		res.setContentType(type);
-		res.setContentLength(buf.length);
+		if (!res.isCommitted()) {
+			res.setStatus(httpStatus);
+			res.setContentType(type);
+			res.setContentLength(buf.length);
+		}
 		try (OutputStream os = res.getOutputStream()) {
 			os.write(buf);
 		}
@@ -272,6 +277,7 @@ private static void send(HttpServletRequest req, HttpServletResponse res,
 	 * @throws IllegalArgumentException
 	 *             the request is not a Git client request. See
 	 *             {@link #isGitClient(HttpServletRequest)}.
+	 * @since 7.0
 	 */
 	public static String getResponseContentType(HttpServletRequest req) {
 		if (isInfoRefs(req))
@@ -313,6 +319,7 @@ public static String stripServiceSuffix(String path) {
 	 * @param req
 	 *            current request.
 	 * @return true if the request is for the /info/refs service.
+	 * @since 7.0
 	 */
 	public static boolean isInfoRefs(HttpServletRequest req) {
 		return req.getRequestURI().endsWith(INFO_REFS_PATH)
@@ -336,6 +343,7 @@ public static boolean isUploadPack(String pathOrUri) {
 	 * @param req
 	 *            current request.
 	 * @return true if the request is for the /git-upload-pack handler.
+	 * @since 7.0
 	 */
 	public static boolean isUploadPack(HttpServletRequest req) {
 		return isUploadPack(req.getRequestURI())
@@ -348,6 +356,7 @@ public static boolean isUploadPack(HttpServletRequest req) {
 	 * @param req
 	 *            current request.
 	 * @return true if the request is for the /git-receive-pack handler.
+	 * @since 7.0
 	 */
 	public static boolean isReceivePack(HttpServletRequest req) {
 		String uri = req.getRequestURI();
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/InfoPacksServlet.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/InfoPacksServlet.java
index d94cc41..74a6da9 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/InfoPacksServlet.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/InfoPacksServlet.java
@@ -15,9 +15,9 @@
 
 import java.io.IOException;
 
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 
 import org.eclipse.jgit.internal.storage.file.ObjectDirectory;
 import org.eclipse.jgit.internal.storage.file.Pack;
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/InfoRefsServlet.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/InfoRefsServlet.java
index 4d86be1..632cbaf 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/InfoRefsServlet.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/InfoRefsServlet.java
@@ -16,9 +16,9 @@
 import java.io.IOException;
 import java.io.OutputStreamWriter;
 
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 
 import org.eclipse.jgit.lib.Constants;
 import org.eclipse.jgit.lib.Repository;
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/IsLocalFilter.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/IsLocalFilter.java
index 434cdb4..2a65a7f 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/IsLocalFilter.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/IsLocalFilter.java
@@ -10,18 +10,18 @@
 
 package org.eclipse.jgit.http.server;
 
-import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN;
+import static jakarta.servlet.http.HttpServletResponse.SC_FORBIDDEN;
 import static org.eclipse.jgit.http.server.ServletUtils.getRepository;
 
 import java.io.IOException;
 
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.Filter;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.FilterConfig;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.ServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 
 import org.eclipse.jgit.internal.storage.file.ObjectDirectory;
 import org.eclipse.jgit.lib.Repository;
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/NoCacheFilter.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/NoCacheFilter.java
index b1a2b30..65ec579 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/NoCacheFilter.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/NoCacheFilter.java
@@ -16,13 +16,13 @@
 
 import java.io.IOException;
 
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.Filter;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.FilterConfig;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.ServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 
 /** Add HTTP response headers to prevent caching by proxies/browsers. */
 class NoCacheFilter implements Filter {
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/ObjectFileServlet.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/ObjectFileServlet.java
index e581707..81ff963 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/ObjectFileServlet.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/ObjectFileServlet.java
@@ -10,8 +10,8 @@
 
 package org.eclipse.jgit.http.server;
 
-import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND;
-import static javax.servlet.http.HttpServletResponse.SC_NOT_MODIFIED;
+import static jakarta.servlet.http.HttpServletResponse.SC_NOT_FOUND;
+import static jakarta.servlet.http.HttpServletResponse.SC_NOT_MODIFIED;
 import static org.eclipse.jgit.http.server.ServletUtils.getRepository;
 import static org.eclipse.jgit.util.HttpSupport.HDR_ETAG;
 import static org.eclipse.jgit.util.HttpSupport.HDR_IF_MODIFIED_SINCE;
@@ -23,10 +23,10 @@
 import java.io.IOException;
 import java.time.Instant;
 
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 
 import org.eclipse.jgit.internal.storage.file.ObjectDirectory;
 import org.eclipse.jgit.lib.Repository;
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/ReceivePackErrorHandler.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/ReceivePackErrorHandler.java
index 09bb78e..843a115 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/ReceivePackErrorHandler.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/ReceivePackErrorHandler.java
@@ -11,8 +11,8 @@
 
 import java.io.IOException;
 
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 
 import org.eclipse.jgit.transport.ReceivePack;
 import org.eclipse.jgit.transport.ServiceMayNotContinueException;
@@ -45,6 +45,7 @@ public interface ReceivePackErrorHandler {
 	 *            A continuation that handles a git-receive-pack request.
 	 * @throws IOException
 	 *             if an IO error occurred
+	 * @since 7.0
 	 */
 	void receive(HttpServletRequest req, HttpServletResponse rsp,
 			ReceivePackRunnable r) throws IOException;
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/ReceivePackServlet.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/ReceivePackServlet.java
index 56b4c80..959d6a5 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/ReceivePackServlet.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/ReceivePackServlet.java
@@ -10,10 +10,10 @@
 
 package org.eclipse.jgit.http.server;
 
-import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN;
-import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
-import static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;
-import static javax.servlet.http.HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE;
+import static jakarta.servlet.http.HttpServletResponse.SC_FORBIDDEN;
+import static jakarta.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
+import static jakarta.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;
+import static jakarta.servlet.http.HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE;
 import static org.eclipse.jgit.http.server.GitSmartHttpTools.RECEIVE_PACK;
 import static org.eclipse.jgit.http.server.GitSmartHttpTools.RECEIVE_PACK_REQUEST_TYPE;
 import static org.eclipse.jgit.http.server.GitSmartHttpTools.RECEIVE_PACK_RESULT_TYPE;
@@ -28,15 +28,15 @@
 import java.text.MessageFormat;
 import java.util.List;
 
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.Filter;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.FilterConfig;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.ServletResponse;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 
 import org.eclipse.jgit.annotations.Nullable;
 import org.eclipse.jgit.errors.CorruptObjectException;
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/RepositoryFilter.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/RepositoryFilter.java
index 9ff922b..ab45b46 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/RepositoryFilter.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/RepositoryFilter.java
@@ -10,25 +10,25 @@
 
 package org.eclipse.jgit.http.server;
 
-import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN;
-import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
-import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND;
-import static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;
+import static jakarta.servlet.http.HttpServletResponse.SC_FORBIDDEN;
+import static jakarta.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
+import static jakarta.servlet.http.HttpServletResponse.SC_NOT_FOUND;
+import static jakarta.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;
 import static org.eclipse.jgit.http.server.GitSmartHttpTools.sendError;
 import static org.eclipse.jgit.http.server.ServletUtils.ATTRIBUTE_REPOSITORY;
 
 import java.io.IOException;
 import java.text.MessageFormat;
 
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.Filter;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.FilterConfig;
+import jakarta.servlet.ServletContext;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.ServletResponse;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 
 import org.eclipse.jgit.errors.RepositoryNotFoundException;
 import org.eclipse.jgit.lib.Repository;
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/ServletUtils.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/ServletUtils.java
index ba143d4..79815c2 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/ServletUtils.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/ServletUtils.java
@@ -27,9 +27,9 @@
 import java.util.zip.GZIPInputStream;
 import java.util.zip.GZIPOutputStream;
 
-import javax.servlet.ServletRequest;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 
 import org.eclipse.jgit.lib.Constants;
 import org.eclipse.jgit.lib.ObjectId;
@@ -56,6 +56,7 @@ public final class ServletUtils {
 	 *             being invoked incorrectly and the programmer should ensure
 	 *             the filter runs before the servlet.
 	 * @see #ATTRIBUTE_REPOSITORY
+	 * @since 7.0
 	 */
 	public static Repository getRepository(ServletRequest req) {
 		Repository db = (Repository) req.getAttribute(ATTRIBUTE_REPOSITORY);
@@ -76,6 +77,7 @@ public static Repository getRepository(ServletRequest req) {
 	 * @return an input stream to read the raw, uncompressed request body.
 	 * @throws IOException
 	 *             if an input or output exception occurred.
+	 * @since 7.0
 	 */
 	public static InputStream getInputStream(HttpServletRequest req)
 			throws IOException {
@@ -94,6 +96,7 @@ else if (enc != null)
 	 *
 	 * @param req
 	 *            the request whose body must be consumed.
+	 * @since 7.0
 	 */
 	public static void consumeRequestBody(HttpServletRequest req) {
 		if (0 < req.getContentLength() || isChunked(req)) {
@@ -154,6 +157,7 @@ public static void consumeRequestBody(InputStream in) {
 	 *            the outgoing response.
 	 * @throws IOException
 	 *             the servlet API rejected sending the body.
+	 * @since 7.0
 	 */
 	public static void sendPlainText(final String content,
 			final HttpServletRequest req, final HttpServletResponse rsp)
@@ -183,6 +187,7 @@ public static void sendPlainText(final String content,
 	 *            the outgoing response.
 	 * @throws IOException
 	 *             the servlet API rejected sending the body.
+	 * @since 7.0
 	 */
 	public static void send(byte[] content, final HttpServletRequest req,
 			final HttpServletResponse rsp) throws IOException {
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/SmartOutputStream.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/SmartOutputStream.java
index fdac79d..19df895 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/SmartOutputStream.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/SmartOutputStream.java
@@ -18,8 +18,8 @@
 import java.io.OutputStream;
 import java.util.zip.GZIPOutputStream;
 
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 
 import org.eclipse.jgit.util.TemporaryBuffer;
 
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/SmartServiceInfoRefs.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/SmartServiceInfoRefs.java
index aa04431..d2d6015 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/SmartServiceInfoRefs.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/SmartServiceInfoRefs.java
@@ -10,8 +10,8 @@
 
 package org.eclipse.jgit.http.server;
 
-import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN;
-import static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;
+import static jakarta.servlet.http.HttpServletResponse.SC_FORBIDDEN;
+import static jakarta.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;
 import static org.eclipse.jgit.http.server.GitSmartHttpTools.infoRefsResultType;
 import static org.eclipse.jgit.http.server.GitSmartHttpTools.sendError;
 import static org.eclipse.jgit.http.server.ServletUtils.ATTRIBUTE_HANDLER;
@@ -20,14 +20,14 @@
 import java.io.IOException;
 import java.util.List;
 
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.Filter;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.FilterConfig;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.ServletResponse;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 
 import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.transport.PacketLineOut;
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/TextFileServlet.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/TextFileServlet.java
index 0b225e7..b857827 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/TextFileServlet.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/TextFileServlet.java
@@ -10,7 +10,7 @@
 
 package org.eclipse.jgit.http.server;
 
-import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND;
+import static jakarta.servlet.http.HttpServletResponse.SC_NOT_FOUND;
 import static org.eclipse.jgit.http.server.ServletUtils.getRepository;
 import static org.eclipse.jgit.http.server.ServletUtils.send;
 
@@ -18,9 +18,9 @@
 import java.io.FileNotFoundException;
 import java.io.IOException;
 
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 
 import org.eclipse.jgit.util.HttpSupport;
 import org.eclipse.jgit.util.IO;
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/UploadPackErrorHandler.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/UploadPackErrorHandler.java
index cff1fa9..5159f6c 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/UploadPackErrorHandler.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/UploadPackErrorHandler.java
@@ -9,14 +9,14 @@
  */
 package org.eclipse.jgit.http.server;
 
-import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN;
-import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
-import static javax.servlet.http.HttpServletResponse.SC_OK;
+import static jakarta.servlet.http.HttpServletResponse.SC_FORBIDDEN;
+import static jakarta.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
+import static jakarta.servlet.http.HttpServletResponse.SC_OK;
 
 import java.io.IOException;
 
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 
 import org.eclipse.jgit.errors.PackProtocolException;
 import org.eclipse.jgit.transport.ServiceMayNotContinueException;
@@ -70,6 +70,7 @@ public static int statusCodeForThrowable(Throwable error) {
 	 *            A continuation that handles a git-upload-pack request.
 	 * @throws IOException
 	 *             if an IO error occurred
+	 * @since 7.0
 	 */
 	void upload(HttpServletRequest req, HttpServletResponse rsp,
 			UploadPackRunnable r) throws IOException;
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/UploadPackServlet.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/UploadPackServlet.java
index 74419a5..3665d35 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/UploadPackServlet.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/UploadPackServlet.java
@@ -10,9 +10,9 @@
 
 package org.eclipse.jgit.http.server;
 
-import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN;
-import static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;
-import static javax.servlet.http.HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE;
+import static jakarta.servlet.http.HttpServletResponse.SC_FORBIDDEN;
+import static jakarta.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;
+import static jakarta.servlet.http.HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE;
 import static org.eclipse.jgit.http.server.GitSmartHttpTools.UPLOAD_PACK;
 import static org.eclipse.jgit.http.server.GitSmartHttpTools.UPLOAD_PACK_REQUEST_TYPE;
 import static org.eclipse.jgit.http.server.GitSmartHttpTools.UPLOAD_PACK_RESULT_TYPE;
@@ -28,15 +28,15 @@
 import java.text.MessageFormat;
 import java.util.List;
 
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.Filter;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.FilterConfig;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.ServletResponse;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 
 import org.eclipse.jgit.annotations.Nullable;
 import org.eclipse.jgit.errors.PackProtocolException;
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/ErrorServlet.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/ErrorServlet.java
index 822bb79..1852f6c 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/ErrorServlet.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/ErrorServlet.java
@@ -12,10 +12,10 @@
 
 import java.io.IOException;
 
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 
 /**
  * Send a fixed status code to the client.
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/MetaFilter.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/MetaFilter.java
index 7cd1ecf..9811105 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/MetaFilter.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/MetaFilter.java
@@ -20,15 +20,15 @@
 import java.util.Set;
 import java.util.regex.Pattern;
 
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.Filter;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.FilterConfig;
+import jakarta.servlet.ServletContext;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.ServletResponse;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 
 import org.eclipse.jgit.http.server.HttpServerText;
 
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/MetaServlet.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/MetaServlet.java
index 9a1a249..f577c69 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/MetaServlet.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/MetaServlet.java
@@ -10,18 +10,18 @@
 
 package org.eclipse.jgit.http.server.glue;
 
-import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND;
+import static jakarta.servlet.http.HttpServletResponse.SC_NOT_FOUND;
 
 import java.io.IOException;
 
-import javax.servlet.ServletConfig;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.ServletConfig;
+import jakarta.servlet.ServletContext;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.ServletResponse;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 
 /**
  * Generic container servlet to manage routing to different pipelines.
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/NoParameterFilterConfig.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/NoParameterFilterConfig.java
index 3f7ee2a..82cf7a8 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/NoParameterFilterConfig.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/NoParameterFilterConfig.java
@@ -13,8 +13,8 @@
 import java.util.Enumeration;
 import java.util.NoSuchElementException;
 
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletContext;
+import jakarta.servlet.FilterConfig;
+import jakarta.servlet.ServletContext;
 
 final class NoParameterFilterConfig implements FilterConfig {
 	private final String filterName;
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/RegexGroupFilter.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/RegexGroupFilter.java
index 68adc2d..1c54071 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/RegexGroupFilter.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/RegexGroupFilter.java
@@ -13,12 +13,12 @@
 import java.io.IOException;
 import java.text.MessageFormat;
 
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
+import jakarta.servlet.Filter;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.FilterConfig;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.ServletResponse;
 
 import org.eclipse.jgit.http.server.HttpServerText;
 
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/RegexPipeline.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/RegexPipeline.java
index 5baa14a..7b856c7 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/RegexPipeline.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/RegexPipeline.java
@@ -10,18 +10,18 @@
 
 package org.eclipse.jgit.http.server.glue;
 
-import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND;
+import static jakarta.servlet.http.HttpServletResponse.SC_NOT_FOUND;
 import static org.eclipse.jgit.http.server.glue.MetaFilter.REGEX_GROUPS;
 
 import java.io.IOException;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-import javax.servlet.Filter;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.Filter;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 
 /**
  * Selects requests by matching the URI against a regular expression.
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/ServletBinder.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/ServletBinder.java
index 81509fb..06993ea 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/ServletBinder.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/ServletBinder.java
@@ -10,8 +10,8 @@
 
 package org.eclipse.jgit.http.server.glue;
 
-import javax.servlet.Filter;
-import javax.servlet.http.HttpServlet;
+import jakarta.servlet.Filter;
+import jakarta.servlet.http.HttpServlet;
 
 /**
  * Binds a servlet to a URL.
@@ -23,6 +23,7 @@ public interface ServletBinder {
 	 * @param filter
 	 *            the filter to trigger while processing the path.
 	 * @return {@code this}.
+	 * @since 7.0
 	 */
 	ServletBinder through(Filter filter);
 
@@ -31,6 +32,7 @@ public interface ServletBinder {
 	 *
 	 * @param servlet
 	 *            the servlet to execute on this path.
+	 * @since 7.0
 	 */
 	void with(HttpServlet servlet);
 }
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/ServletBinderImpl.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/ServletBinderImpl.java
index e77de2b..814a900 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/ServletBinderImpl.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/ServletBinderImpl.java
@@ -13,9 +13,9 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import javax.servlet.Filter;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.Filter;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletResponse;
 
 import org.eclipse.jgit.http.server.HttpServerText;
 
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/SuffixPipeline.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/SuffixPipeline.java
index 39d57b5..f2db9c7 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/SuffixPipeline.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/SuffixPipeline.java
@@ -12,11 +12,11 @@
 
 import java.io.IOException;
 
-import javax.servlet.Filter;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.Filter;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 
 /**
  * Selects requests by matching the suffix of the URI.
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/UrlPipeline.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/UrlPipeline.java
index 7c5170d..a27935f 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/UrlPipeline.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/UrlPipeline.java
@@ -15,16 +15,16 @@
 import java.util.NoSuchElementException;
 import java.util.Set;
 
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.ServletConfig;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.Filter;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.ServletConfig;
+import jakarta.servlet.ServletContext;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.ServletResponse;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 
 /**
  * Encapsulates the entire serving stack for a single URL.
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/WrappedRequest.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/WrappedRequest.java
index 4bac040..5d41791 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/WrappedRequest.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/WrappedRequest.java
@@ -10,8 +10,8 @@
 
 package org.eclipse.jgit.http.server.glue;
 
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletRequestWrapper;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletRequestWrapper;
 
 /**
  * Overrides the path and path info.
@@ -30,6 +30,7 @@ public class WrappedRequest extends HttpServletRequestWrapper {
 	 *            new servlet path to report to callers.
 	 * @param pathInfo
 	 *            new path info to report to callers.
+	 * @since 7.0
 	 */
 	public WrappedRequest(final HttpServletRequest originalRequest,
 			final String path, final String pathInfo) {
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/resolver/AsIsFileService.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/resolver/AsIsFileService.java
index 4d00aa5..69918c0 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/resolver/AsIsFileService.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/resolver/AsIsFileService.java
@@ -10,7 +10,7 @@
 
 package org.eclipse.jgit.http.server.resolver;
 
-import javax.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletRequest;
 
 import org.eclipse.jgit.lib.Config;
 import org.eclipse.jgit.lib.Repository;
@@ -81,6 +81,7 @@ protected static boolean isEnabled(Repository db) {
 	 * @throws ServiceNotAuthorizedException
 	 *             bare file access is not allowed for this HTTP request and
 	 *             repository, such as due to a permission error.
+	 * @since 7.0
 	 */
 	public void access(HttpServletRequest req, Repository db)
 			throws ServiceNotEnabledException, ServiceNotAuthorizedException {
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/resolver/DefaultReceivePackFactory.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/resolver/DefaultReceivePackFactory.java
index 0bf10cb..0bf09f7 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/resolver/DefaultReceivePackFactory.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/resolver/DefaultReceivePackFactory.java
@@ -10,7 +10,7 @@
 
 package org.eclipse.jgit.http.server.resolver;
 
-import javax.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletRequest;
 
 import org.eclipse.jgit.lib.Config;
 import org.eclipse.jgit.lib.PersonIdent;
@@ -27,7 +27,7 @@
  * Writing by receive-pack is permitted if any of the following is true:
  * <ul>
  * <li>The container has authenticated the user and set
- * {@link javax.servlet.http.HttpServletRequest#getRemoteUser()} to the
+ * {@link jakarta.servlet.http.HttpServletRequest#getRemoteUser()} to the
  * authenticated name.
  * <li>The repository configuration file has {@code http.receivepack} explicitly
  * set to true.
@@ -47,6 +47,9 @@ private static class ServiceConfig {
 		}
 	}
 
+	/**
+	 * @since 7.0
+	 */
 	@Override
 	public ReceivePack create(HttpServletRequest req, Repository db)
 			throws ServiceNotEnabledException, ServiceNotAuthorizedException {
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/resolver/DefaultUploadPackFactory.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/resolver/DefaultUploadPackFactory.java
index 2931435..10a1b3e 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/resolver/DefaultUploadPackFactory.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/resolver/DefaultUploadPackFactory.java
@@ -12,7 +12,7 @@
 
 import java.util.Arrays;
 
-import javax.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletRequest;
 
 import org.eclipse.jgit.lib.Config;
 import org.eclipse.jgit.lib.Repository;
@@ -38,6 +38,9 @@ private static class ServiceConfig {
 		}
 	}
 
+	/**
+	 * @since 7.0
+	 */
 	@Override
 	public UploadPack create(HttpServletRequest req, Repository db)
 			throws ServiceNotEnabledException, ServiceNotAuthorizedException {
diff --git a/org.eclipse.jgit.http.test/.classpath b/org.eclipse.jgit.http.test/.classpath
index e736f8e..51caafb 100644
--- a/org.eclipse.jgit.http.test/.classpath
+++ b/org.eclipse.jgit.http.test/.classpath
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17">
 		<attributes>
 			<attribute name="module" value="true"/>
 		</attributes>
diff --git a/org.eclipse.jgit.http.test/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit.http.test/.settings/org.eclipse.jdt.core.prefs
index 69e9221..362915d 100644
--- a/org.eclipse.jgit.http.test/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit.http.test/.settings/org.eclipse.jdt.core.prefs
@@ -7,9 +7,9 @@
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=11
+org.eclipse.jdt.core.compiler.compliance=17
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -115,7 +115,7 @@
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
 org.eclipse.jdt.core.compiler.release=enabled
-org.eclipse.jdt.core.compiler.source=11
+org.eclipse.jdt.core.compiler.source=17
 org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
 org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
diff --git a/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF
index 23d4838..b338ec4 100644
--- a/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF
@@ -3,52 +3,54 @@
 Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.http.test
 Bundle-SymbolicName: org.eclipse.jgit.http.test
-Bundle-Version: 6.10.2.qualifier
+Bundle-Version: 7.0.2.qualifier
 Bundle-Vendor: %Bundle-Vendor
 Bundle-Localization: plugin
-Bundle-RequiredExecutionEnvironment: JavaSE-11
+Bundle-RequiredExecutionEnvironment: JavaSE-17
 Require-Bundle: org.hamcrest.core;bundle-version="[1.3.0,2.0.0)",
  org.hamcrest.library;bundle-version="[1.3.0,2.0.0)"
-Import-Package: javax.servlet;version="[2.5.0,5.0.0)",
- javax.servlet.http;version="[2.5.0,5.0.0)",
+Import-Package: jakarta.servlet;version="[6.0.0,7.0.0)",
+ jakarta.servlet.http;version="[6.0.0,7.0.0)",
+ net.bytebuddy.agent;version="[1.9.0,2.0.0)",
+ net.bytebuddy.dynamic.loading;version="[1.9.0,2.0.0)",
  org.apache.commons.codec;version="[1.6.0,2.0.0)",
  org.apache.commons.codec.binary;version="[1.6.0,2.0.0)",
  org.apache.http;version="[4.3.0,5.0.0)",
  org.apache.http.client;version="[4.4.0,5.0.0)",
  org.apache.http.message;version="[4.3.0,5.0.0)",
- org.eclipse.jetty.http;version="[10.0.0,11.0.0)",
- org.eclipse.jetty.io;version="[10.0.0,11.0.0)",
- org.eclipse.jetty.security;version="[10.0.0,11.0.0)",
- org.eclipse.jetty.security.authentication;version="[10.0.0,11.0.0)",
- org.eclipse.jetty.server;version="[10.0.0,11.0.0)",
- org.eclipse.jetty.server.handler;version="[10.0.0,11.0.0)",
- org.eclipse.jetty.servlet;version="[10.0.0,11.0.0)",
- org.eclipse.jetty.util;version="[10.0.0,11.0.0)",
- org.eclipse.jetty.util.component;version="[10.0.0,11.0.0)",
- org.eclipse.jetty.util.log;version="[10.0.0,11.0.0)",
- org.eclipse.jetty.util.security;version="[10.0.0,11.0.0)",
- org.eclipse.jetty.util.thread;version="[10.0.0,11.0.0)",
- org.eclipse.jgit.api;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.errors;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.http.server;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.http.server.glue;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.http.server.resolver;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.internal;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.internal.storage.dfs;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.internal.storage.file;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.internal.storage.reftable;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.junit;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.junit.http;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.lib;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.nls;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.revwalk;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.storage.file;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.transport;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.transport.http;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.transport.http.apache;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.transport.resolver;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.util;version="[6.10.2,6.11.0)",
+ org.eclipse.jetty.ee10.servlet;version="[12.0.0,13.0.0)",
+ org.eclipse.jetty.http;version="[12.0.0,13.0.0)",
+ org.eclipse.jetty.io;version="[12.0.0,13.0.0)",
+ org.eclipse.jetty.security;version="[12.0.0,13.0.0)",
+ org.eclipse.jetty.security.authentication;version="[12.0.0,13.0.0)",
+ org.eclipse.jetty.server;version="[12.0.0,13.0.0)",
+ 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.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.0.2,7.1.0)",
+ org.eclipse.jgit.errors;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.http.server;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.http.server.glue;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.http.server.resolver;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.internal;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.internal.storage.dfs;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.internal.storage.file;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.internal.storage.reftable;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.junit;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.junit.http;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.lib;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.nls;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.revwalk;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.storage.file;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.transport;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.transport.http;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.transport.http.apache;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.transport.resolver;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.util;version="[7.0.2,7.1.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;version="[4.13,5.0.0)",
+ org.mockito;version="[5.4.0,6.0.0)"
diff --git a/org.eclipse.jgit.http.test/pom.xml b/org.eclipse.jgit.http.test/pom.xml
index c8f8e1a..c69fe90 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>6.10.2-SNAPSHOT</version>
+    <version>7.0.2-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.http.test</artifactId>
@@ -58,6 +58,11 @@
     </dependency>
 
     <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-core</artifactId>
+    </dependency>
+
+    <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit.junit.http</artifactId>
       <version>${project.version}</version>
@@ -77,8 +82,8 @@
     </dependency>
 
     <dependency>
-      <groupId>org.eclipse.jetty</groupId>
-      <artifactId>jetty-servlet</artifactId>
+      <groupId>org.eclipse.jetty.ee10</groupId>
+      <artifactId>jetty-ee10-servlet</artifactId>
     </dependency>
   </dependencies>
 
diff --git a/org.eclipse.jgit.http.test/src/org/eclipse/jgit/http/test/TestRepositoryResolver.java b/org.eclipse.jgit.http.test/src/org/eclipse/jgit/http/test/TestRepositoryResolver.java
index 82168d1..d3a85d1 100644
--- a/org.eclipse.jgit.http.test/src/org/eclipse/jgit/http/test/TestRepositoryResolver.java
+++ b/org.eclipse.jgit.http.test/src/org/eclipse/jgit/http/test/TestRepositoryResolver.java
@@ -9,7 +9,7 @@
  */
 package org.eclipse.jgit.http.test;
 
-import javax.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletRequest;
 
 import org.eclipse.jgit.errors.RepositoryNotFoundException;
 import org.eclipse.jgit.junit.TestRepository;
diff --git a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/AdvertiseErrorTest.java b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/AdvertiseErrorTest.java
index c873be7..fd78ba8 100644
--- a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/AdvertiseErrorTest.java
+++ b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/AdvertiseErrorTest.java
@@ -15,10 +15,10 @@
 
 import java.util.Collections;
 
-import javax.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletRequest;
 
-import org.eclipse.jetty.servlet.ServletContextHandler;
-import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.ee10.servlet.ServletContextHandler;
+import org.eclipse.jetty.ee10.servlet.ServletHolder;
 import org.eclipse.jgit.errors.RemoteRepositoryException;
 import org.eclipse.jgit.errors.RepositoryNotFoundException;
 import org.eclipse.jgit.http.server.GitServlet;
diff --git a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/AsIsServiceTest.java b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/AsIsServiceTest.java
index c5fc5a6..f5db80b 100644
--- a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/AsIsServiceTest.java
+++ b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/AsIsServiceTest.java
@@ -14,9 +14,6 @@
 
 import java.io.IOException;
 
-import javax.servlet.http.HttpServletRequestWrapper;
-
-import org.eclipse.jetty.server.Request;
 import org.eclipse.jgit.http.server.resolver.AsIsFileService;
 import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase;
 import org.eclipse.jgit.lib.Repository;
@@ -25,6 +22,10 @@
 import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException;
 import org.junit.Before;
 import org.junit.Test;
+import org.mockito.Mockito;
+
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletRequestWrapper;
 
 public class AsIsServiceTest extends LocalDiskRepositoryTestCase {
 	private Repository db;
@@ -101,7 +102,7 @@ private static final class R extends HttpServletRequestWrapper {
 		private final String host;
 
 		R(String user, String host) {
-			super(new Request(null, null) /* can't pass null, sigh */);
+			super(Mockito.mock(HttpServletRequest.class));
 			this.user = user;
 			this.host = host;
 		}
diff --git a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DefaultReceivePackFactoryTest.java b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DefaultReceivePackFactoryTest.java
index a017fa4..6297912 100644
--- a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DefaultReceivePackFactoryTest.java
+++ b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DefaultReceivePackFactoryTest.java
@@ -17,10 +17,6 @@
 
 import java.io.IOException;
 
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletRequestWrapper;
-
-import org.eclipse.jetty.server.Request;
 import org.eclipse.jgit.http.server.resolver.DefaultReceivePackFactory;
 import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase;
 import org.eclipse.jgit.lib.PersonIdent;
@@ -32,6 +28,10 @@
 import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException;
 import org.junit.Before;
 import org.junit.Test;
+import org.mockito.Mockito;
+
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletRequestWrapper;
 
 public class DefaultReceivePackFactoryTest extends LocalDiskRepositoryTestCase {
 	private Repository db;
@@ -173,7 +173,7 @@ private static final class R extends HttpServletRequestWrapper {
 		private final String host;
 
 		R(String user, String host) {
-			super(new Request(null, null) /* can't pass null, sigh */);
+			super(Mockito.mock(HttpServletRequest.class));
 			this.user = user;
 			this.host = host;
 		}
diff --git a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DefaultUploadPackFactoryTest.java b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DefaultUploadPackFactoryTest.java
index 1d433e2..90188be 100644
--- a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DefaultUploadPackFactoryTest.java
+++ b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DefaultUploadPackFactoryTest.java
@@ -16,10 +16,6 @@
 
 import java.io.IOException;
 
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletRequestWrapper;
-
-import org.eclipse.jetty.server.Request;
 import org.eclipse.jgit.http.server.resolver.DefaultUploadPackFactory;
 import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase;
 import org.eclipse.jgit.lib.Repository;
@@ -30,6 +26,10 @@
 import org.eclipse.jgit.transport.resolver.UploadPackFactory;
 import org.junit.Before;
 import org.junit.Test;
+import org.mockito.Mockito;
+
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletRequestWrapper;
 
 public class DefaultUploadPackFactoryTest extends LocalDiskRepositoryTestCase {
 	private Repository db;
@@ -129,7 +129,7 @@ private static final class R extends HttpServletRequestWrapper {
 		private final String host;
 
 		R(String user, String host) {
-			super(new Request(null, null) /* can't pass null, sigh */);
+			super(Mockito.mock(HttpServletRequest.class));
 			this.user = user;
 			this.host = host;
 		}
diff --git a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DumbClientDumbServerTest.java b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DumbClientDumbServerTest.java
index 8b28c42..7ccc0e5 100644
--- a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DumbClientDumbServerTest.java
+++ b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DumbClientDumbServerTest.java
@@ -25,9 +25,9 @@
 import java.util.List;
 import java.util.Map;
 
-import org.eclipse.jetty.servlet.DefaultServlet;
-import org.eclipse.jetty.servlet.ServletContextHandler;
-import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.ee10.servlet.DefaultServlet;
+import org.eclipse.jetty.ee10.servlet.ServletContextHandler;
+import org.eclipse.jetty.ee10.servlet.ServletHolder;
 import org.eclipse.jgit.errors.NotSupportedException;
 import org.eclipse.jgit.junit.TestRepository;
 import org.eclipse.jgit.junit.http.AccessEvent;
@@ -70,7 +70,7 @@ public void setUp() throws Exception {
 		final URI base = srcGit.getParentFile().toURI();
 
 		ServletContextHandler app = server.addContext("/git");
-		app.setResourceBase(base.toString());
+		app.setBaseResourceAsString(base.toString());
 		ServletHolder holder = app.addServlet(DefaultServlet.class, "/");
 		// The tmp directory is symlinked on OS X
 		holder.setInitParameter("aliases", "true");
diff --git a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DumbClientSmartServerTest.java b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DumbClientSmartServerTest.java
index 986b5ca..9b9f684 100644
--- a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DumbClientSmartServerTest.java
+++ b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DumbClientSmartServerTest.java
@@ -25,8 +25,8 @@
 import java.util.List;
 import java.util.Map;
 
-import org.eclipse.jetty.servlet.ServletContextHandler;
-import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.ee10.servlet.ServletContextHandler;
+import org.eclipse.jetty.ee10.servlet.ServletHolder;
 import org.eclipse.jgit.errors.NotSupportedException;
 import org.eclipse.jgit.http.server.GitServlet;
 import org.eclipse.jgit.junit.TestRepository;
diff --git a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/ErrorServletTest.java b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/ErrorServletTest.java
index a837db0..9a610c6 100644
--- a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/ErrorServletTest.java
+++ b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/ErrorServletTest.java
@@ -15,8 +15,8 @@
 import java.net.HttpURLConnection;
 import java.net.URI;
 
-import org.eclipse.jetty.servlet.ServletContextHandler;
-import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.ee10.servlet.ServletContextHandler;
+import org.eclipse.jetty.ee10.servlet.ServletHolder;
 import org.eclipse.jgit.http.server.glue.ErrorServlet;
 import org.eclipse.jgit.junit.http.AppServer;
 import org.junit.After;
diff --git a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/GitServletInitTest.java b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/GitServletInitTest.java
index 5453a10..c887360 100644
--- a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/GitServletInitTest.java
+++ b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/GitServletInitTest.java
@@ -13,13 +13,8 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
-import java.util.List;
-
-import javax.servlet.ServletException;
-
-import org.eclipse.jetty.servlet.ServletContextHandler;
-import org.eclipse.jetty.servlet.ServletHolder;
-import org.eclipse.jetty.util.MultiException;
+import org.eclipse.jetty.ee10.servlet.ServletContextHandler;
+import org.eclipse.jetty.ee10.servlet.ServletHolder;
 import org.eclipse.jgit.http.server.GitServlet;
 import org.eclipse.jgit.junit.http.AppServer;
 import org.eclipse.jgit.junit.http.MockServletConfig;
@@ -27,6 +22,8 @@
 import org.junit.After;
 import org.junit.Test;
 
+import jakarta.servlet.ServletException;
+
 public class GitServletInitTest {
 	private AppServer server;
 
@@ -75,14 +72,14 @@ public void testInitUnderContainer_NoBasePath() throws Exception {
 			server.setUp();
 		} catch (Exception e) {
 			Throwable why = null;
-			if (e instanceof MultiException) {
-				MultiException multi = (MultiException) e;
-				List<Throwable> reasons = multi.getThrowables();
-				why = reasons.get(0);
+			Throwable[] reasons = e.getSuppressed();
+			if (reasons.length > 0) {
+				why = reasons[0];
 				assertTrue("Expected ServletException",
 						why instanceof ServletException);
-			} else if (e instanceof ServletException)
+			} else if (e instanceof ServletException) {
 				why = e;
+			}
 
 			if (why != null) {
 				assertTrue("Wanted base-path",
diff --git a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/GitServletResponseTests.java b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/GitServletResponseTests.java
index 8fde56f..9331efa 100644
--- a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/GitServletResponseTests.java
+++ b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/GitServletResponseTests.java
@@ -15,10 +15,10 @@
 import java.util.Collection;
 import java.util.Collections;
 
-import javax.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletRequest;
 
-import org.eclipse.jetty.servlet.ServletContextHandler;
-import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.ee10.servlet.ServletContextHandler;
+import org.eclipse.jetty.ee10.servlet.ServletHolder;
 import org.eclipse.jgit.errors.CorruptObjectException;
 import org.eclipse.jgit.errors.RepositoryNotFoundException;
 import org.eclipse.jgit.errors.TooLargePackException;
diff --git a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/HookMessageTest.java b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/HookMessageTest.java
index 20de256..082d853 100644
--- a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/HookMessageTest.java
+++ b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/HookMessageTest.java
@@ -20,10 +20,10 @@
 import java.util.Collections;
 import java.util.List;
 
-import javax.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletRequest;
 
-import org.eclipse.jetty.servlet.ServletContextHandler;
-import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.ee10.servlet.ServletContextHandler;
+import org.eclipse.jetty.ee10.servlet.ServletHolder;
 import org.eclipse.jgit.errors.RepositoryNotFoundException;
 import org.eclipse.jgit.http.server.GitServlet;
 import org.eclipse.jgit.http.server.resolver.DefaultReceivePackFactory;
diff --git a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/HttpClientTests.java b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/HttpClientTests.java
index 6b06727..3937627 100644
--- a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/HttpClientTests.java
+++ b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/HttpClientTests.java
@@ -28,11 +28,11 @@
 import java.util.List;
 import java.util.Set;
 
-import javax.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletRequest;
 
-import org.eclipse.jetty.servlet.DefaultServlet;
-import org.eclipse.jetty.servlet.ServletContextHandler;
-import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.ee10.servlet.DefaultServlet;
+import org.eclipse.jetty.ee10.servlet.ServletContextHandler;
+import org.eclipse.jetty.ee10.servlet.ServletHolder;
 import org.eclipse.jgit.api.Git;
 import org.eclipse.jgit.errors.NoRemoteRepositoryException;
 import org.eclipse.jgit.errors.RepositoryNotFoundException;
@@ -105,7 +105,7 @@ private ServletContextHandler dumb(String path) {
 		final URI base = srcGit.getParentFile().toURI();
 
 		ServletContextHandler ctx = server.addContext(path);
-		ctx.setResourceBase(base.toString());
+		ctx.setBaseResourceAsString(base.toString());
 		ServletHolder holder = ctx.addServlet(DefaultServlet.class, "/");
 		// The tmp directory is symlinked on OS X
 		holder.setInitParameter("aliases", "true");
diff --git a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/MeasurePackSizeTest.java b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/MeasurePackSizeTest.java
index 000eecd..183043b 100644
--- a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/MeasurePackSizeTest.java
+++ b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/MeasurePackSizeTest.java
@@ -14,10 +14,10 @@
 import java.util.Collection;
 import java.util.Collections;
 
-import javax.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletRequest;
 
-import org.eclipse.jetty.servlet.ServletContextHandler;
-import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.ee10.servlet.ServletContextHandler;
+import org.eclipse.jetty.ee10.servlet.ServletHolder;
 import org.eclipse.jgit.errors.RepositoryNotFoundException;
 import org.eclipse.jgit.http.server.GitServlet;
 import org.eclipse.jgit.http.server.resolver.DefaultReceivePackFactory;
diff --git a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/ProtocolErrorTest.java b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/ProtocolErrorTest.java
index 9b3e9d3..74028d7 100644
--- a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/ProtocolErrorTest.java
+++ b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/ProtocolErrorTest.java
@@ -20,10 +20,10 @@
 import java.net.HttpURLConnection;
 import java.net.URL;
 
-import javax.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletRequest;
 
-import org.eclipse.jetty.servlet.ServletContextHandler;
-import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.ee10.servlet.ServletContextHandler;
+import org.eclipse.jetty.ee10.servlet.ServletHolder;
 import org.eclipse.jgit.errors.RepositoryNotFoundException;
 import org.eclipse.jgit.http.server.GitServlet;
 import org.eclipse.jgit.http.server.GitSmartHttpTools;
diff --git a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/RegexPipelineTest.java b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/RegexPipelineTest.java
index 59c2b4e..dfdb975 100644
--- a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/RegexPipelineTest.java
+++ b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/RegexPipelineTest.java
@@ -55,12 +55,12 @@
 import java.net.HttpURLConnection;
 import java.net.URI;
 
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 
-import org.eclipse.jetty.servlet.ServletContextHandler;
-import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.ee10.servlet.ServletContextHandler;
+import org.eclipse.jetty.ee10.servlet.ServletHolder;
 import org.eclipse.jgit.http.server.glue.MetaServlet;
 import org.eclipse.jgit.http.server.glue.RegexGroupFilter;
 import org.eclipse.jgit.junit.http.AppServer;
diff --git a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SetAdditionalHeadersTest.java b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SetAdditionalHeadersTest.java
index cda2b32..d569431 100644
--- a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SetAdditionalHeadersTest.java
+++ b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SetAdditionalHeadersTest.java
@@ -20,9 +20,9 @@
 import java.util.List;
 import java.util.Map;
 
-import org.eclipse.jetty.servlet.DefaultServlet;
-import org.eclipse.jetty.servlet.ServletContextHandler;
-import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.ee10.servlet.DefaultServlet;
+import org.eclipse.jetty.ee10.servlet.ServletContextHandler;
+import org.eclipse.jetty.ee10.servlet.ServletHolder;
 import org.eclipse.jgit.junit.TestRepository;
 import org.eclipse.jgit.junit.http.AccessEvent;
 import org.eclipse.jgit.lib.Repository;
@@ -58,7 +58,7 @@ public void setUp() throws Exception {
 		final URI base = srcGit.getParentFile().toURI();
 
 		ServletContextHandler app = server.addContext("/git");
-		app.setResourceBase(base.toString());
+		app.setBaseResourceAsString(base.toString());
 		ServletHolder holder = app.addServlet(DefaultServlet.class, "/");
 		// The tmp directory is symlinked on OS X
 		holder.setInitParameter("aliases", "true");
diff --git a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerSslTest.java b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerSslTest.java
index 7bc50ca..13ed36c 100644
--- a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerSslTest.java
+++ b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerSslTest.java
@@ -19,19 +19,19 @@
 import java.util.EnumSet;
 import java.util.List;
 
-import javax.servlet.DispatcherType;
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.DispatcherType;
+import jakarta.servlet.Filter;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.FilterConfig;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.ServletResponse;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 
-import org.eclipse.jetty.servlet.FilterHolder;
-import org.eclipse.jetty.servlet.ServletContextHandler;
-import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.ee10.servlet.FilterHolder;
+import org.eclipse.jetty.ee10.servlet.ServletContextHandler;
+import org.eclipse.jetty.ee10.servlet.ServletHolder;
 import org.eclipse.jgit.errors.TransportException;
 import org.eclipse.jgit.errors.UnsupportedCredentialItem;
 import org.eclipse.jgit.http.server.GitServlet;
diff --git a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerTest.java b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerTest.java
index b9b10b4..850e895 100644
--- a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerTest.java
+++ b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerTest.java
@@ -41,20 +41,20 @@
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-import javax.servlet.DispatcherType;
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.RequestDispatcher;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.DispatcherType;
+import jakarta.servlet.Filter;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.FilterConfig;
+import jakarta.servlet.RequestDispatcher;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.ServletResponse;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 
-import org.eclipse.jetty.servlet.FilterHolder;
-import org.eclipse.jetty.servlet.ServletContextHandler;
-import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.ee10.servlet.FilterHolder;
+import org.eclipse.jetty.ee10.servlet.ServletContextHandler;
+import org.eclipse.jetty.ee10.servlet.ServletHolder;
 import org.eclipse.jgit.api.Git;
 import org.eclipse.jgit.api.TransportConfigCallback;
 import org.eclipse.jgit.errors.NoRemoteRepositoryException;
diff --git a/org.eclipse.jgit.junit.http/.classpath b/org.eclipse.jgit.junit.http/.classpath
index 73d6894..427e49b 100644
--- a/org.eclipse.jgit.junit.http/.classpath
+++ b/org.eclipse.jgit.junit.http/.classpath
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17">
 		<attributes>
 			<attribute name="module" value="true"/>
 		</attributes>
diff --git a/org.eclipse.jgit.junit.http/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit.junit.http/.settings/org.eclipse.jdt.core.prefs
index e9a5a41..9e563cc 100644
--- a/org.eclipse.jgit.junit.http/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit.junit.http/.settings/org.eclipse.jdt.core.prefs
@@ -7,9 +7,9 @@
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=11
+org.eclipse.jdt.core.compiler.compliance=17
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -115,7 +115,7 @@
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
 org.eclipse.jdt.core.compiler.release=enabled
-org.eclipse.jdt.core.compiler.source=11
+org.eclipse.jdt.core.compiler.source=17
 org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
 org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
diff --git a/org.eclipse.jgit.junit.http/BUILD b/org.eclipse.jgit.junit.http/BUILD
index 8e6a508..5ddd0c8 100644
--- a/org.eclipse.jgit.junit.http/BUILD
+++ b/org.eclipse.jgit.junit.http/BUILD
@@ -10,9 +10,11 @@
     # TODO(davido): we want here provided deps
     deps = [
         "//lib:jetty-http",
+        "//lib:jetty-io",
         "//lib:jetty-security",
         "//lib:jetty-server",
         "//lib:jetty-servlet",
+        "//lib:jetty-session",
         "//lib:jetty-util",
         "//lib:junit",
         "//lib:servlet-api",
diff --git a/org.eclipse.jgit.junit.http/META-INF/MANIFEST.MF b/org.eclipse.jgit.junit.http/META-INF/MANIFEST.MF
index df47b67..e4c2174 100644
--- a/org.eclipse.jgit.junit.http/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.junit.http/META-INF/MANIFEST.MF
@@ -3,43 +3,44 @@
 Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.junit.http
 Bundle-SymbolicName: org.eclipse.jgit.junit.http
-Bundle-Version: 6.10.2.qualifier
+Bundle-Version: 7.0.2.qualifier
 Bundle-Localization: OSGI-INF/l10n/plugin
 Bundle-Vendor: %Bundle-Vendor
 Bundle-ActivationPolicy: lazy
-Bundle-RequiredExecutionEnvironment: JavaSE-11
-Import-Package: javax.servlet;version="[2.5.0,5.0.0)",
- javax.servlet.http;version="[2.5.0,5.0.0)",
+Bundle-RequiredExecutionEnvironment: JavaSE-17
+Import-Package: jakarta.servlet;version="[6.0.0,7.0.0)",
+ jakarta.servlet.http;version="[6.0.0,7.0.0)",
  org.apache.commons.logging;version="[1.1.1,2.0.0)",
- org.eclipse.jetty.http;version="[10.0.0,11.0.0)",
- org.eclipse.jetty.security;version="[10.0.0,11.0.0)",
- org.eclipse.jetty.security.authentication;version="[10.0.0,11.0.0)",
- org.eclipse.jetty.server;version="[10.0.0,11.0.0)",
- org.eclipse.jetty.server.handler;version="[10.0.0,11.0.0)",
- org.eclipse.jetty.servlet;version="[10.0.0,11.0.0)",
- org.eclipse.jetty.util.component;version="[10.0.0,11.0.0)",
- org.eclipse.jetty.util.log;version="[10.0.0,11.0.0)",
- org.eclipse.jetty.util.security;version="[10.0.0,11.0.0)",
- org.eclipse.jetty.util.ssl;version="[10.0.0,11.0.0)",
- org.eclipse.jgit.errors;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.http.server;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.internal.storage.file;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.junit;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.lib;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.revwalk;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.transport;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.transport.resolver;version="[6.10.2,6.11.0)",
+ org.eclipse.jetty.ee10.servlet;version="[12.0.0,13.0.0)",
+ org.eclipse.jetty.ee10.servlet.security;version="[12.0.0,13.0.0)",
+ org.eclipse.jetty.http;version="[12.0.0,13.0.0)",
+ org.eclipse.jetty.security;version="[12.0.0,13.0.0)",
+ org.eclipse.jetty.security.authentication;version="[12.0.0,13.0.0)",
+ org.eclipse.jetty.server;version="[12.0.0,13.0.0)",
+ 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.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.0.2,7.1.0)",
+ org.eclipse.jgit.http.server;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.internal.storage.file;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.junit;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.lib;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.revwalk;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.transport;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.transport.resolver;version="[7.0.2,7.1.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="6.10.2";
+Export-Package: org.eclipse.jgit.junit.http;version="7.0.2";
   uses:="org.eclipse.jgit.transport,
+   jakarta.servlet,
+   jakarta.servlet.http,
    org.eclipse.jgit.junit,
-   javax.servlet.http,
    org.eclipse.jgit.lib,
    org.eclipse.jgit.revwalk,
    org.eclipse.jetty.server.handler,
    org.eclipse.jetty.security,
-   javax.servlet,
    org.eclipse.jetty.server,
    org.eclipse.jetty.util.log,
    org.eclipse.jetty.servlet"
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 1799d14..b290a02 100644
--- a/org.eclipse.jgit.junit.http/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.junit.http/META-INF/SOURCE-MANIFEST.MF
@@ -3,5 +3,5 @@
 Bundle-Name: org.eclipse.jgit.junit.http - Sources
 Bundle-SymbolicName: org.eclipse.jgit.junit.http.source
 Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 6.10.2.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit.junit.http;version="6.10.2.qualifier";roots="."
+Bundle-Version: 7.0.2.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit.junit.http;version="7.0.2.qualifier";roots="."
diff --git a/org.eclipse.jgit.junit.http/pom.xml b/org.eclipse.jgit.junit.http/pom.xml
index 2bc53ea..f853464 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>6.10.2-SNAPSHOT</version>
+    <version>7.0.2-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.junit.http</artifactId>
@@ -58,8 +58,13 @@
     </dependency>
 
     <dependency>
+      <groupId>org.eclipse.jetty.ee10</groupId>
+      <artifactId>jetty-ee10-servlet</artifactId>
+    </dependency>
+
+    <dependency>
       <groupId>org.eclipse.jetty</groupId>
-      <artifactId>jetty-servlet</artifactId>
+      <artifactId>jetty-session</artifactId>
     </dependency>
   </dependencies>
 
diff --git a/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/AccessEvent.java b/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/AccessEvent.java
index 3d4f379..36da539 100644
--- a/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/AccessEvent.java
+++ b/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/AccessEvent.java
@@ -11,12 +11,14 @@
 package org.eclipse.jgit.junit.http;
 
 import java.util.Collections;
-import java.util.Enumeration;
 import java.util.Map;
 import java.util.TreeMap;
 
+import org.eclipse.jetty.http.HttpField;
+import org.eclipse.jetty.http.HttpURI;
 import org.eclipse.jetty.server.Request;
 import org.eclipse.jetty.server.Response;
+import org.eclipse.jetty.util.Fields;
 
 /**
  * A single request made through {@link org.eclipse.jgit.junit.http.AppServer}.
@@ -24,7 +26,7 @@
 public class AccessEvent {
 	private final String method;
 
-	private final String uri;
+	private final HttpURI uri;
 
 	private final Map<String, String> requestHeaders;
 
@@ -36,9 +38,9 @@ public class AccessEvent {
 
 	AccessEvent(Request req) {
 		method = req.getMethod();
-		uri = req.getRequestURI();
+		uri = req.getHttpURI();
 		requestHeaders = cloneHeaders(req);
-		parameters = clone(req.getParameterMap());
+		parameters = cloneParameters(req);
 	}
 
 	void setResponse(Response rsp) {
@@ -48,11 +50,10 @@ void setResponse(Response rsp) {
 
 	private static Map<String, String> cloneHeaders(Request req) {
 		Map<String, String> r = new TreeMap<>();
-		Enumeration hn = req.getHeaderNames();
-		while (hn.hasMoreElements()) {
-			String key = (String) hn.nextElement();
+		for (HttpField f : req.getHeaders()) {
+			String key = f.getName();
 			if (!r.containsKey(key)) {
-				r.put(key, req.getHeader(key));
+				r.put(key, f.getValue());
 			}
 		}
 		return Collections.unmodifiableMap(r);
@@ -60,20 +61,29 @@ private static Map<String, String> cloneHeaders(Request req) {
 
 	private static Map<String, String> cloneHeaders(Response rsp) {
 		Map<String, String> r = new TreeMap<>();
-		Enumeration<String> hn = rsp.getHttpFields().getFieldNames();
-		while (hn.hasMoreElements()) {
-			String key = hn.nextElement();
+		for (HttpField f : rsp.getHeaders()) {
+			String key = f.getName();
 			if (!r.containsKey(key)) {
-				Enumeration<String> v = rsp.getHttpFields().getValues(key);
-				r.put(key, v.nextElement());
+				r.put(key, f.getValue());
 			}
 		}
 		return Collections.unmodifiableMap(r);
 	}
 
-	@SuppressWarnings("unchecked")
-	private static Map<String, String[]> clone(Map parameterMap) {
-		return new TreeMap<>(parameterMap);
+	private static Map<String, String[]> cloneParameters(Request req) {
+		Map<String, String[]> r = new TreeMap<>();
+
+		Fields fields;
+		try {
+			fields = Request.getParameters(req);
+			for (String n : fields.getNames()) {
+				r.put(n, fields.getValues(n).toArray(new String[0]));
+			}
+		} catch (Exception e) {
+			throw new RuntimeException("Failed to extract request parameters",
+					e);
+		}
+		return r;
 	}
 
 	/**
@@ -91,7 +101,7 @@ public String getMethod() {
 	 * @return path of the file on the server, e.g. {@code /git/HEAD}.
 	 */
 	public String getPath() {
-		return uri;
+		return uri.getPath();
 	}
 
 	/**
@@ -151,7 +161,7 @@ public String toString() {
 		StringBuilder b = new StringBuilder();
 		b.append(method);
 		b.append(' ');
-		b.append(uri);
+		b.append(uri.getPath());
 		if (!parameters.isEmpty()) {
 			b.append('?');
 			boolean first = true;
diff --git a/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/AppServer.java b/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/AppServer.java
index de4535a..76e437b 100644
--- a/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/AppServer.java
+++ b/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/AppServer.java
@@ -27,10 +27,12 @@
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
+import org.eclipse.jetty.ee10.servlet.ServletContextHandler;
+import org.eclipse.jetty.ee10.servlet.security.ConstraintMapping;
+import org.eclipse.jetty.ee10.servlet.security.ConstraintSecurityHandler;
 import org.eclipse.jetty.security.AbstractLoginService;
 import org.eclipse.jetty.security.Authenticator;
-import org.eclipse.jetty.security.ConstraintMapping;
-import org.eclipse.jetty.security.ConstraintSecurityHandler;
+import org.eclipse.jetty.security.Constraint;
 import org.eclipse.jetty.security.RolePrincipal;
 import org.eclipse.jetty.security.UserPrincipal;
 import org.eclipse.jetty.security.authentication.BasicAuthenticator;
@@ -42,8 +44,6 @@
 import org.eclipse.jetty.server.ServerConnector;
 import org.eclipse.jetty.server.SslConnectionFactory;
 import org.eclipse.jetty.server.handler.ContextHandlerCollection;
-import org.eclipse.jetty.servlet.ServletContextHandler;
-import org.eclipse.jetty.util.security.Constraint;
 import org.eclipse.jetty.util.security.Password;
 import org.eclipse.jetty.util.ssl.SslContextFactory;
 import org.eclipse.jgit.transport.URIish;
@@ -243,6 +243,7 @@ private void makePrivate(File file) {
 	 *            path of the context; use "/" for the root context if binding
 	 *            to the root is desired.
 	 * @return the context to add servlets into.
+	 * @since 7.0
 	 */
 	public ServletContextHandler addContext(String path) {
 		assertNotYetSetUp();
@@ -264,6 +265,7 @@ public ServletContextHandler addContext(String path) {
 	 * @param methods
 	 *            the methods
 	 * @return servlet context handler
+	 * @since 7.0
 	 */
 	public ServletContextHandler authBasic(ServletContextHandler ctx,
 			String... methods) {
@@ -305,10 +307,10 @@ protected List<RolePrincipal> loadRoleInfo(UserPrincipal user) {
 
 	private ConstraintMapping createConstraintMapping() {
 		ConstraintMapping cm = new ConstraintMapping();
-		cm.setConstraint(new Constraint());
-		cm.getConstraint().setAuthenticate(true);
-		cm.getConstraint().setDataConstraint(Constraint.DC_NONE);
-		cm.getConstraint().setRoles(new String[] { authRole });
+		Constraint constraint = new Constraint.Builder()
+				.authorization(Constraint.Authorization.SPECIFIC_ROLE)
+				.roles(new String[] { authRole }).build();
+		cm.setConstraint(constraint);
 		cm.setPathSpec("/*");
 		return cm;
 	}
diff --git a/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/HttpTestCase.java b/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/HttpTestCase.java
index 8a4d363..f399471 100644
--- a/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/HttpTestCase.java
+++ b/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/HttpTestCase.java
@@ -21,7 +21,7 @@
 import java.util.List;
 import java.util.Set;
 
-import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.ee10.servlet.ServletContextHandler;
 import org.eclipse.jgit.internal.storage.file.FileRepository;
 import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase;
 import org.eclipse.jgit.junit.TestRepository;
@@ -109,6 +109,7 @@ protected URIish toURIish(String path) throws URISyntaxException {
 	 * @return the warnings (if any) from the last execution
 	 * @throws URISyntaxException
 	 *             if URI is invalid
+	 * @since 7.0
 	 */
 	protected URIish toURIish(ServletContextHandler app, String name)
 			throws URISyntaxException {
diff --git a/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/MockServletConfig.java b/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/MockServletConfig.java
index cd1eba4..808b076 100644
--- a/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/MockServletConfig.java
+++ b/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/MockServletConfig.java
@@ -15,8 +15,8 @@
 import java.util.Iterator;
 import java.util.Map;
 
-import javax.servlet.ServletConfig;
-import javax.servlet.ServletContext;
+import jakarta.servlet.ServletConfig;
+import jakarta.servlet.ServletContext;
 
 /**
  * Mock ServletConfig
diff --git a/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/SimpleHttpServer.java b/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/SimpleHttpServer.java
index 01f18da..bce4138 100644
--- a/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/SimpleHttpServer.java
+++ b/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/SimpleHttpServer.java
@@ -13,10 +13,10 @@
 import java.net.URI;
 import java.net.URISyntaxException;
 
-import javax.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletRequest;
 
-import org.eclipse.jetty.servlet.ServletContextHandler;
-import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.ee10.servlet.ServletContextHandler;
+import org.eclipse.jetty.ee10.servlet.ServletHolder;
 import org.eclipse.jgit.errors.RepositoryNotFoundException;
 import org.eclipse.jgit.http.server.GitServlet;
 import org.eclipse.jgit.lib.Repository;
diff --git a/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/TestRequestLog.java b/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/TestRequestLog.java
index afa8c35..7a71951 100644
--- a/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/TestRequestLog.java
+++ b/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/TestRequestLog.java
@@ -10,25 +10,22 @@
 
 package org.eclipse.jgit.junit.http;
 
-import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.Semaphore;
 
-import javax.servlet.DispatcherType;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
+import org.eclipse.jetty.server.Handler.Wrapper;
 import org.eclipse.jetty.server.Request;
 import org.eclipse.jetty.server.Response;
-import org.eclipse.jetty.server.handler.HandlerWrapper;
+import org.eclipse.jetty.util.Callback;
 
 /** Logs request made through {@link AppServer}. */
-class TestRequestLog extends HandlerWrapper {
+class TestRequestLog extends Wrapper {
 	private static final int MAX = 16;
 
-	private final List<AccessEvent> events = new ArrayList<>();
+	private final List<AccessEvent> events = Collections
+			.synchronizedList(new ArrayList<>());
 
 	private final Semaphore active = new Semaphore(MAX, true);
 
@@ -43,10 +40,7 @@ void clear() {
 					continue;
 				}
 			}
-
-			synchronized (events) {
-				events.clear();
-			}
+			events.clear();
 		} finally {
 			active.release(MAX);
 		}
@@ -63,19 +57,15 @@ List<AccessEvent> getEvents() {
 					continue;
 				}
 			}
-
-			synchronized (events) {
-				return events;
-			}
+			return Collections.unmodifiableList(new ArrayList<>(events));
 		} finally {
 			active.release(MAX);
 		}
 	}
 
 	@Override
-	public void handle(String target, Request baseRequest,
-			HttpServletRequest request, HttpServletResponse response)
-			throws IOException, ServletException {
+	public boolean handle(Request request, Response response, Callback callback)
+			throws Exception {
 		try {
 			for (;;) {
 				try {
@@ -86,21 +76,13 @@ public void handle(String target, Request baseRequest,
 				}
 			}
 
-			AccessEvent event = null;
-			if (DispatcherType.REQUEST
-					.equals(baseRequest.getDispatcherType())) {
-				event = new AccessEvent((Request) request);
-				synchronized (events) {
-					events.add(event);
-				}
-			}
+			AccessEvent event = new AccessEvent(request);
+			events.add(event);
 
-			super.handle(target, baseRequest, request, response);
+			boolean result = super.handle(request, response, callback);
 
-			if (event != null) {
-				event.setResponse((Response) response);
-			}
-
+			event.setResponse(response);
+			return result;
 		} finally {
 			active.release();
 		}
diff --git a/org.eclipse.jgit.junit.ssh/.classpath b/org.eclipse.jgit.junit.ssh/.classpath
index 1fde318..efeb803 100644
--- a/org.eclipse.jgit.junit.ssh/.classpath
+++ b/org.eclipse.jgit.junit.ssh/.classpath
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17">
 		<attributes>
 			<attribute name="module" value="true"/>
 		</attributes>
diff --git a/org.eclipse.jgit.junit.ssh/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit.junit.ssh/.settings/org.eclipse.jdt.core.prefs
index e9a5a41..9e563cc 100644
--- a/org.eclipse.jgit.junit.ssh/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit.junit.ssh/.settings/org.eclipse.jdt.core.prefs
@@ -7,9 +7,9 @@
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=11
+org.eclipse.jdt.core.compiler.compliance=17
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -115,7 +115,7 @@
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
 org.eclipse.jdt.core.compiler.release=enabled
-org.eclipse.jdt.core.compiler.source=11
+org.eclipse.jdt.core.compiler.source=17
 org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
 org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
diff --git a/org.eclipse.jgit.junit.ssh/META-INF/MANIFEST.MF b/org.eclipse.jgit.junit.ssh/META-INF/MANIFEST.MF
index d634e94..dfa1b7a 100644
--- a/org.eclipse.jgit.junit.ssh/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.junit.ssh/META-INF/MANIFEST.MF
@@ -3,11 +3,11 @@
 Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.junit.ssh
 Bundle-SymbolicName: org.eclipse.jgit.junit.ssh
-Bundle-Version: 6.10.2.qualifier
+Bundle-Version: 7.0.2.qualifier
 Bundle-Localization: OSGI-INF/l10n/plugin
 Bundle-Vendor: %Bundle-Vendor
 Bundle-ActivationPolicy: lazy
-Bundle-RequiredExecutionEnvironment: JavaSE-11
+Bundle-RequiredExecutionEnvironment: JavaSE-17
 Import-Package: org.apache.sshd.common;version="[2.14.0,2.15.0)",
  org.apache.sshd.common.config.keys;version="[2.14.0,2.15.0)",
  org.apache.sshd.common.file.virtualfs;version="[2.14.0,2.15.0)",
@@ -33,16 +33,16 @@
  org.apache.sshd.server.subsystem;version="[2.14.0,2.15.0)",
  org.apache.sshd.sftp;version="[2.14.0,2.15.0)",
  org.apache.sshd.sftp.server;version="[2.14.0,2.15.0)",
- org.eclipse.jgit.annotations;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.api;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.api.errors;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.errors;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.junit;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.lib;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.revwalk;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.transport;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.util;version="[6.10.2,6.11.0)",
+ org.eclipse.jgit.annotations;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.api;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.api.errors;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.errors;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.junit;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.lib;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.revwalk;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.transport;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.util;version="[7.0.2,7.1.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="6.10.2"
+Export-Package: org.eclipse.jgit.junit.ssh;version="7.0.2"
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 9e57cf4..5f840d1 100644
--- a/org.eclipse.jgit.junit.ssh/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.junit.ssh/META-INF/SOURCE-MANIFEST.MF
@@ -3,5 +3,5 @@
 Bundle-Name: org.eclipse.jgit.junit.ssh - Sources
 Bundle-SymbolicName: org.eclipse.jgit.junit.ssh.source
 Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 6.10.2.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit.junit.ssh;version="6.10.2.qualifier";roots="."
+Bundle-Version: 7.0.2.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit.junit.ssh;version="7.0.2.qualifier";roots="."
diff --git a/org.eclipse.jgit.junit.ssh/pom.xml b/org.eclipse.jgit.junit.ssh/pom.xml
index 27631b2..067374b 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>6.10.2-SNAPSHOT</version>
+    <version>7.0.2-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.junit.ssh</artifactId>
diff --git a/org.eclipse.jgit.junit/.classpath b/org.eclipse.jgit.junit/.classpath
index 4a00bec..3628e33 100644
--- a/org.eclipse.jgit.junit/.classpath
+++ b/org.eclipse.jgit.junit/.classpath
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17">
 		<attributes>
 			<attribute name="module" value="true"/>
 		</attributes>
diff --git a/org.eclipse.jgit.junit/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit.junit/.settings/org.eclipse.jdt.core.prefs
index bb15648..c441260 100644
--- a/org.eclipse.jgit.junit/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit.junit/.settings/org.eclipse.jdt.core.prefs
@@ -10,9 +10,9 @@
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=11
+org.eclipse.jdt.core.compiler.compliance=17
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -126,7 +126,7 @@
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
 org.eclipse.jdt.core.compiler.release=enabled
-org.eclipse.jdt.core.compiler.source=11
+org.eclipse.jdt.core.compiler.source=17
 org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
 org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
diff --git a/org.eclipse.jgit.junit/META-INF/MANIFEST.MF b/org.eclipse.jgit.junit/META-INF/MANIFEST.MF
index 498d1b0..c7ae7ce 100644
--- a/org.eclipse.jgit.junit/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.junit/META-INF/MANIFEST.MF
@@ -3,36 +3,36 @@
 Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.junit
 Bundle-SymbolicName: org.eclipse.jgit.junit
-Bundle-Version: 6.10.2.qualifier
+Bundle-Version: 7.0.2.qualifier
 Bundle-Localization: OSGI-INF/l10n/plugin
 Bundle-Vendor: %Bundle-Vendor
 Bundle-ActivationPolicy: lazy
-Bundle-RequiredExecutionEnvironment: JavaSE-11
-Import-Package: org.eclipse.jgit.annotations;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.api;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.api.errors;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.dircache;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.errors;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.internal.storage.file;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.internal.storage.pack;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.internal.util;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.lib;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.merge;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.revwalk;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.storage.file;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.transport;version="6.10.2",
- org.eclipse.jgit.treewalk;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.treewalk.filter;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.util;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.util.io;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.util.time;version="[6.10.2,6.11.0)",
+Bundle-RequiredExecutionEnvironment: JavaSE-17
+Import-Package: org.eclipse.jgit.annotations;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.api;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.api.errors;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.dircache;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.errors;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.internal.storage.file;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.internal.storage.pack;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.internal.util;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.lib;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.merge;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.revwalk;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.storage.file;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.transport;version="7.0.2",
+ org.eclipse.jgit.treewalk;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.treewalk.filter;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.util;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.util.io;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.util.time;version="[7.0.2,7.1.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="6.10.2";
+Export-Package: org.eclipse.jgit.junit;version="7.0.2";
   uses:="org.eclipse.jgit.dircache,
    org.eclipse.jgit.lib,
    org.eclipse.jgit.revwalk,
@@ -45,4 +45,4 @@
    org.junit.runners.model,
    org.junit.runner,
    org.eclipse.jgit.util.time",
- org.eclipse.jgit.junit.time;version="6.10.2";uses:="org.eclipse.jgit.util.time"
+ org.eclipse.jgit.junit.time;version="7.0.2";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 95e47f3..ef76a33 100644
--- a/org.eclipse.jgit.junit/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.junit/META-INF/SOURCE-MANIFEST.MF
@@ -3,5 +3,5 @@
 Bundle-Name: org.eclipse.jgit.junit - Sources
 Bundle-SymbolicName: org.eclipse.jgit.junit.source
 Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 6.10.2.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit.junit;version="6.10.2.qualifier";roots="."
+Bundle-Version: 7.0.2.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit.junit;version="7.0.2.qualifier";roots="."
diff --git a/org.eclipse.jgit.junit/pom.xml b/org.eclipse.jgit.junit/pom.xml
index 3db8b20..b63973f 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>6.10.2-SNAPSHOT</version>
+    <version>7.0.2-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.junit</artifactId>
diff --git a/org.eclipse.jgit.lfs.server.test/.classpath b/org.eclipse.jgit.lfs.server.test/.classpath
index 5899a4e..6fdb99a 100644
--- a/org.eclipse.jgit.lfs.server.test/.classpath
+++ b/org.eclipse.jgit.lfs.server.test/.classpath
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17">
 		<attributes>
 			<attribute name="module" value="true"/>
 		</attributes>
diff --git a/org.eclipse.jgit.lfs.server.test/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit.lfs.server.test/.settings/org.eclipse.jdt.core.prefs
index 9c8bfdb..10304e0e 100644
--- a/org.eclipse.jgit.lfs.server.test/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit.lfs.server.test/.settings/org.eclipse.jdt.core.prefs
@@ -7,9 +7,9 @@
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=11
+org.eclipse.jdt.core.compiler.compliance=17
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -115,7 +115,7 @@
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
 org.eclipse.jdt.core.compiler.release=enabled
-org.eclipse.jdt.core.compiler.source=11
+org.eclipse.jdt.core.compiler.source=17
 org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
 org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
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 2624f1b..3ce8c3e 100644
--- a/org.eclipse.jgit.lfs.server.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.lfs.server.test/META-INF/MANIFEST.MF
@@ -3,47 +3,47 @@
 Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.lfs.server.test
 Bundle-SymbolicName: org.eclipse.jgit.lfs.server.test
-Bundle-Version: 6.10.2.qualifier
+Bundle-Version: 7.0.2.qualifier
 Bundle-Vendor: %Bundle-Vendor
 Bundle-Localization: plugin
-Bundle-RequiredExecutionEnvironment: JavaSE-11
-Import-Package: javax.servlet;version="[3.1.0,5.0.0)",
- javax.servlet.http;version="[3.1.0,5.0.0)",
+Bundle-RequiredExecutionEnvironment: JavaSE-17
+Import-Package: jakarta.servlet;version="[6.0.0,7.0.0)",
+ jakarta.servlet.http;version="[6.0.0,7.0.0)",
  org.apache.http;version="[4.4.0,5.0.0)",
  org.apache.http.client;version="[4.4.0,5.0.0)",
  org.apache.http.client.methods;version="[4.4.0,5.0.0)",
  org.apache.http.entity;version="[4.4.0,5.0.0)",
  org.apache.http.impl.client;version="[4.4.0,5.0.0)",
- org.eclipse.jetty.http;version="[10.0.0,11.0.0)",
- org.eclipse.jetty.io;version="[10.0.0,11.0.0)",
- org.eclipse.jetty.security;version="[10.0.0,11.0.0)",
- org.eclipse.jetty.security.authentication;version="[10.0.0,11.0.0)",
- org.eclipse.jetty.server;version="[10.0.0,11.0.0)",
- org.eclipse.jetty.server.handler;version="[10.0.0,11.0.0)",
- org.eclipse.jetty.servlet;version="[10.0.0,11.0.0)",
- org.eclipse.jetty.util;version="[10.0.0,11.0.0)",
- org.eclipse.jetty.util.component;version="[10.0.0,11.0.0)",
- org.eclipse.jetty.util.log;version="[10.0.0,11.0.0)",
- org.eclipse.jetty.util.security;version="[10.0.0,11.0.0)",
- org.eclipse.jetty.util.thread;version="[10.0.0,11.0.0)",
- org.eclipse.jgit.api;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.api.errors;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.internal.storage.file;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.junit;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.junit.http;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.lfs;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.lfs.errors;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.lfs.lib;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.lfs.server;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.lfs.server.fs;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.lfs.test;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.lib;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.revwalk;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.storage.file;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.transport;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.treewalk;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.treewalk.filter;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.util;version="[6.10.2,6.11.0)",
+ org.eclipse.jetty.ee10.servlet;version="[12.0.0,13.0.0)",
+ org.eclipse.jetty.http;version="[12.0.0,13.0.0)",
+ org.eclipse.jetty.io;version="[12.0.0,13.0.0)",
+ org.eclipse.jetty.security;version="[12.0.0,13.0.0)",
+ org.eclipse.jetty.security.authentication;version="[12.0.0,13.0.0)",
+ org.eclipse.jetty.session;version="[12.0.0,13.0.0)",
+ org.eclipse.jetty.server;version="[12.0.0,13.0.0)",
+ 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.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.0.2,7.1.0)",
+ org.eclipse.jgit.api.errors;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.internal.storage.file;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.junit;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.junit.http;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.lfs;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.lfs.errors;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.lfs.lib;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.lfs.server;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.lfs.server.fs;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.lfs.test;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.lib;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.revwalk;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.storage.file;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.transport;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.treewalk;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.treewalk.filter;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.util;version="[7.0.2,7.1.0)",
  org.hamcrest.core;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.lfs.server.test/pom.xml b/org.eclipse.jgit.lfs.server.test/pom.xml
index bb33336..a3a99b5 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>6.10.2-SNAPSHOT</version>
+    <version>7.0.2-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.lfs.server.test</artifactId>
@@ -74,8 +74,8 @@
     </dependency>
 
     <dependency>
-      <groupId>org.eclipse.jetty</groupId>
-      <artifactId>jetty-servlet</artifactId>
+      <groupId>org.eclipse.jetty.ee10</groupId>
+      <artifactId>jetty-ee10-servlet</artifactId>
       <scope>test</scope>
     </dependency>
 
diff --git a/org.eclipse.jgit.lfs.server.test/tst/org/eclipse/jgit/lfs/server/fs/LfsServerTest.java b/org.eclipse.jgit.lfs.server.test/tst/org/eclipse/jgit/lfs/server/fs/LfsServerTest.java
index b2b9ee0..9a49023 100644
--- a/org.eclipse.jgit.lfs.server.test/tst/org/eclipse/jgit/lfs/server/fs/LfsServerTest.java
+++ b/org.eclipse.jgit.lfs.server.test/tst/org/eclipse/jgit/lfs/server/fs/LfsServerTest.java
@@ -39,8 +39,8 @@
 import org.apache.http.entity.StringEntity;
 import org.apache.http.impl.client.CloseableHttpClient;
 import org.apache.http.impl.client.HttpClientBuilder;
-import org.eclipse.jetty.servlet.ServletContextHandler;
-import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.ee10.servlet.ServletContextHandler;
+import org.eclipse.jetty.ee10.servlet.ServletHolder;
 import org.eclipse.jgit.junit.MockSystemReader;
 import org.eclipse.jgit.junit.http.AppServer;
 import org.eclipse.jgit.lfs.errors.LfsException;
diff --git a/org.eclipse.jgit.lfs.server/.classpath b/org.eclipse.jgit.lfs.server/.classpath
index 139a059..dde8e3f 100644
--- a/org.eclipse.jgit.lfs.server/.classpath
+++ b/org.eclipse.jgit.lfs.server/.classpath
@@ -2,7 +2,7 @@
 <classpath>
 	<classpathentry kind="src" path="src"/>
 	<classpathentry kind="src" path="resources"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17">
 		<attributes>
 			<attribute name="module" value="true"/>
 		</attributes>
diff --git a/org.eclipse.jgit.lfs.server/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit.lfs.server/.settings/org.eclipse.jdt.core.prefs
index 3a92f0c..f810c7b 100644
--- a/org.eclipse.jgit.lfs.server/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit.lfs.server/.settings/org.eclipse.jdt.core.prefs
@@ -7,9 +7,9 @@
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=11
+org.eclipse.jdt.core.compiler.compliance=17
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -115,7 +115,7 @@
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
 org.eclipse.jdt.core.compiler.release=enabled
-org.eclipse.jdt.core.compiler.source=11
+org.eclipse.jdt.core.compiler.source=17
 org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
 org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
diff --git a/org.eclipse.jgit.lfs.server/META-INF/MANIFEST.MF b/org.eclipse.jgit.lfs.server/META-INF/MANIFEST.MF
index 322951d..70d6029 100644
--- a/org.eclipse.jgit.lfs.server/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.lfs.server/META-INF/MANIFEST.MF
@@ -3,36 +3,36 @@
 Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.lfs.server
 Bundle-SymbolicName: org.eclipse.jgit.lfs.server
-Bundle-Version: 6.10.2.qualifier
+Bundle-Version: 7.0.2.qualifier
 Bundle-Localization: OSGI-INF/l10n/plugin
 Bundle-Vendor: %Bundle-Vendor
-Export-Package: org.eclipse.jgit.lfs.server;version="6.10.2";
-  uses:="javax.servlet.http,
+Export-Package: org.eclipse.jgit.lfs.server;version="7.0.2";
+  uses:="jakarta.servlet.http,
    org.eclipse.jgit.lfs.lib",
- org.eclipse.jgit.lfs.server.fs;version="6.10.2";
-  uses:="javax.servlet,
-   javax.servlet.http,
+ org.eclipse.jgit.lfs.server.fs;version="7.0.2";
+  uses:="jakarta.servlet,
+   jakarta.servlet.http,
    org.eclipse.jgit.lfs.server,
    org.eclipse.jgit.lfs.lib",
- org.eclipse.jgit.lfs.server.internal;version="6.10.2";x-internal:=true,
- org.eclipse.jgit.lfs.server.s3;version="6.10.2";
+ org.eclipse.jgit.lfs.server.internal;version="7.0.2";x-internal:=true,
+ org.eclipse.jgit.lfs.server.s3;version="7.0.2";
   uses:="org.eclipse.jgit.lfs.server,
    org.eclipse.jgit.lfs.lib"
-Bundle-RequiredExecutionEnvironment: JavaSE-11
+Bundle-RequiredExecutionEnvironment: JavaSE-17
 Import-Package: com.google.gson;version="[2.8.0,3.0.0)",
- javax.servlet;version="[3.1.0,5.0.0)",
- javax.servlet.annotation;version="[3.1.0,5.0.0)",
- javax.servlet.http;version="[3.1.0,5.0.0)",
+ jakarta.servlet;version="[6.0.0,7.0.0)",
+ 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="[6.10.2,6.11.0)",
- org.eclipse.jgit.internal;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.internal.storage.file;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.lfs.errors;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.lfs.internal;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.lfs.lib;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.lib;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.nls;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.transport.http;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.transport.http.apache;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.util;version="[6.10.2,6.11.0)",
+ org.eclipse.jgit.annotations;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.internal;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.internal.storage.file;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.lfs.errors;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.lfs.internal;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.lfs.lib;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.lib;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.nls;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.transport.http;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.transport.http.apache;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.util;version="[7.0.2,7.1.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 5965f1c..2c07938 100644
--- a/org.eclipse.jgit.lfs.server/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.lfs.server/META-INF/SOURCE-MANIFEST.MF
@@ -3,5 +3,5 @@
 Bundle-Name: org.eclipse.jgit.lfs.server - Sources
 Bundle-SymbolicName: org.eclipse.jgit.lfs.server.source
 Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 6.10.2.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit.lfs.server;version="6.10.2.qualifier";roots="."
+Bundle-Version: 7.0.2.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit.lfs.server;version="7.0.2.qualifier";roots="."
diff --git a/org.eclipse.jgit.lfs.server/pom.xml b/org.eclipse.jgit.lfs.server/pom.xml
index 8da0d6b..679480b 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>6.10.2-SNAPSHOT</version>
+    <version>7.0.2-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.lfs.server</artifactId>
diff --git a/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/LfsProtocolServlet.java b/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/LfsProtocolServlet.java
index 84bab5b..1d245a0 100644
--- a/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/LfsProtocolServlet.java
+++ b/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/LfsProtocolServlet.java
@@ -33,10 +33,10 @@
 import java.text.MessageFormat;
 import java.util.List;
 
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 
 import org.eclipse.jgit.lfs.errors.LfsBandwidthLimitExceeded;
 import org.eclipse.jgit.lfs.errors.LfsException;
diff --git a/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/TransferHandler.java b/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/TransferHandler.java
index b84228b..4662830 100644
--- a/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/TransferHandler.java
+++ b/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/TransferHandler.java
@@ -10,7 +10,7 @@
 
 package org.eclipse.jgit.lfs.server;
 
-import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND;
+import static jakarta.servlet.http.HttpServletResponse.SC_NOT_FOUND;
 import static org.eclipse.jgit.lfs.lib.Constants.DOWNLOAD;
 import static org.eclipse.jgit.lfs.lib.Constants.UPLOAD;
 import static org.eclipse.jgit.lfs.lib.Constants.VERIFY;
diff --git a/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/fs/FileLfsServlet.java b/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/fs/FileLfsServlet.java
index e7cdf9d..e95122d 100644
--- a/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/fs/FileLfsServlet.java
+++ b/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/fs/FileLfsServlet.java
@@ -13,12 +13,12 @@
 import java.io.PrintWriter;
 import java.text.MessageFormat;
 
-import javax.servlet.AsyncContext;
-import javax.servlet.ServletException;
-import javax.servlet.annotation.WebServlet;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.AsyncContext;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.annotation.WebServlet;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 
 import org.apache.http.HttpStatus;
 import org.eclipse.jgit.lfs.errors.InvalidLongObjectIdException;
@@ -93,7 +93,7 @@ protected void doGet(HttpServletRequest req,
 	 *         retrieved
 	 * @throws java.io.IOException
 	 *             if an I/O error occurs
-	 * @since 4.6
+	 * @since 7.0
 	 */
 	protected AnyLongObjectId getObjectToTransfer(HttpServletRequest req,
 			HttpServletResponse rsp) throws IOException {
@@ -140,7 +140,7 @@ protected void doPut(HttpServletRequest req,
 	 *            error message
 	 * @throws java.io.IOException
 	 *             on failure to send the response
-	 * @since 4.6
+	 * @since 7.0
 	 */
 	protected static void sendError(HttpServletResponse rsp, int status, String message)
 			throws IOException {
diff --git a/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/fs/ObjectDownloadListener.java b/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/fs/ObjectDownloadListener.java
index 2ea92da..c826aa6 100644
--- a/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/fs/ObjectDownloadListener.java
+++ b/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/fs/ObjectDownloadListener.java
@@ -17,10 +17,10 @@
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
-import javax.servlet.AsyncContext;
-import javax.servlet.ServletOutputStream;
-import javax.servlet.WriteListener;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.AsyncContext;
+import jakarta.servlet.ServletOutputStream;
+import jakarta.servlet.WriteListener;
+import jakarta.servlet.http.HttpServletResponse;
 
 import org.apache.http.HttpStatus;
 import org.eclipse.jgit.lfs.lib.AnyLongObjectId;
@@ -64,6 +64,7 @@ public class ObjectDownloadListener implements WriteListener {
 	 *            id of the object to be downloaded
 	 * @throws java.io.IOException
 	 *             if an IO error occurred
+	 * @since 7.0
 	 */
 	public ObjectDownloadListener(FileLfsRepository repository,
 			AsyncContext context, HttpServletResponse response,
diff --git a/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/fs/ObjectUploadListener.java b/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/fs/ObjectUploadListener.java
index 1ac2b20..d0c07fb 100644
--- a/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/fs/ObjectUploadListener.java
+++ b/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/fs/ObjectUploadListener.java
@@ -19,11 +19,11 @@
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
-import javax.servlet.AsyncContext;
-import javax.servlet.ReadListener;
-import javax.servlet.ServletInputStream;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.AsyncContext;
+import jakarta.servlet.ReadListener;
+import jakarta.servlet.ServletInputStream;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 
 import org.apache.http.HttpStatus;
 import org.eclipse.jgit.lfs.errors.CorruptLongObjectException;
@@ -84,17 +84,18 @@ public interface Callback {
 	 * @param repository
 	 *            the repository storing large objects
 	 * @param context
-	 *            a {@link javax.servlet.AsyncContext} object.
+	 *            a {@link jakarta.servlet.AsyncContext} object.
 	 * @param request
-	 *            a {@link javax.servlet.http.HttpServletRequest} object.
+	 *            a {@link jakarta.servlet.http.HttpServletRequest} object.
 	 * @param response
-	 *            a {@link javax.servlet.http.HttpServletResponse} object.
+	 *            a {@link jakarta.servlet.http.HttpServletResponse} object.
 	 * @param id
 	 *            a {@link org.eclipse.jgit.lfs.lib.AnyLongObjectId} object.
 	 * @throws java.io.FileNotFoundException
 	 *             if file wasn't found
 	 * @throws java.io.IOException
 	 *             if an IO error occurred
+	 * @since 7.0
 	 */
 	public ObjectUploadListener(FileLfsRepository repository,
 			AsyncContext context, HttpServletRequest request,
diff --git a/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/s3/S3Repository.java b/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/s3/S3Repository.java
index 5ebce5d..01ddc95 100644
--- a/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/s3/S3Repository.java
+++ b/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/s3/S3Repository.java
@@ -10,7 +10,7 @@
  */
 package org.eclipse.jgit.lfs.server.s3;
 
-import static javax.servlet.http.HttpServletResponse.SC_OK;
+import static jakarta.servlet.http.HttpServletResponse.SC_OK;
 import static org.eclipse.jgit.lfs.server.s3.SignerV4.UNSIGNED_PAYLOAD;
 import static org.eclipse.jgit.lfs.server.s3.SignerV4.X_AMZ_CONTENT_SHA256;
 import static org.eclipse.jgit.lfs.server.s3.SignerV4.X_AMZ_EXPIRES;
diff --git a/org.eclipse.jgit.lfs.test/.classpath b/org.eclipse.jgit.lfs.test/.classpath
index 722f302..9737446 100644
--- a/org.eclipse.jgit.lfs.test/.classpath
+++ b/org.eclipse.jgit.lfs.test/.classpath
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17">
 		<attributes>
 			<attribute name="module" value="true"/>
 		</attributes>
diff --git a/org.eclipse.jgit.lfs.test/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit.lfs.test/.settings/org.eclipse.jdt.core.prefs
index 69e9221..362915d 100644
--- a/org.eclipse.jgit.lfs.test/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit.lfs.test/.settings/org.eclipse.jdt.core.prefs
@@ -7,9 +7,9 @@
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=11
+org.eclipse.jdt.core.compiler.compliance=17
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -115,7 +115,7 @@
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
 org.eclipse.jdt.core.compiler.release=enabled
-org.eclipse.jdt.core.compiler.source=11
+org.eclipse.jdt.core.compiler.source=17
 org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
 org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
diff --git a/org.eclipse.jgit.lfs.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.lfs.test/META-INF/MANIFEST.MF
index 0b597d9..2d1acdb 100644
--- a/org.eclipse.jgit.lfs.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.lfs.test/META-INF/MANIFEST.MF
@@ -3,28 +3,28 @@
 Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.lfs.test
 Bundle-SymbolicName: org.eclipse.jgit.lfs.test
-Bundle-Version: 6.10.2.qualifier
+Bundle-Version: 7.0.2.qualifier
 Bundle-Vendor: %Bundle-Vendor
 Bundle-Localization: plugin
-Bundle-RequiredExecutionEnvironment: JavaSE-11
-Import-Package: org.eclipse.jgit.api;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.attributes;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.internal.storage.dfs;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.internal.storage.file;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.junit;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.lfs;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.lfs.errors;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.lfs.internal;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.lfs.lib;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.lib;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.revwalk;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.transport;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.transport.http;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.treewalk;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.treewalk.filter;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.util;version="[6.10.2,6.11.0)",
+Bundle-RequiredExecutionEnvironment: JavaSE-17
+Import-Package: org.eclipse.jgit.api;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.attributes;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.internal.storage.dfs;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.internal.storage.file;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.junit;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.lfs;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.lfs.errors;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.lfs.internal;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.lfs.lib;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.lib;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.revwalk;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.transport;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.transport.http;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.treewalk;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.treewalk.filter;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.util;version="[7.0.2,7.1.0)",
  org.hamcrest.core;version="[1.1.0,3.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="6.10.2";x-friends:="org.eclipse.jgit.lfs.server.test"
+Export-Package: org.eclipse.jgit.lfs.test;version="7.0.2";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 e34dd2b..79601ff 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>6.10.2-SNAPSHOT</version>
+    <version>7.0.2-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.lfs.test</artifactId>
diff --git a/org.eclipse.jgit.lfs/.classpath b/org.eclipse.jgit.lfs/.classpath
index 139a059..dde8e3f 100644
--- a/org.eclipse.jgit.lfs/.classpath
+++ b/org.eclipse.jgit.lfs/.classpath
@@ -2,7 +2,7 @@
 <classpath>
 	<classpathentry kind="src" path="src"/>
 	<classpathentry kind="src" path="resources"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17">
 		<attributes>
 			<attribute name="module" value="true"/>
 		</attributes>
diff --git a/org.eclipse.jgit.lfs/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit.lfs/.settings/org.eclipse.jdt.core.prefs
index 3a92f0c..f810c7b 100644
--- a/org.eclipse.jgit.lfs/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit.lfs/.settings/org.eclipse.jdt.core.prefs
@@ -7,9 +7,9 @@
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=11
+org.eclipse.jdt.core.compiler.compliance=17
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -115,7 +115,7 @@
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
 org.eclipse.jdt.core.compiler.release=enabled
-org.eclipse.jdt.core.compiler.source=11
+org.eclipse.jdt.core.compiler.source=17
 org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
 org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
diff --git a/org.eclipse.jgit.lfs/META-INF/MANIFEST.MF b/org.eclipse.jgit.lfs/META-INF/MANIFEST.MF
index c5f0919..bb87bab 100644
--- a/org.eclipse.jgit.lfs/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.lfs/META-INF/MANIFEST.MF
@@ -3,32 +3,32 @@
 Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.lfs
 Bundle-SymbolicName: org.eclipse.jgit.lfs
-Bundle-Version: 6.10.2.qualifier
+Bundle-Version: 7.0.2.qualifier
 Bundle-Localization: OSGI-INF/l10n/plugin
 Bundle-Vendor: %Bundle-Vendor
-Export-Package: org.eclipse.jgit.lfs;version="6.10.2",
- org.eclipse.jgit.lfs.errors;version="6.10.2",
- org.eclipse.jgit.lfs.internal;version="6.10.2";x-friends:="org.eclipse.jgit.lfs.test,org.eclipse.jgit.lfs.server.fs,org.eclipse.jgit.lfs.server",
- org.eclipse.jgit.lfs.lib;version="6.10.2"
-Bundle-RequiredExecutionEnvironment: JavaSE-11
+Export-Package: org.eclipse.jgit.lfs;version="7.0.2",
+ org.eclipse.jgit.lfs.errors;version="7.0.2",
+ org.eclipse.jgit.lfs.internal;version="7.0.2";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.0.2"
+Bundle-RequiredExecutionEnvironment: JavaSE-17
 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="[6.10.2,6.11.0)";resolution:=optional,
- org.eclipse.jgit.api.errors;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.attributes;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.diff;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.dircache;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.errors;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.hooks;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.internal.storage.file;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.lib;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.nls;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.revwalk;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.storage.file;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.storage.pack;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.transport;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.transport.http;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.treewalk;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.treewalk.filter;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.util;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.util.io;version="[6.10.2,6.11.0)"
+ org.eclipse.jgit.annotations;version="[7.0.2,7.1.0)";resolution:=optional,
+ org.eclipse.jgit.api.errors;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.attributes;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.diff;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.dircache;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.errors;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.hooks;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.internal.storage.file;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.lib;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.nls;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.revwalk;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.storage.file;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.storage.pack;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.transport;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.transport.http;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.treewalk;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.treewalk.filter;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.util;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.util.io;version="[7.0.2,7.1.0)"
diff --git a/org.eclipse.jgit.lfs/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.lfs/META-INF/SOURCE-MANIFEST.MF
index 6ca664d..a1dd5b8 100644
--- a/org.eclipse.jgit.lfs/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.lfs/META-INF/SOURCE-MANIFEST.MF
@@ -3,5 +3,5 @@
 Bundle-Name: org.eclipse.jgit.lfs - Sources
 Bundle-SymbolicName: org.eclipse.jgit.lfs.source
 Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 6.10.2.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit.lfs;version="6.10.2.qualifier";roots="."
+Bundle-Version: 7.0.2.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit.lfs;version="7.0.2.qualifier";roots="."
diff --git a/org.eclipse.jgit.lfs/pom.xml b/org.eclipse.jgit.lfs/pom.xml
index b85a0da..80f047a 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>6.10.2-SNAPSHOT</version>
+    <version>7.0.2-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.lfs</artifactId>
diff --git a/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/lib/AnyLongObjectId.java b/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/lib/AnyLongObjectId.java
index 75d500e..a13a60c 100644
--- a/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/lib/AnyLongObjectId.java
+++ b/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/lib/AnyLongObjectId.java
@@ -41,24 +41,6 @@ public abstract class AnyLongObjectId implements Comparable<AnyLongObjectId> {
 	 * @param secondObjectId
 	 *            the second identifier to compare. Must not be null.
 	 * @return true if the two identifiers are the same.
-	 * @deprecated use {@link #isEqual(AnyLongObjectId, AnyLongObjectId)}
-	 *             instead.
-	 */
-	@Deprecated
-	@SuppressWarnings("AmbiguousMethodReference")
-	public static boolean equals(final AnyLongObjectId firstObjectId,
-			final AnyLongObjectId secondObjectId) {
-		return isEqual(firstObjectId, secondObjectId);
-	}
-
-	/**
-	 * Compare two object identifier byte sequences for equality.
-	 *
-	 * @param firstObjectId
-	 *            the first identifier to compare. Must not be null.
-	 * @param secondObjectId
-	 *            the second identifier to compare. Must not be null.
-	 * @return true if the two identifiers are the same.
 	 * @since 5.4
 	 */
 	public static boolean isEqual(final AnyLongObjectId firstObjectId,
@@ -263,7 +245,7 @@ public final int hashCode() {
 	 */
 	@SuppressWarnings({ "NonOverridingEquals", "AmbiguousMethodReference" })
 	public final boolean equals(AnyLongObjectId other) {
-		return other != null ? equals(this, other) : false;
+		return other != null ? isEqual(this, other) : false;
 	}
 
 	@Override
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 0c2419c..98a3615 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="6.10.2.qualifier"
+      version="7.0.2.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 d20bb38..bf22c74 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>6.10.2-SNAPSHOT</version>
+    <version>7.0.2-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 51c8dcc..987a925 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="6.10.2.qualifier"
+      version="7.0.2.qualifier"
       provider-name="%providerName">
 
    <description url="http://www.eclipse.org/jgit/">
@@ -23,7 +23,7 @@
    </url>
 
    <requires>
-      <import plugin="org.eclipse.jgit" version="6.10.2" match="equivalent"/>
+      <import plugin="org.eclipse.jgit" version="7.0.2" 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 d610412..7d2f4d9 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>6.10.2-SNAPSHOT</version>
+    <version>7.0.2-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 54d5ba3..459e77c 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="6.10.2.qualifier"
+      version="7.0.2.qualifier"
       provider-name="%providerName">
 
    <description url="http://www.eclipse.org/jgit/">
@@ -23,7 +23,7 @@
    </url>
 
    <requires>
-      <import plugin="org.eclipse.jgit" version="6.10.2" match="equivalent"/>
+      <import plugin="org.eclipse.jgit" version="7.0.2" 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 e5eebd4..7c5b580 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>6.10.2-SNAPSHOT</version>
+    <version>7.0.2-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 6f4ed14..fe4d8d7 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="6.10.2.qualifier"
+      version="7.0.2.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="6.10.2" match="equivalent"/>
+      <import plugin="org.eclipse.jgit" version="7.0.2" 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 28d4de2..03c53de 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>6.10.2-SNAPSHOT</version>
+    <version>7.0.2-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 0c290f5..e991f99 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="6.10.2.qualifier"
+      version="7.0.2.qualifier"
       provider-name="%providerName">
 
    <description url="http://www.eclipse.org/jgit/">
@@ -23,7 +23,7 @@
    </url>
 
    <requires>
-      <import feature="org.eclipse.jgit" version="6.10.2" match="equivalent"/>
+      <import feature="org.eclipse.jgit" version="7.0.2" 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 9e01453..57c62b2 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>6.10.2-SNAPSHOT</version>
+    <version>7.0.2-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 233b0e8..aa6ad24 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="6.10.2.qualifier"
+      version="7.0.2.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="6.10.2" match="equivalent"/>
-      <import feature="org.eclipse.jgit.lfs" version="6.10.2" match="equivalent"/>
-      <import feature="org.eclipse.jgit.ssh.apache" version="6.10.2" match="equivalent"/>
+      <import feature="org.eclipse.jgit" version="7.0.2" match="equivalent"/>
+      <import feature="org.eclipse.jgit.lfs" version="7.0.2" match="equivalent"/>
+      <import feature="org.eclipse.jgit.ssh.apache" version="7.0.2" 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 5bd5675..bb595d6 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>6.10.2-SNAPSHOT</version>
+    <version>7.0.2-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 bf24cb8..de54772 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.repository/category.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.repository/category.xml
@@ -105,10 +105,10 @@
    <bundle id="org.eclipse.jetty.server.source">
       <category name="JGit-dependency-bundles"/>
    </bundle>
-   <bundle id="org.eclipse.jetty.servlet">
+   <bundle id="org.eclipse.jetty.ee10.servlet">
       <category name="JGit-dependency-bundles"/>
    </bundle>
-   <bundle id="org.eclipse.jetty.servlet.source">
+   <bundle id="org.eclipse.jetty.ee10.servlet.source">
       <category name="JGit-dependency-bundles"/>
    </bundle>
    <bundle id="org.eclipse.jetty.util">
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 cc55a36..2c890e2 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>6.10.2-SNAPSHOT</version>
+    <version>7.0.2-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 c4e512c..79d09f7 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="6.10.2.qualifier"
+      version="7.0.2.qualifier"
       provider-name="%providerName">
 
    <description url="http://www.eclipse.org/jgit/">
@@ -23,7 +23,7 @@
    </url>
 
    <requires>
-      <import feature="org.eclipse.jgit" version="6.10.2" match="equivalent"/>
+      <import feature="org.eclipse.jgit" version="7.0.2" 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 efbac2d..51bab0c 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>6.10.2-SNAPSHOT</version>
+    <version>7.0.2-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>6.10.2-SNAPSHOT</version>
+      <version>7.0.2-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 7b5752d..c84de5d 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="6.10.2.qualifier"
+      version="7.0.2.qualifier"
       provider-name="%providerName">
 
    <description url="http://www.eclipse.org/jgit/">
@@ -23,7 +23,7 @@
    </url>
 
    <requires>
-      <import feature="org.eclipse.jgit" version="6.10.2" match="equivalent"/>
+      <import feature="org.eclipse.jgit" version="7.0.2" 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 e3afca2..b135ca0 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>6.10.2-SNAPSHOT</version>
+    <version>7.0.2-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 0b3df89..52d0f3d 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="6.10.2.qualifier"
+      version="7.0.2.qualifier"
       provider-name="%providerName">
 
    <description url="http://www.eclipse.org/jgit/">
@@ -23,7 +23,7 @@
    </url>
 
    <requires>
-      <import plugin="org.eclipse.jgit" version="6.10.2" match="equivalent"/>
+      <import plugin="org.eclipse.jgit" version="7.0.2" 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 502dec4..fb42902 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>6.10.2-SNAPSHOT</version>
+    <version>7.0.2-SNAPSHOT</version>
   </parent>
 
   <groupId>org.eclipse.jgit.feature</groupId>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.32.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.32.target
index b254725..c1964c9 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.32.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.32.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.32" sequenceNumber="1728511223">
+<target name="jgit-4.32" sequenceNumber="1729714537">
   <locations>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
       <unit id="com.jcraft.jsch" version="0.1.55.v20230916-1400"/>
@@ -37,7 +37,7 @@
         <dependency>
           <groupId>org.tukaani</groupId>
           <artifactId>xz</artifactId>
-          <version>1.9</version>
+          <version>1.10</version>
           <type>jar</type>
         </dependency>
       </dependencies>
@@ -103,51 +103,57 @@
     <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.0.10</version>
+          <type>jar</type>
+        </dependency>
+        <dependency>
           <groupId>org.eclipse.jetty</groupId>
           <artifactId>jetty-http</artifactId>
-          <version>10.0.21</version>
+          <version>12.0.12</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.eclipse.jetty</groupId>
           <artifactId>jetty-io</artifactId>
-          <version>10.0.21</version>
+          <version>12.0.12</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.eclipse.jetty</groupId>
           <artifactId>jetty-security</artifactId>
-          <version>10.0.21</version>
+          <version>12.0.12</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.eclipse.jetty</groupId>
           <artifactId>jetty-server</artifactId>
-          <version>10.0.21</version>
+          <version>12.0.12</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.eclipse.jetty</groupId>
-          <artifactId>jetty-servlet</artifactId>
-          <version>10.0.21</version>
+          <artifactId>jetty-session</artifactId>
+          <version>12.0.12</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.eclipse.jetty</groupId>
           <artifactId>jetty-util</artifactId>
-          <version>10.0.21</version>
+          <version>12.0.12</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.eclipse.jetty</groupId>
           <artifactId>jetty-util-ajax</artifactId>
-          <version>10.0.21</version>
+          <version>12.0.12</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>jakarta.servlet</groupId>
           <artifactId>jakarta.servlet-api</artifactId>
-          <version>4.0.4</version>
+          <version>6.1.0</version>
           <type>jar</type>
         </dependency>
       </dependencies>
@@ -187,13 +193,13 @@
         <dependency>
           <groupId>net.bytebuddy</groupId>
           <artifactId>byte-buddy</artifactId>
-          <version>1.14.16</version>
+          <version>1.15.0</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>net.bytebuddy</groupId>
           <artifactId>byte-buddy-agent</artifactId>
-          <version>1.14.16</version>
+          <version>1.15.0</version>
           <type>jar</type>
         </dependency>
       </dependencies>
@@ -231,7 +237,7 @@
         <dependency>
           <groupId>org.assertj</groupId>
           <artifactId>assertj-core</artifactId>
-          <version>3.26.0</version>
+          <version>3.26.3</version>
           <type>jar</type>
         </dependency>
       </dependencies>
@@ -251,19 +257,19 @@
         <dependency>
           <groupId>commons-codec</groupId>
           <artifactId>commons-codec</artifactId>
-          <version>1.17.0</version>
+          <version>1.17.1</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.apache.commons</groupId>
           <artifactId>commons-compress</artifactId>
-          <version>1.26.2</version>
+          <version>1.27.1</version>
           <type>jar</type>
         </dependency>
         <dependency>
           <groupId>org.apache.commons</groupId>
           <artifactId>commons-lang3</artifactId>
-          <version>3.14.0</version>
+          <version>3.16.0</version>
           <type>jar</type>
         </dependency>
         <dependency>
@@ -275,7 +281,7 @@
         <dependency>
           <groupId>commons-logging</groupId>
           <artifactId>commons-logging</artifactId>
-          <version>1.3.2</version>
+          <version>1.3.4</version>
           <type>jar</type>
         </dependency>
       </dependencies>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.33.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.33.target
new file mode 100644
index 0000000..4d9f630
--- /dev/null
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.33.target
@@ -0,0 +1,290 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<?pde?>
+<!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
+<target name="jgit-4.33" sequenceNumber="1729714538">
+  <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="net.i2p.crypto.eddsa" version="0.3.0"/>
+      <unit id="net.i2p.crypto.eddsa.source" version="0.3.0"/>
+      <unit id="org.apache.ant" version="1.10.14.v20230922-1200"/>
+      <unit id="org.apache.ant.source" version="1.10.14.v20230922-1200"/>
+      <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.core" version="1.3.0.v20230809-1000"/>
+      <unit id="org.hamcrest.core.source" version="1.3.0.v20230809-1000"/>
+      <unit id="org.hamcrest.library" version="1.3.0.v20230809-1000"/>
+      <unit id="org.hamcrest.library.source" version="1.3.0.v20230809-1000"/>
+      <unit id="org.junit" version="4.13.2.v20230809-1000"/>
+      <unit id="org.junit.source" version="4.13.2.v20230809-1000"/>
+      <unit id="org.objenesis" version="3.4.0"/>
+      <unit id="org.objenesis.source" version="3.4.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/2024-09"/>
+    </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/2024-09/"/>
+    </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.10</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>1.7.36</version>
+          <type>jar</type>
+        </dependency>
+        <dependency>
+          <groupId>org.slf4j</groupId>
+          <artifactId>slf4j-simple</artifactId>
+          <version>1.7.36</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.14.0</version>
+          <type>jar</type>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.sshd</groupId>
+          <artifactId>sshd-sftp</artifactId>
+          <version>2.14.0</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.12.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.14.0</version>
+          <type>jar</type>
+        </dependency>
+        <dependency>
+          <groupId>net.java.dev.jna</groupId>
+          <artifactId>jna-platform</artifactId>
+          <version>5.14.0</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.0.10</version>
+          <type>jar</type>
+        </dependency>
+        <dependency>
+          <groupId>org.eclipse.jetty</groupId>
+          <artifactId>jetty-http</artifactId>
+          <version>12.0.12</version>
+          <type>jar</type>
+        </dependency>
+        <dependency>
+          <groupId>org.eclipse.jetty</groupId>
+          <artifactId>jetty-io</artifactId>
+          <version>12.0.12</version>
+          <type>jar</type>
+        </dependency>
+        <dependency>
+          <groupId>org.eclipse.jetty</groupId>
+          <artifactId>jetty-security</artifactId>
+          <version>12.0.12</version>
+          <type>jar</type>
+        </dependency>
+        <dependency>
+          <groupId>org.eclipse.jetty</groupId>
+          <artifactId>jetty-server</artifactId>
+          <version>12.0.12</version>
+          <type>jar</type>
+        </dependency>
+        <dependency>
+          <groupId>org.eclipse.jetty</groupId>
+          <artifactId>jetty-session</artifactId>
+          <version>12.0.12</version>
+          <type>jar</type>
+        </dependency>
+        <dependency>
+          <groupId>org.eclipse.jetty</groupId>
+          <artifactId>jetty-util</artifactId>
+          <version>12.0.12</version>
+          <type>jar</type>
+        </dependency>
+        <dependency>
+          <groupId>org.eclipse.jetty</groupId>
+          <artifactId>jetty-util-ajax</artifactId>
+          <version>12.0.12</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>2.2</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.11.0</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.15.0</version>
+          <type>jar</type>
+        </dependency>
+        <dependency>
+          <groupId>net.bytebuddy</groupId>
+          <artifactId>byte-buddy-agent</artifactId>
+          <version>1.15.0</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.78.1</version>
+          <type>jar</type>
+        </dependency>
+        <dependency>
+          <groupId>org.bouncycastle</groupId>
+          <artifactId>bcprov-jdk18on</artifactId>
+          <version>1.78.1</version>
+          <type>jar</type>
+        </dependency>
+        <dependency>
+          <groupId>org.bouncycastle</groupId>
+          <artifactId>bcpkix-jdk18on</artifactId>
+          <version>1.78.1</version>
+          <type>jar</type>
+        </dependency>
+        <dependency>
+          <groupId>org.bouncycastle</groupId>
+          <artifactId>bcutil-jdk18on</artifactId>
+          <version>1.78.1</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.26.3</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.17.1</version>
+          <type>jar</type>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.commons</groupId>
+          <artifactId>commons-compress</artifactId>
+          <version>1.27.1</version>
+          <type>jar</type>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.commons</groupId>
+          <artifactId>commons-lang3</artifactId>
+          <version>3.16.0</version>
+          <type>jar</type>
+        </dependency>
+        <dependency>
+          <groupId>commons-io</groupId>
+          <artifactId>commons-io</artifactId>
+          <version>2.16.1</version>
+          <type>jar</type>
+        </dependency>
+        <dependency>
+          <groupId>commons-logging</groupId>
+          <artifactId>commons-logging</artifactId>
+          <version>1.3.4</version>
+          <type>jar</type>
+        </dependency>
+      </dependencies>
+    </location>
+  </locations>
+</target>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.33.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.33.tpd
new file mode 100644
index 0000000..d01a8a9
--- /dev/null
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.33.tpd
@@ -0,0 +1,8 @@
+target "jgit-4.33" with source configurePhase
+
+include "orbit/orbit-4.33.tpd"
+include "maven/dependencies.tpd"
+
+location "https://download.eclipse.org/staging/2024-09/" {
+	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 7aae03b..42712c0 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,17 +10,17 @@
 	dependency {
 		groupId = "commons-codec"
 		artifactId = "commons-codec"
-		version = "1.17.0"
+		version = "1.17.1"
 	}
 	dependency {
 		groupId = "org.apache.commons"
 		artifactId = "commons-compress"
-		version = "1.26.2"
+		version = "1.27.1"
 	}
 	dependency {
 		groupId = "org.apache.commons"
 		artifactId = "commons-lang3"
-		version = "3.14.0"
+		version = "3.16.0"
 	}
 	dependency {
 		groupId = "commons-io"
@@ -30,7 +30,7 @@
 	dependency {
 		groupId = "commons-logging"
 		artifactId = "commons-logging"
-		version = "1.3.2"
+		version = "1.3.4"
 	}
 }
 
@@ -56,7 +56,7 @@
 	dependency {
 		groupId = "org.assertj"
 		artifactId = "assertj-core"
-		version = "3.26.0"
+		version = "3.26.3"
 	}
 }
 
@@ -97,12 +97,12 @@
 	dependency {
 		groupId = "net.bytebuddy"
 		artifactId = "byte-buddy"
-		version = "1.14.16"
+		version = "1.15.0"
 	}
 	dependency {
 		groupId = "net.bytebuddy"
 		artifactId = "byte-buddy-agent"
-		version = "1.14.16"
+		version = "1.15.0"
 	}
 }
 
@@ -152,44 +152,49 @@
 	includeSources
 {
 	dependency {
+		groupId = "org.eclipse.jetty.ee10"
+		artifactId = "jetty-ee10-servlet"
+		version = "12.0.10"
+	}
+	dependency {
 		groupId = "org.eclipse.jetty"
 		artifactId = "jetty-http"
-		version = "10.0.21"
+		version = "12.0.12"
 	}
 	dependency {
 		groupId = "org.eclipse.jetty"
 		artifactId = "jetty-io"
-		version = "10.0.21"
+		version = "12.0.12"
 	}
 	dependency {
 		groupId = "org.eclipse.jetty"
 		artifactId = "jetty-security"
-		version = "10.0.21"
+		version = "12.0.12"
 	}
 	dependency {
 		groupId = "org.eclipse.jetty"
 		artifactId = "jetty-server"
-		version = "10.0.21"
+		version = "12.0.12"
 	}
 	dependency {
 		groupId = "org.eclipse.jetty"
-		artifactId = "jetty-servlet"
-		version = "10.0.21"
+		artifactId = "jetty-session"
+		version = "12.0.12"
 	}
 	dependency {
 		groupId = "org.eclipse.jetty"
 		artifactId = "jetty-util"
-		version = "10.0.21"
+		version = "12.0.12"
 	}
 	dependency {
 		groupId = "org.eclipse.jetty"
 		artifactId = "jetty-util-ajax"
-		version = "10.0.21"
+		version = "12.0.12"
 	}
 	dependency {
 		groupId = "jakarta.servlet"
 		artifactId = "jakarta.servlet-api"
-		version = "4.0.4"
+		version = "6.1.0"
 	}
 }
 
@@ -269,6 +274,6 @@
 	dependency {
 		groupId = "org.tukaani"
 		artifactId = "xz"
-		version = "1.9"
+		version = "1.10"
 	}
 }
\ No newline at end of file
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.31.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.31.tpd
index 0554a85..9d00cb4 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.31.tpd
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.31.tpd
@@ -1,4 +1,4 @@
-target "orbit-4.30" with source configurePhase
+target "orbit-4.31" with source configurePhase
 // see https://download.eclipse.org/tools/orbit/downloads/
 
 location "https://download.eclipse.org/tools/orbit/simrel/orbit-aggregation/2023-12" {
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.33.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.33.tpd
new file mode 100644
index 0000000..8dca4cb
--- /dev/null
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.33.tpd
@@ -0,0 +1,27 @@
+target "orbit-4.33" with source configurePhase
+// see https://download.eclipse.org/tools/orbit/downloads/
+
+location "https://download.eclipse.org/tools/orbit/simrel/orbit-aggregation/2024-09" {
+	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]
+	net.i2p.crypto.eddsa [0.3.0,0.3.0]
+	net.i2p.crypto.eddsa.source [0.3.0,0.3.0]
+	org.apache.ant [1.10.14.v20230922-1200,1.10.14.v20230922-1200]
+	org.apache.ant.source [1.10.14.v20230922-1200,1.10.14.v20230922-1200]
+	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.core [1.3.0.v20230809-1000,1.3.0.v20230809-1000]
+	org.hamcrest.core.source [1.3.0.v20230809-1000,1.3.0.v20230809-1000]
+	org.hamcrest.library [1.3.0.v20230809-1000,1.3.0.v20230809-1000]
+	org.hamcrest.library.source [1.3.0.v20230809-1000,1.3.0.v20230809-1000]
+	org.junit [4.13.2.v20230809-1000,4.13.2.v20230809-1000]
+	org.junit.source [4.13.2.v20230809-1000,4.13.2.v20230809-1000]
+	org.objenesis [3.4,3.4]
+	org.objenesis.source [3.4,3.4]
+	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 789963a..5d750fb 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>6.10.2-SNAPSHOT</version>
+  <version>7.0.2-SNAPSHOT</version>
   <packaging>pom</packaging>
 
   <name>JGit Tycho Parent</name>
@@ -29,7 +29,7 @@
   </licenses>
 
   <properties>
-    <java.version>11</java.version>
+    <java.version>17</java.version>
     <tycho-version>4.0.13</tycho-version>
     <target-platform>jgit-4.32</target-platform>
     <project.build.outputTimestamp>${git.commit.time}</project.build.outputTimestamp>
diff --git a/org.eclipse.jgit.pgm.test/.classpath b/org.eclipse.jgit.pgm.test/.classpath
index 855f717..02bc21c 100644
--- a/org.eclipse.jgit.pgm.test/.classpath
+++ b/org.eclipse.jgit.pgm.test/.classpath
@@ -10,7 +10,7 @@
 			<attribute name="test" value="true"/>
 		</attributes>
 	</classpathentry>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17">
 		<attributes>
 			<attribute name="module" value="true"/>
 		</attributes>
diff --git a/org.eclipse.jgit.pgm.test/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit.pgm.test/.settings/org.eclipse.jdt.core.prefs
index 69e9221..362915d 100644
--- a/org.eclipse.jgit.pgm.test/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit.pgm.test/.settings/org.eclipse.jdt.core.prefs
@@ -7,9 +7,9 @@
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=11
+org.eclipse.jdt.core.compiler.compliance=17
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -115,7 +115,7 @@
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
 org.eclipse.jdt.core.compiler.release=enabled
-org.eclipse.jdt.core.compiler.source=11
+org.eclipse.jdt.core.compiler.source=17
 org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
 org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
diff --git a/org.eclipse.jgit.pgm.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.pgm.test/META-INF/MANIFEST.MF
index 6569af1..339b969 100644
--- a/org.eclipse.jgit.pgm.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.pgm.test/META-INF/MANIFEST.MF
@@ -3,30 +3,30 @@
 Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.pgm.test
 Bundle-SymbolicName: org.eclipse.jgit.pgm.test
-Bundle-Version: 6.10.2.qualifier
+Bundle-Version: 7.0.2.qualifier
 Bundle-Vendor: %Bundle-Vendor
 Bundle-Localization: plugin
 Bundle-ActivationPolicy: lazy
-Bundle-RequiredExecutionEnvironment: JavaSE-11
-Import-Package: org.eclipse.jgit.api;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.api.errors;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.diff;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.dircache;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.internal.diffmergetool;version="6.10.2",
- org.eclipse.jgit.internal.storage.file;version="6.10.2",
- org.eclipse.jgit.junit;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.lib;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.lib.internal;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.merge;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.pgm;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.pgm.internal;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.pgm.opt;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.revwalk;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.storage.file;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.transport;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.treewalk;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.util;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.util.io;version="[6.10.2,6.11.0)",
+Bundle-RequiredExecutionEnvironment: JavaSE-17
+Import-Package: org.eclipse.jgit.api;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.api.errors;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.diff;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.dircache;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.internal.diffmergetool;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.internal.storage.file;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.junit;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.lib;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.lib.internal;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.merge;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.pgm;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.pgm.internal;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.pgm.opt;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.revwalk;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.storage.file;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.transport;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.treewalk;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.util;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.util.io;version="[7.0.2,7.1.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/org.eclipse.jgit.pgm--All-Tests \050Java11\051 \050de\051.launch" "b/org.eclipse.jgit.pgm.test/org.eclipse.jgit.pgm--All-Tests \050Java17\051 \050de\051.launch"
similarity index 97%
rename from "org.eclipse.jgit.pgm.test/org.eclipse.jgit.pgm--All-Tests \050Java11\051 \050de\051.launch"
rename to "org.eclipse.jgit.pgm.test/org.eclipse.jgit.pgm--All-Tests \050Java17\051 \050de\051.launch"
index b860abb..c64458c 100644
--- "a/org.eclipse.jgit.pgm.test/org.eclipse.jgit.pgm--All-Tests \050Java11\051 \050de\051.launch"
+++ "b/org.eclipse.jgit.pgm.test/org.eclipse.jgit.pgm--All-Tests \050Java17\051 \050de\051.launch"
@@ -24,7 +24,7 @@
 <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry id=&quot;org.eclipse.jdt.launching.classpathentry.defaultClasspath&quot;&gt;&#10;&lt;memento exportedEntriesOnly=&quot;false&quot; project=&quot;org.eclipse.jgit.pgm.test&quot;/&gt;&#10;&lt;/runtimeClasspathEntry&gt;&#10;"/>
 </listAttribute>
 <booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/>
-<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11"/>
+<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17"/>
 <stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value=""/>
 <stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.jgit.pgm.test"/>
 </launchConfiguration>
diff --git "a/org.eclipse.jgit.pgm.test/org.eclipse.jgit.pgm--All-Tests \050Java11\051.launch" "b/org.eclipse.jgit.pgm.test/org.eclipse.jgit.pgm--All-Tests \050Java17\051.launch"
similarity index 97%
rename from "org.eclipse.jgit.pgm.test/org.eclipse.jgit.pgm--All-Tests \050Java11\051.launch"
rename to "org.eclipse.jgit.pgm.test/org.eclipse.jgit.pgm--All-Tests \050Java17\051.launch"
index 02a4dab..48040cc 100644
--- "a/org.eclipse.jgit.pgm.test/org.eclipse.jgit.pgm--All-Tests \050Java11\051.launch"
+++ "b/org.eclipse.jgit.pgm.test/org.eclipse.jgit.pgm--All-Tests \050Java17\051.launch"
@@ -21,7 +21,7 @@
 <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry id=&quot;org.eclipse.jdt.launching.classpathentry.defaultClasspath&quot;&gt;&#10;&lt;memento exportedEntriesOnly=&quot;false&quot; project=&quot;org.eclipse.jgit.pgm.test&quot;/&gt;&#10;&lt;/runtimeClasspathEntry&gt;&#10;"/>
 </listAttribute>
 <booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/>
-<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11"/>
+<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17"/>
 <stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value=""/>
 <stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.jgit.pgm.test"/>
 </launchConfiguration>
diff --git a/org.eclipse.jgit.pgm.test/pom.xml b/org.eclipse.jgit.pgm.test/pom.xml
index b950924..8009940 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>6.10.2-SNAPSHOT</version>
+    <version>7.0.2-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.pgm.test</artifactId>
diff --git a/org.eclipse.jgit.pgm/.classpath b/org.eclipse.jgit.pgm/.classpath
index e8b509e..c37bfe6 100644
--- a/org.eclipse.jgit.pgm/.classpath
+++ b/org.eclipse.jgit.pgm/.classpath
@@ -3,7 +3,7 @@
 	<classpathentry kind="src" path="src"/>
 	<classpathentry excluding="*|resources/|resources/" including="META-INF/" kind="src" path=""/>
 	<classpathentry kind="src" path="resources"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17">
 		<attributes>
 			<attribute name="module" value="true"/>
 		</attributes>
diff --git a/org.eclipse.jgit.pgm/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit.pgm/.settings/org.eclipse.jdt.core.prefs
index b27b6c3..c4dc76f 100644
--- a/org.eclipse.jgit.pgm/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit.pgm/.settings/org.eclipse.jdt.core.prefs
@@ -7,9 +7,9 @@
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=11
+org.eclipse.jdt.core.compiler.compliance=17
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -115,7 +115,7 @@
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
 org.eclipse.jdt.core.compiler.release=enabled
-org.eclipse.jdt.core.compiler.source=11
+org.eclipse.jdt.core.compiler.source=17
 org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
 org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
diff --git a/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF b/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF
index 882122a..0d41cb8 100644
--- a/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF
@@ -3,60 +3,60 @@
 Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.pgm
 Bundle-SymbolicName: org.eclipse.jgit.pgm
-Bundle-Version: 6.10.2.qualifier
+Bundle-Version: 7.0.2.qualifier
 Bundle-Vendor: %Bundle-Vendor
 Bundle-Localization: OSGI-INF/l10n/plugin
-Bundle-RequiredExecutionEnvironment: JavaSE-11
-Import-Package: javax.servlet;version="[3.1.0,5.0.0)",
+Bundle-RequiredExecutionEnvironment: JavaSE-17
+Import-Package: jakarta.servlet;version="[6.0.0,7.0.0)",
  org.apache.commons.logging;version="[1.2,2.0)",
- org.eclipse.jetty.server;version="[10.0.0,11.0.0)",
- org.eclipse.jetty.server.handler;version="[10.0.0,11.0.0)",
- org.eclipse.jetty.servlet;version="[10.0.0,11.0.0)",
- org.eclipse.jetty.util;version="[10.0.0,11.0.0)",
- org.eclipse.jetty.util.component;version="[10.0.0,11.0.0)",
- org.eclipse.jgit.api;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.api.errors;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.archive;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.awtui;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.blame;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.diff;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.dircache;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.errors;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.gitrepo;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.internal.storage.file;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.internal.diffmergetool;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.internal.storage.io;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.internal.storage.pack;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.internal.storage.reftable;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.lfs;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.lfs.server;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.lfs.server.fs;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.lfs.server.s3;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.lib;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.merge;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.lib.internal;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.nls;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.notes;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.revplot;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.revwalk;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.revwalk.filter;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.storage.file;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.storage.pack;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.transport;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.transport.http.apache;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.transport.resolver;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.transport.ssh.jsch;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.transport.sshd;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.treewalk;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.treewalk.filter;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.util;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.util.io;version="[6.10.2,6.11.0)",
+ org.eclipse.jetty.ee10.servlet;version="[12.0.0,13.0.0)",
+ org.eclipse.jetty.server;version="[12.0.0,13.0.0)",
+ 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.0.2,7.1.0)",
+ org.eclipse.jgit.api.errors;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.archive;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.awtui;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.blame;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.diff;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.dircache;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.errors;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.gitrepo;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.internal.storage.file;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.internal.diffmergetool;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.internal.storage.io;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.internal.storage.pack;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.internal.storage.reftable;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.lfs;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.lfs.server;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.lfs.server.fs;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.lfs.server.s3;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.lib;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.merge;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.lib.internal;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.nls;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.notes;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.revplot;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.revwalk;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.revwalk.filter;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.storage.file;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.storage.pack;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.transport;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.transport.http.apache;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.transport.resolver;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.transport.ssh.jsch;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.transport.sshd;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.treewalk;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.treewalk.filter;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.util;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.util.io;version="[7.0.2,7.1.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="6.10.2";
+Export-Package: org.eclipse.jgit.console;version="7.0.2";
  uses:="org.eclipse.jgit.transport,
   org.eclipse.jgit.util",
- org.eclipse.jgit.pgm;version="6.10.2";
+ org.eclipse.jgit.pgm;version="7.0.2";
   uses:="org.eclipse.jgit.transport,
    org.eclipse.jgit.util.io,
    org.eclipse.jgit.awtui,
@@ -68,14 +68,14 @@
    org.eclipse.jgit.treewalk,
    org.eclipse.jgit.api,
    javax.swing",
- org.eclipse.jgit.pgm.debug;version="6.10.2";
+ org.eclipse.jgit.pgm.debug;version="7.0.2";
   uses:="org.eclipse.jgit.util.io,
    org.eclipse.jgit.pgm,
    org.eclipse.jetty.servlet",
- org.eclipse.jgit.pgm.internal;version="6.10.2";
+ org.eclipse.jgit.pgm.internal;version="7.0.2";
   x-friends:="org.eclipse.jgit.pgm.test,
    org.eclipse.jgit.test",
- org.eclipse.jgit.pgm.opt;version="6.10.2";
+ org.eclipse.jgit.pgm.opt;version="7.0.2";
   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 78e2979..7b5009f 100644
--- a/org.eclipse.jgit.pgm/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.pgm/META-INF/SOURCE-MANIFEST.MF
@@ -3,5 +3,5 @@
 Bundle-Name: org.eclipse.jgit.pgm - Sources
 Bundle-SymbolicName: org.eclipse.jgit.pgm.source
 Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 6.10.2.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit.pgm;version="6.10.2.qualifier";roots="."
+Bundle-Version: 7.0.2.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit.pgm;version="7.0.2.qualifier";roots="."
diff --git a/org.eclipse.jgit.pgm/pom.xml b/org.eclipse.jgit.pgm/pom.xml
index 0bc4d7e..a44e19c 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>6.10.2-SNAPSHOT</version>
+    <version>7.0.2-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.pgm</artifactId>
@@ -107,8 +107,8 @@
     </dependency>
 
     <dependency>
-      <groupId>org.eclipse.jetty</groupId>
-      <artifactId>jetty-servlet</artifactId>
+      <groupId>org.eclipse.jetty.ee10</groupId>
+      <artifactId>jetty-ee10-servlet</artifactId>
     </dependency>
 
     <dependency>
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Config.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Config.java
index 52f40c2..f5de704 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Config.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Config.java
@@ -94,7 +94,7 @@ private void list() throws IOException, ConfigInvalidException {
 		if (global || isListAll())
 			list(SystemReader.getInstance().openUserConfig(null, fs));
 		if (local || isListAll())
-			list(new FileBasedConfig(fs.resolve(getRepository().getDirectory(),
+			list(new FileBasedConfig(fs.resolve(getRepository().getCommonDirectory(),
 					Constants.CONFIG), fs));
 	}
 
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Log.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Log.java
index 852a4b3..958e566 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Log.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Log.java
@@ -32,13 +32,12 @@
 import org.eclipse.jgit.lib.AnyObjectId;
 import org.eclipse.jgit.lib.Constants;
 import org.eclipse.jgit.lib.GpgConfig;
-import org.eclipse.jgit.lib.GpgSignatureVerifier;
-import org.eclipse.jgit.lib.GpgSignatureVerifier.SignatureVerification;
-import org.eclipse.jgit.lib.GpgSignatureVerifierFactory;
+import org.eclipse.jgit.lib.SignatureVerifier.SignatureVerification;
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.PersonIdent;
 import org.eclipse.jgit.lib.Ref;
 import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.SignatureVerifiers;
 import org.eclipse.jgit.notes.NoteMap;
 import org.eclipse.jgit.pgm.internal.CLIText;
 import org.eclipse.jgit.pgm.internal.VerificationUtils;
@@ -174,8 +173,6 @@ void noPrefix(@SuppressWarnings("unused") boolean on) {
 	// END -- Options shared with Diff
 
 
-	private GpgSignatureVerifier verifier;
-
 	private GpgConfig config;
 
 	Log() {
@@ -227,9 +224,6 @@ protected void run() {
 			throw die(e.getMessage(), e);
 		} finally {
 			diffFmt.close();
-			if (verifier != null) {
-				verifier.clear();
-			}
 		}
 	}
 
@@ -293,21 +287,13 @@ private void showSignature(RevCommit c) throws IOException {
 		if (c.getRawGpgSignature() == null) {
 			return;
 		}
-		if (verifier == null) {
-			GpgSignatureVerifierFactory factory = GpgSignatureVerifierFactory
-					.getDefault();
-			if (factory == null) {
-				throw die(CLIText.get().logNoSignatureVerifier, null);
-			}
-			verifier = factory.getVerifier();
-		}
-		SignatureVerification verification = verifier.verifySignature(c,
-				config);
+		SignatureVerification verification = SignatureVerifiers.verify(db,
+				config, c);
 		if (verification == null) {
 			return;
 		}
 		VerificationUtils.writeVerification(outw, verification,
-				verifier.getName(), c.getCommitterIdent());
+				verification.verifierName(), c.getCommitterIdent());
 	}
 
 	/**
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Show.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Show.java
index 4feb090..1576792 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Show.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Show.java
@@ -30,12 +30,11 @@
 import org.eclipse.jgit.lib.Constants;
 import org.eclipse.jgit.lib.FileMode;
 import org.eclipse.jgit.lib.GpgConfig;
-import org.eclipse.jgit.lib.GpgSignatureVerifier;
-import org.eclipse.jgit.lib.GpgSignatureVerifierFactory;
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.PersonIdent;
 import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.lib.GpgSignatureVerifier.SignatureVerification;
+import org.eclipse.jgit.lib.SignatureVerifier.SignatureVerification;
+import org.eclipse.jgit.lib.SignatureVerifiers;
 import org.eclipse.jgit.pgm.internal.CLIText;
 import org.eclipse.jgit.pgm.internal.VerificationUtils;
 import org.eclipse.jgit.pgm.opt.PathTreeFilterHandler;
@@ -335,23 +334,13 @@ private void showSignature(RevCommit c) throws IOException {
 		if (c.getRawGpgSignature() == null) {
 			return;
 		}
-		GpgSignatureVerifierFactory factory = GpgSignatureVerifierFactory
-				.getDefault();
-		if (factory == null) {
+		GpgConfig config = new GpgConfig(db.getConfig());
+		SignatureVerification verification = SignatureVerifiers.verify(db,
+				config, c);
+		if (verification == null) {
 			throw die(CLIText.get().logNoSignatureVerifier, null);
 		}
-		GpgSignatureVerifier verifier = factory.getVerifier();
-		GpgConfig config = new GpgConfig(db.getConfig());
-		try {
-			SignatureVerification verification = verifier.verifySignature(c,
-					config);
-			if (verification == null) {
-				return;
-			}
-			VerificationUtils.writeVerification(outw, verification,
-					verifier.getName(), c.getCommitterIdent());
-		} finally {
-			verifier.clear();
-		}
+		VerificationUtils.writeVerification(outw, verification,
+				verification.verifierName(), c.getCommitterIdent());
 	}
 }
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Tag.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Tag.java
index 4ea67ab..6be30c9 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Tag.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Tag.java
@@ -27,10 +27,10 @@
 import org.eclipse.jgit.api.errors.GitAPIException;
 import org.eclipse.jgit.api.errors.RefAlreadyExistsException;
 import org.eclipse.jgit.lib.Constants;
-import org.eclipse.jgit.lib.GpgSignatureVerifier.SignatureVerification;
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.Ref;
 import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.SignatureVerifier.SignatureVerification;
 import org.eclipse.jgit.pgm.internal.CLIText;
 import org.eclipse.jgit.pgm.internal.VerificationUtils;
 import org.eclipse.jgit.revwalk.RevCommit;
@@ -106,7 +106,8 @@ protected void run() {
 						if (error != null) {
 							throw die(error.getMessage(), error);
 						}
-						writeVerification(verifySig.getVerifier().getName(),
+						writeVerification(
+								verification.getVerification().verifierName(),
 								(RevTag) verification.getObject(),
 								verification.getVerification());
 					}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/LfsStore.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/LfsStore.java
index 653530d..757c435 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/LfsStore.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/LfsStore.java
@@ -26,8 +26,8 @@
 import org.eclipse.jetty.server.Server;
 import org.eclipse.jetty.server.ServerConnector;
 import org.eclipse.jetty.server.handler.ContextHandlerCollection;
-import org.eclipse.jetty.servlet.ServletContextHandler;
-import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.ee10.servlet.ServletContextHandler;
+import org.eclipse.jetty.ee10.servlet.ServletHolder;
 import org.eclipse.jgit.errors.ConfigInvalidException;
 import org.eclipse.jgit.lfs.server.LargeFileRepository;
 import org.eclipse.jgit.lfs.server.LfsProtocolServlet;
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/internal/VerificationUtils.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/internal/VerificationUtils.java
index c1f8a86..64ee602 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/internal/VerificationUtils.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/internal/VerificationUtils.java
@@ -11,7 +11,7 @@
 
 import java.io.IOException;
 
-import org.eclipse.jgit.lib.GpgSignatureVerifier.SignatureVerification;
+import org.eclipse.jgit.lib.SignatureVerifier.SignatureVerification;
 import org.eclipse.jgit.lib.PersonIdent;
 import org.eclipse.jgit.util.GitDateFormatter;
 import org.eclipse.jgit.util.SignatureUtils;
diff --git a/org.eclipse.jgit.ssh.apache.agent/.classpath b/org.eclipse.jgit.ssh.apache.agent/.classpath
index df1b324..db7adf1 100644
--- a/org.eclipse.jgit.ssh.apache.agent/.classpath
+++ b/org.eclipse.jgit.ssh.apache.agent/.classpath
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17"/>
 	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
 	<classpathentry kind="src" path="src"/>
 	<classpathentry kind="src" path="resources"/>
diff --git a/org.eclipse.jgit.ssh.apache.agent/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit.ssh.apache.agent/.settings/org.eclipse.jdt.core.prefs
index d5c0e6c..270fc64 100644
--- a/org.eclipse.jgit.ssh.apache.agent/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit.ssh.apache.agent/.settings/org.eclipse.jdt.core.prefs
@@ -7,9 +7,9 @@
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=11
+org.eclipse.jdt.core.compiler.compliance=17
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -115,7 +115,7 @@
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
 org.eclipse.jdt.core.compiler.release=enabled
-org.eclipse.jdt.core.compiler.source=11
+org.eclipse.jdt.core.compiler.source=17
 org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
 org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
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 9536488..0cdec4d 100644
--- a/org.eclipse.jgit.ssh.apache.agent/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.ssh.apache.agent/META-INF/MANIFEST.MF
@@ -2,16 +2,16 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %Bundle-Name
 Bundle-SymbolicName: org.eclipse.jgit.ssh.apache.agent;singleton:=true
-Bundle-Version: 6.10.2.qualifier
+Bundle-Version: 7.0.2.qualifier
 Bundle-Localization: OSGI-INF/l10n/agent
 Bundle-Vendor: %Bundle-Vendor
-Fragment-Host: org.eclipse.jgit.ssh.apache;bundle-version="[6.10.2,6.11.0)"
+Fragment-Host: org.eclipse.jgit.ssh.apache;bundle-version="[7.0.2,7.1.0)"
 Bundle-ActivationPolicy: lazy
 Automatic-Module-Name: org.eclipse.jgit.ssh.apache.agent
-Bundle-RequiredExecutionEnvironment: JavaSE-11
-Import-Package: org.eclipse.jgit.transport.sshd;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.nls;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.util;version="[6.10.2,6.11.0)"
+Bundle-RequiredExecutionEnvironment: JavaSE-17
+Import-Package: org.eclipse.jgit.transport.sshd;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.nls;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.util;version="[7.0.2,7.1.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="6.10.2";x-internal:=true
+Export-Package: org.eclipse.jgit.internal.transport.sshd.agent.connector;version="7.0.2";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 89faf86..d4fea05 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,5 +3,5 @@
 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: 6.10.2.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit.ssh.apache.agent;version="6.10.2.qualifier";roots="."
+Bundle-Version: 7.0.2.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit.ssh.apache.agent;version="7.0.2.qualifier";roots="."
diff --git a/org.eclipse.jgit.ssh.apache.agent/pom.xml b/org.eclipse.jgit.ssh.apache.agent/pom.xml
index f940edd..9a44834 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>6.10.2-SNAPSHOT</version>
+    <version>7.0.2-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.ssh.apache.agent</artifactId>
diff --git a/org.eclipse.jgit.ssh.apache.test/.classpath b/org.eclipse.jgit.ssh.apache.test/.classpath
index 5899a4e..6fdb99a 100644
--- a/org.eclipse.jgit.ssh.apache.test/.classpath
+++ b/org.eclipse.jgit.ssh.apache.test/.classpath
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17">
 		<attributes>
 			<attribute name="module" value="true"/>
 		</attributes>
diff --git a/org.eclipse.jgit.ssh.apache.test/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit.ssh.apache.test/.settings/org.eclipse.jdt.core.prefs
index 76f48d8..489fd95 100644
--- a/org.eclipse.jgit.ssh.apache.test/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit.ssh.apache.test/.settings/org.eclipse.jdt.core.prefs
@@ -7,9 +7,9 @@
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=11
+org.eclipse.jdt.core.compiler.compliance=17
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -115,7 +115,7 @@
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
 org.eclipse.jdt.core.compiler.release=enabled
-org.eclipse.jdt.core.compiler.source=11
+org.eclipse.jdt.core.compiler.source=17
 org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
 org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
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 9502803..cc382fb 100644
--- a/org.eclipse.jgit.ssh.apache.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.ssh.apache.test/META-INF/MANIFEST.MF
@@ -3,10 +3,10 @@
 Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.ssh.apache.test
 Bundle-SymbolicName: org.eclipse.jgit.ssh.apache.test
-Bundle-Version: 6.10.2.qualifier
+Bundle-Version: 7.0.2.qualifier
 Bundle-Vendor: %Bundle-Vendor
 Bundle-Localization: plugin
-Bundle-RequiredExecutionEnvironment: JavaSE-11
+Bundle-RequiredExecutionEnvironment: JavaSE-17
 Require-Bundle: org.hamcrest.core;bundle-version="[1.3.0,2.0.0)"
 Import-Package: org.apache.sshd.client.config.hosts;version="[2.14.0,2.15.0)",
  org.apache.sshd.common;version="[2.14.0,2.15.0)",
@@ -22,17 +22,17 @@
  org.apache.sshd.core;version="[2.14.0,2.15.0)",
  org.apache.sshd.server;version="[2.14.0,2.15.0)",
  org.apache.sshd.server.forward;version="[2.14.0,2.15.0)",
- org.eclipse.jgit.api;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.api.errors;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.internal.storage.file;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.internal.transport.sshd.proxy;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.junit;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.junit.ssh;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.lib;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.transport;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.transport.sshd;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.transport.sshd.agent;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.util;version="[6.10.2,6.11.0)",
+ org.eclipse.jgit.api;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.api.errors;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.internal.storage.file;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.internal.transport.sshd.proxy;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.junit;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.junit.ssh;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.lib;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.transport;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.transport.sshd;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.transport.sshd.agent;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.util;version="[7.0.2,7.1.0)",
  org.junit;version="[4.13,5.0.0)",
  org.junit.experimental.theories;version="[4.13,5.0.0)",
  org.junit.runner;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 009af2d..624104d 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>6.10.2-SNAPSHOT</version>
+    <version>7.0.2-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.ssh.apache.test</artifactId>
diff --git a/org.eclipse.jgit.ssh.apache/.classpath b/org.eclipse.jgit.ssh.apache/.classpath
index 1fde318..efeb803 100644
--- a/org.eclipse.jgit.ssh.apache/.classpath
+++ b/org.eclipse.jgit.ssh.apache/.classpath
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17">
 		<attributes>
 			<attribute name="module" value="true"/>
 		</attributes>
diff --git a/org.eclipse.jgit.ssh.apache/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit.ssh.apache/.settings/org.eclipse.jdt.core.prefs
index d5c0e6c..270fc64 100644
--- a/org.eclipse.jgit.ssh.apache/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit.ssh.apache/.settings/org.eclipse.jdt.core.prefs
@@ -7,9 +7,9 @@
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=11
+org.eclipse.jdt.core.compiler.compliance=17
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -115,7 +115,7 @@
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
 org.eclipse.jdt.core.compiler.release=enabled
-org.eclipse.jdt.core.compiler.source=11
+org.eclipse.jdt.core.compiler.source=17
 org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
 org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
diff --git a/org.eclipse.jgit.ssh.apache/META-INF/MANIFEST.MF b/org.eclipse.jgit.ssh.apache/META-INF/MANIFEST.MF
index cff6235..b7ea87f 100644
--- a/org.eclipse.jgit.ssh.apache/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.ssh.apache/META-INF/MANIFEST.MF
@@ -6,9 +6,9 @@
 Bundle-Vendor: %Bundle-Vendor
 Bundle-Localization: OSGI-INF/l10n/plugin
 Bundle-ActivationPolicy: lazy
-Bundle-Version: 6.10.2.qualifier
-Bundle-RequiredExecutionEnvironment: JavaSE-11
-Export-Package: org.eclipse.jgit.internal.transport.sshd;version="6.10.2";x-internal:=true;
+Bundle-Version: 7.0.2.qualifier
+Bundle-RequiredExecutionEnvironment: JavaSE-17
+Export-Package: org.eclipse.jgit.internal.transport.sshd;version="7.0.2";x-internal:=true;
   uses:="org.apache.sshd.client,
    org.apache.sshd.client.auth,
    org.apache.sshd.client.auth.keyboard,
@@ -23,18 +23,18 @@
    org.apache.sshd.common.signature,
    org.apache.sshd.common.util.buffer,
    org.eclipse.jgit.transport",
- org.eclipse.jgit.internal.transport.sshd.agent;version="6.10.2";x-internal:=true,
- org.eclipse.jgit.internal.transport.sshd.auth;version="6.10.2";x-internal:=true,
- org.eclipse.jgit.internal.transport.sshd.pkcs11;version="6.10.2";x-internal:=true,
- org.eclipse.jgit.internal.transport.sshd.proxy;version="6.10.2";x-friends:="org.eclipse.jgit.ssh.apache.test",
- org.eclipse.jgit.transport.sshd;version="6.10.2";
+ org.eclipse.jgit.internal.transport.sshd.agent;version="7.0.2";x-internal:=true,
+ org.eclipse.jgit.internal.transport.sshd.auth;version="7.0.2";x-internal:=true,
+ org.eclipse.jgit.internal.transport.sshd.pkcs11;version="7.0.2";x-internal:=true,
+ org.eclipse.jgit.internal.transport.sshd.proxy;version="7.0.2";x-friends:="org.eclipse.jgit.ssh.apache.test",
+ org.eclipse.jgit.transport.sshd;version="7.0.2";
   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="6.10.2",
+ org.eclipse.jgit.transport.sshd.agent;version="7.0.2",
  sun.security.x509
 Import-Package: net.i2p.crypto.eddsa;version="[0.3.0,0.4.0)",
  org.apache.sshd.agent;version="[2.14.0,2.15.0)",
@@ -89,12 +89,12 @@
  org.apache.sshd.sftp;version="[2.14.0,2.15.0)",
  org.apache.sshd.sftp.client;version="[2.14.0,2.15.0)",
  org.apache.sshd.sftp.common;version="[2.14.0,2.15.0)",
- org.eclipse.jgit.annotations;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.errors;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.fnmatch;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.internal.storage.file;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.internal.transport.ssh;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.nls;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.transport;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.util;version="[6.10.2,6.11.0)",
+ org.eclipse.jgit.annotations;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.errors;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.fnmatch;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.internal.storage.file;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.internal.transport.ssh;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.nls;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.transport;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.util;version="[7.0.2,7.1.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 b237d0e..c328382 100644
--- a/org.eclipse.jgit.ssh.apache/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.ssh.apache/META-INF/SOURCE-MANIFEST.MF
@@ -3,5 +3,5 @@
 Bundle-Name: org.eclipse.jgit.ssh.apache - Sources
 Bundle-SymbolicName: org.eclipse.jgit.ssh.apache.source
 Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 6.10.2.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit.ssh.apache;version="6.10.2.qualifier";roots="."
+Bundle-Version: 7.0.2.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit.ssh.apache;version="7.0.2.qualifier";roots="."
diff --git a/org.eclipse.jgit.ssh.apache/pom.xml b/org.eclipse.jgit.ssh.apache/pom.xml
index 63b36de..c189776 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>6.10.2-SNAPSHOT</version>
+    <version>7.0.2-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.ssh.apache</artifactId>
diff --git a/org.eclipse.jgit.ssh.jsch.test/.classpath b/org.eclipse.jgit.ssh.jsch.test/.classpath
index 5899a4e..6fdb99a 100644
--- a/org.eclipse.jgit.ssh.jsch.test/.classpath
+++ b/org.eclipse.jgit.ssh.jsch.test/.classpath
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17">
 		<attributes>
 			<attribute name="module" value="true"/>
 		</attributes>
diff --git a/org.eclipse.jgit.ssh.jsch.test/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit.ssh.jsch.test/.settings/org.eclipse.jdt.core.prefs
index b012856..d881a80 100644
--- a/org.eclipse.jgit.ssh.jsch.test/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit.ssh.jsch.test/.settings/org.eclipse.jdt.core.prefs
@@ -7,9 +7,9 @@
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=11
+org.eclipse.jdt.core.compiler.compliance=17
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -116,7 +116,7 @@
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
 org.eclipse.jdt.core.compiler.processAnnotations=disabled
 org.eclipse.jdt.core.compiler.release=enabled
-org.eclipse.jdt.core.compiler.source=11
+org.eclipse.jdt.core.compiler.source=17
 org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
 org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
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 59eb20e..8821702 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: 6.10.2.qualifier
+Bundle-Version: 7.0.2.qualifier
 Bundle-Vendor: %Bundle-Vendor
 Bundle-Localization: plugin
-Bundle-RequiredExecutionEnvironment: JavaSE-11
+Bundle-RequiredExecutionEnvironment: JavaSE-17
 Require-Bundle: org.hamcrest.core;bundle-version="[1.3.0,2.0.0)"
 Import-Package: com.jcraft.jsch;version="[0.1.54,0.2.0)",
- org.eclipse.jgit.errors;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.internal.storage.file;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.junit;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.junit.ssh;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.lib;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.transport;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.transport.ssh.jsch;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.util;version="[6.10.2,6.11.0)",
+ org.eclipse.jgit.errors;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.internal.storage.file;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.junit;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.junit.ssh;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.lib;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.transport;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.transport.ssh.jsch;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.util;version="[7.0.2,7.1.0)",
  org.hamcrest;version="[1.1.0,3.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 0241204..4c9097a 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>6.10.2-SNAPSHOT</version>
+    <version>7.0.2-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.ssh.jsch.test</artifactId>
diff --git a/org.eclipse.jgit.ssh.jsch/.classpath b/org.eclipse.jgit.ssh.jsch/.classpath
index 1fde318..efeb803 100644
--- a/org.eclipse.jgit.ssh.jsch/.classpath
+++ b/org.eclipse.jgit.ssh.jsch/.classpath
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17">
 		<attributes>
 			<attribute name="module" value="true"/>
 		</attributes>
diff --git a/org.eclipse.jgit.ssh.jsch/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit.ssh.jsch/.settings/org.eclipse.jdt.core.prefs
index d5c0e6c..270fc64 100644
--- a/org.eclipse.jgit.ssh.jsch/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit.ssh.jsch/.settings/org.eclipse.jdt.core.prefs
@@ -7,9 +7,9 @@
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=11
+org.eclipse.jdt.core.compiler.compliance=17
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -115,7 +115,7 @@
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
 org.eclipse.jdt.core.compiler.release=enabled
-org.eclipse.jdt.core.compiler.source=11
+org.eclipse.jdt.core.compiler.source=17
 org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
 org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
diff --git a/org.eclipse.jgit.ssh.jsch/META-INF/MANIFEST.MF b/org.eclipse.jgit.ssh.jsch/META-INF/MANIFEST.MF
index aad3c29..92840a9 100644
--- a/org.eclipse.jgit.ssh.jsch/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.ssh.jsch/META-INF/MANIFEST.MF
@@ -3,19 +3,19 @@
 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="[6.10.2,6.11.0)"
+Fragment-Host: org.eclipse.jgit;bundle-version="[7.0.2,7.1.0)"
 Bundle-Vendor: %Bundle-Vendor
 Bundle-Localization: OSGI-INF/l10n/jsch
 Bundle-ActivationPolicy: lazy
-Bundle-Version: 6.10.2.qualifier
-Bundle-RequiredExecutionEnvironment: JavaSE-11
-Export-Package: org.eclipse.jgit.transport.ssh.jsch;version="6.10.2"
+Bundle-Version: 7.0.2.qualifier
+Bundle-RequiredExecutionEnvironment: JavaSE-17
+Export-Package: org.eclipse.jgit.transport.ssh.jsch;version="7.0.2"
 Import-Package: com.jcraft.jsch;version="[0.1.37,0.2.0)",
- org.eclipse.jgit.errors;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.internal;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.internal.transport.ssh;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.nls;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.transport;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.util;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.util.io;version="[6.10.2,6.11.0)",
+ org.eclipse.jgit.errors;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.internal;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.internal.transport.ssh;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.nls;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.transport;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.util;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.util.io;version="[7.0.2,7.1.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 883cbdf..c0e1acc 100644
--- a/org.eclipse.jgit.ssh.jsch/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.ssh.jsch/META-INF/SOURCE-MANIFEST.MF
@@ -3,5 +3,5 @@
 Bundle-Name: org.eclipse.jgit.ssh.jsch - Sources
 Bundle-SymbolicName: org.eclipse.jgit.ssh.jsch.source
 Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 6.10.2.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit.ssh.jsch;version="6.10.2.qualifier";roots="."
+Bundle-Version: 7.0.2.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit.ssh.jsch;version="7.0.2.qualifier";roots="."
diff --git a/org.eclipse.jgit.ssh.jsch/pom.xml b/org.eclipse.jgit.ssh.jsch/pom.xml
index bab2eea..1f4564c 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>6.10.2-SNAPSHOT</version>
+    <version>7.0.2-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.ssh.jsch</artifactId>
diff --git a/org.eclipse.jgit.ssh.jsch/src/org/eclipse/jgit/transport/ssh/jsch/JschSession.java b/org.eclipse.jgit.ssh.jsch/src/org/eclipse/jgit/transport/ssh/jsch/JschSession.java
index 5f36dad..ad58ae1 100644
--- a/org.eclipse.jgit.ssh.jsch/src/org/eclipse/jgit/transport/ssh/jsch/JschSession.java
+++ b/org.eclipse.jgit.ssh.jsch/src/org/eclipse/jgit/transport/ssh/jsch/JschSession.java
@@ -34,7 +34,6 @@
 import org.eclipse.jgit.transport.URIish;
 import org.eclipse.jgit.util.io.IsolatedOutputStream;
 
-import com.jcraft.jsch.Channel;
 import com.jcraft.jsch.ChannelExec;
 import com.jcraft.jsch.ChannelSftp;
 import com.jcraft.jsch.JSchException;
@@ -86,22 +85,6 @@ public void disconnect() {
 	}
 
 	/**
-	 * A kludge to allow {@link org.eclipse.jgit.transport.TransportSftp} to get
-	 * an Sftp channel from Jsch. Ideally, this method would be generic, which
-	 * would require implementing generic Sftp channel operations in the
-	 * RemoteSession class.
-	 *
-	 * @return a channel suitable for Sftp operations.
-	 * @throws com.jcraft.jsch.JSchException
-	 *             on problems getting the channel.
-	 * @deprecated since 5.2; use {@link #getFtpChannel()} instead
-	 */
-	@Deprecated
-	public Channel getSftpChannel() throws JSchException {
-		return sock.openChannel("sftp"); //$NON-NLS-1$
-	}
-
-	/**
 	 * {@inheritDoc}
 	 *
 	 * @since 5.2
diff --git a/org.eclipse.jgit.test/.classpath b/org.eclipse.jgit.test/.classpath
index 363ffa3..4789883 100644
--- a/org.eclipse.jgit.test/.classpath
+++ b/org.eclipse.jgit.test/.classpath
@@ -16,7 +16,7 @@
 			<attribute name="test" value="true"/>
 		</attributes>
 	</classpathentry>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17">
 		<attributes>
 			<attribute name="module" value="true"/>
 		</attributes>
diff --git a/org.eclipse.jgit.test/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit.test/.settings/org.eclipse.jdt.core.prefs
index 69e9221..362915d 100644
--- a/org.eclipse.jgit.test/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit.test/.settings/org.eclipse.jdt.core.prefs
@@ -7,9 +7,9 @@
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=11
+org.eclipse.jdt.core.compiler.compliance=17
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -115,7 +115,7 @@
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
 org.eclipse.jdt.core.compiler.release=enabled
-org.eclipse.jdt.core.compiler.source=11
+org.eclipse.jdt.core.compiler.source=17
 org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
 org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
diff --git a/org.eclipse.jgit.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.test/META-INF/MANIFEST.MF
index 15331d4..eb95243 100644
--- a/org.eclipse.jgit.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.test/META-INF/MANIFEST.MF
@@ -3,10 +3,10 @@
 Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.test
 Bundle-SymbolicName: org.eclipse.jgit.test
-Bundle-Version: 6.10.2.qualifier
+Bundle-Version: 7.0.2.qualifier
 Bundle-Localization: plugin
 Bundle-Vendor: %Bundle-Vendor
-Bundle-RequiredExecutionEnvironment: JavaSE-11
+Bundle-RequiredExecutionEnvironment: JavaSE-17
 Require-Bundle: org.hamcrest.core;bundle-version="[1.3.0,2.0.0)",
  org.hamcrest.library;bundle-version="[1.3.0,2.0.0)"
 Import-Package: com.googlecode.javaewah;version="[1.1.6,2.0.0)",
@@ -21,64 +21,64 @@
  org.apache.commons.io;version="[2.15.0,3.0.0)",
  org.apache.commons.io.output;version="[2.15.0,3.0.0)",
  org.assertj.core.api;version="[3.14.0,4.0.0)",
- org.eclipse.jgit.annotations;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.api;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.api.errors;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.archive;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.attributes;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.awtui;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.blame;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.diff;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.dircache;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.errors;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.events;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.fnmatch;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.gitrepo;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.hooks;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.ignore;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.ignore.internal;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.internal;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.internal.diff;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.internal.diffmergetool;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.internal.fsck;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.internal.revwalk;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.internal.storage.commitgraph;version="6.10.2",
- org.eclipse.jgit.internal.storage.dfs;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.internal.storage.file;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.internal.storage.io;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.internal.storage.memory;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.internal.storage.pack;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.internal.storage.reftable;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.internal.transport.connectivity;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.internal.transport.http;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.internal.transport.parser;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.internal.transport.ssh;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.junit;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.junit.time;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.lfs;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.lib;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.lib.internal;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.logging;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.merge;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.nls;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.notes;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.patch;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.pgm;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.pgm.internal;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.revplot;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.revwalk;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.revwalk.filter;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.storage.file;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.storage.pack;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.submodule;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.transport;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.transport.http;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.transport.resolver;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.treewalk;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.treewalk.filter;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.util;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.util.io;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.util.sha1;version="[6.10.2,6.11.0)",
+ org.eclipse.jgit.annotations;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.api;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.api.errors;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.archive;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.attributes;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.awtui;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.blame;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.diff;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.dircache;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.errors;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.events;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.fnmatch;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.gitrepo;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.hooks;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.ignore;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.ignore.internal;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.internal;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.internal.diff;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.internal.diffmergetool;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.internal.fsck;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.internal.revwalk;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.internal.storage.commitgraph;version="7.0.2",
+ org.eclipse.jgit.internal.storage.dfs;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.internal.storage.file;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.internal.storage.io;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.internal.storage.memory;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.internal.storage.pack;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.internal.storage.reftable;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.internal.transport.connectivity;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.internal.transport.http;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.internal.transport.parser;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.internal.transport.ssh;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.junit;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.junit.time;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.lfs;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.lib;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.lib.internal;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.logging;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.merge;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.nls;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.notes;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.patch;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.pgm;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.pgm.internal;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.revplot;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.revwalk;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.revwalk.filter;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.storage.file;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.storage.pack;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.submodule;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.transport;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.transport.http;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.transport.resolver;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.treewalk;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.treewalk.filter;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.util;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.util.io;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.util.sha1;version="[7.0.2,7.1.0)",
  org.junit;version="[4.13,5.0.0)",
  org.junit.experimental.theories;version="[4.13,5.0.0)",
  org.junit.function;version="[4.13.0,5.0.0)",
diff --git "a/org.eclipse.jgit.test/org.eclipse.jgit.core--All-Tests \050Java 11\051 \050de\051.launch" "b/org.eclipse.jgit.test/org.eclipse.jgit.core--All-Tests \050Java 17\051 \050de\051.launch"
similarity index 97%
rename from "org.eclipse.jgit.test/org.eclipse.jgit.core--All-Tests \050Java 11\051 \050de\051.launch"
rename to "org.eclipse.jgit.test/org.eclipse.jgit.core--All-Tests \050Java 17\051 \050de\051.launch"
index fdfdce8..de83c6c 100644
--- "a/org.eclipse.jgit.test/org.eclipse.jgit.core--All-Tests \050Java 11\051 \050de\051.launch"
+++ "b/org.eclipse.jgit.test/org.eclipse.jgit.core--All-Tests \050Java 17\051 \050de\051.launch"
@@ -24,7 +24,7 @@
 <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry id=&quot;org.eclipse.jdt.launching.classpathentry.defaultClasspath&quot;&gt;&#10;&lt;memento exportedEntriesOnly=&quot;false&quot; project=&quot;org.eclipse.jgit.test&quot;/&gt;&#10;&lt;/runtimeClasspathEntry&gt;&#10;"/>
 </listAttribute>
 <booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/>
-<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11"/>
+<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17"/>
 <stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value=""/>
 <stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.jgit.test"/>
 <stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xmx256m"/>
diff --git "a/org.eclipse.jgit.test/org.eclipse.jgit.core--All-Tests \050Java 11\051.launch" "b/org.eclipse.jgit.test/org.eclipse.jgit.core--All-Tests \050Java 17\051.launch"
similarity index 97%
rename from "org.eclipse.jgit.test/org.eclipse.jgit.core--All-Tests \050Java 11\051.launch"
rename to "org.eclipse.jgit.test/org.eclipse.jgit.core--All-Tests \050Java 17\051.launch"
index 89c23c3..fabfa31 100644
--- "a/org.eclipse.jgit.test/org.eclipse.jgit.core--All-Tests \050Java 11\051.launch"
+++ "b/org.eclipse.jgit.test/org.eclipse.jgit.core--All-Tests \050Java 17\051.launch"
@@ -21,7 +21,7 @@
 <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry id=&quot;org.eclipse.jdt.launching.classpathentry.defaultClasspath&quot;&gt;&#10;&lt;memento exportedEntriesOnly=&quot;false&quot; project=&quot;org.eclipse.jgit.test&quot;/&gt;&#10;&lt;/runtimeClasspathEntry&gt;&#10;"/>
 </listAttribute>
 <booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/>
-<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11"/>
+<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17"/>
 <stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value=""/>
 <stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.jgit.test"/>
 <stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xmx256m"/>
diff --git a/org.eclipse.jgit.test/pom.xml b/org.eclipse.jgit.test/pom.xml
index 55dbf31..d44ca07 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>6.10.2-SNAPSHOT</version>
+    <version>7.0.2-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.test</artifactId>
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitCommandTest.java
index 35de73e..e74e234 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitCommandTest.java
@@ -27,6 +27,7 @@
 import org.eclipse.jgit.api.CherryPickResult.CherryPickStatus;
 import org.eclipse.jgit.api.errors.CanceledException;
 import org.eclipse.jgit.api.errors.EmptyCommitException;
+import org.eclipse.jgit.api.errors.UnsupportedSigningFormatException;
 import org.eclipse.jgit.api.errors.WrongRepositoryStateException;
 import org.eclipse.jgit.diff.DiffEntry;
 import org.eclipse.jgit.dircache.DirCache;
@@ -34,19 +35,23 @@
 import org.eclipse.jgit.dircache.DirCacheEntry;
 import org.eclipse.jgit.junit.RepositoryTestCase;
 import org.eclipse.jgit.junit.time.TimeUtil;
-import org.eclipse.jgit.lib.CommitBuilder;
+import org.eclipse.jgit.lib.CommitConfig.CleanupMode;
 import org.eclipse.jgit.lib.ConfigConstants;
 import org.eclipse.jgit.lib.Constants;
 import org.eclipse.jgit.lib.FileMode;
-import org.eclipse.jgit.lib.GpgSigner;
+import org.eclipse.jgit.lib.GpgConfig;
+import org.eclipse.jgit.lib.GpgConfig.GpgFormat;
+import org.eclipse.jgit.lib.GpgSignature;
+import org.eclipse.jgit.lib.ObjectBuilder;
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.PersonIdent;
 import org.eclipse.jgit.lib.RefUpdate;
 import org.eclipse.jgit.lib.RefUpdate.Result;
 import org.eclipse.jgit.lib.ReflogEntry;
 import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.Signer;
+import org.eclipse.jgit.lib.Signers;
 import org.eclipse.jgit.lib.StoredConfig;
-import org.eclipse.jgit.lib.CommitConfig.CleanupMode;
 import org.eclipse.jgit.revwalk.RevCommit;
 import org.eclipse.jgit.storage.file.FileBasedConfig;
 import org.eclipse.jgit.submodule.SubmoduleWalk;
@@ -839,21 +844,39 @@ public void callSignerWithProperSigningKey() throws Exception {
 			String[] signingKey = new String[1];
 			PersonIdent[] signingCommitters = new PersonIdent[1];
 			AtomicInteger callCount = new AtomicInteger();
-			GpgSigner.setDefault(new GpgSigner() {
+			// Since GpgFormat defaults to OpenPGP just set a new signer for
+			// that.
+			Signers.set(GpgFormat.OPENPGP, new Signer() {
+
 				@Override
-				public void sign(CommitBuilder commit, String gpgSigningKey,
-						PersonIdent signingCommitter, CredentialsProvider credentialsProvider) {
-					signingKey[0] = gpgSigningKey;
+				public void signObject(Repository repo, GpgConfig config,
+						ObjectBuilder builder, PersonIdent signingCommitter,
+						String signingKeySpec,
+						CredentialsProvider credentialsProvider)
+						throws CanceledException,
+						UnsupportedSigningFormatException {
+					signingKey[0] = signingKeySpec;
 					signingCommitters[0] = signingCommitter;
 					callCount.incrementAndGet();
 				}
 
 				@Override
-				public boolean canLocateSigningKey(String gpgSigningKey,
-						PersonIdent signingCommitter,
+				public GpgSignature sign(Repository repo, GpgConfig config,
+						byte[] data, PersonIdent signingCommitter,
+						String signingKeySpec,
+						CredentialsProvider credentialsProvider)
+						throws CanceledException,
+						UnsupportedSigningFormatException {
+					throw new CanceledException("Unexpected call");
+				}
+
+				@Override
+				public boolean canLocateSigningKey(Repository repo,
+						GpgConfig config, PersonIdent signingCommitter,
+						String signingKeySpec,
 						CredentialsProvider credentialsProvider)
 						throws CanceledException {
-					return false;
+					throw new CanceledException("Unexpected call");
 				}
 			});
 
@@ -904,19 +927,37 @@ public void callSignerOnlyWhenSigning() throws Exception {
 			git.add().addFilepattern("file1").call();
 
 			AtomicInteger callCount = new AtomicInteger();
-			GpgSigner.setDefault(new GpgSigner() {
+			// Since GpgFormat defaults to OpenPGP just set a new signer for
+			// that.
+			Signers.set(GpgFormat.OPENPGP, new Signer() {
+
 				@Override
-				public void sign(CommitBuilder commit, String gpgSigningKey,
-						PersonIdent signingCommitter, CredentialsProvider credentialsProvider) {
+				public void signObject(Repository repo, GpgConfig config,
+						ObjectBuilder builder, PersonIdent signingCommitter,
+						String signingKeySpec,
+						CredentialsProvider credentialsProvider)
+						throws CanceledException,
+						UnsupportedSigningFormatException {
 					callCount.incrementAndGet();
 				}
 
 				@Override
-				public boolean canLocateSigningKey(String gpgSigningKey,
-						PersonIdent signingCommitter,
+				public GpgSignature sign(Repository repo, GpgConfig config,
+						byte[] data, PersonIdent signingCommitter,
+						String signingKeySpec,
+						CredentialsProvider credentialsProvider)
+						throws CanceledException,
+						UnsupportedSigningFormatException {
+					throw new CanceledException("Unexpected call");
+				}
+
+				@Override
+				public boolean canLocateSigningKey(Repository repo,
+						GpgConfig config, PersonIdent signingCommitter,
+						String signingKeySpec,
 						CredentialsProvider credentialsProvider)
 						throws CanceledException {
-					return false;
+					throw new CanceledException("Unexpected call");
 				}
 			});
 
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/EolRepositoryTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/EolRepositoryTest.java
index b937b1f..4c971ff 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/EolRepositoryTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/EolRepositoryTest.java
@@ -559,7 +559,7 @@ private void setupGitAndDoHardReset(AutoCRLF autoCRLF, EOL eol,
 
 		}
 		if (infoAttributesContent != null) {
-			File f = new File(db.getDirectory(), Constants.INFO_ATTRIBUTES);
+			File f = new File(db.getCommonDirectory(), Constants.INFO_ATTRIBUTES);
 			write(f, infoAttributesContent);
 		}
 		config.save();
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/LinkedWorktreeTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/LinkedWorktreeTest.java
new file mode 100644
index 0000000..3b60e1b
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/LinkedWorktreeTest.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2024, Broadcom and others
+ *
+ * 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.api;
+
+import static org.eclipse.jgit.lib.Constants.HEAD;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.Collection;
+import java.util.Iterator;
+
+import org.eclipse.jgit.internal.storage.file.FileRepository;
+import org.eclipse.jgit.junit.JGitTestUtil;
+import org.eclipse.jgit.junit.RepositoryTestCase;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ReflogEntry;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.util.FS;
+import org.eclipse.jgit.util.FS.ExecutionResult;
+import org.eclipse.jgit.util.RawParseUtils;
+import org.eclipse.jgit.util.TemporaryBuffer;
+import org.junit.Test;
+
+public class LinkedWorktreeTest extends RepositoryTestCase {
+
+	@Override
+	public void setUp() throws Exception {
+		super.setUp();
+
+		try (Git git = new Git(db)) {
+			git.commit().setMessage("Initial commit").call();
+		}
+	}
+
+	@Test
+	public void testWeCanReadFromLinkedWorktreeFromBare() throws Exception {
+		FS fs = db.getFS();
+		File directory = trash.getParentFile();
+		String dbDirName = db.getWorkTree().getName();
+		cloneBare(fs, directory, dbDirName, "bare");
+		File bareDirectory = new File(directory, "bare");
+		worktreeAddExisting(fs, bareDirectory, "master");
+
+		File worktreesDir = new File(bareDirectory, "worktrees");
+		File masterWorktreesDir = new File(worktreesDir, "master");
+
+		FileRepository repository = new FileRepository(masterWorktreesDir);
+		try (Git git = new Git(repository)) {
+			ObjectId objectId = repository.resolve(HEAD);
+			assertNotNull(objectId);
+
+			Iterator<RevCommit> log = git.log().all().call().iterator();
+			assertTrue(log.hasNext());
+			assertTrue("Initial commit".equals(log.next().getShortMessage()));
+
+			// we have reflog entry
+			// depending on git version we either have one or
+			// two entries where extra is zeroid entry with
+			// same message or no message
+			Collection<ReflogEntry> reflog = git.reflog().call();
+			assertNotNull(reflog);
+			assertTrue(reflog.size() > 0);
+			ReflogEntry[] reflogs = reflog.toArray(new ReflogEntry[0]);
+			assertEquals(reflogs[reflogs.length - 1].getComment(),
+					"reset: moving to HEAD");
+
+			// index works with file changes
+			File masterDir = new File(directory, "master");
+			File testFile = new File(masterDir, "test");
+
+			Status status = git.status().call();
+			assertTrue(status.getUncommittedChanges().size() == 0);
+			assertTrue(status.getUntracked().size() == 0);
+
+			JGitTestUtil.write(testFile, "test");
+			status = git.status().call();
+			assertTrue(status.getUncommittedChanges().size() == 0);
+			assertTrue(status.getUntracked().size() == 1);
+
+			git.add().addFilepattern("test").call();
+			status = git.status().call();
+			assertTrue(status.getUncommittedChanges().size() == 1);
+			assertTrue(status.getUntracked().size() == 0);
+		}
+	}
+
+	@Test
+	public void testWeCanReadFromLinkedWorktreeFromNonBare() throws Exception {
+		FS fs = db.getFS();
+		worktreeAddNew(fs, db.getWorkTree(), "wt");
+
+		File worktreesDir = new File(db.getDirectory(), "worktrees");
+		File masterWorktreesDir = new File(worktreesDir, "wt");
+
+		FileRepository repository = new FileRepository(masterWorktreesDir);
+		try (Git git = new Git(repository)) {
+			ObjectId objectId = repository.resolve(HEAD);
+			assertNotNull(objectId);
+
+			Iterator<RevCommit> log = git.log().all().call().iterator();
+			assertTrue(log.hasNext());
+			assertTrue("Initial commit".equals(log.next().getShortMessage()));
+
+			// we have reflog entry
+			Collection<ReflogEntry> reflog = git.reflog().call();
+			assertNotNull(reflog);
+			assertTrue(reflog.size() > 0);
+			ReflogEntry[] reflogs = reflog.toArray(new ReflogEntry[0]);
+			assertEquals(reflogs[reflogs.length - 1].getComment(),
+					"reset: moving to HEAD");
+
+			// index works with file changes
+			File directory = trash.getParentFile();
+			File wtDir = new File(directory, "wt");
+			File testFile = new File(wtDir, "test");
+
+			Status status = git.status().call();
+			assertTrue(status.getUncommittedChanges().size() == 0);
+			assertTrue(status.getUntracked().size() == 0);
+
+			JGitTestUtil.write(testFile, "test");
+			status = git.status().call();
+			assertTrue(status.getUncommittedChanges().size() == 0);
+			assertTrue(status.getUntracked().size() == 1);
+
+			git.add().addFilepattern("test").call();
+			status = git.status().call();
+			assertTrue(status.getUncommittedChanges().size() == 1);
+			assertTrue(status.getUntracked().size() == 0);
+		}
+
+	}
+
+	private static void cloneBare(FS fs, File directory, String from, String to) throws IOException, InterruptedException {
+		ProcessBuilder builder = fs.runInShell("git",
+				new String[] { "clone", "--bare", from, to });
+		builder.directory(directory);
+		builder.environment().put("HOME", fs.userHome().getAbsolutePath());
+		StringBuilder input = new StringBuilder();
+		ExecutionResult result = fs.execute(builder, new ByteArrayInputStream(
+				input.toString().getBytes(StandardCharsets.UTF_8)));
+		String stdOut = toString(result.getStdout());
+		String errorOut = toString(result.getStderr());
+		assertNotNull(stdOut);
+		assertNotNull(errorOut);
+	}
+
+	private static void worktreeAddExisting(FS fs, File directory, String name) throws IOException, InterruptedException {
+		ProcessBuilder builder = fs.runInShell("git",
+				new String[] { "worktree", "add", "../" + name, name });
+		builder.directory(directory);
+		builder.environment().put("HOME", fs.userHome().getAbsolutePath());
+		StringBuilder input = new StringBuilder();
+		ExecutionResult result = fs.execute(builder, new ByteArrayInputStream(
+				input.toString().getBytes(StandardCharsets.UTF_8)));
+		String stdOut = toString(result.getStdout());
+		String errorOut = toString(result.getStderr());
+		assertNotNull(stdOut);
+		assertNotNull(errorOut);
+	}
+
+	private static void worktreeAddNew(FS fs, File directory, String name) throws IOException, InterruptedException {
+		ProcessBuilder builder = fs.runInShell("git",
+				new String[] { "worktree", "add", "-b", name, "../" + name, "master"});
+		builder.directory(directory);
+		builder.environment().put("HOME", fs.userHome().getAbsolutePath());
+		StringBuilder input = new StringBuilder();
+		ExecutionResult result = fs.execute(builder, new ByteArrayInputStream(
+				input.toString().getBytes(StandardCharsets.UTF_8)));
+		String stdOut = toString(result.getStdout());
+		String errorOut = toString(result.getStderr());
+		assertNotNull(stdOut);
+		assertNotNull(errorOut);
+	}
+
+	private static String toString(TemporaryBuffer b) throws IOException {
+		return RawParseUtils.decode(b.toByteArray());
+	}
+
+}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesHandlerTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesHandlerTest.java
index 7fb98ec..c41dd81 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesHandlerTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesHandlerTest.java
@@ -584,7 +584,7 @@ private void setupRepo(
 
 		}
 		if (infoAttributesContent != null) {
-			File f = new File(db.getDirectory(), Constants.INFO_ATTRIBUTES);
+			File f = new File(db.getCommonDirectory(), Constants.INFO_ATTRIBUTES);
 			write(f, infoAttributesContent);
 		}
 		config.save();
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/commitgraph/CommitGraphWriterTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/commitgraph/CommitGraphWriterTest.java
index 9f65ee2..80a0f0c 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/commitgraph/CommitGraphWriterTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/commitgraph/CommitGraphWriterTest.java
@@ -10,6 +10,7 @@
 
 package org.eclipse.jgit.internal.storage.commitgraph;
 
+import static java.util.stream.Collectors.toList;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.containsInAnyOrder;
 import static org.junit.Assert.assertArrayEquals;
@@ -19,8 +20,12 @@
 
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
 import java.util.Collections;
 import java.util.HashSet;
+import java.util.List;
+import java.util.Optional;
 import java.util.Set;
 
 import org.eclipse.jgit.dircache.DirCacheEntry;
@@ -413,6 +418,27 @@ public void testReuseBloomFilters() throws Exception {
 				"119,69,63,-8,0,"));
 	}
 
+	@Test
+	public void testPathDiffCalculator_skipUnchangedTree() throws Exception {
+		RevCommit root = tr.commit(tr.tree(
+				tr.file("d/sd1/f1", tr.blob("f1")),
+				tr.file("d/sd2/f2", tr.blob("f2"))));
+		RevCommit tip = tr.commit(tr.tree(
+				tr.file("d/sd1/f1", tr.blob("f1")),
+				tr.file("d/sd2/f2", tr.blob("f2B"))), root);
+		CommitGraphWriter.PathDiffCalculator c = new CommitGraphWriter.PathDiffCalculator();
+
+		Optional<HashSet<ByteBuffer>> byteBuffers = c.changedPaths(walk.getObjectReader(), tip);
+
+		assertTrue(byteBuffers.isPresent());
+		List<String> asString = byteBuffers.get().stream()
+				.map(b -> StandardCharsets.UTF_8.decode(b).toString())
+				.collect(toList());
+		assertThat(asString, containsInAnyOrder("d", "d/sd2", "d/sd2/f2"));
+		// We don't walk into d/sd1/f1
+		assertEquals(1, c.stepCounter);
+	}
+
 	RevCommit commit(RevCommit... parents) throws Exception {
 		return tr.commit(parents);
 	}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsBlockCacheConfigTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsBlockCacheConfigTest.java
index 2df0ba1..c93f48d 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsBlockCacheConfigTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsBlockCacheConfigTest.java
@@ -38,13 +38,30 @@
 
 package org.eclipse.jgit.internal.storage.dfs;
 
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_CORE_SECTION;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_DFS_CACHE_PREFIX;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_DFS_SECTION;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_BLOCK_LIMIT;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_BLOCK_SIZE;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_CONCURRENCY_LEVEL;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_PACK_EXTENSIONS;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_STREAM_RATIO;
 import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.closeTo;
+import static org.hamcrest.Matchers.hasSize;
 import static org.hamcrest.Matchers.is;
 import static org.junit.Assert.assertThrows;
 
+import java.util.List;
+import java.util.stream.Collectors;
+
 import org.eclipse.jgit.internal.JGitText;
+import org.eclipse.jgit.internal.storage.dfs.DfsBlockCacheConfig.DfsBlockCachePackExtConfig;
+import org.eclipse.jgit.internal.storage.pack.PackExt;
+import org.eclipse.jgit.lib.Config;
 import org.junit.Test;
 
+@SuppressWarnings("boxing")
 public class DfsBlockCacheConfigTest {
 
 	@Test
@@ -55,7 +72,6 @@ public void blockSizeNotPowerOfTwoExpectsException() {
 	}
 
 	@Test
-	@SuppressWarnings("boxing")
 	public void negativeBlockSizeIsConvertedToDefault() {
 		DfsBlockCacheConfig config = new DfsBlockCacheConfig();
 		config.setBlockSize(-1);
@@ -64,7 +80,6 @@ public void negativeBlockSizeIsConvertedToDefault() {
 	}
 
 	@Test
-	@SuppressWarnings("boxing")
 	public void tooSmallBlockSizeIsConvertedToDefault() {
 		DfsBlockCacheConfig config = new DfsBlockCacheConfig();
 		config.setBlockSize(10);
@@ -73,11 +88,153 @@ public void tooSmallBlockSizeIsConvertedToDefault() {
 	}
 
 	@Test
-	@SuppressWarnings("boxing")
 	public void validBlockSize() {
 		DfsBlockCacheConfig config = new DfsBlockCacheConfig();
 		config.setBlockSize(65536);
 
 		assertThat(config.getBlockSize(), is(65536));
 	}
+
+	@Test
+	public void fromConfigs() {
+		Config config = new Config();
+		config.setLong(CONFIG_CORE_SECTION, CONFIG_DFS_SECTION,
+				CONFIG_KEY_BLOCK_LIMIT, 50 * 1024);
+		config.setInt(CONFIG_CORE_SECTION, CONFIG_DFS_SECTION,
+				CONFIG_KEY_BLOCK_SIZE, 1024);
+		config.setInt(CONFIG_CORE_SECTION, CONFIG_DFS_SECTION,
+				CONFIG_KEY_CONCURRENCY_LEVEL, 3);
+		config.setString(CONFIG_CORE_SECTION, CONFIG_DFS_SECTION,
+				CONFIG_KEY_STREAM_RATIO, "0.5");
+
+		DfsBlockCacheConfig cacheConfig = new DfsBlockCacheConfig()
+				.fromConfig(config);
+		assertThat(cacheConfig.getBlockLimit(), is(50L * 1024L));
+		assertThat(cacheConfig.getBlockSize(), is(1024));
+		assertThat(cacheConfig.getConcurrencyLevel(), is(3));
+		assertThat(cacheConfig.getStreamRatio(), closeTo(0.5, 0.0001));
+	}
+
+	@Test
+	public void fromConfig_blockLimitNotAMultipleOfBlockSize_throws() {
+		Config config = new Config();
+		config.setLong(CONFIG_CORE_SECTION, CONFIG_DFS_SECTION,
+				CONFIG_KEY_BLOCK_LIMIT, 1025);
+		config.setInt(CONFIG_CORE_SECTION, CONFIG_DFS_SECTION,
+				CONFIG_KEY_BLOCK_SIZE, 1024);
+
+		assertThrows(IllegalArgumentException.class,
+				() -> new DfsBlockCacheConfig().fromConfig(config));
+	}
+
+	@Test
+	public void fromConfig_streamRatioInvalidFormat_throws() {
+		Config config = new Config();
+		config.setString(CONFIG_CORE_SECTION, CONFIG_DFS_SECTION,
+				CONFIG_KEY_STREAM_RATIO, "0.a5");
+
+		assertThrows(IllegalArgumentException.class,
+				() -> new DfsBlockCacheConfig().fromConfig(config));
+	}
+
+	@Test
+	public void fromConfig_generatesDfsBlockCachePackExtConfigs() {
+		Config config = new Config();
+		addPackExtConfigEntry(config, "pack", List.of(PackExt.PACK),
+				/* blockLimit= */ 20 * 512, /* blockSize= */ 512);
+
+		addPackExtConfigEntry(config, "bitmap", List.of(PackExt.BITMAP_INDEX),
+				/* blockLimit= */ 25 * 1024, /* blockSize= */ 1024);
+
+		addPackExtConfigEntry(config, "index",
+				List.of(PackExt.INDEX, PackExt.OBJECT_SIZE_INDEX,
+						PackExt.REVERSE_INDEX),
+				/* blockLimit= */ 30 * 1024, /* blockSize= */ 1024);
+
+		DfsBlockCacheConfig cacheConfig = new DfsBlockCacheConfig()
+				.fromConfig(config);
+		var configs = cacheConfig.getPackExtCacheConfigurations();
+		assertThat(configs, hasSize(3));
+		var packConfig = getConfigForExt(configs, PackExt.PACK);
+		assertThat(packConfig.getBlockLimit(), is(20L * 512L));
+		assertThat(packConfig.getBlockSize(), is(512));
+
+		var bitmapConfig = getConfigForExt(configs, PackExt.BITMAP_INDEX);
+		assertThat(bitmapConfig.getBlockLimit(), is(25L * 1024L));
+		assertThat(bitmapConfig.getBlockSize(), is(1024));
+
+		var indexConfig = getConfigForExt(configs, PackExt.INDEX);
+		assertThat(indexConfig.getBlockLimit(), is(30L * 1024L));
+		assertThat(indexConfig.getBlockSize(), is(1024));
+		assertThat(getConfigForExt(configs, PackExt.OBJECT_SIZE_INDEX),
+				is(indexConfig));
+		assertThat(getConfigForExt(configs, PackExt.REVERSE_INDEX),
+				is(indexConfig));
+	}
+
+	@Test
+	public void fromConfigs_dfsBlockCachePackExtConfigWithDuplicateExtensions_throws() {
+		Config config = new Config();
+		config.setString(CONFIG_CORE_SECTION, CONFIG_DFS_CACHE_PREFIX + "pack1",
+				CONFIG_KEY_PACK_EXTENSIONS, PackExt.PACK.name());
+
+		config.setString(CONFIG_CORE_SECTION, CONFIG_DFS_CACHE_PREFIX + "pack2",
+				CONFIG_KEY_PACK_EXTENSIONS, PackExt.PACK.name());
+
+		assertThrows(IllegalArgumentException.class,
+				() -> new DfsBlockCacheConfig().fromConfig(config));
+	}
+
+	@Test
+	public void fromConfigs_dfsBlockCachePackExtConfigWithEmptyExtensions_throws() {
+		Config config = new Config();
+		config.setString(CONFIG_CORE_SECTION, CONFIG_DFS_CACHE_PREFIX + "pack1",
+				CONFIG_KEY_PACK_EXTENSIONS, "");
+
+		assertThrows(IllegalArgumentException.class,
+				() -> new DfsBlockCacheConfig().fromConfig(config));
+	}
+
+	@Test
+	public void fromConfigs_dfsBlockCachePackExtConfigWithNoExtensions_throws() {
+		Config config = new Config();
+		config.setInt(CONFIG_CORE_SECTION, CONFIG_DFS_CACHE_PREFIX + "pack1",
+				CONFIG_KEY_BLOCK_SIZE, 0);
+
+		assertThrows(IllegalArgumentException.class,
+				() -> new DfsBlockCacheConfig().fromConfig(config));
+	}
+
+	@Test
+	public void fromConfigs_dfsBlockCachePackExtConfigWithUnknownExtensions_throws() {
+		Config config = new Config();
+		config.setString(CONFIG_CORE_SECTION,
+				CONFIG_DFS_CACHE_PREFIX + "unknownExt",
+				CONFIG_KEY_PACK_EXTENSIONS, "NotAKnownExt");
+
+		assertThrows(IllegalArgumentException.class,
+				() -> new DfsBlockCacheConfig().fromConfig(config));
+	}
+
+	private static void addPackExtConfigEntry(Config config, String configName,
+			List<PackExt> packExts, long blockLimit, int blockSize) {
+		String packExtConfigName = CONFIG_DFS_CACHE_PREFIX + configName;
+		config.setString(CONFIG_CORE_SECTION, packExtConfigName,
+				CONFIG_KEY_PACK_EXTENSIONS, packExts.stream().map(PackExt::name)
+						.collect(Collectors.joining(" ")));
+		config.setLong(CONFIG_CORE_SECTION, packExtConfigName,
+				CONFIG_KEY_BLOCK_LIMIT, blockLimit);
+		config.setInt(CONFIG_CORE_SECTION, packExtConfigName,
+				CONFIG_KEY_BLOCK_SIZE, blockSize);
+	}
+
+	private static DfsBlockCacheConfig getConfigForExt(
+			List<DfsBlockCachePackExtConfig> configs, PackExt packExt) {
+		for (DfsBlockCachePackExtConfig config : configs) {
+			if (config.getPackExts().contains(packExt)) {
+				return config.getPackExtCacheConfiguration();
+			}
+		}
+		return null;
+	}
 }
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 e193de9..2be11d3 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
@@ -18,6 +18,7 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.concurrent.TimeUnit;
+
 import org.eclipse.jgit.internal.storage.commitgraph.CommitGraph;
 import org.eclipse.jgit.internal.storage.commitgraph.CommitGraphWriter;
 import org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource;
@@ -1171,6 +1172,7 @@ public void objectSizeIdx_reachableBlob_bigEnough_indexed() throws Exception {
 
 		gcWithObjectSizeIndex(10);
 
+		odb.getReaderOptions().setUseObjectSizeIndex(true);
 		DfsReader reader = odb.newReader();
 		DfsPackFile gcPack = findFirstBySource(odb.getPacks(), GC);
 		assertTrue(gcPack.hasObjectSizeIndex(reader));
@@ -1191,6 +1193,7 @@ public void objectSizeIdx_reachableBlob_tooSmall_notIndexed() throws Exception {
 
 		gcWithObjectSizeIndex(10);
 
+		odb.getReaderOptions().setUseObjectSizeIndex(true);
 		DfsReader reader = odb.newReader();
 		DfsPackFile gcPack = findFirstBySource(odb.getPacks(), GC);
 		assertTrue(gcPack.hasObjectSizeIndex(reader));
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsInserterTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsInserterTest.java
index b84a0b0..0b558ed 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsInserterTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsInserterTest.java
@@ -295,6 +295,7 @@ public void testObjectSizePopulated() throws IOException {
 	public void testObjectSizeIndexOnInsert() throws IOException {
 		db.getConfig().setInt(CONFIG_PACK_SECTION, null,
 				CONFIG_KEY_MIN_BYTES_OBJ_SIZE_INDEX, 0);
+		db.getObjectDatabase().getReaderOptions().setUseObjectSizeIndex(true);
 
 		byte[] contents = Constants.encode("foo");
 		ObjectId fooId;
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackFileTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackFileTest.java
index d21e51f..bc851f8 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackFileTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackFileTest.java
@@ -126,6 +126,7 @@ public void testLoadObjectSizeIndex() throws IOException {
 		setObjectSizeIndexMinBytes(0);
 		ObjectId blobId = setupPack(512, 800);
 
+		db.getObjectDatabase().getReaderOptions().setUseObjectSizeIndex(true);
 		DfsReader reader = db.getObjectDatabase().newReader();
 		DfsPackFile pack = db.getObjectDatabase().getPacks()[0];
 		assertTrue(pack.hasObjectSizeIndex(reader));
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackParserTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackParserTest.java
index 130af27..c1cd231 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackParserTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackParserTest.java
@@ -61,6 +61,7 @@ public void parse_writeObjSizeIdx() throws IOException {
 			ins.flush();
 		}
 
+		repo.getObjectDatabase().getReaderOptions().setUseObjectSizeIndex(true);
 		DfsReader reader = repo.getObjectDatabase().newReader();
 		PackList packList = repo.getObjectDatabase().getPackList();
 		assertEquals(1, packList.packs.length);
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsReaderTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsReaderTest.java
index 254184e..a0c2289 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsReaderTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsReaderTest.java
@@ -37,6 +37,8 @@ public class DfsReaderTest {
 	@Before
 	public void setUp() {
 		db = new InMemoryRepository(new DfsRepositoryDescription("test"));
+		// These tests assume the object size index is enabled.
+		db.getObjectDatabase().getReaderOptions().setUseObjectSizeIndex(true);
 	}
 
 	@Test
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/PackExtBlockCacheTableTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/PackExtBlockCacheTableTest.java
new file mode 100644
index 0000000..8c003e0
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/PackExtBlockCacheTableTest.java
@@ -0,0 +1,591 @@
+/*
+ * Copyright (c) 2024, Google LLC and others
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+package org.eclipse.jgit.internal.storage.dfs;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.sameInstance;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.when;
+
+import java.util.EnumSet;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.jgit.internal.storage.dfs.DfsBlockCache.Ref;
+import org.eclipse.jgit.internal.storage.dfs.DfsBlockCache.RefLoader;
+import org.eclipse.jgit.internal.storage.dfs.DfsBlockCacheConfig.DfsBlockCachePackExtConfig;
+import org.eclipse.jgit.internal.storage.dfs.DfsBlockCacheTable.DfsBlockCacheStats;
+import org.eclipse.jgit.internal.storage.pack.PackExt;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+@SuppressWarnings({ "boxing", "unchecked" })
+public class PackExtBlockCacheTableTest {
+	@Test
+	public void fromBlockCacheConfigs_createsDfsPackExtBlockCacheTables() {
+		DfsBlockCacheConfig cacheConfig = new DfsBlockCacheConfig();
+		cacheConfig.setPackExtCacheConfigurations(
+				List.of(new DfsBlockCachePackExtConfig(EnumSet.of(PackExt.PACK),
+						new DfsBlockCacheConfig())));
+		assertNotNull(
+				PackExtBlockCacheTable.fromBlockCacheConfigs(cacheConfig));
+	}
+
+	@Test
+	public void fromBlockCacheConfigs_noPackExtConfigurationGiven_packExtCacheConfigurationsIsEmpty_throws() {
+		DfsBlockCacheConfig cacheConfig = new DfsBlockCacheConfig();
+		cacheConfig.setPackExtCacheConfigurations(List.of());
+		assertThrows(IllegalArgumentException.class,
+				() -> PackExtBlockCacheTable
+						.fromBlockCacheConfigs(cacheConfig));
+	}
+
+	@Test
+	public void hasBlock0_packExtMapsToCacheTable_callsBitmapIndexCacheTable() {
+		DfsStreamKey streamKey = new TestKey(PackExt.BITMAP_INDEX);
+		DfsBlockCacheTable defaultBlockCacheTable = mock(
+				DfsBlockCacheTable.class);
+		DfsBlockCacheTable bitmapIndexCacheTable = mock(
+				DfsBlockCacheTable.class);
+		when(bitmapIndexCacheTable.hasBlock0(any(DfsStreamKey.class)))
+				.thenReturn(true);
+
+		PackExtBlockCacheTable tables = PackExtBlockCacheTable.fromCacheTables(
+				defaultBlockCacheTable,
+				Map.of(PackExt.BITMAP_INDEX, bitmapIndexCacheTable));
+
+		assertTrue(tables.hasBlock0(streamKey));
+	}
+
+	@Test
+	public void hasBlock0_packExtDoesNotMapToCacheTable_callsDefaultCache() {
+		DfsStreamKey streamKey = new TestKey(PackExt.PACK);
+		DfsBlockCacheTable defaultBlockCacheTable = mock(
+				DfsBlockCacheTable.class);
+		when(defaultBlockCacheTable.hasBlock0(any(DfsStreamKey.class)))
+				.thenReturn(true);
+		DfsBlockCacheTable bitmapIndexCacheTable = mock(
+				DfsBlockCacheTable.class);
+
+		PackExtBlockCacheTable tables = PackExtBlockCacheTable.fromCacheTables(
+				defaultBlockCacheTable,
+				Map.of(PackExt.BITMAP_INDEX, bitmapIndexCacheTable));
+
+		assertTrue(tables.hasBlock0(streamKey));
+	}
+
+	@Test
+	public void getOrLoad_packExtMapsToCacheTable_callsBitmapIndexCacheTable()
+			throws Exception {
+		BlockBasedFile blockBasedFile = new BlockBasedFile(null,
+				mock(DfsPackDescription.class), PackExt.BITMAP_INDEX) {
+			// empty
+		};
+		DfsBlock dfsBlock = mock(DfsBlock.class);
+		DfsBlockCacheTable defaultBlockCacheTable = mock(
+				DfsBlockCacheTable.class);
+		when(defaultBlockCacheTable.getOrLoad(any(BlockBasedFile.class),
+				anyLong(), any(DfsReader.class),
+				any(DfsBlockCache.ReadableChannelSupplier.class)))
+				.thenReturn(mock(DfsBlock.class));
+		DfsBlockCacheTable bitmapIndexCacheTable = mock(
+				DfsBlockCacheTable.class);
+		when(bitmapIndexCacheTable.getOrLoad(any(BlockBasedFile.class),
+				anyLong(), any(DfsReader.class),
+				any(DfsBlockCache.ReadableChannelSupplier.class)))
+				.thenReturn(dfsBlock);
+
+		PackExtBlockCacheTable tables = PackExtBlockCacheTable.fromCacheTables(
+				defaultBlockCacheTable,
+				Map.of(PackExt.BITMAP_INDEX, bitmapIndexCacheTable));
+
+		assertThat(
+				tables.getOrLoad(blockBasedFile, 0, mock(DfsReader.class),
+						mock(DfsBlockCache.ReadableChannelSupplier.class)),
+				sameInstance(dfsBlock));
+	}
+
+	@Test
+	public void getOrLoad_packExtDoesNotMapToCacheTable_callsDefaultCache()
+			throws Exception {
+		BlockBasedFile blockBasedFile = new BlockBasedFile(null,
+				mock(DfsPackDescription.class), PackExt.PACK) {
+			// empty
+		};
+		DfsBlock dfsBlock = mock(DfsBlock.class);
+		DfsBlockCacheTable defaultBlockCacheTable = mock(
+				DfsBlockCacheTable.class);
+		when(defaultBlockCacheTable.getOrLoad(any(BlockBasedFile.class),
+				anyLong(), any(DfsReader.class),
+				any(DfsBlockCache.ReadableChannelSupplier.class)))
+				.thenReturn(dfsBlock);
+		DfsBlockCacheTable bitmapIndexCacheTable = mock(
+				DfsBlockCacheTable.class);
+		when(bitmapIndexCacheTable.getOrLoad(any(BlockBasedFile.class),
+				anyLong(), any(DfsReader.class),
+				any(DfsBlockCache.ReadableChannelSupplier.class)))
+				.thenReturn(mock(DfsBlock.class));
+
+		PackExtBlockCacheTable tables = PackExtBlockCacheTable.fromCacheTables(
+				defaultBlockCacheTable,
+				Map.of(PackExt.BITMAP_INDEX, bitmapIndexCacheTable));
+
+		assertThat(
+				tables.getOrLoad(blockBasedFile, 0, mock(DfsReader.class),
+						mock(DfsBlockCache.ReadableChannelSupplier.class)),
+				sameInstance(dfsBlock));
+	}
+
+	@Test
+	public void getOrLoadRef_packExtMapsToCacheTable_callsBitmapIndexCacheTable()
+			throws Exception {
+		Ref<Integer> ref = mock(Ref.class);
+		DfsStreamKey dfsStreamKey = new TestKey(PackExt.BITMAP_INDEX);
+		DfsBlockCacheTable defaultBlockCacheTable = mock(
+				DfsBlockCacheTable.class);
+		when(defaultBlockCacheTable.getOrLoadRef(any(DfsStreamKey.class),
+				anyLong(), any(RefLoader.class))).thenReturn(mock(Ref.class));
+		DfsBlockCacheTable bitmapIndexCacheTable = mock(
+				DfsBlockCacheTable.class);
+		when(bitmapIndexCacheTable.getOrLoadRef(any(DfsStreamKey.class),
+				anyLong(), any(RefLoader.class))).thenReturn(ref);
+
+		PackExtBlockCacheTable tables = PackExtBlockCacheTable.fromCacheTables(
+				defaultBlockCacheTable,
+				Map.of(PackExt.BITMAP_INDEX, bitmapIndexCacheTable));
+
+		assertThat(tables.getOrLoadRef(dfsStreamKey, 0, mock(RefLoader.class)),
+				sameInstance(ref));
+	}
+
+	@Test
+	public void getOrLoadRef_packExtDoesNotMapToCacheTable_callsDefaultCache()
+			throws Exception {
+		Ref<Integer> ref = mock(Ref.class);
+		DfsStreamKey dfsStreamKey = new TestKey(PackExt.PACK);
+		DfsBlockCacheTable defaultBlockCacheTable = mock(
+				DfsBlockCacheTable.class);
+		when(defaultBlockCacheTable.getOrLoadRef(any(DfsStreamKey.class),
+				anyLong(), any(RefLoader.class))).thenReturn(ref);
+		DfsBlockCacheTable bitmapIndexCacheTable = mock(
+				DfsBlockCacheTable.class);
+		when(bitmapIndexCacheTable.getOrLoadRef(any(DfsStreamKey.class),
+				anyLong(), any(RefLoader.class))).thenReturn(mock(Ref.class));
+
+		PackExtBlockCacheTable tables = PackExtBlockCacheTable.fromCacheTables(
+				defaultBlockCacheTable,
+				Map.of(PackExt.BITMAP_INDEX, bitmapIndexCacheTable));
+
+		assertThat(tables.getOrLoadRef(dfsStreamKey, 0, mock(RefLoader.class)),
+				sameInstance(ref));
+	}
+
+	@Test
+	public void putDfsBlock_packExtMapsToCacheTable_callsBitmapIndexCacheTable() {
+		DfsStreamKey dfsStreamKey = new TestKey(PackExt.BITMAP_INDEX);
+		DfsBlock dfsBlock = new DfsBlock(dfsStreamKey, 0, new byte[0]);
+		DfsBlockCacheTable defaultBlockCacheTable = mock(
+				DfsBlockCacheTable.class);
+		DfsBlockCacheTable bitmapIndexCacheTable = mock(
+				DfsBlockCacheTable.class);
+
+		PackExtBlockCacheTable tables = PackExtBlockCacheTable.fromCacheTables(
+				defaultBlockCacheTable,
+				Map.of(PackExt.BITMAP_INDEX, bitmapIndexCacheTable));
+
+		tables.put(dfsBlock);
+		Mockito.verify(bitmapIndexCacheTable, times(1)).put(dfsBlock);
+	}
+
+	@Test
+	public void putDfsBlock_packExtDoesNotMapToCacheTable_callsDefaultCache() {
+		DfsStreamKey dfsStreamKey = new TestKey(PackExt.PACK);
+		DfsBlock dfsBlock = new DfsBlock(dfsStreamKey, 0, new byte[0]);
+		DfsBlockCacheTable defaultBlockCacheTable = mock(
+				DfsBlockCacheTable.class);
+		DfsBlockCacheTable bitmapIndexCacheTable = mock(
+				DfsBlockCacheTable.class);
+
+		PackExtBlockCacheTable tables = PackExtBlockCacheTable.fromCacheTables(
+				defaultBlockCacheTable,
+				Map.of(PackExt.BITMAP_INDEX, bitmapIndexCacheTable));
+
+		tables.put(dfsBlock);
+		Mockito.verify(defaultBlockCacheTable, times(1)).put(dfsBlock);
+	}
+
+	@Test
+	public void putDfsStreamKey_packExtMapsToCacheTable_callsBitmapIndexCacheTable() {
+		DfsStreamKey dfsStreamKey = new TestKey(PackExt.BITMAP_INDEX);
+		Ref<Integer> ref = mock(Ref.class);
+		DfsBlockCacheTable defaultBlockCacheTable = mock(
+				DfsBlockCacheTable.class);
+		when(defaultBlockCacheTable.put(any(DfsStreamKey.class), anyLong(),
+				anyLong(), anyInt())).thenReturn(mock(Ref.class));
+		DfsBlockCacheTable bitmapIndexCacheTable = mock(
+				DfsBlockCacheTable.class);
+		when(bitmapIndexCacheTable.put(any(DfsStreamKey.class), anyLong(),
+				anyLong(), anyInt())).thenReturn(ref);
+
+		PackExtBlockCacheTable tables = PackExtBlockCacheTable.fromCacheTables(
+				defaultBlockCacheTable,
+				Map.of(PackExt.BITMAP_INDEX, bitmapIndexCacheTable));
+
+		assertThat(tables.put(dfsStreamKey, 0, 0, 0), sameInstance(ref));
+	}
+
+	@Test
+	public void putDfsStreamKey_packExtDoesNotMapToCacheTable_callsDefaultCache() {
+		DfsStreamKey dfsStreamKey = new TestKey(PackExt.PACK);
+		Ref<Integer> ref = mock(Ref.class);
+		DfsBlockCacheTable defaultBlockCacheTable = mock(
+				DfsBlockCacheTable.class);
+		when(defaultBlockCacheTable.put(any(DfsStreamKey.class), anyLong(),
+				anyLong(), anyInt())).thenReturn(ref);
+		DfsBlockCacheTable bitmapIndexCacheTable = mock(
+				DfsBlockCacheTable.class);
+		when(bitmapIndexCacheTable.put(any(DfsStreamKey.class), anyLong(),
+				anyLong(), anyInt())).thenReturn(mock(Ref.class));
+
+		PackExtBlockCacheTable tables = PackExtBlockCacheTable.fromCacheTables(
+				defaultBlockCacheTable,
+				Map.of(PackExt.BITMAP_INDEX, bitmapIndexCacheTable));
+
+		assertThat(tables.put(dfsStreamKey, 0, 0, 0), sameInstance(ref));
+	}
+
+	@Test
+	public void putRef_packExtMapsToCacheTable_callsBitmapIndexCacheTable() {
+		DfsStreamKey dfsStreamKey = new TestKey(PackExt.BITMAP_INDEX);
+		Ref<Integer> ref = mock(Ref.class);
+		DfsBlockCacheTable defaultBlockCacheTable = mock(
+				DfsBlockCacheTable.class);
+		when(defaultBlockCacheTable.putRef(any(DfsStreamKey.class), anyLong(),
+				anyInt())).thenReturn(mock(Ref.class));
+		DfsBlockCacheTable bitmapIndexCacheTable = mock(
+				DfsBlockCacheTable.class);
+		when(bitmapIndexCacheTable.putRef(any(DfsStreamKey.class), anyLong(),
+				anyInt())).thenReturn(ref);
+
+		PackExtBlockCacheTable tables = PackExtBlockCacheTable.fromCacheTables(
+				defaultBlockCacheTable,
+				Map.of(PackExt.BITMAP_INDEX, bitmapIndexCacheTable));
+
+		assertThat(tables.putRef(dfsStreamKey, 0, 0), sameInstance(ref));
+	}
+
+	@Test
+	public void putRef_packExtDoesNotMapToCacheTable_callsDefaultCache() {
+		DfsStreamKey dfsStreamKey = new TestKey(PackExt.PACK);
+		Ref<Integer> ref = mock(Ref.class);
+		DfsBlockCacheTable defaultBlockCacheTable = mock(
+				DfsBlockCacheTable.class);
+		when(defaultBlockCacheTable.putRef(any(DfsStreamKey.class), anyLong(),
+				anyInt())).thenReturn(ref);
+		DfsBlockCacheTable bitmapIndexCacheTable = mock(
+				DfsBlockCacheTable.class);
+		when(bitmapIndexCacheTable.putRef(any(DfsStreamKey.class), anyLong(),
+				anyInt())).thenReturn(mock(Ref.class));
+
+		PackExtBlockCacheTable tables = PackExtBlockCacheTable.fromCacheTables(
+				defaultBlockCacheTable,
+				Map.of(PackExt.BITMAP_INDEX, bitmapIndexCacheTable));
+
+		assertThat(tables.putRef(dfsStreamKey, 0, 0), sameInstance(ref));
+	}
+
+	@Test
+	public void contains_packExtMapsToCacheTable_callsBitmapIndexCacheTable() {
+		DfsStreamKey streamKey = new TestKey(PackExt.BITMAP_INDEX);
+		DfsBlockCacheTable defaultBlockCacheTable = mock(
+				DfsBlockCacheTable.class);
+		DfsBlockCacheTable bitmapIndexCacheTable = mock(
+				DfsBlockCacheTable.class);
+		when(bitmapIndexCacheTable.contains(any(DfsStreamKey.class), anyLong()))
+				.thenReturn(true);
+
+		PackExtBlockCacheTable tables = PackExtBlockCacheTable.fromCacheTables(
+				defaultBlockCacheTable,
+				Map.of(PackExt.BITMAP_INDEX, bitmapIndexCacheTable));
+
+		assertTrue(tables.contains(streamKey, 0));
+	}
+
+	@Test
+	public void contains_packExtDoesNotMapToCacheTable_callsDefaultCache() {
+		DfsStreamKey streamKey = new TestKey(PackExt.PACK);
+		DfsBlockCacheTable defaultBlockCacheTable = mock(
+				DfsBlockCacheTable.class);
+		when(defaultBlockCacheTable.contains(any(DfsStreamKey.class),
+				anyLong())).thenReturn(true);
+		DfsBlockCacheTable bitmapIndexCacheTable = mock(
+				DfsBlockCacheTable.class);
+
+		PackExtBlockCacheTable tables = PackExtBlockCacheTable.fromCacheTables(
+				defaultBlockCacheTable,
+				Map.of(PackExt.BITMAP_INDEX, bitmapIndexCacheTable));
+
+		assertTrue(tables.contains(streamKey, 0));
+	}
+
+	@Test
+	public void get_packExtMapsToCacheTable_callsBitmapIndexCacheTable() {
+		DfsStreamKey dfsStreamKey = new TestKey(PackExt.BITMAP_INDEX);
+		Ref<Integer> ref = mock(Ref.class);
+		DfsBlockCacheTable defaultBlockCacheTable = mock(
+				DfsBlockCacheTable.class);
+		when(defaultBlockCacheTable.get(any(DfsStreamKey.class), anyLong()))
+				.thenReturn(mock(Ref.class));
+		DfsBlockCacheTable bitmapIndexCacheTable = mock(
+				DfsBlockCacheTable.class);
+		when(bitmapIndexCacheTable.get(any(DfsStreamKey.class), anyLong()))
+				.thenReturn(ref);
+
+		PackExtBlockCacheTable tables = PackExtBlockCacheTable.fromCacheTables(
+				defaultBlockCacheTable,
+				Map.of(PackExt.BITMAP_INDEX, bitmapIndexCacheTable));
+
+		assertThat(tables.get(dfsStreamKey, 0), sameInstance(ref));
+	}
+
+	@Test
+	public void get_packExtDoesNotMapToCacheTable_callsDefaultCache() {
+		DfsStreamKey dfsStreamKey = new TestKey(PackExt.PACK);
+		Ref<Integer> ref = mock(Ref.class);
+		DfsBlockCacheTable defaultBlockCacheTable = mock(
+				DfsBlockCacheTable.class);
+		when(defaultBlockCacheTable.get(any(DfsStreamKey.class), anyLong()))
+				.thenReturn(ref);
+		DfsBlockCacheTable bitmapIndexCacheTable = mock(
+				DfsBlockCacheTable.class);
+		when(bitmapIndexCacheTable.get(any(DfsStreamKey.class), anyLong()))
+				.thenReturn(mock(Ref.class));
+
+		PackExtBlockCacheTable tables = PackExtBlockCacheTable.fromCacheTables(
+				defaultBlockCacheTable,
+				Map.of(PackExt.BITMAP_INDEX, bitmapIndexCacheTable));
+
+		assertThat(tables.get(dfsStreamKey, 0), sameInstance(ref));
+	}
+
+	@Test
+	public void getBlockCacheStats_getCurrentSize_consolidatesAllTableCurrentSizes() {
+		long[] currentSizes = createEmptyStatsArray();
+
+		DfsBlockCacheStats packStats = new DfsBlockCacheStats();
+		packStats.addToLiveBytes(new TestKey(PackExt.PACK), 5);
+		currentSizes[PackExt.PACK.getPosition()] = 5;
+
+		DfsBlockCacheStats bitmapStats = new DfsBlockCacheStats();
+		bitmapStats.addToLiveBytes(new TestKey(PackExt.BITMAP_INDEX), 6);
+		currentSizes[PackExt.BITMAP_INDEX.getPosition()] = 6;
+
+		DfsBlockCacheStats indexStats = new DfsBlockCacheStats();
+		indexStats.addToLiveBytes(new TestKey(PackExt.INDEX), 7);
+		currentSizes[PackExt.INDEX.getPosition()] = 7;
+
+		PackExtBlockCacheTable tables = PackExtBlockCacheTable
+				.fromCacheTables(cacheTableWithStats(packStats),
+						Map.of(PackExt.BITMAP_INDEX,
+								cacheTableWithStats(bitmapStats), PackExt.INDEX,
+								cacheTableWithStats(indexStats)));
+
+		assertArrayEquals(tables.getBlockCacheStats().getCurrentSize(),
+				currentSizes);
+	}
+
+	@Test
+	public void getBlockCacheStats_GetHitCount_consolidatesAllTableHitCounts() {
+		long[] hitCounts = createEmptyStatsArray();
+
+		DfsBlockCacheStats packStats = new DfsBlockCacheStats();
+		incrementCounter(5,
+				() -> packStats.incrementHit(new TestKey(PackExt.PACK)));
+		hitCounts[PackExt.PACK.getPosition()] = 5;
+
+		DfsBlockCacheStats bitmapStats = new DfsBlockCacheStats();
+		incrementCounter(6, () -> bitmapStats
+				.incrementHit(new TestKey(PackExt.BITMAP_INDEX)));
+		hitCounts[PackExt.BITMAP_INDEX.getPosition()] = 6;
+
+		DfsBlockCacheStats indexStats = new DfsBlockCacheStats();
+		incrementCounter(7,
+				() -> indexStats.incrementHit(new TestKey(PackExt.INDEX)));
+		hitCounts[PackExt.INDEX.getPosition()] = 7;
+
+		PackExtBlockCacheTable tables = PackExtBlockCacheTable
+				.fromCacheTables(cacheTableWithStats(packStats),
+						Map.of(PackExt.BITMAP_INDEX,
+								cacheTableWithStats(bitmapStats), PackExt.INDEX,
+								cacheTableWithStats(indexStats)));
+
+		assertArrayEquals(tables.getBlockCacheStats().getHitCount(), hitCounts);
+	}
+
+	@Test
+	public void getBlockCacheStats_getMissCount_consolidatesAllTableMissCounts() {
+		long[] missCounts = createEmptyStatsArray();
+
+		DfsBlockCacheStats packStats = new DfsBlockCacheStats();
+		incrementCounter(5,
+				() -> packStats.incrementMiss(new TestKey(PackExt.PACK)));
+		missCounts[PackExt.PACK.getPosition()] = 5;
+
+		DfsBlockCacheStats bitmapStats = new DfsBlockCacheStats();
+		incrementCounter(6, () -> bitmapStats
+				.incrementMiss(new TestKey(PackExt.BITMAP_INDEX)));
+		missCounts[PackExt.BITMAP_INDEX.getPosition()] = 6;
+
+		DfsBlockCacheStats indexStats = new DfsBlockCacheStats();
+		incrementCounter(7,
+				() -> indexStats.incrementMiss(new TestKey(PackExt.INDEX)));
+		missCounts[PackExt.INDEX.getPosition()] = 7;
+
+		PackExtBlockCacheTable tables = PackExtBlockCacheTable
+				.fromCacheTables(cacheTableWithStats(packStats),
+						Map.of(PackExt.BITMAP_INDEX,
+								cacheTableWithStats(bitmapStats), PackExt.INDEX,
+								cacheTableWithStats(indexStats)));
+
+		assertArrayEquals(tables.getBlockCacheStats().getMissCount(),
+				missCounts);
+	}
+
+	@Test
+	public void getBlockCacheStats_getTotalRequestCount_consolidatesAllTableTotalRequestCounts() {
+		long[] totalRequestCounts = createEmptyStatsArray();
+
+		DfsBlockCacheStats packStats = new DfsBlockCacheStats();
+		incrementCounter(5, () -> {
+			packStats.incrementHit(new TestKey(PackExt.PACK));
+			packStats.incrementMiss(new TestKey(PackExt.PACK));
+		});
+		totalRequestCounts[PackExt.PACK.getPosition()] = 10;
+
+		DfsBlockCacheStats bitmapStats = new DfsBlockCacheStats();
+		incrementCounter(6, () -> {
+			bitmapStats.incrementHit(new TestKey(PackExt.BITMAP_INDEX));
+			bitmapStats.incrementMiss(new TestKey(PackExt.BITMAP_INDEX));
+		});
+		totalRequestCounts[PackExt.BITMAP_INDEX.getPosition()] = 12;
+
+		DfsBlockCacheStats indexStats = new DfsBlockCacheStats();
+		incrementCounter(7, () -> {
+			indexStats.incrementHit(new TestKey(PackExt.INDEX));
+			indexStats.incrementMiss(new TestKey(PackExt.INDEX));
+		});
+		totalRequestCounts[PackExt.INDEX.getPosition()] = 14;
+
+		PackExtBlockCacheTable tables = PackExtBlockCacheTable
+				.fromCacheTables(cacheTableWithStats(packStats),
+						Map.of(PackExt.BITMAP_INDEX,
+								cacheTableWithStats(bitmapStats), PackExt.INDEX,
+								cacheTableWithStats(indexStats)));
+
+		assertArrayEquals(tables.getBlockCacheStats().getTotalRequestCount(),
+				totalRequestCounts);
+	}
+
+	@Test
+	public void getBlockCacheStats_getHitRatio_consolidatesAllTableHitRatios() {
+		long[] hitRatios = createEmptyStatsArray();
+
+		DfsBlockCacheStats packStats = new DfsBlockCacheStats();
+		incrementCounter(5,
+				() -> packStats.incrementHit(new TestKey(PackExt.PACK)));
+		hitRatios[PackExt.PACK.getPosition()] = 100;
+
+		DfsBlockCacheStats bitmapStats = new DfsBlockCacheStats();
+		incrementCounter(6, () -> {
+			bitmapStats.incrementHit(new TestKey(PackExt.BITMAP_INDEX));
+			bitmapStats.incrementMiss(new TestKey(PackExt.BITMAP_INDEX));
+		});
+		hitRatios[PackExt.BITMAP_INDEX.getPosition()] = 50;
+
+		DfsBlockCacheStats indexStats = new DfsBlockCacheStats();
+		incrementCounter(7,
+				() -> indexStats.incrementMiss(new TestKey(PackExt.INDEX)));
+		hitRatios[PackExt.INDEX.getPosition()] = 0;
+
+		PackExtBlockCacheTable tables = PackExtBlockCacheTable
+				.fromCacheTables(cacheTableWithStats(packStats),
+						Map.of(PackExt.BITMAP_INDEX,
+								cacheTableWithStats(bitmapStats), PackExt.INDEX,
+								cacheTableWithStats(indexStats)));
+
+		assertArrayEquals(tables.getBlockCacheStats().getHitRatio(), hitRatios);
+	}
+
+	@Test
+	public void getBlockCacheStats_getEvictions_consolidatesAllTableEvictions() {
+		long[] evictions = createEmptyStatsArray();
+
+		DfsBlockCacheStats packStats = new DfsBlockCacheStats();
+		incrementCounter(5,
+				() -> packStats.incrementEvict(new TestKey(PackExt.PACK)));
+		evictions[PackExt.PACK.getPosition()] = 5;
+
+		DfsBlockCacheStats bitmapStats = new DfsBlockCacheStats();
+		incrementCounter(6, () -> bitmapStats
+				.incrementEvict(new TestKey(PackExt.BITMAP_INDEX)));
+		evictions[PackExt.BITMAP_INDEX.getPosition()] = 6;
+
+		DfsBlockCacheStats indexStats = new DfsBlockCacheStats();
+		incrementCounter(7,
+				() -> indexStats.incrementEvict(new TestKey(PackExt.INDEX)));
+		evictions[PackExt.INDEX.getPosition()] = 7;
+
+		PackExtBlockCacheTable tables = PackExtBlockCacheTable
+				.fromCacheTables(cacheTableWithStats(packStats),
+						Map.of(PackExt.BITMAP_INDEX,
+								cacheTableWithStats(bitmapStats), PackExt.INDEX,
+								cacheTableWithStats(indexStats)));
+
+		assertArrayEquals(tables.getBlockCacheStats().getEvictions(),
+				evictions);
+	}
+
+	private static void incrementCounter(int amount, Runnable fn) {
+		for (int i = 0; i < amount; i++) {
+			fn.run();
+		}
+	}
+
+	private static long[] createEmptyStatsArray() {
+		return new long[PackExt.values().length];
+	}
+
+	private static DfsBlockCacheTable cacheTableWithStats(
+			DfsBlockCacheStats dfsBlockCacheStats) {
+		DfsBlockCacheTable cacheTable = mock(DfsBlockCacheTable.class);
+		when(cacheTable.getBlockCacheStats()).thenReturn(dfsBlockCacheStats);
+		return cacheTable;
+	}
+
+	private static class TestKey extends DfsStreamKey {
+		TestKey(PackExt packExt) {
+			super(0, packExt);
+		}
+
+		@Override
+		public boolean equals(Object o) {
+			return false;
+		}
+	}
+}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/BatchRefUpdateTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/BatchRefUpdateTest.java
index daf4382..1af42cb 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/BatchRefUpdateTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/BatchRefUpdateTest.java
@@ -171,7 +171,7 @@ public void packedRefsFileIsSorted() throws IOException {
 			assertEquals(c2.getResult(), ReceiveCommand.Result.OK);
 		}
 
-		File packed = new File(diskRepo.getDirectory(), "packed-refs");
+		File packed = new File(diskRepo.getCommonDirectory(), "packed-refs");
 		String packedStr = new String(Files.readAllBytes(packed.toPath()),
 				UTF_8);
 
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcPackRefsTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcPackRefsTest.java
index 8baa3cc..c572955 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcPackRefsTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcPackRefsTest.java
@@ -58,7 +58,7 @@ public void emptyRefDirectoryDeleted() throws Exception {
 		String ref = "dir/ref";
 		tr.branch(ref).commit().create();
 		String name = repo.findRef(ref).getName();
-		Path dir = repo.getDirectory().toPath().resolve(name).getParent();
+		Path dir = repo.getCommonDirectory().toPath().resolve(name).getParent();
 		assertNotNull(dir);
 		gc.packRefs();
 		assertFalse(Files.exists(dir));
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcReflogTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcReflogTest.java
index e6c1ee5..29f180d 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcReflogTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcReflogTest.java
@@ -30,7 +30,7 @@ public void testPruneNone() throws Exception {
 		BranchBuilder bb = tr.branch("refs/heads/master");
 		bb.commit().add("A", "A").add("B", "B").create();
 		bb.commit().add("A", "A2").add("B", "B2").create();
-		new File(repo.getDirectory(), Constants.LOGS + "/refs/heads/master")
+		new File(repo.getCommonDirectory(), Constants.LOGS + "/refs/heads/master")
 				.delete();
 		stats = gc.getStatistics();
 		assertEquals(8, stats.numberOfLooseObjects);
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ObjectDirectoryTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ObjectDirectoryTest.java
index 746a0a1..d1342c0 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ObjectDirectoryTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ObjectDirectoryTest.java
@@ -243,17 +243,18 @@ public void testWindowCursorGetCommitGraph() throws Exception {
 		db.getConfig().setBoolean(ConfigConstants.CONFIG_GC_SECTION, null,
 				ConfigConstants.CONFIG_KEY_WRITE_COMMIT_GRAPH, true);
 
-		WindowCursor curs = new WindowCursor(db.getObjectDatabase());
-		assertTrue(curs.getCommitGraph().isEmpty());
-		commitFile("file.txt", "content", "master");
-		GC gc = new GC(db);
-		gc.gc().get();
-		assertTrue(curs.getCommitGraph().isPresent());
+		try (WindowCursor curs = new WindowCursor(db.getObjectDatabase())) {
+			assertTrue(curs.getCommitGraph().isEmpty());
+			commitFile("file.txt", "content", "master");
+			GC gc = new GC(db);
+			gc.gc().get();
+			assertTrue(curs.getCommitGraph().isPresent());
 
-		db.getConfig().setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null,
-				ConfigConstants.CONFIG_COMMIT_GRAPH, false);
+			db.getConfig().setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null,
+					ConfigConstants.CONFIG_COMMIT_GRAPH, false);
 
-		assertTrue(curs.getCommitGraph().isEmpty());
+			assertTrue(curs.getCommitGraph().isEmpty());
+		}
 	}
 
 	@Test
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 2bafde6..baa0182 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
@@ -90,25 +90,26 @@ public void refDirectorySetup() throws Exception {
 	@Test
 	public void testCreate() throws IOException {
 		// setUp above created the directory. We just have to test it.
-		File d = diskRepo.getDirectory();
+		File gitDir = diskRepo.getDirectory();
+		File commonDir = diskRepo.getCommonDirectory();
 		assertSame(diskRepo, refdir.getRepository());
 
-		assertTrue(new File(d, "refs").isDirectory());
-		assertTrue(new File(d, "logs").isDirectory());
-		assertTrue(new File(d, "logs/refs").isDirectory());
-		assertFalse(new File(d, "packed-refs").exists());
+		assertTrue(new File(commonDir, "refs").isDirectory());
+		assertTrue(new File(commonDir, "logs").isDirectory());
+		assertTrue(new File(commonDir, "logs/refs").isDirectory());
+		assertFalse(new File(commonDir, "packed-refs").exists());
 
-		assertTrue(new File(d, "refs/heads").isDirectory());
-		assertTrue(new File(d, "refs/tags").isDirectory());
-		assertEquals(2, new File(d, "refs").list().length);
-		assertEquals(0, new File(d, "refs/heads").list().length);
-		assertEquals(0, new File(d, "refs/tags").list().length);
+		assertTrue(new File(commonDir, "refs/heads").isDirectory());
+		assertTrue(new File(commonDir, "refs/tags").isDirectory());
+		assertEquals(2, new File(commonDir, "refs").list().length);
+		assertEquals(0, new File(commonDir, "refs/heads").list().length);
+		assertEquals(0, new File(commonDir, "refs/tags").list().length);
 
-		assertTrue(new File(d, "logs/refs/heads").isDirectory());
-		assertFalse(new File(d, "logs/HEAD").exists());
-		assertEquals(0, new File(d, "logs/refs/heads").list().length);
+		assertTrue(new File(commonDir, "logs/refs/heads").isDirectory());
+		assertFalse(new File(gitDir, "logs/HEAD").exists());
+		assertEquals(0, new File(commonDir, "logs/refs/heads").list().length);
 
-		assertEquals("ref: refs/heads/master\n", read(new File(d, HEAD)));
+		assertEquals("ref: refs/heads/master\n", read(new File(gitDir, HEAD)));
 	}
 
 	@Test(expected = UnsupportedOperationException.class)
@@ -1382,7 +1383,7 @@ private void writeLooseRef(String name, String content) throws IOException {
 	}
 
 	private void deleteLooseRef(String name) {
-		File path = new File(diskRepo.getDirectory(), name);
+		File path = new File(diskRepo.getCommonDirectory(), name);
 		assertTrue("deleted " + name, path.delete());
 	}
 }
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ReflogReaderTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ReflogReaderTest.java
index dc0e749..eb521ff 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ReflogReaderTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ReflogReaderTest.java
@@ -238,7 +238,7 @@ public void testSpecificEntryNumber() throws Exception {
 
 	private void setupReflog(String logName, byte[] data)
 			throws FileNotFoundException, IOException {
-		File logfile = new File(db.getDirectory(), logName);
+		File logfile = new File(db.getCommonDirectory(), logName);
 		if (!logfile.getParentFile().mkdirs()
 				&& !logfile.getParentFile().isDirectory()) {
 			throw new IOException(
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ReflogWriterTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ReflogWriterTest.java
index 8d0e99d..8e9b7b8 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ReflogWriterTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ReflogWriterTest.java
@@ -48,7 +48,7 @@ public void shouldFilterLineFeedFromMessage() throws Exception {
 
 	private void readReflog(byte[] buffer)
 			throws FileNotFoundException, IOException {
-		File logfile = new File(db.getDirectory(), "logs/refs/heads/master");
+		File logfile = new File(db.getCommonDirectory(), "logs/refs/heads/master");
 		if (!logfile.getParentFile().mkdirs()
 				&& !logfile.getParentFile().isDirectory()) {
 			throw new IOException(
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/GpgConfigTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/GpgConfigTest.java
index 32f6766..5c2b190 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/GpgConfigTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/GpgConfigTest.java
@@ -96,6 +96,16 @@ public void testGetKeyFormat_x509() throws Exception {
 	}
 
 	@Test
+	public void testGetKeyFormat_ssh() throws Exception {
+		Config c = parse("" //
+				+ "[gpg]\n" //
+				+ "  format = ssh\n" //
+		);
+
+		assertEquals(GpgConfig.GpgFormat.SSH, new GpgConfig(c).getKeyFormat());
+	}
+
+	@Test
 	public void testGetSigningKey() throws Exception {
 		Config c = parse("" //
 				+ "[user]\n" //
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ObjectIdTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ObjectIdTest.java
index 21032c3..d6f0b03 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ObjectIdTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ObjectIdTest.java
@@ -16,6 +16,7 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
+import java.nio.ByteBuffer;
 import java.util.Locale;
 
 import org.eclipse.jgit.errors.InvalidObjectIdException;
@@ -153,4 +154,16 @@ public void testSetByte() {
 			assertEquals(ObjectId.fromRaw(exp).name(), id.name());
 		}
 	}
+
+	@Test
+	public void test_toFromByteBuffer_raw() {
+		ObjectId oid = ObjectId
+				.fromString("ff00eedd003713bb1bb26b808ec9312548e73946");
+		ByteBuffer anObject = ByteBuffer.allocate(Constants.OBJECT_ID_LENGTH);
+		oid.copyRawTo(anObject);
+		anObject.flip();
+
+		ObjectId actual = ObjectId.fromRaw(anObject);
+		assertEquals(oid.name(), actual.name());
+	}
 }
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/FileTreeIteratorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/FileTreeIteratorTest.java
index e463e90..7b9e70d 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/FileTreeIteratorTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/FileTreeIteratorTest.java
@@ -25,8 +25,9 @@
 
 import org.eclipse.jgit.api.Git;
 import org.eclipse.jgit.api.ResetCommand.ResetType;
+import org.eclipse.jgit.dircache.Checkout;
 import org.eclipse.jgit.dircache.DirCache;
-import org.eclipse.jgit.dircache.DirCacheCheckout;
+import org.eclipse.jgit.dircache.DirCacheCheckout.CheckoutMetadata;
 import org.eclipse.jgit.dircache.DirCacheEditor;
 import org.eclipse.jgit.dircache.DirCacheEditor.PathEdit;
 import org.eclipse.jgit.dircache.DirCacheEntry;
@@ -38,6 +39,7 @@
 import org.eclipse.jgit.junit.RepositoryTestCase;
 import org.eclipse.jgit.lib.ConfigConstants;
 import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.CoreConfig.EolStreamType;
 import org.eclipse.jgit.lib.FileMode;
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.ObjectInserter;
@@ -303,11 +305,12 @@ public void testIsModifiedSymlinkAsFile() throws Exception {
 		DirCacheEntry dce = db.readDirCache().getEntry("symlink");
 		dce.setFileMode(FileMode.SYMLINK);
 		try (ObjectReader objectReader = db.newObjectReader()) {
+			Checkout checkout = new Checkout(db).setRecursiveDeletion(false);
+			checkout.checkout(dce,
+					new CheckoutMetadata(EolStreamType.DIRECT, null),
+					objectReader, null);
 			WorkingTreeOptions options = db.getConfig()
 					.get(WorkingTreeOptions.KEY);
-			DirCacheCheckout.checkoutEntry(db, dce, objectReader, false, null,
-					options);
-
 			FileTreeIterator fti = new FileTreeIterator(trash, db.getFS(),
 					options);
 			while (!fti.getEntryPathString().equals("symlink")) {
diff --git a/org.eclipse.jgit.ui/.classpath b/org.eclipse.jgit.ui/.classpath
index 1fde318..efeb803 100644
--- a/org.eclipse.jgit.ui/.classpath
+++ b/org.eclipse.jgit.ui/.classpath
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17">
 		<attributes>
 			<attribute name="module" value="true"/>
 		</attributes>
diff --git a/org.eclipse.jgit.ui/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit.ui/.settings/org.eclipse.jdt.core.prefs
index 3a92f0c..f810c7b 100644
--- a/org.eclipse.jgit.ui/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit.ui/.settings/org.eclipse.jdt.core.prefs
@@ -7,9 +7,9 @@
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=11
+org.eclipse.jdt.core.compiler.compliance=17
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -115,7 +115,7 @@
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
 org.eclipse.jdt.core.compiler.release=enabled
-org.eclipse.jdt.core.compiler.source=11
+org.eclipse.jdt.core.compiler.source=17
 org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
 org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
diff --git a/org.eclipse.jgit.ui/META-INF/MANIFEST.MF b/org.eclipse.jgit.ui/META-INF/MANIFEST.MF
index 6c2ced4..7c98d77 100644
--- a/org.eclipse.jgit.ui/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.ui/META-INF/MANIFEST.MF
@@ -4,14 +4,14 @@
 Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.ui
 Bundle-SymbolicName: org.eclipse.jgit.ui
-Bundle-Version: 6.10.2.qualifier
+Bundle-Version: 7.0.2.qualifier
 Bundle-Vendor: %Bundle-Vendor
-Bundle-RequiredExecutionEnvironment: JavaSE-11
-Export-Package: org.eclipse.jgit.awtui;version="6.10.2"
-Import-Package: org.eclipse.jgit.errors;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.lib;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.nls;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.revplot;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.revwalk;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.transport;version="[6.10.2,6.11.0)",
- org.eclipse.jgit.util;version="[6.10.2,6.11.0)"
+Bundle-RequiredExecutionEnvironment: JavaSE-17
+Export-Package: org.eclipse.jgit.awtui;version="7.0.2"
+Import-Package: org.eclipse.jgit.errors;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.lib;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.nls;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.revplot;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.revwalk;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.transport;version="[7.0.2,7.1.0)",
+ org.eclipse.jgit.util;version="[7.0.2,7.1.0)"
diff --git a/org.eclipse.jgit.ui/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.ui/META-INF/SOURCE-MANIFEST.MF
index b690752..0d64d01 100644
--- a/org.eclipse.jgit.ui/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.ui/META-INF/SOURCE-MANIFEST.MF
@@ -3,5 +3,5 @@
 Bundle-Name: org.eclipse.jgit.ui - Sources
 Bundle-SymbolicName: org.eclipse.jgit.ui.source
 Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 6.10.2.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit.ui;version="6.10.2.qualifier";roots="."
+Bundle-Version: 7.0.2.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit.ui;version="7.0.2.qualifier";roots="."
diff --git a/org.eclipse.jgit.ui/pom.xml b/org.eclipse.jgit.ui/pom.xml
index 92f86c3..ea73b43 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>6.10.2-SNAPSHOT</version>
+    <version>7.0.2-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.ui</artifactId>
diff --git a/org.eclipse.jgit/.classpath b/org.eclipse.jgit/.classpath
index 139a059..dde8e3f 100644
--- a/org.eclipse.jgit/.classpath
+++ b/org.eclipse.jgit/.classpath
@@ -2,7 +2,7 @@
 <classpath>
 	<classpathentry kind="src" path="src"/>
 	<classpathentry kind="src" path="resources"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17">
 		<attributes>
 			<attribute name="module" value="true"/>
 		</attributes>
diff --git a/org.eclipse.jgit/.settings/.api_filters b/org.eclipse.jgit/.settings/.api_filters
deleted file mode 100644
index ce79170..0000000
--- a/org.eclipse.jgit/.settings/.api_filters
+++ /dev/null
@@ -1,107 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<component id="org.eclipse.jgit" version="2">
-    <resource path="src/org/eclipse/jgit/diff/DiffDriver.java" type="org.eclipse.jgit.diff.DiffDriver">
-        <filter id="1109393411">
-            <message_arguments>
-                <message_argument value="6.10.1"/>
-                <message_argument value="org.eclipse.jgit.diff.DiffDriver"/>
-            </message_arguments>
-        </filter>
-    </resource>
-    <resource path="src/org/eclipse/jgit/diff/DiffFormatter.java" type="org.eclipse.jgit.diff.DiffFormatter">
-        <filter id="1142947843">
-            <message_arguments>
-                <message_argument value="6.10.1"/>
-                <message_argument value="format(EditList, RawText, RawText, DiffDriver)"/>
-            </message_arguments>
-        </filter>
-        <filter id="1142947843">
-            <message_arguments>
-                <message_argument value="6.10.1"/>
-                <message_argument value="format(FileHeader, RawText, RawText, DiffDriver)"/>
-            </message_arguments>
-        </filter>
-        <filter id="1142947843">
-            <message_arguments>
-                <message_argument value="6.10.1"/>
-                <message_argument value="writeHunkHeader(int, int, int, int, String)"/>
-            </message_arguments>
-        </filter>
-    </resource>
-    <resource path="src/org/eclipse/jgit/gitrepo/RepoProject.java" type="org.eclipse.jgit.gitrepo.RepoProject">
-        <filter id="1141899266">
-            <message_arguments>
-                <message_argument value="7.0"/>
-                <message_argument value="6.10"/>
-                <message_argument value="getDestBranch()"/>
-            </message_arguments>
-        </filter>
-        <filter id="1141899266">
-            <message_arguments>
-                <message_argument value="7.0"/>
-                <message_argument value="6.10"/>
-                <message_argument value="setDestBranch(String)"/>
-            </message_arguments>
-        </filter>
-    </resource>
-    <resource path="src/org/eclipse/jgit/lib/Constants.java" type="org.eclipse.jgit.lib.Constants">
-        <filter id="1142947843">
-            <message_arguments>
-                <message_argument value="6.10.1"/>
-                <message_argument value="ATTR_BUILTIN_UNION_MERGE_DRIVER"/>
-            </message_arguments>
-        </filter>
-    </resource>
-    <resource path="src/org/eclipse/jgit/merge/ContentMergeStrategy.java" type="org.eclipse.jgit.merge.ContentMergeStrategy">
-        <filter id="1176502275">
-            <message_arguments>
-                <message_argument value="6.10.1"/>
-                <message_argument value="UNION"/>
-            </message_arguments>
-        </filter>
-    </resource>
-    <resource path="src/org/eclipse/jgit/merge/ResolveMerger.java" type="org.eclipse.jgit.merge.ResolveMerger">
-        <filter id="336658481">
-            <message_arguments>
-                <message_argument value="org.eclipse.jgit.merge.ResolveMerger"/>
-                <message_argument value="attributesNodeProvider"/>
-            </message_arguments>
-        </filter>
-        <filter id="1142947843">
-            <message_arguments>
-                <message_argument value="6.10.1"/>
-                <message_argument value="attributesNodeProvider"/>
-            </message_arguments>
-        </filter>
-        <filter id="1142947843">
-            <message_arguments>
-                <message_argument value="6.10.1"/>
-                <message_argument value="setAttributesNodeProvider(AttributesNodeProvider)"/>
-            </message_arguments>
-        </filter>
-    </resource>
-    <resource path="src/org/eclipse/jgit/revwalk/RevWalk.java" type="org.eclipse.jgit.revwalk.RevWalk">
-        <filter id="1142947843">
-            <message_arguments>
-                <message_argument value="6.10.1"/>
-                <message_argument value="isMergedIntoAnyCommit(RevCommit, Collection&lt;RevCommit&gt;)"/>
-            </message_arguments>
-        </filter>
-    </resource>
-    <resource path="src/org/eclipse/jgit/transport/UploadPack.java" type="org.eclipse.jgit.transport.UploadPack$RequestPolicy">
-        <filter id="1176502275">
-            <message_arguments>
-                <message_argument value="6.10.1"/>
-                <message_argument value="implies(UploadPack.RequestPolicy)"/>
-            </message_arguments>
-        </filter>
-    </resource>
-    <resource path="src/org/eclipse/jgit/util/Iterators.java" type="org.eclipse.jgit.util.Iterators">
-        <filter id="1109393411">
-            <message_arguments>
-                <message_argument value="6.10.2"/>
-                <message_argument value="org.eclipse.jgit.util.Iterators"/>
-            </message_arguments>
-        </filter>
-    </resource>
-</component>
diff --git a/org.eclipse.jgit/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit/.settings/org.eclipse.jdt.core.prefs
index b27b6c3..c4dc76f 100644
--- a/org.eclipse.jgit/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit/.settings/org.eclipse.jdt.core.prefs
@@ -7,9 +7,9 @@
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=11
+org.eclipse.jdt.core.compiler.compliance=17
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -115,7 +115,7 @@
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
 org.eclipse.jdt.core.compiler.release=enabled
-org.eclipse.jdt.core.compiler.source=11
+org.eclipse.jdt.core.compiler.source=17
 org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
 org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
diff --git a/org.eclipse.jgit/META-INF/MANIFEST.MF b/org.eclipse.jgit/META-INF/MANIFEST.MF
index 6041244..0d4f772 100644
--- a/org.eclipse.jgit/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit/META-INF/MANIFEST.MF
@@ -3,14 +3,14 @@
 Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit
 Bundle-SymbolicName: org.eclipse.jgit
-Bundle-Version: 6.10.2.qualifier
+Bundle-Version: 7.0.2.qualifier
 Bundle-Localization: OSGI-INF/l10n/plugin
 Bundle-Vendor: %Bundle-Vendor
 Bundle-ActivationPolicy: lazy
 Service-Component: OSGI-INF/org.eclipse.jgit.internal.util.CleanupService.xml
 Eclipse-ExtensibleAPI: true
-Export-Package: org.eclipse.jgit.annotations;version="6.10.2",
- org.eclipse.jgit.api;version="6.10.2";
+Export-Package: org.eclipse.jgit.annotations;version="7.0.2",
+ org.eclipse.jgit.api;version="7.0.2";
   uses:="org.eclipse.jgit.transport,
    org.eclipse.jgit.notes,
    org.eclipse.jgit.dircache,
@@ -25,18 +25,18 @@
    org.eclipse.jgit.revwalk.filter,
    org.eclipse.jgit.blame,
    org.eclipse.jgit.merge",
- org.eclipse.jgit.api.errors;version="6.10.2";
+ org.eclipse.jgit.api.errors;version="7.0.2";
   uses:="org.eclipse.jgit.lib,
    org.eclipse.jgit.errors",
- org.eclipse.jgit.attributes;version="6.10.2";
+ org.eclipse.jgit.attributes;version="7.0.2";
   uses:="org.eclipse.jgit.lib,
    org.eclipse.jgit.treewalk",
- org.eclipse.jgit.blame;version="6.10.2";
+ org.eclipse.jgit.blame;version="7.0.2";
   uses:="org.eclipse.jgit.lib,
    org.eclipse.jgit.revwalk,
    org.eclipse.jgit.treewalk.filter,
    org.eclipse.jgit.diff",
- org.eclipse.jgit.diff;version="6.10.2";
+ org.eclipse.jgit.diff;version="7.0.2";
   uses:="org.eclipse.jgit.lib,
    org.eclipse.jgit.attributes,
    org.eclipse.jgit.revwalk,
@@ -44,53 +44,53 @@
    org.eclipse.jgit.treewalk.filter,
    org.eclipse.jgit.treewalk,
    org.eclipse.jgit.util",
- org.eclipse.jgit.dircache;version="6.10.2";
+ org.eclipse.jgit.dircache;version="7.0.2";
   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="6.10.2";
+ org.eclipse.jgit.errors;version="7.0.2";
   uses:="org.eclipse.jgit.transport,
    org.eclipse.jgit.dircache,
    org.eclipse.jgit.lib,
    org.eclipse.jgit.internal.storage.pack",
- org.eclipse.jgit.events;version="6.10.2";
+ org.eclipse.jgit.events;version="7.0.2";
   uses:="org.eclipse.jgit.lib",
- org.eclipse.jgit.fnmatch;version="6.10.2",
- org.eclipse.jgit.gitrepo;version="6.10.2";
+ org.eclipse.jgit.fnmatch;version="7.0.2",
+ org.eclipse.jgit.gitrepo;version="7.0.2";
   uses:="org.xml.sax.helpers,
    org.eclipse.jgit.api,
    org.eclipse.jgit.lib,
    org.eclipse.jgit.revwalk,
    org.xml.sax",
- org.eclipse.jgit.gitrepo.internal;version="6.10.2";x-internal:=true,
- org.eclipse.jgit.hooks;version="6.10.2";uses:="org.eclipse.jgit.lib",
- org.eclipse.jgit.ignore;version="6.10.2",
- org.eclipse.jgit.ignore.internal;version="6.10.2";
+ org.eclipse.jgit.gitrepo.internal;version="7.0.2";x-internal:=true,
+ org.eclipse.jgit.hooks;version="7.0.2";uses:="org.eclipse.jgit.lib",
+ org.eclipse.jgit.ignore;version="7.0.2",
+ org.eclipse.jgit.ignore.internal;version="7.0.2";
   x-friends:="org.eclipse.jgit.test",
- org.eclipse.jgit.internal;version="6.10.2";
+ org.eclipse.jgit.internal;version="7.0.2";
   x-friends:="org.eclipse.jgit.test,
    org.eclipse.jgit.http.test",
- org.eclipse.jgit.internal.diff;version="6.10.2";
+ org.eclipse.jgit.internal.diff;version="7.0.2";
   x-friends:="org.eclipse.jgit.test",
- org.eclipse.jgit.internal.diffmergetool;version="6.10.2";
+ org.eclipse.jgit.internal.diffmergetool;version="7.0.2";
   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="6.10.2";
+ org.eclipse.jgit.internal.fsck;version="7.0.2";
   x-friends:="org.eclipse.jgit.test",
- org.eclipse.jgit.internal.revwalk;version="6.10.2";
+ org.eclipse.jgit.internal.revwalk;version="7.0.2";
   x-friends:="org.eclipse.jgit.test",
- org.eclipse.jgit.internal.storage.commitgraph;version="6.10.2";
+ org.eclipse.jgit.internal.storage.commitgraph;version="7.0.2";
   x-friends:="org.eclipse.jgit.test",
- org.eclipse.jgit.internal.storage.dfs;version="6.10.2";
+ org.eclipse.jgit.internal.storage.dfs;version="7.0.2";
   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="6.10.2";
+ org.eclipse.jgit.internal.storage.file;version="7.0.2";
   x-friends:="org.eclipse.jgit.test,
    org.eclipse.jgit.junit,
    org.eclipse.jgit.junit.http,
@@ -102,36 +102,36 @@
    org.eclipse.jgit.ssh.apache,
    org.eclipse.jgit.ssh.apache.test,
    org.eclipse.jgit.ssh.jsch.test",
- org.eclipse.jgit.internal.storage.io;version="6.10.2";
+ org.eclipse.jgit.internal.storage.io;version="7.0.2";
   x-friends:="org.eclipse.jgit.junit,
    org.eclipse.jgit.test,
    org.eclipse.jgit.pgm",
- org.eclipse.jgit.internal.storage.memory;version="6.10.2";
+ org.eclipse.jgit.internal.storage.memory;version="7.0.2";
   x-friends:="org.eclipse.jgit.test",
- org.eclipse.jgit.internal.storage.pack;version="6.10.2";
+ org.eclipse.jgit.internal.storage.pack;version="7.0.2";
   x-friends:="org.eclipse.jgit.junit,
    org.eclipse.jgit.test,
    org.eclipse.jgit.pgm",
- org.eclipse.jgit.internal.storage.reftable;version="6.10.2";
+ org.eclipse.jgit.internal.storage.reftable;version="7.0.2";
   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="6.10.2";x-internal:=true,
- org.eclipse.jgit.internal.transport.connectivity;version="6.10.2";
+ org.eclipse.jgit.internal.submodule;version="7.0.2";x-internal:=true,
+ org.eclipse.jgit.internal.transport.connectivity;version="7.0.2";
   x-friends:="org.eclipse.jgit.test",
- org.eclipse.jgit.internal.transport.http;version="6.10.2";
+ org.eclipse.jgit.internal.transport.http;version="7.0.2";
   x-friends:="org.eclipse.jgit.test",
- org.eclipse.jgit.internal.transport.parser;version="6.10.2";
+ org.eclipse.jgit.internal.transport.parser;version="7.0.2";
   x-friends:="org.eclipse.jgit.http.server,
    org.eclipse.jgit.test",
- org.eclipse.jgit.internal.transport.ssh;version="6.10.2";
+ org.eclipse.jgit.internal.transport.ssh;version="7.0.2";
   x-friends:="org.eclipse.jgit.ssh.apache,
    org.eclipse.jgit.ssh.jsch,
    org.eclipse.jgit.test",
- org.eclipse.jgit.internal.util;version="6.10.2";
+ org.eclipse.jgit.internal.util;version="7.0.2";
   x-friends:=" org.eclipse.jgit.junit",
- org.eclipse.jgit.lib;version="6.10.2";
+ org.eclipse.jgit.lib;version="7.0.2";
   uses:="org.eclipse.jgit.transport,
    org.eclipse.jgit.util.sha1,
    org.eclipse.jgit.dircache,
@@ -145,12 +145,12 @@
    org.eclipse.jgit.util,
    org.eclipse.jgit.submodule,
    org.eclipse.jgit.util.time",
- org.eclipse.jgit.lib.internal;version="6.10.2";
+ org.eclipse.jgit.lib.internal;version="7.0.2";
   x-friends:="org.eclipse.jgit.test,
    org.eclipse.jgit.pgm,
    org.eclipse.egit.ui",
- org.eclipse.jgit.logging;version="6.10.2",
- org.eclipse.jgit.merge;version="6.10.2";
+ org.eclipse.jgit.logging;version="7.0.2",
+ org.eclipse.jgit.merge;version="7.0.2";
   uses:="org.eclipse.jgit.dircache,
    org.eclipse.jgit.lib,
    org.eclipse.jgit.revwalk,
@@ -159,40 +159,40 @@
    org.eclipse.jgit.util,
    org.eclipse.jgit.api,
    org.eclipse.jgit.attributes",
- org.eclipse.jgit.nls;version="6.10.2",
- org.eclipse.jgit.notes;version="6.10.2";
+ org.eclipse.jgit.nls;version="7.0.2",
+ org.eclipse.jgit.notes;version="7.0.2";
   uses:="org.eclipse.jgit.lib,
    org.eclipse.jgit.revwalk,
    org.eclipse.jgit.treewalk,
    org.eclipse.jgit.merge",
- org.eclipse.jgit.patch;version="6.10.2";
+ org.eclipse.jgit.patch;version="7.0.2";
   uses:="org.eclipse.jgit.lib,
    org.eclipse.jgit.diff",
- org.eclipse.jgit.revplot;version="6.10.2";
+ org.eclipse.jgit.revplot;version="7.0.2";
   uses:="org.eclipse.jgit.lib,
    org.eclipse.jgit.revwalk",
- org.eclipse.jgit.revwalk;version="6.10.2";
+ org.eclipse.jgit.revwalk;version="7.0.2";
   uses:="org.eclipse.jgit.lib,
    org.eclipse.jgit.diff,
    org.eclipse.jgit.treewalk.filter,
    org.eclipse.jgit.revwalk.filter,
    org.eclipse.jgit.treewalk",
- org.eclipse.jgit.revwalk.filter;version="6.10.2";
+ org.eclipse.jgit.revwalk.filter;version="7.0.2";
   uses:="org.eclipse.jgit.revwalk,
    org.eclipse.jgit.lib,
    org.eclipse.jgit.util",
- org.eclipse.jgit.storage.file;version="6.10.2";
+ org.eclipse.jgit.storage.file;version="7.0.2";
   uses:="org.eclipse.jgit.lib,
    org.eclipse.jgit.util",
- org.eclipse.jgit.storage.pack;version="6.10.2";
+ org.eclipse.jgit.storage.pack;version="7.0.2";
   uses:="org.eclipse.jgit.lib",
- org.eclipse.jgit.submodule;version="6.10.2";
+ org.eclipse.jgit.submodule;version="7.0.2";
   uses:="org.eclipse.jgit.lib,
    org.eclipse.jgit.diff,
    org.eclipse.jgit.treewalk.filter,
    org.eclipse.jgit.treewalk,
    org.eclipse.jgit.util",
- org.eclipse.jgit.transport;version="6.10.2";
+ org.eclipse.jgit.transport;version="7.0.2";
   uses:="javax.crypto,
    org.eclipse.jgit.util.io,
    org.eclipse.jgit.lib,
@@ -205,21 +205,21 @@
    org.eclipse.jgit.transport.resolver,
    org.eclipse.jgit.storage.pack,
    org.eclipse.jgit.errors",
- org.eclipse.jgit.transport.http;version="6.10.2";
+ org.eclipse.jgit.transport.http;version="7.0.2";
   uses:="javax.net.ssl",
- org.eclipse.jgit.transport.resolver;version="6.10.2";
+ org.eclipse.jgit.transport.resolver;version="7.0.2";
   uses:="org.eclipse.jgit.transport,
    org.eclipse.jgit.lib",
- org.eclipse.jgit.treewalk;version="6.10.2";
+ org.eclipse.jgit.treewalk;version="7.0.2";
   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="6.10.2";
+ org.eclipse.jgit.treewalk.filter;version="7.0.2";
   uses:="org.eclipse.jgit.treewalk",
- org.eclipse.jgit.util;version="6.10.2";
+ org.eclipse.jgit.util;version="7.0.2";
   uses:="org.eclipse.jgit.transport,
    org.eclipse.jgit.hooks,
    org.eclipse.jgit.revwalk,
@@ -232,13 +232,13 @@
    org.eclipse.jgit.treewalk,
    javax.net.ssl,
    org.eclipse.jgit.util.time",
- org.eclipse.jgit.util.io;version="6.10.2";
+ org.eclipse.jgit.util.io;version="7.0.2";
   uses:="org.eclipse.jgit.attributes,
    org.eclipse.jgit.lib,
    org.eclipse.jgit.treewalk",
- org.eclipse.jgit.util.sha1;version="6.10.2",
- org.eclipse.jgit.util.time;version="6.10.2"
-Bundle-RequiredExecutionEnvironment: JavaSE-11
+ org.eclipse.jgit.util.sha1;version="7.0.2",
+ org.eclipse.jgit.util.time;version="7.0.2"
+Bundle-RequiredExecutionEnvironment: JavaSE-17
 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 4d5f3e9..2315007 100644
--- a/org.eclipse.jgit/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit/META-INF/SOURCE-MANIFEST.MF
@@ -3,5 +3,5 @@
 Bundle-Name: org.eclipse.jgit - Sources
 Bundle-SymbolicName: org.eclipse.jgit.source
 Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 6.10.2.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit;version="6.10.2.qualifier";roots="."
+Bundle-Version: 7.0.2.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit;version="7.0.2.qualifier";roots="."
diff --git a/org.eclipse.jgit/pom.xml b/org.eclipse.jgit/pom.xml
index f4e23c8..a18b1fd 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>6.10.2-SNAPSHOT</version>
+    <version>7.0.2-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 c54c811..fd0995a 100644
--- a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
+++ b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
@@ -283,6 +283,9 @@
 downloadCancelled=Download cancelled
 downloadCancelledDuringIndexing=Download cancelled during indexing
 duplicateAdvertisementsOf=duplicate advertisements of {0}
+duplicateCacheTablesGiven=Duplicate cache tables given
+duplicatePackExtensionsForCacheTables=Duplicate pack extension {0} in cache tables
+duplicatePackExtensionsSet=Attempting to configure duplicate pack extensions: {0}.{1}.{2} contains {3}
 duplicateRef=Duplicate ref: {0}
 duplicateRefAttribute=Duplicate ref attribute: {0}
 duplicateRemoteRefUpdateIsIllegal=Duplicate remote ref update is illegal. Affected remote name: {0}
@@ -537,6 +540,8 @@
 noMergeHeadSpecified=No merge head specified
 nonBareLinkFilesNotSupported=Link files are not supported with nonbare repos
 nonCommitToHeads=Cannot point a branch to a non-commit object
+noPackExtConfigurationGiven=No PackExt configuration given
+noPackExtGivenForConfiguration=No PackExt given for configuration
 noPathAttributesFound=No Attributes found for {0}.
 noSuchRef=no such ref
 noSuchRefKnown=no such ref: {0}
@@ -569,7 +574,6 @@
 oldIdMustNotBeNull=Expected old ID must not be null
 onlyOneFetchSupported=Only one fetch supported
 onlyOneOperationCallPerConnectionIsSupported=Only one operation call per connection is supported.
-onlyOpenPgpSupportedForSigning=OpenPGP is the only supported signing option with JGit at this time (gpg.format must be set to openpgp).
 openFilesMustBeAtLeast1=Open files must be >= 1
 openingConnection=Opening connection
 operationCanceled=Operation {0} was canceled
@@ -716,6 +720,8 @@
 shutdownCleanup=Cleanup {} during JVM shutdown
 shutdownCleanupFailed=Cleanup during JVM shutdown failed
 shutdownCleanupListenerFailed=Cleanup of {0} during JVM shutdown failed
+signatureServiceConflict={0} conflict for type {1}. Already registered is {2}; additional factory {3} is ignored.
+signatureTypeUnknown=No signer for {0} signatures. Use another signature type for git config gpg.format, or do not sign.
 signatureVerificationError=Signature verification failed
 signatureVerificationUnavailable=No signature verifier registered
 signedTagMessageNoLf=A non-empty message of a signed tag must end in LF.
@@ -801,6 +807,7 @@
 tSizeMustBeGreaterOrEqual1=tSize must be >= 1
 unableToCheckConnectivity=Unable to check connectivity.
 unableToCreateNewObject=Unable to create new object: {0}
+unableToReadFullArray=Unable to read an array with {0} elements from the stream
 unableToReadFullInt=Unable to read a full int from the stream
 unableToReadPackfile=Unable to read packfile {0}
 unableToRemovePath=Unable to remove path ''{0}''
@@ -827,6 +834,7 @@
 unknownObjectInIndex=unknown object {0} found in index but not in pack file
 unknownObjectType=Unknown object type {0}.
 unknownObjectType2=unknown
+unknownPackExtension=Unknown pack extension: {0}.{1}.{2}={3}
 unknownPositionEncoding=Unknown position encoding %s
 unknownRefStorageFormat=Unknown ref storage format "{0}"
 unknownRepositoryFormat=Unknown repository format
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java
index c133219..32c242f 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java
@@ -644,24 +644,6 @@ public CheckoutCommand setOrphan(boolean orphan) {
 	/**
 	 * Specify to force the ref update in case of a branch switch.
 	 *
-	 * @param force
-	 *            if <code>true</code> and the branch with the given name
-	 *            already exists, the start-point of an existing branch will be
-	 *            set to a new start-point; if false, the existing branch will
-	 *            not be changed
-	 * @return this instance
-	 * @deprecated this method was badly named comparing its semantics to native
-	 *             git's checkout --force option, use
-	 *             {@link #setForceRefUpdate(boolean)} instead
-	 */
-	@Deprecated
-	public CheckoutCommand setForce(boolean force) {
-		return setForceRefUpdate(force);
-	}
-
-	/**
-	 * Specify to force the ref update in case of a branch switch.
-	 *
 	 * In releases prior to 5.2 this method was called setForce() but this name
 	 * was misunderstood to implement native git's --force option, which is not
 	 * true.
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/CommitCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/CommitCommand.java
index a1a2cc0..a7d409c 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/CommitCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/CommitCommand.java
@@ -51,9 +51,6 @@
 import org.eclipse.jgit.lib.Constants;
 import org.eclipse.jgit.lib.FileMode;
 import org.eclipse.jgit.lib.GpgConfig;
-import org.eclipse.jgit.lib.GpgConfig.GpgFormat;
-import org.eclipse.jgit.lib.GpgObjectSigner;
-import org.eclipse.jgit.lib.GpgSigner;
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.ObjectInserter;
 import org.eclipse.jgit.lib.PersonIdent;
@@ -62,6 +59,8 @@
 import org.eclipse.jgit.lib.RefUpdate.Result;
 import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.lib.RepositoryState;
+import org.eclipse.jgit.lib.Signer;
+import org.eclipse.jgit.lib.Signers;
 import org.eclipse.jgit.revwalk.RevCommit;
 import org.eclipse.jgit.revwalk.RevObject;
 import org.eclipse.jgit.revwalk.RevTag;
@@ -129,7 +128,7 @@ public class CommitCommand extends GitCommand<RevCommit> {
 
 	private String signingKey;
 
-	private GpgSigner gpgSigner;
+	private Signer signer;
 
 	private GpgConfig gpgConfig;
 
@@ -319,30 +318,22 @@ private void checkIfEmpty(RevWalk rw, ObjectId headId, ObjectId indexTreeId)
 		}
 	}
 
-	private void sign(CommitBuilder commit) throws ServiceUnavailableException,
-			CanceledException, UnsupportedSigningFormatException {
-		if (gpgSigner == null) {
-			gpgSigner = GpgSigner.getDefault();
-			if (gpgSigner == null) {
-				throw new ServiceUnavailableException(
-						JGitText.get().signingServiceUnavailable);
+	private void sign(CommitBuilder commit)
+			throws CanceledException, IOException,
+			UnsupportedSigningFormatException {
+		if (signer == null) {
+			signer = Signers.get(gpgConfig.getKeyFormat());
+			if (signer == null) {
+				throw new UnsupportedSigningFormatException(MessageFormat
+						.format(JGitText.get().signatureTypeUnknown,
+								gpgConfig.getKeyFormat().toConfigValue()));
 			}
 		}
 		if (signingKey == null) {
 			signingKey = gpgConfig.getSigningKey();
 		}
-		if (gpgSigner instanceof GpgObjectSigner) {
-			((GpgObjectSigner) gpgSigner).signObject(commit,
-					signingKey, committer, credentialsProvider,
-					gpgConfig);
-		} else {
-			if (gpgConfig.getKeyFormat() != GpgFormat.OPENPGP) {
-				throw new UnsupportedSigningFormatException(JGitText
-						.get().onlyOpenPgpSupportedForSigning);
-			}
-			gpgSigner.sign(commit, signingKey, committer,
-					credentialsProvider);
-		}
+		signer.signObject(repo, gpgConfig, commit, committer, signingKey,
+				credentialsProvider);
 	}
 
 	private void updateRef(RepositoryState state, ObjectId headId,
@@ -1097,22 +1088,22 @@ public CommitCommand setSign(Boolean sign) {
 	}
 
 	/**
-	 * Sets the {@link GpgSigner} to use if the commit is to be signed.
+	 * Sets the {@link Signer} to use if the commit is to be signed.
 	 *
 	 * @param signer
 	 *            to use; if {@code null}, the default signer will be used
 	 * @return {@code this}
-	 * @since 5.11
+	 * @since 7.0
 	 */
-	public CommitCommand setGpgSigner(GpgSigner signer) {
+	public CommitCommand setSigner(Signer signer) {
 		checkCallable();
-		this.gpgSigner = signer;
+		this.signer = signer;
 		return this;
 	}
 
 	/**
 	 * Sets an external {@link GpgConfig} to use. Whether it will be used is at
-	 * the discretion of the {@link #setGpgSigner(GpgSigner)}.
+	 * the discretion of the {@link #setSigner(Signer)}.
 	 *
 	 * @param config
 	 *            to set; if {@code null}, the config will be loaded from the
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/RemoteRemoveCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/RemoteRemoveCommand.java
index 553fc2e..ad553f0 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/RemoteRemoveCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/RemoteRemoveCommand.java
@@ -49,18 +49,6 @@ protected RemoteRemoveCommand(Repository repo) {
 	/**
 	 * The name of the remote to remove.
 	 *
-	 * @param name
-	 *            a remote name
-	 * @deprecated use {@link #setRemoteName} instead
-	 */
-	@Deprecated
-	public void setName(String name) {
-		this.remoteName = name;
-	}
-
-	/**
-	 * The name of the remote to remove.
-	 *
 	 * @param remoteName
 	 *            a remote name
 	 * @return {@code this}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/RemoteSetUrlCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/RemoteSetUrlCommand.java
index e3d0186..68ddce3 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/RemoteSetUrlCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/RemoteSetUrlCommand.java
@@ -71,18 +71,6 @@ protected RemoteSetUrlCommand(Repository repo) {
 	/**
 	 * The name of the remote to change the URL for.
 	 *
-	 * @param name
-	 *            a remote name
-	 * @deprecated use {@link #setRemoteName} instead
-	 */
-	@Deprecated
-	public void setName(String name) {
-		this.remoteName = name;
-	}
-
-	/**
-	 * The name of the remote to change the URL for.
-	 *
 	 * @param remoteName
 	 *            a remote remoteName
 	 * @return {@code this}
@@ -96,18 +84,6 @@ public RemoteSetUrlCommand setRemoteName(String remoteName) {
 	/**
 	 * The new URL for the remote.
 	 *
-	 * @param uri
-	 *            an URL for the remote
-	 * @deprecated use {@link #setRemoteUri} instead
-	 */
-	@Deprecated
-	public void setUri(URIish uri) {
-		this.remoteUri = uri;
-	}
-
-	/**
-	 * The new URL for the remote.
-	 *
 	 * @param remoteUri
 	 *            an URL for the remote
 	 * @return {@code this}
@@ -121,23 +97,6 @@ public RemoteSetUrlCommand setRemoteUri(URIish remoteUri) {
 	/**
 	 * Whether to change the push URL of the remote instead of the fetch URL.
 	 *
-	 * @param push
-	 *            <code>true</code> to set the push url, <code>false</code> to
-	 *            set the fetch url
-	 * @deprecated use {@link #setUriType} instead
-	 */
-	@Deprecated
-	public void setPush(boolean push) {
-		if (push) {
-			setUriType(UriType.PUSH);
-		} else {
-			setUriType(UriType.FETCH);
-		}
-	}
-
-	/**
-	 * Whether to change the push URL of the remote instead of the fetch URL.
-	 *
 	 * @param type
 	 *            the <code>UriType</code> value to set
 	 * @return {@code this}
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 e415728..b0b715e 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/StashApplyCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/StashApplyCommand.java
@@ -263,18 +263,6 @@ public ObjectId call() throws GitAPIException,
 	/**
 	 * Whether to restore the index state
 	 *
-	 * @param applyIndex
-	 *            true (default) if the command should restore the index state
-	 * @deprecated use {@link #setRestoreIndex} instead
-	 */
-	@Deprecated
-	public void setApplyIndex(boolean applyIndex) {
-		this.restoreIndex = applyIndex;
-	}
-
-	/**
-	 * Whether to restore the index state
-	 *
 	 * @param restoreIndex
 	 *            true (default) if the command should restore the index state
 	 * @return {@code this}
@@ -319,19 +307,6 @@ public StashApplyCommand setContentMergeStrategy(
 	/**
 	 * Whether the command should restore untracked files
 	 *
-	 * @param applyUntracked
-	 *            true (default) if the command should restore untracked files
-	 * @since 3.4
-	 * @deprecated use {@link #setRestoreUntracked} instead
-	 */
-	@Deprecated
-	public void setApplyUntracked(boolean applyUntracked) {
-		this.restoreUntracked = applyUntracked;
-	}
-
-	/**
-	 * Whether the command should restore untracked files
-	 *
 	 * @param restoreUntracked
 	 *            true (default) if the command should restore untracked files
 	 * @return {@code this}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleAddCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleAddCommand.java
index 8fb5d60..401f069 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleAddCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleAddCommand.java
@@ -176,7 +176,7 @@ public Repository call() throws GitAPIException {
 		CloneCommand clone = Git.cloneRepository();
 		configure(clone);
 		clone.setDirectory(moduleDirectory);
-		clone.setGitDir(new File(new File(repo.getDirectory(),
+		clone.setGitDir(new File(new File(repo.getCommonDirectory(),
 				Constants.MODULES), path));
 		clone.setURI(resolvedUri);
 		if (monitor != null)
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleUpdateCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleUpdateCommand.java
index df73164..751dabc 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleUpdateCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleUpdateCommand.java
@@ -128,7 +128,7 @@ private Repository getOrCloneSubmodule(SubmoduleWalk generator, String url)
 			clone.setURI(url);
 			clone.setDirectory(generator.getDirectory());
 			clone.setGitDir(
-					new File(new File(repo.getDirectory(), Constants.MODULES),
+					new File(new File(repo.getCommonDirectory(), Constants.MODULES),
 							generator.getPath()));
 			if (monitor != null) {
 				clone.setProgressMonitor(monitor);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/TagCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/TagCommand.java
index 3edaf5e..cc8589f 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/TagCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/TagCommand.java
@@ -18,14 +18,11 @@
 import org.eclipse.jgit.api.errors.JGitInternalException;
 import org.eclipse.jgit.api.errors.NoHeadException;
 import org.eclipse.jgit.api.errors.RefAlreadyExistsException;
-import org.eclipse.jgit.api.errors.ServiceUnavailableException;
 import org.eclipse.jgit.api.errors.UnsupportedSigningFormatException;
 import org.eclipse.jgit.internal.JGitText;
 import org.eclipse.jgit.lib.Constants;
 import org.eclipse.jgit.lib.GpgConfig;
 import org.eclipse.jgit.lib.GpgConfig.GpgFormat;
-import org.eclipse.jgit.lib.GpgObjectSigner;
-import org.eclipse.jgit.lib.GpgSigner;
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.ObjectInserter;
 import org.eclipse.jgit.lib.PersonIdent;
@@ -33,6 +30,8 @@
 import org.eclipse.jgit.lib.RefUpdate;
 import org.eclipse.jgit.lib.RefUpdate.Result;
 import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.Signer;
+import org.eclipse.jgit.lib.Signers;
 import org.eclipse.jgit.lib.TagBuilder;
 import org.eclipse.jgit.revwalk.RevObject;
 import org.eclipse.jgit.revwalk.RevWalk;
@@ -79,7 +78,7 @@ public class TagCommand extends GitCommand<Ref> {
 
 	private GpgConfig gpgConfig;
 
-	private GpgObjectSigner gpgSigner;
+	private Signer signer;
 
 	private CredentialsProvider credentialsProvider;
 
@@ -133,9 +132,9 @@ public Ref call() throws GitAPIException, ConcurrentRefUpdateException,
 			newTag.setTagger(tagger);
 			newTag.setObjectId(id);
 
-			if (gpgSigner != null) {
-				gpgSigner.signObject(newTag, signingKey, tagger,
-						credentialsProvider, gpgConfig);
+			if (signer != null) {
+				signer.signObject(repo, gpgConfig, newTag, tagger, signingKey,
+						credentialsProvider);
 			}
 
 			// write the tag object
@@ -196,15 +195,12 @@ private Ref updateTagRef(ObjectId tagId, RevWalk revWalk,
 	 *
 	 * @throws InvalidTagNameException
 	 *             if the tag name is null or invalid
-	 * @throws ServiceUnavailableException
-	 *             if the tag should be signed but no signer can be found
 	 * @throws UnsupportedSigningFormatException
 	 *             if the tag should be signed but {@code gpg.format} is not
 	 *             {@link GpgFormat#OPENPGP}
 	 */
 	private void processOptions()
-			throws InvalidTagNameException, ServiceUnavailableException,
-			UnsupportedSigningFormatException {
+			throws InvalidTagNameException, UnsupportedSigningFormatException {
 		if (name == null
 				|| !Repository.isValidRefName(Constants.R_TAGS + name)) {
 			throw new InvalidTagNameException(
@@ -230,16 +226,15 @@ private void processOptions()
 					doSign = gpgConfig.isSignAnnotated();
 				}
 				if (doSign) {
-					if (signingKey == null) {
-						signingKey = gpgConfig.getSigningKey();
-					}
-					if (gpgSigner == null) {
-						GpgSigner signer = GpgSigner.getDefault();
-						if (!(signer instanceof GpgObjectSigner)) {
-							throw new ServiceUnavailableException(
-									JGitText.get().signingServiceUnavailable);
+					if (signer == null) {
+						signer = Signers.get(gpgConfig.getKeyFormat());
+						if (signer == null) {
+							throw new UnsupportedSigningFormatException(
+									MessageFormat.format(
+											JGitText.get().signatureTypeUnknown,
+											gpgConfig.getKeyFormat()
+													.toConfigValue()));
 						}
-						gpgSigner = (GpgObjectSigner) signer;
 					}
 					// The message of a signed tag must end in a newline because
 					// the signature will be appended.
@@ -326,22 +321,22 @@ public TagCommand setSigned(boolean signed) {
 	}
 
 	/**
-	 * Sets the {@link GpgSigner} to use if the commit is to be signed.
+	 * Sets the {@link Signer} to use if the commit is to be signed.
 	 *
 	 * @param signer
 	 *            to use; if {@code null}, the default signer will be used
 	 * @return {@code this}
-	 * @since 5.11
+	 * @since 7.0
 	 */
-	public TagCommand setGpgSigner(GpgObjectSigner signer) {
+	public TagCommand setSigner(Signer signer) {
 		checkCallable();
-		this.gpgSigner = signer;
+		this.signer = signer;
 		return this;
 	}
 
 	/**
 	 * Sets an external {@link GpgConfig} to use. Whether it will be used is at
-	 * the discretion of the {@link #setGpgSigner(GpgObjectSigner)}.
+	 * the discretion of the {@link #setSigner(Signer)}.
 	 *
 	 * @param config
 	 *            to set; if {@code null}, the config will be loaded from the
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/VerificationResult.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/VerificationResult.java
index 21cddf7..f5f4b06 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/VerificationResult.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/VerificationResult.java
@@ -9,7 +9,7 @@
  */
 package org.eclipse.jgit.api;
 
-import org.eclipse.jgit.lib.GpgSignatureVerifier;
+import org.eclipse.jgit.lib.SignatureVerifier;
 import org.eclipse.jgit.revwalk.RevObject;
 
 /**
@@ -34,8 +34,9 @@ public interface VerificationResult {
 	 * Retrieves the signature verification result.
 	 *
 	 * @return the result, or {@code null} if none was computed
+	 * @since 7.0
 	 */
-	GpgSignatureVerifier.SignatureVerification getVerification();
+	SignatureVerifier.SignatureVerification getVerification();
 
 	/**
 	 * Retrieves the git object of which the signature was verified.
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/VerifySignatureCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/VerifySignatureCommand.java
index 6a2a44e..487ff04 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/VerifySignatureCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/VerifySignatureCommand.java
@@ -25,11 +25,10 @@
 import org.eclipse.jgit.internal.JGitText;
 import org.eclipse.jgit.lib.Constants;
 import org.eclipse.jgit.lib.GpgConfig;
-import org.eclipse.jgit.lib.GpgSignatureVerifier;
-import org.eclipse.jgit.lib.GpgSignatureVerifier.SignatureVerification;
-import org.eclipse.jgit.lib.GpgSignatureVerifierFactory;
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.SignatureVerifier.SignatureVerification;
+import org.eclipse.jgit.lib.SignatureVerifiers;
 import org.eclipse.jgit.revwalk.RevObject;
 import org.eclipse.jgit.revwalk.RevWalk;
 
@@ -65,12 +64,8 @@ public enum VerifyMode {
 
 	private VerifyMode mode = VerifyMode.ANY;
 
-	private GpgSignatureVerifier verifier;
-
 	private GpgConfig config;
 
-	private boolean ownVerifier;
-
 	/**
 	 * Creates a new {@link VerifySignatureCommand} for the given {@link Repository}.
 	 *
@@ -140,22 +135,7 @@ public VerifySignatureCommand setMode(@NonNull VerifyMode mode) {
 	}
 
 	/**
-	 * Sets the {@link GpgSignatureVerifier} to use.
-	 *
-	 * @param verifier
-	 *            the {@link GpgSignatureVerifier} to use, or {@code null} to
-	 *            use the default verifier
-	 * @return {@code this}
-	 */
-	public VerifySignatureCommand setVerifier(GpgSignatureVerifier verifier) {
-		checkCallable();
-		this.verifier = verifier;
-		return this;
-	}
-
-	/**
-	 * Sets an external {@link GpgConfig} to use. Whether it will be used it at
-	 * the discretion of the {@link #setVerifier(GpgSignatureVerifier)}.
+	 * Sets an external {@link GpgConfig} to use.
 	 *
 	 * @param config
 	 *            to set; if {@code null}, the config will be loaded from the
@@ -170,16 +150,6 @@ public VerifySignatureCommand setGpgConfig(GpgConfig config) {
 	}
 
 	/**
-	 * Retrieves the currently set {@link GpgSignatureVerifier}. Can be used
-	 * after a successful {@link #call()} to get the verifier that was used.
-	 *
-	 * @return the {@link GpgSignatureVerifier}
-	 */
-	public GpgSignatureVerifier getVerifier() {
-		return verifier;
-	}
-
-	/**
 	 * {@link Repository#resolve(String) Resolves} all names added to the
 	 * command to git objects and verifies their signature. Non-existing objects
 	 * are ignored.
@@ -193,9 +163,6 @@ public GpgSignatureVerifier getVerifier() {
 	 *
 	 * @return a map of the given names to the corresponding
 	 *         {@link VerificationResult}, excluding ignored or skipped objects.
-	 * @throws ServiceUnavailableException
-	 *             if no {@link GpgSignatureVerifier} was set and no
-	 *             {@link GpgSignatureVerifierFactory} is available
 	 * @throws WrongObjectTypeException
 	 *             if a name resolves to an object of a type not allowed by the
 	 *             {@link #setMode(VerifyMode)} mode
@@ -207,16 +174,6 @@ public Map<String, VerificationResult> call()
 		checkCallable();
 		setCallable(false);
 		Map<String, VerificationResult> result = new HashMap<>();
-		if (verifier == null) {
-			GpgSignatureVerifierFactory factory = GpgSignatureVerifierFactory
-					.getDefault();
-			if (factory == null) {
-				throw new ServiceUnavailableException(
-						JGitText.get().signatureVerificationUnavailable);
-			}
-			verifier = factory.getVerifier();
-			ownVerifier = true;
-		}
 		if (config == null) {
 			config = new GpgConfig(repo.getConfig());
 		}
@@ -239,10 +196,6 @@ public Map<String, VerificationResult> call()
 		} catch (IOException e) {
 			throw new JGitInternalException(
 					JGitText.get().signatureVerificationError, e);
-		} finally {
-			if (ownVerifier) {
-				verifier.clear();
-			}
 		}
 		return result;
 	}
@@ -258,8 +211,8 @@ private VerificationResult verifyOne(RevObject object)
 		}
 		if (type == Constants.OBJ_COMMIT || type == Constants.OBJ_TAG) {
 			try {
-				GpgSignatureVerifier.SignatureVerification verification = verifier
-						.verifySignature(object, config);
+				SignatureVerification verification = SignatureVerifiers
+						.verify(repo, config, object);
 				if (verification == null) {
 					// Not signed
 					return null;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java
index 6ae5153..4f78404 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java
@@ -1401,127 +1401,6 @@ private boolean isModifiedSubtree_IndexTree(String path, ObjectId tree)
 	}
 
 	/**
-	 * Updates the file in the working tree with content and mode from an entry
-	 * in the index. The new content is first written to a new temporary file in
-	 * the same directory as the real file. Then that new file is renamed to the
-	 * final filename.
-	 *
-	 * <p>
-	 * <b>Note:</b> if the entry path on local file system exists as a non-empty
-	 * directory, and the target entry type is a link or file, the checkout will
-	 * fail with {@link java.io.IOException} since existing non-empty directory
-	 * cannot be renamed to file or link without deleting it recursively.
-	 * </p>
-	 *
-	 * @param repo
-	 *            repository managing the destination work tree.
-	 * @param entry
-	 *            the entry containing new mode and content
-	 * @param or
-	 *            object reader to use for checkout
-	 * @throws java.io.IOException
-	 *             if an IO error occurred
-	 * @since 3.6
-	 * @deprecated since 5.1, use
-	 *             {@link #checkoutEntry(Repository, DirCacheEntry, ObjectReader, boolean, CheckoutMetadata, WorkingTreeOptions)}
-	 *             instead
-	 */
-	@Deprecated
-	public static void checkoutEntry(Repository repo, DirCacheEntry entry,
-			ObjectReader or) throws IOException {
-		checkoutEntry(repo, entry, or, false, null, null);
-	}
-
-
-	/**
-	 * Updates the file in the working tree with content and mode from an entry
-	 * in the index. The new content is first written to a new temporary file in
-	 * the same directory as the real file. Then that new file is renamed to the
-	 * final filename.
-	 *
-	 * <p>
-	 * <b>Note:</b> if the entry path on local file system exists as a file, it
-	 * will be deleted and if it exists as a directory, it will be deleted
-	 * recursively, independently if has any content.
-	 * </p>
-	 *
-	 * @param repo
-	 *            repository managing the destination work tree.
-	 * @param entry
-	 *            the entry containing new mode and content
-	 * @param or
-	 *            object reader to use for checkout
-	 * @param deleteRecursive
-	 *            true to recursively delete final path if it exists on the file
-	 *            system
-	 * @param checkoutMetadata
-	 *            containing
-	 *            <ul>
-	 *            <li>smudgeFilterCommand to be run for smudging the entry to be
-	 *            checked out</li>
-	 *            <li>eolStreamType used for stream conversion</li>
-	 *            </ul>
-	 * @throws java.io.IOException
-	 *             if an IO error occurred
-	 * @since 4.2
-	 * @deprecated since 6.3, use
-	 *             {@link #checkoutEntry(Repository, DirCacheEntry, ObjectReader, boolean, CheckoutMetadata, WorkingTreeOptions)}
-	 *             instead
-	 */
-	@Deprecated
-	public static void checkoutEntry(Repository repo, DirCacheEntry entry,
-			ObjectReader or, boolean deleteRecursive,
-			CheckoutMetadata checkoutMetadata) throws IOException {
-		checkoutEntry(repo, entry, or, deleteRecursive, checkoutMetadata, null);
-	}
-
-	/**
-	 * Updates the file in the working tree with content and mode from an entry
-	 * in the index. The new content is first written to a new temporary file in
-	 * the same directory as the real file. Then that new file is renamed to the
-	 * final filename.
-	 *
-	 * <p>
-	 * <b>Note:</b> if the entry path on local file system exists as a file, it
-	 * will be deleted and if it exists as a directory, it will be deleted
-	 * recursively, independently if has any content.
-	 * </p>
-	 *
-	 * @param repo
-	 *            repository managing the destination work tree.
-	 * @param entry
-	 *            the entry containing new mode and content
-	 * @param or
-	 *            object reader to use for checkout
-	 * @param deleteRecursive
-	 *            true to recursively delete final path if it exists on the file
-	 *            system
-	 * @param checkoutMetadata
-	 *            containing
-	 *            <ul>
-	 *            <li>smudgeFilterCommand to be run for smudging the entry to be
-	 *            checked out</li>
-	 *            <li>eolStreamType used for stream conversion</li>
-	 *            </ul>
-	 * @param options
-	 *            {@link WorkingTreeOptions} that are effective; if {@code null}
-	 *            they are loaded from the repository config
-	 * @throws java.io.IOException
-	 *             if an IO error occurred
-	 * @since 6.3
-	 * @deprecated since 6.6.1; use {@link Checkout} instead
-	 */
-	@Deprecated
-	public static void checkoutEntry(Repository repo, DirCacheEntry entry,
-			ObjectReader or, boolean deleteRecursive,
-			CheckoutMetadata checkoutMetadata, WorkingTreeOptions options)
-			throws IOException {
-		Checkout checkout = new Checkout(repo, options)
-				.setRecursiveDeletion(deleteRecursive);
-		checkout.checkout(entry, checkoutMetadata, or, null);
-	}
-
-	/**
 	 * Return filtered content for a specific object (blob). EOL handling and
 	 * smudge-filter handling are applied in the same way as it would be done
 	 * during a checkout.
@@ -1647,6 +1526,8 @@ private static void runExternalFilterCommand(Repository repo, String path,
 		filterProcessBuilder.directory(repo.getWorkTree());
 		filterProcessBuilder.environment().put(Constants.GIT_DIR_KEY,
 				repo.getDirectory().getAbsolutePath());
+		filterProcessBuilder.environment().put(Constants.GIT_COMMON_DIR_KEY,
+				repo.getCommonDirectory().getAbsolutePath());
 		ExecutionResult result;
 		int rc;
 		try {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheEntry.java b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheEntry.java
index c5e1e4e..5a22938 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheEntry.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheEntry.java
@@ -396,28 +396,6 @@ void write(OutputStream os, DirCacheVersion version, DirCacheEntry previous)
 	 * timestamp. This method tests to see if file was written out at the same
 	 * time as the index.
 	 *
-	 * @param smudge_s
-	 *            seconds component of the index's last modified time.
-	 * @param smudge_ns
-	 *            nanoseconds component of the index's last modified time.
-	 * @return true if extra careful checks should be used.
-	 * @deprecated use {@link #mightBeRacilyClean(Instant)} instead
-	 */
-	@Deprecated
-	public final boolean mightBeRacilyClean(int smudge_s, int smudge_ns) {
-		return mightBeRacilyClean(Instant.ofEpochSecond(smudge_s, smudge_ns));
-	}
-
-	/**
-	 * Is it possible for this entry to be accidentally assumed clean?
-	 * <p>
-	 * The "racy git" problem happens when a work file can be updated faster
-	 * than the filesystem records file modification timestamps. It is possible
-	 * for an application to edit a work file, update the index, then edit it
-	 * again before the filesystem will give the work file a new modification
-	 * timestamp. This method tests to see if file was written out at the same
-	 * time as the index.
-	 *
 	 * @param smudge
 	 *            index's last modified time.
 	 * @return true if extra careful checks should be used.
@@ -653,22 +631,6 @@ public void setCreationTime(long when) {
 	}
 
 	/**
-	 * Get the cached last modification date of this file, in milliseconds.
-	 * <p>
-	 * One of the indicators that the file has been modified by an application
-	 * changing the working tree is if the last modification time for the file
-	 * differs from the time stored in this entry.
-	 *
-	 * @return last modification time of this file, in milliseconds since the
-	 *         Java epoch (midnight Jan 1, 1970 UTC).
-	 * @deprecated use {@link #getLastModifiedInstant()} instead
-	 */
-	@Deprecated
-	public long getLastModified() {
-		return decodeTS(P_MTIME);
-	}
-
-	/**
 	 * Get the cached last modification date of this file.
 	 * <p>
 	 * One of the indicators that the file has been modified by an application
@@ -683,18 +645,6 @@ public Instant getLastModifiedInstant() {
 	}
 
 	/**
-	 * Set the cached last modification date of this file, using milliseconds.
-	 *
-	 * @param when
-	 *            new cached modification date of the file, in milliseconds.
-	 * @deprecated use {@link #setLastModified(Instant)} instead
-	 */
-	@Deprecated
-	public void setLastModified(long when) {
-		encodeTS(P_MTIME, when);
-	}
-
-	/**
 	 * Set the cached last modification date of this file.
 	 *
 	 * @param when
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/errors/PackInvalidException.java b/org.eclipse.jgit/src/org/eclipse/jgit/errors/PackInvalidException.java
index 1fd8086..38982fd 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/errors/PackInvalidException.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/errors/PackInvalidException.java
@@ -23,18 +23,6 @@ public class PackInvalidException extends IOException {
 	private static final long serialVersionUID = 1L;
 
 	/**
-	 * Construct a pack invalid error.
-	 *
-	 * @param path
-	 *            path of the invalid pack file.
-	 * @deprecated Use {@link #PackInvalidException(File, Throwable)}.
-	 */
-	@Deprecated
-	public PackInvalidException(File path) {
-		this(path, null);
-	}
-
-	/**
 	 * Construct a pack invalid error with cause.
 	 *
 	 * @param path
@@ -48,18 +36,6 @@ public PackInvalidException(File path, Throwable cause) {
 	}
 
 	/**
-	 * Construct a pack invalid error.
-	 *
-	 * @param path
-	 *            path of the invalid pack file.
-	 * @deprecated Use {@link #PackInvalidException(String, Throwable)}.
-	 */
-	@Deprecated
-	public PackInvalidException(String path) {
-		this(path, null);
-	}
-
-	/**
 	 * Construct a pack invalid error with cause.
 	 *
 	 * @param path
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/BareSuperprojectWriter.java b/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/BareSuperprojectWriter.java
index d191e23..e511a68 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/BareSuperprojectWriter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/BareSuperprojectWriter.java
@@ -157,7 +157,7 @@ private void prepareIndex(List<RepoProject> projects, DirCache index,
 			if (ObjectId.isId(proj.getRevision())) {
 				objectId = ObjectId.fromString(proj.getRevision());
 				if (config.recordRemoteBranch && proj.getUpstream() != null) {
-					cfg.setString("submodule", name, "ref", proj.getUpstream());
+					cfg.setString("submodule", name, "ref", proj.getUpstream()); //$NON-NLS-1$//$NON-NLS-2$
 				}
 			} else {
 				objectId = callback.sha1(url, proj.getRevision());
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoCommand.java
index 9979664..be77fca 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoCommand.java
@@ -111,32 +111,6 @@ public interface RemoteReader {
 		public ObjectId sha1(String uri, String ref) throws GitAPIException;
 
 		/**
-		 * Read a file from a remote repository.
-		 *
-		 * @param uri
-		 *            The URI of the remote repository
-		 * @param ref
-		 *            The ref (branch/tag/etc.) to read
-		 * @param path
-		 *            The relative path (inside the repo) to the file to read
-		 * @return the file content.
-		 * @throws GitAPIException
-		 *             If the ref have an invalid or ambiguous name, or it does
-		 *             not exist in the repository,
-		 * @throws IOException
-		 *             If the object does not exist or is too large
-		 * @since 3.5
-		 *
-		 * @deprecated Use {@link #readFileWithMode(String, String, String)}
-		 *             instead
-		 */
-		@Deprecated
-		public default byte[] readFile(String uri, String ref, String path)
-				throws GitAPIException, IOException {
-			return readFileWithMode(uri, ref, path).getContents();
-		}
-
-		/**
 		 * Read contents and mode (i.e. permissions) of the file from a remote
 		 * repository.
 		 *
@@ -255,7 +229,8 @@ public RemoteFile readFileWithMode(String uri, String ref, String path)
 	@SuppressWarnings("serial")
 	static class ManifestErrorException extends GitAPIException {
 		ManifestErrorException(Throwable cause) {
-			super(RepoText.get().invalidManifest + " " + cause.getMessage(), cause);
+			super(RepoText.get().invalidManifest + " " + cause.getMessage(), //$NON-NLS-1$
+					cause);
 		}
 	}
 
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoProject.java b/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoProject.java
index b7a9ac5..2630da3 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoProject.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoProject.java
@@ -407,7 +407,7 @@ public String getUpstream() {
 	 *
 	 * @return the dest-branch value if present, null otherwise.
 	 *
-	 * @since 7.0
+	 * @since 6.10
 	 */
 	public String getDestBranch() {
 		return this.destBranch;
@@ -419,7 +419,8 @@ public String getDestBranch() {
 	 * Name of the git ref in which a sha1 can be found, when the revision is a
 	 * sha1.
 	 *
-	 * @param upstream value of the attribute in the manifest
+	 * @param upstream
+	 *            value of the attribute in the manifest
 	 *
 	 * @since 6.10
 	 */
@@ -435,7 +436,7 @@ public void setUpstream(String upstream) {
 	 * @param destBranch
 	 *            value of the attribute in the manifest
 	 *
-	 * @since 7.0
+	 * @since 6.10
 	 */
 	public void setDestBranch(String destBranch) {
 		this.destBranch = destBranch;
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 b717550..c309182 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
@@ -313,6 +313,9 @@ public static JGitText get() {
 	/***/ public String downloadCancelled;
 	/***/ public String downloadCancelledDuringIndexing;
 	/***/ public String duplicateAdvertisementsOf;
+	/***/ public String duplicateCacheTablesGiven;
+	/***/ public String duplicatePackExtensionsForCacheTables;
+	/***/ public String duplicatePackExtensionsSet;
 	/***/ public String duplicateRef;
 	/***/ public String duplicateRefAttribute;
 	/***/ public String duplicateRemoteRefUpdateIsIllegal;
@@ -567,6 +570,8 @@ public static JGitText get() {
 	/***/ public String noMergeHeadSpecified;
 	/***/ public String nonBareLinkFilesNotSupported;
 	/***/ public String nonCommitToHeads;
+	/***/ public String noPackExtConfigurationGiven;
+	/***/ public String noPackExtGivenForConfiguration;
 	/***/ public String noPathAttributesFound;
 	/***/ public String noSuchRef;
 	/***/ public String noSuchRefKnown;
@@ -599,7 +604,6 @@ public static JGitText get() {
 	/***/ public String oldIdMustNotBeNull;
 	/***/ public String onlyOneFetchSupported;
 	/***/ public String onlyOneOperationCallPerConnectionIsSupported;
-	/***/ public String onlyOpenPgpSupportedForSigning;
 	/***/ public String openFilesMustBeAtLeast1;
 	/***/ public String openingConnection;
 	/***/ public String operationCanceled;
@@ -745,6 +749,8 @@ public static JGitText get() {
 	/***/ public String shutdownCleanup;
 	/***/ public String shutdownCleanupFailed;
 	/***/ public String shutdownCleanupListenerFailed;
+	/***/ public String signatureServiceConflict;
+	/***/ public String signatureTypeUnknown;
 	/***/ public String signatureVerificationError;
 	/***/ public String signatureVerificationUnavailable;
 	/***/ public String signedTagMessageNoLf;
@@ -831,6 +837,7 @@ public static JGitText get() {
 	/***/ public String unableToCheckConnectivity;
 	/***/ public String unableToCreateNewObject;
 	/***/ public String unableToReadFullInt;
+	/***/ public String unableToReadFullArray;
 	/***/ public String unableToReadPackfile;
 	/***/ public String unableToRemovePath;
 	/***/ public String unableToWrite;
@@ -856,6 +863,7 @@ public static JGitText get() {
 	/***/ public String unknownObjectInIndex;
 	/***/ public String unknownObjectType;
 	/***/ public String unknownObjectType2;
+	/***/ public String unknownPackExtension;
 	/***/ public String unknownPositionEncoding;
 	/***/ public String unknownRefStorageFormat;
 	/***/ public String unknownRepositoryFormat;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/commitgraph/CommitGraphWriter.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/commitgraph/CommitGraphWriter.java
index 84123ad..45ca470 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/commitgraph/CommitGraphWriter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/commitgraph/CommitGraphWriter.java
@@ -52,6 +52,7 @@
 import org.eclipse.jgit.revwalk.RevWalk;
 import org.eclipse.jgit.treewalk.EmptyTreeIterator;
 import org.eclipse.jgit.treewalk.TreeWalk;
+import org.eclipse.jgit.treewalk.filter.TreeFilter;
 import org.eclipse.jgit.util.NB;
 
 /**
@@ -71,6 +72,9 @@ public class CommitGraphWriter {
 
 	private static final int MAX_CHANGED_PATHS = 512;
 
+	private static final PathDiffCalculator PATH_DIFF_CALCULATOR
+			= new PathDiffCalculator();
+
 	private final int hashsz;
 
 	private final GraphCommits graphCommits;
@@ -375,37 +379,6 @@ private void writeCommitData(CancellableDigestOutputStream out)
 		return generations;
 	}
 
-	private static Optional<HashSet<ByteBuffer>> computeBloomFilterPaths(
-			ObjectReader or, RevCommit cmit) throws MissingObjectException,
-			IncorrectObjectTypeException, CorruptObjectException, IOException {
-		HashSet<ByteBuffer> paths = new HashSet<>();
-		try (TreeWalk walk = new TreeWalk(null, or)) {
-			walk.setRecursive(true);
-			if (cmit.getParentCount() == 0) {
-				walk.addTree(new EmptyTreeIterator());
-			} else {
-				walk.addTree(cmit.getParent(0).getTree());
-			}
-			walk.addTree(cmit.getTree());
-			while (walk.next()) {
-				if (walk.idEqual(0, 1)) {
-					continue;
-				}
-				byte[] rawPath = walk.getRawPath();
-				paths.add(ByteBuffer.wrap(rawPath));
-				for (int i = 0; i < rawPath.length; i++) {
-					if (rawPath[i] == '/') {
-						paths.add(ByteBuffer.wrap(rawPath, 0, i));
-					}
-					if (paths.size() > MAX_CHANGED_PATHS) {
-						return Optional.empty();
-					}
-				}
-			}
-		}
-		return Optional.of(paths);
-	}
-
 	private BloomFilterChunks computeBloomFilterChunks(ProgressMonitor monitor)
 			throws MissingObjectException, IncorrectObjectTypeException,
 			CorruptObjectException, IOException {
@@ -436,8 +409,8 @@ private BloomFilterChunks computeBloomFilterChunks(ProgressMonitor monitor)
 					filtersReused++;
 				} else {
 					filtersComputed++;
-					Optional<HashSet<ByteBuffer>> paths = computeBloomFilterPaths(
-							graphCommits.getObjectReader(), cmit);
+					Optional<HashSet<ByteBuffer>> paths = PATH_DIFF_CALCULATOR
+							.changedPaths(graphCommits.getObjectReader(), cmit);
 					if (paths.isEmpty()) {
 						cpf = ChangedPathFilter.FULL;
 					} else {
@@ -474,6 +447,44 @@ private void writeExtraEdges(CancellableDigestOutputStream out)
 		}
 	}
 
+	// Visible for testing
+	static class PathDiffCalculator {
+
+		// Walk steps in the last invocation of changedPaths
+		int stepCounter;
+
+		Optional<HashSet<ByteBuffer>> changedPaths(
+				ObjectReader or, RevCommit cmit) throws MissingObjectException,
+				IncorrectObjectTypeException, CorruptObjectException, IOException {
+			stepCounter = 0;
+			HashSet<ByteBuffer> paths = new HashSet<>();
+			try (TreeWalk walk = new TreeWalk(null, or)) {
+				walk.setRecursive(true);
+				walk.setFilter(TreeFilter.ANY_DIFF);
+				if (cmit.getParentCount() == 0) {
+					walk.addTree(new EmptyTreeIterator());
+				} else {
+					walk.addTree(cmit.getParent(0).getTree());
+				}
+				walk.addTree(cmit.getTree());
+				while (walk.next()) {
+					stepCounter += 1;
+					byte[] rawPath = walk.getRawPath();
+					paths.add(ByteBuffer.wrap(rawPath));
+					for (int i = 0; i < rawPath.length; i++) {
+						if (rawPath[i] == '/') {
+							paths.add(ByteBuffer.wrap(rawPath, 0, i));
+						}
+						if (paths.size() > MAX_CHANGED_PATHS) {
+							return Optional.empty();
+						}
+					}
+				}
+			}
+			return Optional.of(paths);
+		}
+	}
+
 	private static class ChunkHeader {
 		final int id;
 
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/ClockBlockCacheTable.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/ClockBlockCacheTable.java
index d0907bc..ce71a71 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/ClockBlockCacheTable.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/ClockBlockCacheTable.java
@@ -135,7 +135,7 @@ final class ClockBlockCacheTable implements DfsBlockCacheTable {
 	}
 
 	@Override
-	public DfsBlockCacheStats getDfsBlockCacheStats() {
+	public BlockCacheStats getBlockCacheStats() {
 		return dfsBlockCacheStats;
 	}
 
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlockCache.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlockCache.java
index 56719cf..3e1300c 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlockCache.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlockCache.java
@@ -119,7 +119,7 @@ boolean shouldCopyThroughCache(long length) {
 	 * @return total number of bytes in the cache, per pack file extension.
 	 */
 	public long[] getCurrentSize() {
-		return dfsBlockCacheTable.getDfsBlockCacheStats().getCurrentSize();
+		return dfsBlockCacheTable.getBlockCacheStats().getCurrentSize();
 	}
 
 	/**
@@ -138,7 +138,7 @@ public long getFillPercentage() {
 	 *         extension.
 	 */
 	public long[] getHitCount() {
-		return dfsBlockCacheTable.getDfsBlockCacheStats().getHitCount();
+		return dfsBlockCacheTable.getBlockCacheStats().getHitCount();
 	}
 
 	/**
@@ -149,7 +149,7 @@ public long getFillPercentage() {
 	 *         extension.
 	 */
 	public long[] getMissCount() {
-		return dfsBlockCacheTable.getDfsBlockCacheStats().getMissCount();
+		return dfsBlockCacheTable.getBlockCacheStats().getMissCount();
 	}
 
 	/**
@@ -158,7 +158,7 @@ public long getFillPercentage() {
 	 * @return total number of requests (hit + miss), per pack file extension.
 	 */
 	public long[] getTotalRequestCount() {
-		return dfsBlockCacheTable.getDfsBlockCacheStats()
+		return dfsBlockCacheTable.getBlockCacheStats()
 				.getTotalRequestCount();
 	}
 
@@ -168,7 +168,7 @@ public long getFillPercentage() {
 	 * @return hit ratios
 	 */
 	public long[] getHitRatio() {
-		return dfsBlockCacheTable.getDfsBlockCacheStats().getHitRatio();
+		return dfsBlockCacheTable.getBlockCacheStats().getHitRatio();
 	}
 
 	/**
@@ -179,7 +179,7 @@ public long getFillPercentage() {
 	 *         file extension.
 	 */
 	public long[] getEvictions() {
-		return dfsBlockCacheTable.getDfsBlockCacheStats().getEvictions();
+		return dfsBlockCacheTable.getBlockCacheStats().getEvictions();
 	}
 
 	/**
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlockCacheConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlockCacheConfig.java
index 77273ce..fa68b97 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlockCacheConfig.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlockCacheConfig.java
@@ -11,17 +11,25 @@
 package org.eclipse.jgit.internal.storage.dfs;
 
 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_CORE_SECTION;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_DFS_CACHE_PREFIX;
 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_DFS_SECTION;
 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_BLOCK_LIMIT;
 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_BLOCK_SIZE;
 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_CONCURRENCY_LEVEL;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_PACK_EXTENSIONS;
 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_STREAM_RATIO;
 
 import java.text.MessageFormat;
 import java.time.Duration;
+import java.util.ArrayList;
 import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.function.Consumer;
+import java.util.stream.Collectors;
 
 import org.eclipse.jgit.internal.JGitText;
 import org.eclipse.jgit.internal.storage.pack.PackExt;
@@ -42,15 +50,21 @@ public class DfsBlockCacheConfig {
 	public static final int DEFAULT_CACHE_HOT_MAX = 1;
 
 	private long blockLimit;
+
 	private int blockSize;
+
 	private double streamRatio;
+
 	private int concurrencyLevel;
 
 	private Consumer<Long> refLock;
+
 	private Map<PackExt, Integer> cacheHotMap;
 
 	private IndexEventConsumer indexEventConsumer;
 
+	private List<DfsBlockCachePackExtConfig> packExtCacheConfigurations;
+
 	/**
 	 * Create a default configuration.
 	 */
@@ -60,6 +74,7 @@ public DfsBlockCacheConfig() {
 		setStreamRatio(0.30);
 		setConcurrencyLevel(32);
 		cacheHotMap = Collections.emptyMap();
+		packExtCacheConfigurations = Collections.emptyList();
 	}
 
 	/**
@@ -77,10 +92,10 @@ public long getBlockLimit() {
 	 * Set maximum number bytes of heap memory to dedicate to caching pack file
 	 * data.
 	 * <p>
-	 * It is strongly recommended to set the block limit to be an integer multiple
-	 * of the block size. This constraint is not enforced by this method (since
-	 * it may be called before {@link #setBlockSize(int)}), but it is enforced by
-	 * {@link #fromConfig(Config)}.
+	 * It is strongly recommended to set the block limit to be an integer
+	 * multiple of the block size. This constraint is not enforced by this
+	 * method (since it may be called before {@link #setBlockSize(int)}), but it
+	 * is enforced by {@link #fromConfig(Config)}.
 	 *
 	 * @param newLimit
 	 *            maximum number bytes of heap memory to dedicate to caching
@@ -89,9 +104,9 @@ public long getBlockLimit() {
 	 */
 	public DfsBlockCacheConfig setBlockLimit(long newLimit) {
 		if (newLimit <= 0) {
-			throw new IllegalArgumentException(MessageFormat.format(
-					JGitText.get().blockLimitNotPositive,
-					Long.valueOf(newLimit)));
+			throw new IllegalArgumentException(
+					MessageFormat.format(JGitText.get().blockLimitNotPositive,
+							Long.valueOf(newLimit)));
 		}
 		blockLimit = newLimit;
 		return this;
@@ -240,61 +255,115 @@ public DfsBlockCacheConfig setIndexEventConsumer(
 	}
 
 	/**
+	 * Get the list of pack ext cache configs.
+	 *
+	 * @return the list of pack ext cache configs.
+	 */
+	List<DfsBlockCachePackExtConfig> getPackExtCacheConfigurations() {
+		return packExtCacheConfigurations;
+	}
+
+	/**
+	 * Set the list of pack ext cache configs.
+	 *
+	 * Made visible for testing.
+	 *
+	 * @param packExtCacheConfigurations
+	 *            the list of pack ext cache configs to set.
+	 * @return {@code this}
+	 */
+	DfsBlockCacheConfig setPackExtCacheConfigurations(
+			List<DfsBlockCachePackExtConfig> packExtCacheConfigurations) {
+		this.packExtCacheConfigurations = packExtCacheConfigurations;
+		return this;
+	}
+
+	/**
 	 * Update properties by setting fields from the configuration.
 	 * <p>
 	 * If a property is not defined in the configuration, then it is left
 	 * unmodified.
 	 * <p>
-	 * Enforces certain constraints on the combination of settings in the config,
-	 * for example that the block limit is a multiple of the block size.
+	 * Enforces certain constraints on the combination of settings in the
+	 * config, for example that the block limit is a multiple of the block size.
 	 *
 	 * @param rc
 	 *            configuration to read properties from.
 	 * @return {@code this}
 	 */
 	public DfsBlockCacheConfig fromConfig(Config rc) {
-		long cfgBlockLimit = rc.getLong(
-				CONFIG_CORE_SECTION,
-				CONFIG_DFS_SECTION,
-				CONFIG_KEY_BLOCK_LIMIT,
-				getBlockLimit());
-		int cfgBlockSize = rc.getInt(
-				CONFIG_CORE_SECTION,
-				CONFIG_DFS_SECTION,
-				CONFIG_KEY_BLOCK_SIZE,
+		fromConfig(CONFIG_CORE_SECTION, CONFIG_DFS_SECTION, rc);
+		loadPackExtConfigs(rc);
+		return this;
+	}
+
+	private void fromConfig(String section, String subSection, Config rc) {
+		long cfgBlockLimit = rc.getLong(section, subSection,
+				CONFIG_KEY_BLOCK_LIMIT, getBlockLimit());
+		int cfgBlockSize = rc.getInt(section, subSection, CONFIG_KEY_BLOCK_SIZE,
 				getBlockSize());
 		if (cfgBlockLimit % cfgBlockSize != 0) {
 			throw new IllegalArgumentException(MessageFormat.format(
 					JGitText.get().blockLimitNotMultipleOfBlockSize,
-					Long.valueOf(cfgBlockLimit),
-					Long.valueOf(cfgBlockSize)));
+					Long.valueOf(cfgBlockLimit), Long.valueOf(cfgBlockSize)));
 		}
 
 		setBlockLimit(cfgBlockLimit);
 		setBlockSize(cfgBlockSize);
 
-		setConcurrencyLevel(rc.getInt(
-				CONFIG_CORE_SECTION,
-				CONFIG_DFS_SECTION,
-				CONFIG_KEY_CONCURRENCY_LEVEL,
-				getConcurrencyLevel()));
+		setConcurrencyLevel(rc.getInt(section, subSection,
+				CONFIG_KEY_CONCURRENCY_LEVEL, getConcurrencyLevel()));
 
-		String v = rc.getString(
-				CONFIG_CORE_SECTION,
-				CONFIG_DFS_SECTION,
-				CONFIG_KEY_STREAM_RATIO);
+		String v = rc.getString(section, subSection, CONFIG_KEY_STREAM_RATIO);
 		if (v != null) {
 			try {
 				setStreamRatio(Double.parseDouble(v));
 			} catch (NumberFormatException e) {
 				throw new IllegalArgumentException(MessageFormat.format(
-						JGitText.get().enumValueNotSupported3,
-						CONFIG_CORE_SECTION,
-						CONFIG_DFS_SECTION,
-						CONFIG_KEY_STREAM_RATIO, v), e);
+						JGitText.get().enumValueNotSupported3, section,
+						subSection, CONFIG_KEY_STREAM_RATIO, v), e);
 			}
 		}
-		return this;
+	}
+
+	private void loadPackExtConfigs(Config config) {
+		List<String> subSections = config.getSubsections(CONFIG_CORE_SECTION)
+				.stream()
+				.filter(section -> section.startsWith(CONFIG_DFS_CACHE_PREFIX))
+				.collect(Collectors.toList());
+		if (subSections.size() == 0) {
+			return;
+		}
+		ArrayList<DfsBlockCachePackExtConfig> cacheConfigs = new ArrayList<>();
+		Set<PackExt> extensionsSeen = new HashSet<>();
+		for (String subSection : subSections) {
+			var cacheConfig = DfsBlockCachePackExtConfig.fromConfig(config,
+					CONFIG_CORE_SECTION, subSection);
+			Set<PackExt> packExtsDuplicates = intersection(extensionsSeen,
+					cacheConfig.packExts);
+			if (packExtsDuplicates.size() > 0) {
+				String duplicatePackExts = packExtsDuplicates.stream()
+						.map(PackExt::toString)
+						.collect(Collectors.joining(",")); //$NON-NLS-1$
+				throw new IllegalArgumentException(MessageFormat.format(
+						JGitText.get().duplicatePackExtensionsSet,
+						CONFIG_CORE_SECTION, subSection,
+						CONFIG_KEY_PACK_EXTENSIONS, duplicatePackExts));
+			}
+			extensionsSeen.addAll(cacheConfig.packExts);
+			cacheConfigs.add(cacheConfig);
+		}
+		packExtCacheConfigurations = cacheConfigs;
+	}
+
+	private static <T> Set<T> intersection(Set<T> first, Set<T> second) {
+		Set<T> ret = new HashSet<>();
+		for (T entry : second) {
+			if (first.contains(entry)) {
+				ret.add(entry);
+			}
+		}
+		return ret;
 	}
 
 	/** Consumer of DfsBlockCache loading and eviction events for indexes. */
@@ -346,4 +415,88 @@ default boolean shouldReportEvictedEvent() {
 			return false;
 		}
 	}
+
+	/**
+	 * A configuration for a single cache table storing 1 or more Pack
+	 * extensions.
+	 * <p>
+	 * The current pack ext cache tables implementation supports the same
+	 * parameters the ClockBlockCacheTable (current default implementation).
+	 * <p>
+	 * Configuration falls back to the defaults coded values defined in the
+	 * {@link DfsBlockCacheConfig} when not set on each cache table
+	 * configuration and NOT the values of the basic dfs section.
+	 * <p>
+	 * <code>
+	 *
+	 * Format:
+	 * [core "dfs.packCache"]
+	 *   packExtensions = "PACK"
+	 *   blockSize = 512
+	 *   blockLimit = 100
+	 *   concurrencyLevel = 5
+	 *
+	 * [core "dfs.multipleExtensionCache"]
+	 *   packExtensions = "INDEX REFTABLE BITMAP_INDEX"
+	 *   blockSize = 512
+	 *   blockLimit = 100
+	 *   concurrencyLevel = 5
+	 * </code>
+	 */
+	static class DfsBlockCachePackExtConfig {
+		// Set of pack extensions that will map to the cache instance.
+		private final EnumSet<PackExt> packExts;
+
+		// Configuration for the cache instance.
+		private final DfsBlockCacheConfig packExtCacheConfiguration;
+
+		/**
+		 * Made visible for testing.
+		 *
+		 * @param packExts
+		 *            Set of {@link PackExt}s associated to this cache config.
+		 * @param packExtCacheConfiguration
+		 *            {@link DfsBlockCacheConfig} for this cache config.
+		 */
+		DfsBlockCachePackExtConfig(EnumSet<PackExt> packExts,
+				DfsBlockCacheConfig packExtCacheConfiguration) {
+			this.packExts = packExts;
+			this.packExtCacheConfiguration = packExtCacheConfiguration;
+		}
+
+		Set<PackExt> getPackExts() {
+			return packExts;
+		}
+
+		DfsBlockCacheConfig getPackExtCacheConfiguration() {
+			return packExtCacheConfiguration;
+		}
+
+		private static DfsBlockCachePackExtConfig fromConfig(Config config,
+				String section, String subSection) {
+			String packExtensions = config.getString(section, subSection,
+					CONFIG_KEY_PACK_EXTENSIONS);
+			if (packExtensions == null) {
+				throw new IllegalArgumentException(
+						JGitText.get().noPackExtGivenForConfiguration);
+			}
+			String[] extensions = packExtensions.split(" ", -1); //$NON-NLS-1$
+			Set<PackExt> packExts = new HashSet<>(extensions.length);
+			for (String extension : extensions) {
+				try {
+					packExts.add(PackExt.valueOf(extension));
+				} catch (IllegalArgumentException e) {
+					throw new IllegalArgumentException(MessageFormat.format(
+							JGitText.get().unknownPackExtension, section,
+							subSection, CONFIG_KEY_PACK_EXTENSIONS, extension),
+							e);
+				}
+			}
+
+			DfsBlockCacheConfig dfsBlockCacheConfig = new DfsBlockCacheConfig();
+			dfsBlockCacheConfig.fromConfig(section, subSection, config);
+			return new DfsBlockCachePackExtConfig(EnumSet.copyOf(packExts),
+					dfsBlockCacheConfig);
+		}
+	}
 }
\ No newline at end of file
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlockCacheTable.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlockCacheTable.java
index 701d1fd..309f2d1 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlockCacheTable.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlockCacheTable.java
@@ -129,18 +129,72 @@ <T> DfsBlockCache.Ref<T> getOrLoadRef(DfsStreamKey key, long position,
 	<T> T get(DfsStreamKey key, long position);
 
 	/**
-	 * Get the DfsBlockCacheStats object for this block cache table's
+	 * Get the {@link BlockCacheStats} object for this block cache table's
 	 * statistics.
 	 *
-	 * @return the DfsBlockCacheStats tracking this block cache table's
+	 * @return the {@link BlockCacheStats} tracking this block cache table's
 	 *         statistics.
 	 */
-	DfsBlockCacheStats getDfsBlockCacheStats();
+	BlockCacheStats getBlockCacheStats();
+
+	/**
+	 * Provides methods used with Block Cache statistics.
+	 */
+	interface BlockCacheStats {
+		/**
+		 * Get total number of bytes in the cache, per pack file extension.
+		 *
+		 * @return total number of bytes in the cache, per pack file extension.
+		 */
+		long[] getCurrentSize();
+
+		/**
+		 * Get number of requests for items in the cache, per pack file
+		 * extension.
+		 *
+		 * @return the number of requests for items in the cache, per pack file
+		 *         extension.
+		 */
+		long[] getHitCount();
+
+		/**
+		 * Get number of requests for items not in the cache, per pack file
+		 * extension.
+		 *
+		 * @return the number of requests for items not in the cache, per pack
+		 *         file extension.
+		 */
+		long[] getMissCount();
+
+		/**
+		 * Get total number of requests (hit + miss), per pack file extension.
+		 *
+		 * @return total number of requests (hit + miss), per pack file
+		 *         extension.
+		 */
+		long[] getTotalRequestCount();
+
+		/**
+		 * Get hit ratios.
+		 *
+		 * @return hit ratios.
+		 */
+		long[] getHitRatio();
+
+		/**
+		 * Get number of evictions performed due to cache being full, per pack
+		 * file extension.
+		 *
+		 * @return the number of evictions performed due to cache being full,
+		 *         per pack file extension.
+		 */
+		long[] getEvictions();
+	}
 
 	/**
 	 * Keeps track of stats for a Block Cache table.
 	 */
-	class DfsBlockCacheStats {
+	class DfsBlockCacheStats implements BlockCacheStats {
 		/**
 		 * Number of times a block was found in the cache, per pack file
 		 * extension.
@@ -214,44 +268,23 @@ void addToLiveBytes(DfsStreamKey key, long size) {
 			getStat(liveBytes, key).addAndGet(size);
 		}
 
-		/**
-		 * Get total number of bytes in the cache, per pack file extension.
-		 *
-		 * @return total number of bytes in the cache, per pack file extension.
-		 */
-		long[] getCurrentSize() {
+		@Override
+		public long[] getCurrentSize() {
 			return getStatVals(liveBytes);
 		}
 
-		/**
-		 * Get number of requests for items in the cache, per pack file
-		 * extension.
-		 *
-		 * @return the number of requests for items in the cache, per pack file
-		 *         extension.
-		 */
-		long[] getHitCount() {
+		@Override
+		public long[] getHitCount() {
 			return getStatVals(statHit);
 		}
 
-		/**
-		 * Get number of requests for items not in the cache, per pack file
-		 * extension.
-		 *
-		 * @return the number of requests for items not in the cache, per pack
-		 *         file extension.
-		 */
-		long[] getMissCount() {
+		@Override
+		public long[] getMissCount() {
 			return getStatVals(statMiss);
 		}
 
-		/**
-		 * Get total number of requests (hit + miss), per pack file extension.
-		 *
-		 * @return total number of requests (hit + miss), per pack file
-		 *         extension.
-		 */
-		long[] getTotalRequestCount() {
+		@Override
+		public long[] getTotalRequestCount() {
 			AtomicLong[] hit = statHit.get();
 			AtomicLong[] miss = statMiss.get();
 			long[] cnt = new long[Math.max(hit.length, miss.length)];
@@ -264,12 +297,8 @@ void addToLiveBytes(DfsStreamKey key, long size) {
 			return cnt;
 		}
 
-		/**
-		 * Get hit ratios.
-		 *
-		 * @return hit ratios.
-		 */
-		long[] getHitRatio() {
+		@Override
+		public long[] getHitRatio() {
 			AtomicLong[] hit = statHit.get();
 			AtomicLong[] miss = statMiss.get();
 			long[] ratio = new long[Math.max(hit.length, miss.length)];
@@ -288,14 +317,8 @@ void addToLiveBytes(DfsStreamKey key, long size) {
 			return ratio;
 		}
 
-		/**
-		 * Get number of evictions performed due to cache being full, per pack
-		 * file extension.
-		 *
-		 * @return the number of evictions performed due to cache being full,
-		 *         per pack file extension.
-		 */
-		long[] getEvictions() {
+		@Override
+		public long[] getEvictions() {
 			return getStatVals(statEvict);
 		}
 
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 5cc2a57..48ed47a 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
@@ -29,6 +29,7 @@
 import java.text.MessageFormat;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
 import java.util.zip.CRC32;
 import java.util.zip.DataFormatException;
 import java.util.zip.Inflater;
@@ -106,6 +107,53 @@ public final class DfsPackFile extends BlockBasedFile {
 	/** Lock for {@link #corruptObjects}. */
 	private final Object corruptObjectsLock = new Object();
 
+	private final IndexFactory indexFactory;
+
+	/**
+	 * Returns the indexes for this pack.
+	 * <p>
+	 * We define indexes in different sub interfaces to allow implementing the
+	 * indexes over different combinations of backends.
+	 * <p>
+	 * Implementations decide if/how to cache the indexes. The calling
+	 * DfsPackFile will keep the reference to the index as long as it needs it.
+	 */
+	public interface IndexFactory {
+		/**
+		 * Take care of loading the primary and reverse indexes for this pack.
+		 */
+		interface PackIndexes {
+			/**
+			 * Load the primary index for the pack.
+			 *
+			 * @param ctx
+			 *            reader to find the raw bytes
+			 * @return a primary index
+			 * @throws IOException
+			 *             a problem finding/parsing the index
+			 */
+			PackIndex index(DfsReader ctx) throws IOException;
+
+			/**
+			 * Load the reverse index of the pack
+			 *
+			 * @param ctx
+			 *            reader to find the raw bytes
+			 * @return the reverse index of the pack
+			 * @throws IOException
+			 *             a problem finding/parsing the reverse index
+			 */
+			PackReverseIndex reverseIndex(DfsReader ctx) throws IOException;
+		}
+
+		/**
+		 * Returns a provider of the primary and reverse indexes of this pack
+		 *
+		 * @return an implementation of the {@link PackIndexes} interface
+		 */
+		PackIndexes getPackIndexes();
+	}
+
 	/**
 	 * Construct a reader for an existing, packfile.
 	 *
@@ -115,7 +163,8 @@ public final class DfsPackFile extends BlockBasedFile {
 	 *            description of the pack within the DFS.
 	 */
 	DfsPackFile(DfsBlockCache cache, DfsPackDescription desc) {
-		this(cache, desc, DEFAULT_BITMAP_LOADER);
+		this(cache, desc, DEFAULT_BITMAP_LOADER,
+				new CachedStreamIndexFactory(cache, desc));
 	}
 
 	/**
@@ -127,9 +176,11 @@ public final class DfsPackFile extends BlockBasedFile {
 	 *            description of the pack within the DFS
 	 * @param bitmapLoader
 	 *            loader to get the bitmaps of this pack (if any)
+	 * @param indexFactory
+	 *            an IndexFactory to get references to the indexes of this pack
 	 */
 	public DfsPackFile(DfsBlockCache cache, DfsPackDescription desc,
-			PackBitmapIndexLoader bitmapLoader) {
+			PackBitmapIndexLoader bitmapLoader, IndexFactory indexFactory) {
 		super(cache, desc, PACK);
 
 		int bs = desc.getBlockSize(PACK);
@@ -141,6 +192,7 @@ public DfsPackFile(DfsBlockCache cache, DfsPackDescription desc,
 		length = sz > 0 ? sz : -1;
 
 		this.bitmapLoader = bitmapLoader;
+		this.indexFactory = indexFactory;
 	}
 
 	/**
@@ -195,19 +247,10 @@ private PackIndex idx(DfsReader ctx) throws IOException {
 		Repository.getGlobalListenerList()
 				.dispatch(new BeforeDfsPackIndexLoadedEvent(this));
 		try {
-			DfsStreamKey idxKey = desc.getStreamKey(INDEX);
-			AtomicBoolean cacheHit = new AtomicBoolean(true);
-			DfsBlockCache.Ref<PackIndex> idxref = cache.getOrLoadRef(idxKey,
-					REF_POSITION, () -> {
-						cacheHit.set(false);
-						return loadPackIndex(ctx, idxKey);
-					});
-			if (cacheHit.get()) {
-				ctx.stats.idxCacheHit++;
-			}
-			PackIndex idx = idxref.get();
-			if (index == null && idx != null) {
-				index = idx;
+			index = indexFactory.getPackIndexes().index(ctx);
+			if (index == null) {
+				throw new IOException(
+						"Couldn't get a reference to the primary index"); //$NON-NLS-1$
 			}
 			ctx.emitIndexLoad(desc, INDEX, index);
 			return index;
@@ -321,20 +364,10 @@ public PackReverseIndex getReverseIdx(DfsReader ctx) throws IOException {
 			return reverseIndex;
 		}
 
-		PackIndex idx = idx(ctx);
-		DfsStreamKey revKey = desc.getStreamKey(REVERSE_INDEX);
-		AtomicBoolean cacheHit = new AtomicBoolean(true);
-		DfsBlockCache.Ref<PackReverseIndex> revref = cache.getOrLoadRef(revKey,
-				REF_POSITION, () -> {
-					cacheHit.set(false);
-					return loadReverseIdx(ctx, revKey, idx);
-				});
-		if (cacheHit.get()) {
-			ctx.stats.ridxCacheHit++;
-		}
-		PackReverseIndex revidx = revref.get();
-		if (reverseIndex == null && revidx != null) {
-			reverseIndex = revidx;
+		reverseIndex = indexFactory.getPackIndexes().reverseIndex(ctx);
+		if (reverseIndex == null) {
+			throw new IOException(
+					"Couldn't get a reference to the reverse index"); //$NON-NLS-1$
 		}
 		ctx.emitIndexLoad(desc, REVERSE_INDEX, reverseIndex);
 		return reverseIndex;
@@ -347,6 +380,7 @@ private PackObjectSizeIndex getObjectSizeIndex(DfsReader ctx)
 		}
 
 		if (objectSizeIndexLoadAttempted
+				|| !ctx.getOptions().shouldUseObjectSizeIndex()
 				|| !desc.hasFileExt(OBJECT_SIZE_INDEX)) {
 			// Pack doesn't have object size index
 			return null;
@@ -1210,48 +1244,6 @@ private void setCorrupt(long offset) {
 		}
 	}
 
-	private DfsBlockCache.Ref<PackIndex> loadPackIndex(
-			DfsReader ctx, DfsStreamKey idxKey) throws IOException {
-		try {
-			ctx.stats.readIdx++;
-			long start = System.nanoTime();
-			try (ReadableChannel rc = ctx.db.openFile(desc, INDEX)) {
-				PackIndex idx = PackIndex.read(alignTo8kBlocks(rc));
-				ctx.stats.readIdxBytes += rc.position();
-				index = idx;
-				return new DfsBlockCache.Ref<>(
-						idxKey,
-						REF_POSITION,
-						idx.getObjectCount() * REC_SIZE,
-						idx);
-			} finally {
-				ctx.stats.readIdxMicros += elapsedMicros(start);
-			}
-		} catch (EOFException e) {
-			throw new IOException(MessageFormat.format(
-					DfsText.get().shortReadOfIndex,
-					desc.getFileName(INDEX)), e);
-		} catch (IOException e) {
-			throw new IOException(MessageFormat.format(
-					DfsText.get().cannotReadIndex,
-					desc.getFileName(INDEX)), e);
-		}
-	}
-
-	private DfsBlockCache.Ref<PackReverseIndex> loadReverseIdx(
-			DfsReader ctx, DfsStreamKey revKey, PackIndex idx) {
-		ctx.stats.readReverseIdx++;
-		long start = System.nanoTime();
-		PackReverseIndex revidx = PackReverseIndexFactory.computeFromIndex(idx);
-		reverseIndex = revidx;
-		ctx.stats.readReverseIdxMicros += elapsedMicros(start);
-		return new DfsBlockCache.Ref<>(
-				revKey,
-				REF_POSITION,
-				idx.getObjectCount() * 8,
-				revidx);
-	}
-
 	private DfsBlockCache.Ref<PackObjectSizeIndex> loadObjectSizeIndex(
 			DfsReader ctx, DfsStreamKey objectSizeIndexKey) throws IOException {
 		ctx.stats.readObjectSizeIndex++;
@@ -1288,9 +1280,12 @@ private DfsBlockCache.Ref<PackObjectSizeIndex> loadObjectSizeIndex(
 	private DfsBlockCache.Ref<PackBitmapIndex> loadBitmapIndex(DfsReader ctx,
 			DfsStreamKey bitmapKey) throws IOException {
 		ctx.stats.readBitmap++;
+		long start = System.nanoTime();
 		PackBitmapIndexLoader.LoadResult result = bitmapLoader
 				.loadPackBitmapIndex(ctx, this);
 		bitmapIndex = result.bitmapIndex;
+		ctx.stats.readBitmapIdxBytes += result.bytesRead;
+		ctx.stats.readBitmapIdxMicros += elapsedMicros(start);
 		return new DfsBlockCache.Ref<>(bitmapKey, REF_POSITION,
 				result.bytesRead, result.bitmapIndex);
 	}
@@ -1449,4 +1444,141 @@ public LoadResult loadPackBitmapIndex(DfsReader ctx, DfsPackFile pack)
 			}
 		}
 	}
+
+	/**
+	 * An index factory backed by Dfs streams and references cached in
+	 * DfsBlockCache
+	 */
+	public static final class CachedStreamIndexFactory implements IndexFactory {
+		private final CachedStreamPackIndexes indexes;
+
+		/**
+		 * An index factory
+		 *
+		 * @param cache
+		 *            DFS block cache to use for the references
+		 * @param desc
+		 *            This factory loads indexes for this package
+		 */
+		public CachedStreamIndexFactory(DfsBlockCache cache,
+				DfsPackDescription desc) {
+			this.indexes = new CachedStreamPackIndexes(cache, desc);
+		}
+
+		@Override
+		public PackIndexes getPackIndexes() {
+			return indexes;
+		}
+	}
+
+	/**
+	 * Load primary and reverse index from Dfs streams and cache the references
+	 * in DfsBlockCache.
+	 */
+	public static final class CachedStreamPackIndexes implements IndexFactory.PackIndexes {
+		private final DfsBlockCache cache;
+
+		private final DfsPackDescription desc;
+
+		/**
+		 * An index factory
+		 *
+		 * @param cache
+		 *            DFS block cache to use for the references
+		 * @param desc This factory loads indexes for this package
+		 */
+		public CachedStreamPackIndexes(DfsBlockCache cache,
+									   DfsPackDescription desc) {
+			this.cache = cache;
+			this.desc = desc;
+		}
+
+		@Override
+		public PackIndex index(DfsReader ctx) throws IOException {
+			DfsStreamKey idxKey = desc.getStreamKey(INDEX);
+			// Keep the value parsed in the loader, in case the Ref<> is
+			// nullified in ClockBlockCacheTable#reserveSpace
+			// before we read its value.
+			AtomicReference<PackIndex> loadedRef = new AtomicReference<>(null);
+			DfsBlockCache.Ref<PackIndex> cachedRef = cache.getOrLoadRef(idxKey,
+					REF_POSITION, () -> {
+						RefWithSize<PackIndex> idx = loadPackIndex(ctx, desc);
+						loadedRef.set(idx.ref);
+						return new DfsBlockCache.Ref<>(idxKey, REF_POSITION,
+								idx.size, idx.ref);
+					});
+			if (loadedRef.get() == null) {
+				ctx.stats.idxCacheHit++;
+			}
+			return cachedRef.get() != null ? cachedRef.get() : loadedRef.get();
+		}
+
+		private static RefWithSize<PackIndex> loadPackIndex(DfsReader ctx,
+				DfsPackDescription desc) throws IOException {
+			try {
+				ctx.stats.readIdx++;
+				long start = System.nanoTime();
+				try (ReadableChannel rc = ctx.db.openFile(desc, INDEX)) {
+					PackIndex idx = PackIndex.read(alignTo8kBlocks(rc));
+					ctx.stats.readIdxBytes += rc.position();
+					return new RefWithSize<>(idx,
+							idx.getObjectCount() * REC_SIZE);
+				} finally {
+					ctx.stats.readIdxMicros += elapsedMicros(start);
+				}
+			} catch (EOFException e) {
+				throw new IOException(
+						MessageFormat.format(DfsText.get().shortReadOfIndex,
+								desc.getFileName(INDEX)),
+						e);
+			} catch (IOException e) {
+				throw new IOException(
+						MessageFormat.format(DfsText.get().cannotReadIndex,
+								desc.getFileName(INDEX)),
+						e);
+			}
+		}
+
+		@Override
+		public PackReverseIndex reverseIndex(DfsReader ctx) throws IOException {
+			PackIndex idx = index(ctx);
+			DfsStreamKey revKey = desc.getStreamKey(REVERSE_INDEX);
+			// Keep the value parsed in the loader, in case the Ref<> is
+			// nullified in ClockBlockCacheTable#reserveSpace
+			// before we read its value.
+			AtomicReference<PackReverseIndex> loadedRef = new AtomicReference<>(
+					null);
+			DfsBlockCache.Ref<PackReverseIndex> cachedRef = cache
+					.getOrLoadRef(revKey, REF_POSITION, () -> {
+						RefWithSize<PackReverseIndex> ridx = loadReverseIdx(ctx,
+								idx);
+						loadedRef.set(ridx.ref);
+						return new DfsBlockCache.Ref<>(revKey, REF_POSITION,
+								ridx.size, ridx.ref);
+					});
+			if (loadedRef.get() == null) {
+				ctx.stats.ridxCacheHit++;
+			}
+			return cachedRef.get() != null ? cachedRef.get() : loadedRef.get();
+		}
+
+		private static RefWithSize<PackReverseIndex> loadReverseIdx(
+				DfsReader ctx, PackIndex idx) {
+			ctx.stats.readReverseIdx++;
+			long start = System.nanoTime();
+			PackReverseIndex revidx = PackReverseIndexFactory
+					.computeFromIndex(idx);
+			ctx.stats.readReverseIdxMicros += elapsedMicros(start);
+			return new RefWithSize<>(revidx, idx.getObjectCount() * 8);
+		}
+	}
+
+	private static final class RefWithSize<V> {
+		final V ref;
+		final long size;
+		RefWithSize(V ref, long size) {
+			this.ref = ref;
+			this.size = size;
+		}
+	}
 }
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReaderIoStats.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReaderIoStats.java
index adb4673..fcfa3e0 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReaderIoStats.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReaderIoStats.java
@@ -40,12 +40,12 @@ public static class Accumulator {
 		/** Total number of complete pack indexes read into memory. */
 		long readIdx;
 
-		/** Total number of complete bitmap indexes read into memory. */
-		long readBitmap;
-
 		/** Total number of reverse indexes added into memory. */
 		long readReverseIdx;
 
+		/** Total number of complete bitmap indexes read into memory. */
+		long readBitmap;
+
 		/** Total number of complete commit graphs read into memory. */
 		long readCommitGraph;
 
@@ -55,6 +55,9 @@ public static class Accumulator {
 		/** Total number of bytes read from pack indexes. */
 		long readIdxBytes;
 
+		/** Total number of bytes read from bitmap indexes. */
+		long readBitmapIdxBytes;
+
 		/** Total number of bytes read from commit graphs. */
 		long readCommitGraphBytes;
 
@@ -67,18 +70,15 @@ public static class Accumulator {
 		/** Total microseconds spent creating reverse indexes. */
 		long readReverseIdxMicros;
 
+		/** Total microseconds spent reading bitmap indexes. */
+		long readBitmapIdxMicros;
+
 		/** Total microseconds spent creating commit graphs. */
 		long readCommitGraphMicros;
 
 		/** Total microseconds spent creating object size indexes */
 		long readObjectSizeIndexMicros;
 
-		/** Total number of bytes read from bitmap indexes. */
-		long readBitmapIdxBytes;
-
-		/** Total microseconds spent reading bitmap indexes. */
-		long readBitmapIdxMicros;
-
 		/** Total number of block cache hits. */
 		long blockCacheHit;
 
@@ -195,15 +195,6 @@ public long getReadReverseIndexCount() {
 	}
 
 	/**
-	 * Get total number of times the commit graph read into memory.
-	 *
-	 * @return total number of commit graph read into memory.
-	 */
-	public long getReadCommitGraphCount() {
-		return stats.readCommitGraph;
-	}
-
-	/**
 	 * Get total number of complete bitmap indexes read into memory.
 	 *
 	 * @return total number of complete bitmap indexes read into memory.
@@ -213,6 +204,15 @@ public long getReadBitmapIndexCount() {
 	}
 
 	/**
+	 * Get total number of times the commit graph read into memory.
+	 *
+	 * @return total number of commit graph read into memory.
+	 */
+	public long getReadCommitGraphCount() {
+		return stats.readCommitGraph;
+	}
+
+	/**
 	 * Get total number of complete object size indexes read into memory.
 	 *
 	 * @return total number of complete object size indexes read into memory.
@@ -231,6 +231,15 @@ public long getReadIndexBytes() {
 	}
 
 	/**
+	 * Get total number of bytes read from bitmap indexes.
+	 *
+	 * @return total number of bytes read from bitmap indexes.
+	 */
+	public long getReadBitmapIndexBytes() {
+		return stats.readBitmapIdxBytes;
+	}
+
+	/**
 	 * Get total number of bytes read from commit graphs.
 	 *
 	 * @return total number of bytes read from commit graphs.
@@ -240,6 +249,15 @@ public long getCommitGraphBytes() {
 	}
 
 	/**
+	 * Get total number of bytes read from object size indexes.
+	 *
+	 * @return total number of bytes read from object size indexes.
+	 */
+	public long getObjectSizeIndexBytes() {
+		return stats.readObjectSizeIndexBytes;
+	}
+
+	/**
 	 * Get total microseconds spent reading pack indexes.
 	 *
 	 * @return total microseconds spent reading pack indexes.
@@ -258,6 +276,15 @@ public long getReadReverseIndexMicros() {
 	}
 
 	/**
+	 * Get total microseconds spent reading bitmap indexes.
+	 *
+	 * @return total microseconds spent reading bitmap indexes.
+	 */
+	public long getReadBitmapIndexMicros() {
+		return stats.readBitmapIdxMicros;
+	}
+
+	/**
 	 * Get total microseconds spent reading commit graphs.
 	 *
 	 * @return total microseconds spent reading commit graphs.
@@ -267,21 +294,12 @@ public long getReadCommitGraphMicros() {
 	}
 
 	/**
-	 * Get total number of bytes read from bitmap indexes.
+	 * Get total microseconds spent reading object size indexes.
 	 *
-	 * @return total number of bytes read from bitmap indexes.
+	 * @return total microseconds spent reading object size indexes.
 	 */
-	public long getReadBitmapIndexBytes() {
-		return stats.readBitmapIdxBytes;
-	}
-
-	/**
-	 * Get total microseconds spent reading bitmap indexes.
-	 *
-	 * @return total microseconds spent reading bitmap indexes.
-	 */
-	public long getReadBitmapIndexMicros() {
-		return stats.readBitmapIdxMicros;
+	public long getReadObjectSizeIndexMicros() {
+		return stats.readObjectSizeIndexMicros;
 	}
 
 	/**
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 f2ac461..5f5e819 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
@@ -15,6 +15,7 @@
 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_DELTA_BASE_CACHE_LIMIT;
 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_STREAM_BUFFER;
 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_STREAM_FILE_THRESHOLD;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_USE_OBJECT_SIZE_INDEX;
 
 import org.eclipse.jgit.lib.Config;
 import org.eclipse.jgit.storage.pack.PackConfig;
@@ -36,6 +37,8 @@ public class DfsReaderOptions {
 
 	private boolean loadRevIndexInParallel;
 
+	private boolean useObjectSizeIndex;
+
 	/**
 	 * Create a default reader configuration.
 	 */
@@ -137,6 +140,28 @@ public DfsReaderOptions setLoadRevIndexInParallel(
 	}
 
 	/**
+	 * Use the object size index if available.
+	 *
+	 * @return true if the reader should try to use the object size index. if
+	 *         false, the reader ignores that index.
+	 */
+	public boolean shouldUseObjectSizeIndex() {
+		return useObjectSizeIndex;
+	}
+
+	/**
+	 * Set if the reader should try to use the object size index
+	 *
+	 * @param useObjectSizeIndex true to use it, false to ignore the object size index
+	 *
+	 * @return {@code this}
+	 */
+	public DfsReaderOptions setUseObjectSizeIndex(boolean useObjectSizeIndex) {
+		this.useObjectSizeIndex = useObjectSizeIndex;
+		return this;
+	}
+
+	/**
 	 * Update properties by setting fields from the configuration.
 	 * <p>
 	 * If a property is not defined in the configuration, then it is left
@@ -168,6 +193,10 @@ public DfsReaderOptions fromConfig(Config rc) {
 				CONFIG_DFS_SECTION,
 				CONFIG_KEY_STREAM_BUFFER,
 				getStreamPackBufferSize()));
+
+		setUseObjectSizeIndex(rc.getBoolean(CONFIG_CORE_SECTION,
+				CONFIG_DFS_SECTION, CONFIG_KEY_USE_OBJECT_SIZE_INDEX,
+				false));
 		return this;
 	}
 }
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/PackExtBlockCacheTable.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/PackExtBlockCacheTable.java
new file mode 100644
index 0000000..858f731
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/PackExtBlockCacheTable.java
@@ -0,0 +1,289 @@
+/*
+ * Copyright (c) 2024, Google LLC and others
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * http://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.text.MessageFormat;
+import java.util.HashMap;
+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.internal.JGitText;
+import org.eclipse.jgit.internal.storage.dfs.DfsBlockCache.ReadableChannelSupplier;
+import org.eclipse.jgit.internal.storage.dfs.DfsBlockCache.Ref;
+import org.eclipse.jgit.internal.storage.dfs.DfsBlockCache.RefLoader;
+import org.eclipse.jgit.internal.storage.dfs.DfsBlockCacheConfig.DfsBlockCachePackExtConfig;
+import org.eclipse.jgit.internal.storage.pack.PackExt;
+
+/**
+ * A table that holds multiple cache tables accessed by {@link PackExt} types.
+ *
+ * <p>
+ * Allows the separation of entries from different {@link PackExt} types to
+ * limit churn in cache caused by entries of differing sizes.
+ * <p>
+ * Separating these tables enables the fine-tuning of cache tables per extension
+ * type.
+ */
+class PackExtBlockCacheTable implements DfsBlockCacheTable {
+	private final DfsBlockCacheTable defaultBlockCacheTable;
+
+	// Holds the unique tables backing the extBlockCacheTables values.
+	private final List<DfsBlockCacheTable> blockCacheTableList;
+
+	// Holds the mapping of PackExt to DfsBlockCacheTables.
+	// The relation between the size of extBlockCacheTables entries and
+	// blockCacheTableList entries is:
+	// blockCacheTableList.size() <= extBlockCacheTables.size()
+	private final Map<PackExt, DfsBlockCacheTable> extBlockCacheTables;
+
+	/**
+	 * Builds the PackExtBlockCacheTable from a list of
+	 * {@link DfsBlockCachePackExtConfig}s.
+	 *
+	 * @param cacheConfig
+	 *            {@link DfsBlockCacheConfig} containing
+	 *            {@link DfsBlockCachePackExtConfig}s used to configure
+	 *            PackExtBlockCacheTable. The {@link DfsBlockCacheConfig} holds
+	 *            the configuration for the default cache table.
+	 * @return the cache table built from the given configs.
+	 * @throws IllegalArgumentException
+	 *             when no {@link DfsBlockCachePackExtConfig} exists in the
+	 *             {@link DfsBlockCacheConfig}.
+	 */
+	static PackExtBlockCacheTable fromBlockCacheConfigs(
+			DfsBlockCacheConfig cacheConfig) {
+		DfsBlockCacheTable defaultTable = new ClockBlockCacheTable(cacheConfig);
+		Map<PackExt, DfsBlockCacheTable> packExtBlockCacheTables = new HashMap<>();
+		List<DfsBlockCachePackExtConfig> packExtConfigs = cacheConfig
+				.getPackExtCacheConfigurations();
+		if (packExtConfigs == null || packExtConfigs.size() == 0) {
+			throw new IllegalArgumentException(
+					JGitText.get().noPackExtConfigurationGiven);
+		}
+		for (DfsBlockCachePackExtConfig packExtCacheConfig : packExtConfigs) {
+			DfsBlockCacheTable table = new ClockBlockCacheTable(
+					packExtCacheConfig.getPackExtCacheConfiguration());
+			for (PackExt packExt : packExtCacheConfig.getPackExts()) {
+				if (packExtBlockCacheTables.containsKey(packExt)) {
+					throw new IllegalArgumentException(MessageFormat.format(
+							JGitText.get().duplicatePackExtensionsForCacheTables,
+							packExt));
+				}
+				packExtBlockCacheTables.put(packExt, table);
+			}
+		}
+		return fromCacheTables(defaultTable, packExtBlockCacheTables);
+	}
+
+	/**
+	 * Creates a new PackExtBlockCacheTable from the combination of a default
+	 * {@link DfsBlockCacheTable} and a map of {@link PackExt}s to
+	 * {@link DfsBlockCacheTable}s.
+	 * <p>
+	 * This method allows for the PackExtBlockCacheTable to handle a mapping of
+	 * {@link PackExt}s to arbitrarily defined {@link DfsBlockCacheTable}
+	 * implementations. This is especially useful for users wishing to implement
+	 * custom cache tables.
+	 * <p>
+	 * This is currently made visible for testing.
+	 *
+	 * @param defaultBlockCacheTable
+	 *            the default table used when a handling a {@link PackExt} type
+	 *            that does not map to a {@link DfsBlockCacheTable} mapped by
+	 *            packExtsCacheTablePairs.
+	 * @param packExtBlockCacheTables
+	 *            the mapping of {@link PackExt}s to
+	 *            {@link DfsBlockCacheTable}s. A single
+	 *            {@link DfsBlockCacheTable} can be defined for multiple
+	 *            {@link PackExt}s in a many-to-one relationship.
+	 * @return the PackExtBlockCacheTable created from the
+	 *         defaultBlockCacheTable and packExtsCacheTablePairs mapping.
+	 * @throws IllegalArgumentException
+	 *             when a {@link PackExt} is defined for multiple
+	 *             {@link DfsBlockCacheTable}s.
+	 */
+	static PackExtBlockCacheTable fromCacheTables(
+			DfsBlockCacheTable defaultBlockCacheTable,
+			Map<PackExt, DfsBlockCacheTable> packExtBlockCacheTables) {
+		Set<DfsBlockCacheTable> blockCacheTables = new HashSet<>();
+		blockCacheTables.add(defaultBlockCacheTable);
+		blockCacheTables.addAll(packExtBlockCacheTables.values());
+		return new PackExtBlockCacheTable(defaultBlockCacheTable,
+				List.copyOf(blockCacheTables), packExtBlockCacheTables);
+	}
+
+	private PackExtBlockCacheTable(DfsBlockCacheTable defaultBlockCacheTable,
+			List<DfsBlockCacheTable> blockCacheTableList,
+			Map<PackExt, DfsBlockCacheTable> extBlockCacheTables) {
+		this.defaultBlockCacheTable = defaultBlockCacheTable;
+		this.blockCacheTableList = blockCacheTableList;
+		this.extBlockCacheTables = extBlockCacheTables;
+	}
+
+	@Override
+	public boolean hasBlock0(DfsStreamKey key) {
+		return getTable(key).hasBlock0(key);
+	}
+
+	@Override
+	public DfsBlock getOrLoad(BlockBasedFile file, long position,
+			DfsReader dfsReader, ReadableChannelSupplier fileChannel)
+			throws IOException {
+		return getTable(file.ext).getOrLoad(file, position, dfsReader,
+				fileChannel);
+	}
+
+	@Override
+	public <T> Ref<T> getOrLoadRef(DfsStreamKey key, long position,
+			RefLoader<T> loader) throws IOException {
+		return getTable(key).getOrLoadRef(key, position, loader);
+	}
+
+	@Override
+	public void put(DfsBlock v) {
+		getTable(v.stream).put(v);
+	}
+
+	@Override
+	public <T> Ref<T> put(DfsStreamKey key, long pos, long size, T v) {
+		return getTable(key).put(key, pos, size, v);
+	}
+
+	@Override
+	public <T> Ref<T> putRef(DfsStreamKey key, long size, T v) {
+		return getTable(key).putRef(key, size, v);
+	}
+
+	@Override
+	public boolean contains(DfsStreamKey key, long position) {
+		return getTable(key).contains(key, position);
+	}
+
+	@Override
+	public <T> T get(DfsStreamKey key, long position) {
+		return getTable(key).get(key, position);
+	}
+
+	@Override
+	public BlockCacheStats getBlockCacheStats() {
+		return new CacheStats(blockCacheTableList.stream()
+				.map(DfsBlockCacheTable::getBlockCacheStats)
+				.collect(Collectors.toList()));
+	}
+
+	private DfsBlockCacheTable getTable(PackExt packExt) {
+		return extBlockCacheTables.getOrDefault(packExt,
+				defaultBlockCacheTable);
+	}
+
+	private DfsBlockCacheTable getTable(DfsStreamKey key) {
+		return extBlockCacheTables.getOrDefault(getPackExt(key),
+				defaultBlockCacheTable);
+	}
+
+	private static PackExt getPackExt(DfsStreamKey key) {
+		return PackExt.values()[key.packExtPos];
+	}
+
+	private static class CacheStats implements BlockCacheStats {
+		private final List<BlockCacheStats> blockCacheStats;
+
+		private CacheStats(List<BlockCacheStats> blockCacheStats) {
+			this.blockCacheStats = blockCacheStats;
+		}
+
+		@Override
+		public long[] getCurrentSize() {
+			long[] sums = emptyPackStats();
+			for (BlockCacheStats blockCacheStatsEntry : blockCacheStats) {
+				sums = add(sums, blockCacheStatsEntry.getCurrentSize());
+			}
+			return sums;
+		}
+
+		@Override
+		public long[] getHitCount() {
+			long[] sums = emptyPackStats();
+			for (BlockCacheStats blockCacheStatsEntry : blockCacheStats) {
+				sums = add(sums, blockCacheStatsEntry.getHitCount());
+			}
+			return sums;
+		}
+
+		@Override
+		public long[] getMissCount() {
+			long[] sums = emptyPackStats();
+			for (BlockCacheStats blockCacheStatsEntry : blockCacheStats) {
+				sums = add(sums, blockCacheStatsEntry.getMissCount());
+			}
+			return sums;
+		}
+
+		@Override
+		public long[] getTotalRequestCount() {
+			long[] sums = emptyPackStats();
+			for (BlockCacheStats blockCacheStatsEntry : blockCacheStats) {
+				sums = add(sums, blockCacheStatsEntry.getTotalRequestCount());
+			}
+			return sums;
+		}
+
+		@Override
+		public long[] getHitRatio() {
+			long[] hit = getHitCount();
+			long[] miss = getMissCount();
+			long[] ratio = new long[Math.max(hit.length, miss.length)];
+			for (int i = 0; i < ratio.length; i++) {
+				if (i >= hit.length) {
+					ratio[i] = 0;
+				} else if (i >= miss.length) {
+					ratio[i] = 100;
+				} else {
+					long total = hit[i] + miss[i];
+					ratio[i] = total == 0 ? 0 : hit[i] * 100 / total;
+				}
+			}
+			return ratio;
+		}
+
+		@Override
+		public long[] getEvictions() {
+			long[] sums = emptyPackStats();
+			for (BlockCacheStats blockCacheStatsEntry : blockCacheStats) {
+				sums = add(sums, blockCacheStatsEntry.getEvictions());
+			}
+			return sums;
+		}
+
+		private static long[] emptyPackStats() {
+			return new long[PackExt.values().length];
+		}
+
+		private static long[] add(long[] first, long[] second) {
+			long[] sums = new long[Integer.max(first.length, second.length)];
+			int i;
+			for (i = 0; i < Integer.min(first.length, second.length); i++) {
+				sums[i] = first[i] + second[i];
+			}
+			for (int j = i; j < first.length; j++) {
+				sums[j] = first[i];
+			}
+			for (int j = i; j < second.length; j++) {
+				sums[j] = second[i];
+			}
+			return sums;
+		}
+	}
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileReftableDatabase.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileReftableDatabase.java
index ed2516d..80240e5 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileReftableDatabase.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileReftableDatabase.java
@@ -68,14 +68,14 @@ public class FileReftableDatabase extends RefDatabase {
 	private final FileReftableStack reftableStack;
 
 	FileReftableDatabase(FileRepository repo) throws IOException {
-		this(repo, new File(new File(repo.getDirectory(), Constants.REFTABLE),
+		this(repo, new File(new File(repo.getCommonDirectory(), Constants.REFTABLE),
 				Constants.TABLES_LIST));
 	}
 
 	FileReftableDatabase(FileRepository repo, File refstackName) throws IOException {
 		this.fileRepository = repo;
 		this.reftableStack = new FileReftableStack(refstackName,
-			new File(fileRepository.getDirectory(), Constants.REFTABLE),
+				new File(fileRepository.getCommonDirectory(), Constants.REFTABLE),
 			() -> fileRepository.fireEvent(new RefsChangedEvent()),
 			() -> fileRepository.getConfig());
 		this.reftableDatabase = new ReftableDatabase() {
@@ -318,7 +318,7 @@ public void close() {
 	@Override
 	public void create() throws IOException {
 		FileUtils.mkdir(
-				new File(fileRepository.getDirectory(), Constants.REFTABLE),
+				new File(fileRepository.getCommonDirectory(), Constants.REFTABLE),
 				true);
 	}
 
@@ -615,7 +615,7 @@ public static FileReftableDatabase convertFrom(FileRepository repo,
 		FileReftableDatabase newDb = null;
 		File reftableList = null;
 		try {
-			File reftableDir = new File(repo.getDirectory(),
+			File reftableDir = new File(repo.getCommonDirectory(),
 					Constants.REFTABLE);
 			reftableList = new File(reftableDir, Constants.TABLES_LIST);
 			if (!reftableDir.isDirectory()) {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileRepository.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileRepository.java
index e5a00d3..b5d29a3 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileRepository.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileRepository.java
@@ -165,7 +165,7 @@ public FileRepository(BaseRepositoryBuilder options) throws IOException {
 			throw new IOException(e.getMessage(), e);
 		}
 		repoConfig = new FileBasedConfig(userConfig, getFS().resolve(
-				getDirectory(), Constants.CONFIG),
+				getCommonDirectory(), Constants.CONFIG),
 				getFS());
 		loadRepoConfig();
 
@@ -193,7 +193,7 @@ public FileRepository(BaseRepositoryBuilder options) throws IOException {
 				options.getObjectDirectory(), //
 				options.getAlternateObjectDirectories(), //
 				getFS(), //
-				new File(getDirectory(), Constants.SHALLOW));
+				new File(getCommonDirectory(), Constants.SHALLOW));
 
 		if (objectDatabase.exists()) {
 			if (repositoryFormatVersion > 1)
@@ -622,16 +622,17 @@ public void autoGC(ProgressMonitor monitor) {
 	 *             on IO problem
 	 */
 	void convertToPackedRefs(boolean writeLogs, boolean backup) throws IOException {
+		File commonDirectory = getCommonDirectory();
 		List<Ref> all = refs.getRefs();
-		File packedRefs = new File(getDirectory(), Constants.PACKED_REFS);
+		File packedRefs = new File(commonDirectory, Constants.PACKED_REFS);
 		if (packedRefs.exists()) {
 			throw new IOException(MessageFormat.format(JGitText.get().fileAlreadyExists,
 				packedRefs.getName()));
 		}
 
-		File refsFile = new File(getDirectory(), "refs"); //$NON-NLS-1$
+		File refsFile = new File(commonDirectory, "refs"); //$NON-NLS-1$
 		File refsHeadsFile = new File(refsFile, "heads");//$NON-NLS-1$
-		File headFile = new File(getDirectory(), Constants.HEAD);
+		File headFile = new File(commonDirectory, Constants.HEAD);
 		FileReftableDatabase oldDb = (FileReftableDatabase) refs;
 
 		// Remove the dummy files that ensure compatibility with older git
@@ -701,7 +702,7 @@ void convertToPackedRefs(boolean writeLogs, boolean backup) throws IOException {
 		}
 
 		if (!backup) {
-			File reftableDir = new File(getDirectory(), Constants.REFTABLE);
+			File reftableDir = new File(commonDirectory, Constants.REFTABLE);
 			FileUtils.delete(reftableDir,
 					FileUtils.RECURSIVE | FileUtils.IGNORE_ERRORS);
 		}
@@ -730,8 +731,10 @@ void convertToPackedRefs(boolean writeLogs, boolean backup) throws IOException {
 	@SuppressWarnings("nls")
 	void convertToReftable(boolean writeLogs, boolean backup)
 			throws IOException {
-		File reftableDir = new File(getDirectory(), Constants.REFTABLE);
-		File headFile = new File(getDirectory(), Constants.HEAD);
+		File commonDirectory = getCommonDirectory();
+		File directory = getDirectory();
+		File reftableDir = new File(commonDirectory, Constants.REFTABLE);
+		File headFile = new File(directory, Constants.HEAD);
 		if (reftableDir.exists() && FileUtils.hasFiles(reftableDir.toPath())) {
 			throw new IOException(JGitText.get().reftableDirExists);
 		}
@@ -739,28 +742,28 @@ void convertToReftable(boolean writeLogs, boolean backup)
 		// Ignore return value, as it is tied to temporary newRefs file.
 		FileReftableDatabase.convertFrom(this, writeLogs);
 
-		File refsFile = new File(getDirectory(), "refs");
+		File refsFile = new File(commonDirectory, "refs");
 
 		// non-atomic: remove old data.
-		File packedRefs = new File(getDirectory(), Constants.PACKED_REFS);
-		File logsDir = new File(getDirectory(), Constants.LOGS);
+		File packedRefs = new File(commonDirectory, Constants.PACKED_REFS);
+		File logsDir = new File(commonDirectory, Constants.LOGS);
 
 		List<String> additional = getRefDatabase().getAdditionalRefs().stream()
 				.map(Ref::getName).collect(toList());
 		additional.add(Constants.HEAD);
 		if (backup) {
-			FileUtils.rename(refsFile, new File(getDirectory(), "refs.old"));
+			FileUtils.rename(refsFile, new File(commonDirectory, "refs.old"));
 			if (packedRefs.exists()) {
-				FileUtils.rename(packedRefs, new File(getDirectory(),
+				FileUtils.rename(packedRefs, new File(commonDirectory,
 						Constants.PACKED_REFS + ".old"));
 			}
 			if (logsDir.exists()) {
 				FileUtils.rename(logsDir,
-						new File(getDirectory(), Constants.LOGS + ".old"));
+						new File(commonDirectory, Constants.LOGS + ".old"));
 			}
 			for (String r : additional) {
-				FileUtils.rename(new File(getDirectory(), r),
-					new File(getDirectory(), r + ".old"));
+				FileUtils.rename(new File(commonDirectory, r),
+						new File(commonDirectory, r + ".old"));
 			}
 		} else {
 			FileUtils.delete(packedRefs, FileUtils.SKIP_MISSING);
@@ -770,7 +773,7 @@ void convertToReftable(boolean writeLogs, boolean backup)
 			FileUtils.delete(refsFile,
 					FileUtils.RECURSIVE | FileUtils.SKIP_MISSING);
 			for (String r : additional) {
-				new File(getDirectory(), r).delete();
+				new File(commonDirectory, r).delete();
 			}
 		}
 
@@ -784,7 +787,7 @@ void convertToReftable(boolean writeLogs, boolean backup)
 
 		// Some tools might write directly into .git/refs/heads/BRANCH. By
 		// putting a file here, this fails spectacularly.
-		FileUtils.createNewFile(new File(refsFile, "heads"));
+		FileUtils.createNewFile(new File(refsFile, Constants.HEADS));
 
 		repoConfig.setString(ConfigConstants.CONFIG_EXTENSIONS_SECTION, null,
 				ConfigConstants.CONFIG_KEY_REF_STORAGE,
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileSnapshot.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileSnapshot.java
index 7f34aed..b8911f5 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileSnapshot.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileSnapshot.java
@@ -142,29 +142,6 @@ private static Object getFileKey(BasicFileAttributes fileAttributes) {
 	 * @param modified
 	 *            the last modification time of the file
 	 * @return the snapshot.
-	 * @deprecated use {@link #save(Instant)} instead.
-	 */
-	@Deprecated
-	public static FileSnapshot save(long modified) {
-		final Instant read = Instant.now();
-		return new FileSnapshot(read, Instant.ofEpochMilli(modified),
-				UNKNOWN_SIZE, FALLBACK_TIMESTAMP_RESOLUTION, MISSING_FILEKEY);
-	}
-
-	/**
-	 * Record a snapshot for a file for which the last modification time is
-	 * already known.
-	 * <p>
-	 * This method should be invoked before the file is accessed.
-	 * <p>
-	 * Note that this method cannot rely on measuring file timestamp resolution
-	 * to avoid racy git issues caused by finite file timestamp resolution since
-	 * it's unknown in which filesystem the file is located. Hence the worst
-	 * case fallback for timestamp resolution is used.
-	 *
-	 * @param modified
-	 *            the last modification time of the file
-	 * @return the snapshot.
 	 */
 	public static FileSnapshot save(Instant modified) {
 		final Instant read = Instant.now();
@@ -279,17 +256,6 @@ private FileSnapshot(Instant read, Instant modified, long size,
 	 * Get time of last snapshot update
 	 *
 	 * @return time of last snapshot update
-	 * @deprecated use {@link #lastModifiedInstant()} instead
-	 */
-	@Deprecated
-	public long lastModified() {
-		return lastModified.toEpochMilli();
-	}
-
-	/**
-	 * Get time of last snapshot update
-	 *
-	 * @return time of last snapshot update
 	 */
 	public Instant lastModifiedInstant() {
 		return lastModified;
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 426776c..67b43cb 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
@@ -1043,7 +1043,7 @@ private static boolean isTag(Ref ref) {
 	}
 
 	private void deleteEmptyRefsFolders() throws IOException {
-		Path refs = repo.getDirectory().toPath().resolve(Constants.R_REFS);
+		Path refs = repo.getCommonDirectory().toPath().resolve(Constants.R_REFS);
 		// Avoid deleting a folder that was created after the threshold so that concurrent
 		// operations trying to create a reference are not impacted
 		Instant threshold = Instant.now().minus(30, ChronoUnit.SECONDS);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GcLog.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GcLog.java
index 628bf5d..8647b3e 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GcLog.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GcLog.java
@@ -50,7 +50,7 @@ class GcLog {
 	 */
 	GcLog(FileRepository repo) {
 		this.repo = repo;
-		logFile = new File(repo.getDirectory(), "gc.log"); //$NON-NLS-1$
+		logFile = new File(repo.getCommonDirectory(), "gc.log"); //$NON-NLS-1$
 		lock = new LockFile(logFile);
 	}
 
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/InfoAttributesNode.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/InfoAttributesNode.java
index 11d842b..e8d442b 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/InfoAttributesNode.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/InfoAttributesNode.java
@@ -46,7 +46,7 @@ public AttributesNode load() throws IOException {
 
 		FS fs = repository.getFS();
 
-		File attributes = fs.resolve(repository.getDirectory(),
+		File attributes = fs.resolve(repository.getCommonDirectory(),
 				Constants.INFO_ATTRIBUTES);
 		FileRepository.AttributesNodeProviderImpl.loadRulesFromFile(r, attributes);
 
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/LockFile.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/LockFile.java
index 1983541..9e12ee8 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/LockFile.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/LockFile.java
@@ -528,17 +528,6 @@ private void saveStatInformation() {
 	 * Get the modification time of the output file when it was committed.
 	 *
 	 * @return modification time of the lock file right before we committed it.
-	 * @deprecated use {@link #getCommitLastModifiedInstant()} instead
-	 */
-	@Deprecated
-	public long getCommitLastModified() {
-		return commitSnapshot.lastModified();
-	}
-
-	/**
-	 * Get the modification time of the output file when it was committed.
-	 *
-	 * @return modification time of the lock file right before we committed it.
 	 */
 	public Instant getCommitLastModifiedInstant() {
 		return commitSnapshot.lastModifiedInstant();
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackObjectSizeIndexV1.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackObjectSizeIndexV1.java
index a3d74be..9957f54 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackObjectSizeIndexV1.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackObjectSizeIndexV1.java
@@ -12,7 +12,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.UnsupportedEncodingException;
-import java.util.Arrays;
+import java.text.MessageFormat;
 
 import org.eclipse.jgit.internal.JGitText;
 import org.eclipse.jgit.util.NB;
@@ -35,7 +35,7 @@ class PackObjectSizeIndexV1 implements PackObjectSizeIndex {
 
 	private final UInt24Array positions24;
 
-	private final int[] positions32;
+	private final IntArray positions32;
 
 	/**
 	 * Parallel array to concat(positions24, positions32) with the size of the
@@ -45,35 +45,37 @@ class PackObjectSizeIndexV1 implements PackObjectSizeIndex {
 	 * doesn't fit in an int and |value|-1 is the position for the size in the
 	 * size64 array e.g. a value of -1 is sizes64[0], -2 = sizes64[1], ...
 	 */
-	private final int[] sizes32;
+	private final IntArray sizes32;
 
-	private final long[] sizes64;
+	private final LongArray sizes64;
 
 	static PackObjectSizeIndex parse(InputStream in) throws IOException {
 		/** Header and version already out of the input */
-		IndexInputStreamReader stream = new IndexInputStreamReader(in);
-		int threshold = stream.readInt(); // minSize
-		int objCount = stream.readInt();
+		byte[] buffer = new byte[8];
+		in.readNBytes(buffer, 0, 8);
+		int threshold = NB.decodeInt32(buffer, 0); // minSize
+		int objCount = NB.decodeInt32(buffer, 4);
 		if (objCount == 0) {
 			return new EmptyPackObjectSizeIndex(threshold);
 		}
-		return new PackObjectSizeIndexV1(stream, threshold, objCount);
+		return new PackObjectSizeIndexV1(in, threshold, objCount);
 	}
 
-	private PackObjectSizeIndexV1(IndexInputStreamReader stream, int threshold,
+	private PackObjectSizeIndexV1(InputStream stream, int threshold,
 			int objCount) throws IOException {
 		this.threshold = threshold;
 		UInt24Array pos24 = null;
-		int[] pos32 = null;
+		IntArray pos32 = null;
 
+		StreamHelper helper = new StreamHelper();
 		byte positionEncoding;
-		while ((positionEncoding = stream.readByte()) != 0) {
+		while ((positionEncoding = helper.readByte(stream)) != 0) {
 			if (Byte.compareUnsigned(positionEncoding, BITS_24) == 0) {
-				int sz = stream.readInt();
+				int sz = helper.readInt(stream);
 				pos24 = new UInt24Array(stream.readNBytes(sz * 3));
 			} else if (Byte.compareUnsigned(positionEncoding, BITS_32) == 0) {
-				int sz = stream.readInt();
-				pos32 = stream.readIntArray(sz);
+				int sz = helper.readInt(stream);
+				pos32 = IntArray.from(stream, sz);
 			} else {
 				throw new UnsupportedEncodingException(
 						String.format(JGitText.get().unknownPositionEncoding,
@@ -81,16 +83,16 @@ private PackObjectSizeIndexV1(IndexInputStreamReader stream, int threshold,
 			}
 		}
 		positions24 = pos24 != null ? pos24 : UInt24Array.EMPTY;
-		positions32 = pos32 != null ? pos32 : new int[0];
+		positions32 = pos32 != null ? pos32 : IntArray.EMPTY;
 
-		sizes32 = stream.readIntArray(objCount);
-		int c64sizes = stream.readInt();
+		sizes32 = IntArray.from(stream, objCount);
+		int c64sizes = helper.readInt(stream);
 		if (c64sizes == 0) {
-			sizes64 = new long[0];
+			sizes64 = LongArray.EMPTY;
 			return;
 		}
-		sizes64 = stream.readLongArray(c64sizes);
-		int c128sizes = stream.readInt();
+		sizes64 = LongArray.from(stream, c64sizes);
+		int c128sizes = helper.readInt(stream);
 		if (c128sizes != 0) {
 			// this MUST be 0 (we don't support 128 bits sizes yet)
 			throw new IOException(JGitText.get().unsupportedSizesObjSizeIndex);
@@ -102,8 +104,8 @@ public long getSize(int idxOffset) {
 		int pos = -1;
 		if (!positions24.isEmpty() && idxOffset <= positions24.getLastValue()) {
 			pos = positions24.binarySearch(idxOffset);
-		} else if (positions32.length > 0 && idxOffset >= positions32[0]) {
-			int pos32 = Arrays.binarySearch(positions32, idxOffset);
+		} else if (!positions32.empty() && idxOffset >= positions32.get(0)) {
+			int pos32 = positions32.binarySearch(idxOffset);
 			if (pos32 >= 0) {
 				pos = pos32 + positions24.size();
 			}
@@ -112,17 +114,17 @@ public long getSize(int idxOffset) {
 			return -1;
 		}
 
-		int objSize = sizes32[pos];
+		int objSize = sizes32.get(pos);
 		if (objSize < 0) {
 			int secondPos = Math.abs(objSize) - 1;
-			return sizes64[secondPos];
+			return sizes64.get(secondPos);
 		}
 		return objSize;
 	}
 
 	@Override
 	public long getObjectCount() {
-		return (long) positions24.size() + positions32.length;
+		return (long) positions24.size() + positions32.size();
 	}
 
 	@Override
@@ -131,19 +133,114 @@ public int getThreshold() {
 	}
 
 	/**
-	 * Wrapper to read parsed content from the byte stream
+	 * A byte[] that should be interpreted as an int[]
 	 */
-	private static class IndexInputStreamReader {
+	private static class IntArray {
+		private static final IntArray EMPTY = new IntArray(new byte[0]);
 
-		private final byte[] buffer = new byte[8];
+		private static final int INT_SIZE = 4;
 
-		private final InputStream in;
+		private final byte[] data;
 
-		IndexInputStreamReader(InputStream in) {
-			this.in = in;
+		private final int size;
+
+		static IntArray from(InputStream in, int ints) throws IOException {
+			int expectedBytes = ints * INT_SIZE;
+			byte[] data = in.readNBytes(expectedBytes);
+			if (data.length < expectedBytes) {
+				throw new IOException(MessageFormat
+						.format(JGitText.get().unableToReadFullArray,
+								Integer.valueOf(ints)));
+			}
+			return new IntArray(data);
 		}
 
-		int readInt() throws IOException {
+		private IntArray(byte[] data) {
+			this.data = data;
+			size = data.length / INT_SIZE;
+		}
+
+		/**
+		 * Returns position of element in array, -1 if not there
+		 *
+		 * @param needle
+		 *            element to look for
+		 * @return position of the element in the array or -1 if not found
+		 */
+		int binarySearch(int needle) {
+			if (size == 0) {
+				return -1;
+			}
+			int high = size;
+			int low = 0;
+			do {
+				int mid = (low + high) >>> 1;
+				int cmp = Integer.compare(needle, get(mid));
+				if (cmp < 0)
+					high = mid;
+				else if (cmp == 0) {
+					return mid;
+				} else
+					low = mid + 1;
+			} while (low < high);
+			return -1;
+		}
+
+		int get(int position) {
+			if (position < 0 || position >= size) {
+				throw new IndexOutOfBoundsException(position);
+			}
+			return NB.decodeInt32(data, position * INT_SIZE);
+		}
+
+		boolean empty() {
+			return size == 0;
+		}
+
+		int size() {
+			return size;
+		}
+	}
+
+	/**
+	 * A byte[] that should be interpreted as an long[]
+	 */
+	private static class LongArray {
+		private static final LongArray EMPTY = new LongArray(new byte[0]);
+
+		private static final int LONG_SIZE = 8; // bytes
+
+		private final byte[] data;
+
+		private final int size;
+
+		static LongArray from(InputStream in, int longs) throws IOException {
+			byte[] data = in.readNBytes(longs * LONG_SIZE);
+			if (data.length < longs * LONG_SIZE) {
+				throw new IOException(MessageFormat
+						.format(JGitText.get().unableToReadFullArray,
+								Integer.valueOf(longs)));
+			}
+			return new LongArray(data);
+		}
+
+		private LongArray(byte[] data) {
+			this.data = data;
+			size = data.length / LONG_SIZE;
+		}
+
+		long get(int position) {
+			if (position < 0 || position >= size) {
+				throw new IndexOutOfBoundsException(position);
+			}
+			return NB.decodeInt64(data, position * LONG_SIZE);
+		}
+	}
+
+	private static class StreamHelper {
+		private final byte[] buffer = new byte[8];
+
+		int readInt(InputStream in) throws IOException {
 			int n = in.readNBytes(buffer, 0, 4);
 			if (n < 4) {
 				throw new IOException(JGitText.get().unableToReadFullInt);
@@ -151,49 +248,13 @@ int readInt() throws IOException {
 			return NB.decodeInt32(buffer, 0);
 		}
 
-		int[] readIntArray(int intsCount) throws IOException {
-			if (intsCount == 0) {
-				return new int[0];
-			}
-
-			int[] dest = new int[intsCount];
-			for (int i = 0; i < intsCount; i++) {
-				dest[i] = readInt();
-			}
-			return dest;
-		}
-
-		long readLong() throws IOException {
-			int n = in.readNBytes(buffer, 0, 8);
-			if (n < 8) {
-				throw new IOException(JGitText.get().unableToReadFullInt);
-			}
-			return NB.decodeInt64(buffer, 0);
-		}
-
-		long[] readLongArray(int longsCount) throws IOException {
-			if (longsCount == 0) {
-				return new long[0];
-			}
-
-			long[] dest = new long[longsCount];
-			for (int i = 0; i < longsCount; i++) {
-				dest[i] = readLong();
-			}
-			return dest;
-		}
-
-		byte readByte() throws IOException {
+		byte readByte(InputStream in) throws IOException {
 			int n = in.readNBytes(buffer, 0, 1);
 			if (n != 1) {
 				throw new IOException(JGitText.get().cannotReadByte);
 			}
 			return buffer[0];
 		}
-
-		byte[] readNBytes(int sz) throws IOException {
-			return in.readNBytes(sz);
-		}
 	}
 
 	private static class EmptyPackObjectSizeIndex
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 52deac8..cc48176 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
@@ -16,6 +16,7 @@
 import static java.nio.charset.StandardCharsets.UTF_8;
 import static org.eclipse.jgit.lib.Constants.HEAD;
 import static org.eclipse.jgit.lib.Constants.LOGS;
+import static org.eclipse.jgit.lib.Constants.L_LOGS;
 import static org.eclipse.jgit.lib.Constants.OBJECT_ID_STRING_LENGTH;
 import static org.eclipse.jgit.lib.Constants.PACKED_REFS;
 import static org.eclipse.jgit.lib.Constants.R_HEADS;
@@ -126,6 +127,8 @@ public class RefDirectory extends RefDatabase {
 
 	private final File gitDir;
 
+	private final File gitCommonDir;
+
 	final File refsDir;
 
 	final File packedRefsFile;
@@ -193,6 +196,7 @@ public class RefDirectory extends RefDatabase {
 	RefDirectory(RefDirectory refDb) {
 		parent = refDb.parent;
 		gitDir = refDb.gitDir;
+		gitCommonDir = refDb.gitCommonDir;
 		refsDir = refDb.refsDir;
 		logsDir = refDb.logsDir;
 		logsRefsDir = refDb.logsRefsDir;
@@ -209,10 +213,11 @@ public class RefDirectory extends RefDatabase {
 		final FS fs = db.getFS();
 		parent = db;
 		gitDir = db.getDirectory();
-		refsDir = fs.resolve(gitDir, R_REFS);
-		logsDir = fs.resolve(gitDir, LOGS);
-		logsRefsDir = fs.resolve(gitDir, LOGS + '/' + R_REFS);
-		packedRefsFile = fs.resolve(gitDir, PACKED_REFS);
+		gitCommonDir = db.getCommonDirectory();
+		refsDir = fs.resolve(gitCommonDir, R_REFS);
+		logsDir = fs.resolve(gitCommonDir, LOGS);
+		logsRefsDir = fs.resolve(gitCommonDir, L_LOGS + R_REFS);
+		packedRefsFile = fs.resolve(gitCommonDir, PACKED_REFS);
 
 		looseRefs.set(RefList.<LooseRef> emptyList());
 		packedRefs.set(NO_PACKED_REFS);
@@ -1381,7 +1386,12 @@ File fileFor(String name) {
 			name = name.substring(R_REFS.length());
 			return new File(refsDir, name);
 		}
-		return new File(gitDir, name);
+		// HEAD needs to get resolved from git dir as resolving it from common dir
+		// would always lead back to current default branch
+		if (name.equals(HEAD)) {
+			return new File(gitDir, name);
+		}
+		return new File(gitCommonDir, name);
 	}
 
 	static int levelsIn(String name) {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ReflogReaderImpl.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ReflogReaderImpl.java
index 21b5a54..f1888eb 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ReflogReaderImpl.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ReflogReaderImpl.java
@@ -10,6 +10,8 @@
 
 package org.eclipse.jgit.internal.storage.file;
 
+import static org.eclipse.jgit.lib.Constants.HEAD;
+
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.IOException;
@@ -37,7 +39,9 @@ class ReflogReaderImpl implements ReflogReader {
 	 *            {@code Ref} name
 	 */
 	ReflogReaderImpl(Repository db, String refname) {
-		logName = new File(db.getDirectory(), Constants.LOGS + '/' + refname);
+		File logBaseDir = refname.equals(HEAD) ? db.getDirectory()
+				: db.getCommonDirectory();
+		logName = new File(logBaseDir, Constants.L_LOGS + refname);
 	}
 
 	/* (non-Javadoc)
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/AbstractGpgSignatureVerifier.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/AbstractGpgSignatureVerifier.java
deleted file mode 100644
index 06a89dc..0000000
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/AbstractGpgSignatureVerifier.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2024, Thomas Wolf <twolf@apache.org> and others
-*
-* 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 java.io.IOException;
-import java.util.Arrays;
-
-import org.eclipse.jgit.revwalk.RevCommit;
-import org.eclipse.jgit.revwalk.RevObject;
-import org.eclipse.jgit.revwalk.RevTag;
-import org.eclipse.jgit.util.RawParseUtils;
-
-/**
- * Provides a base implementation of
- * {@link GpgSignatureVerifier#verifySignature(RevObject, GpgConfig)}.
- *
- * @since 6.9
- */
-public abstract class AbstractGpgSignatureVerifier
-		implements GpgSignatureVerifier {
-
-	@Override
-	public SignatureVerification verifySignature(RevObject object,
-			GpgConfig config) throws IOException {
-		if (object instanceof RevCommit) {
-			RevCommit commit = (RevCommit) object;
-			byte[] signatureData = commit.getRawGpgSignature();
-			if (signatureData == null) {
-				return null;
-			}
-			byte[] raw = commit.getRawBuffer();
-			// Now remove the GPG signature
-			byte[] header = { 'g', 'p', 'g', 's', 'i', 'g' };
-			int start = RawParseUtils.headerStart(header, raw, 0);
-			if (start < 0) {
-				return null;
-			}
-			int end = RawParseUtils.nextLfSkippingSplitLines(raw, start);
-			// start is at the beginning of the header's content
-			start -= header.length + 1;
-			// end is on the terminating LF; we need to skip that, too
-			if (end < raw.length) {
-				end++;
-			}
-			byte[] data = new byte[raw.length - (end - start)];
-			System.arraycopy(raw, 0, data, 0, start);
-			System.arraycopy(raw, end, data, start, raw.length - end);
-			return verify(config, data, signatureData);
-		} else if (object instanceof RevTag) {
-			RevTag tag = (RevTag) object;
-			byte[] signatureData = tag.getRawGpgSignature();
-			if (signatureData == null) {
-				return null;
-			}
-			byte[] raw = tag.getRawBuffer();
-			// The signature is just tacked onto the end of the message, which
-			// is last in the buffer.
-			byte[] data = Arrays.copyOfRange(raw, 0,
-					raw.length - signatureData.length);
-			return verify(config, data, signatureData);
-		}
-		return null;
-	}
-}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/AnyObjectId.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/AnyObjectId.java
index c58133a..f742e99 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/AnyObjectId.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/AnyObjectId.java
@@ -35,23 +35,6 @@ public abstract class AnyObjectId implements Comparable<AnyObjectId> {
 	 * @param secondObjectId
 	 *            the second identifier to compare. Must not be null.
 	 * @return true if the two identifiers are the same.
-	 * @deprecated use {@link #isEqual(AnyObjectId, AnyObjectId)} instead
-	 */
-	@Deprecated
-	@SuppressWarnings("AmbiguousMethodReference")
-	public static boolean equals(final AnyObjectId firstObjectId,
-			final AnyObjectId secondObjectId) {
-		return isEqual(firstObjectId, secondObjectId);
-	}
-
-	/**
-	 * Compare two object identifier byte sequences for equality.
-	 *
-	 * @param firstObjectId
-	 *            the first identifier to compare. Must not be null.
-	 * @param secondObjectId
-	 *            the second identifier to compare. Must not be null.
-	 * @return true if the two identifiers are the same.
 	 * @since 5.4
 	 */
 	public static boolean isEqual(final AnyObjectId firstObjectId,
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/BaseRepositoryBuilder.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/BaseRepositoryBuilder.java
index 5dfb648..d232be6 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/BaseRepositoryBuilder.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/BaseRepositoryBuilder.java
@@ -13,13 +13,17 @@
 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_CORE_SECTION;
 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_BARE;
 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_WORKTREE;
+import static org.eclipse.jgit.lib.Constants.CONFIG;
 import static org.eclipse.jgit.lib.Constants.DOT_GIT;
 import static org.eclipse.jgit.lib.Constants.GIT_ALTERNATE_OBJECT_DIRECTORIES_KEY;
 import static org.eclipse.jgit.lib.Constants.GIT_CEILING_DIRECTORIES_KEY;
+import static org.eclipse.jgit.lib.Constants.GIT_COMMON_DIR_KEY;
 import static org.eclipse.jgit.lib.Constants.GIT_DIR_KEY;
 import static org.eclipse.jgit.lib.Constants.GIT_INDEX_FILE_KEY;
 import static org.eclipse.jgit.lib.Constants.GIT_OBJECT_DIRECTORY_KEY;
 import static org.eclipse.jgit.lib.Constants.GIT_WORK_TREE_KEY;
+import static org.eclipse.jgit.lib.Constants.OBJECTS;
+import static org.eclipse.jgit.lib.Constants.GITDIR_FILE;
 
 import java.io.File;
 import java.io.IOException;
@@ -70,7 +74,21 @@ private static boolean isSymRef(byte[] ref) {
 				&& ref[7] == ' ';
 	}
 
-	private static File getSymRef(File workTree, File dotGit, FS fs)
+	/**
+	 * Read symbolic reference file
+	 *
+	 * @param workTree
+	 *            the work tree path
+	 * @param dotGit
+	 *            the .git file
+	 * @param fs
+	 *            th FS util
+	 * @return the file read from symbolic reference file
+	 * @throws java.io.IOException
+	 *             the dotGit file is invalid reference
+	 * @since 7.0
+	 */
+	static File getSymRef(File workTree, File dotGit, FS fs)
 			throws IOException {
 		byte[] content = IO.readFully(dotGit);
 		if (!isSymRef(content)) {
@@ -102,6 +120,8 @@ private static File getSymRef(File workTree, File dotGit, FS fs)
 
 	private File gitDir;
 
+	private File gitCommonDir;
+
 	private File objectDirectory;
 
 	private List<File> alternateObjectDirectories;
@@ -172,6 +192,30 @@ public File getGitDir() {
 	}
 
 	/**
+	 * Set common dir.
+	 *
+	 * @param gitCommonDir
+	 *            {@code GIT_COMMON_DIR}, the common repository meta directory.
+	 * @return {@code this} (for chaining calls).
+	 * @since 7.0
+	 */
+	public B setGitCommonDir(File gitCommonDir) {
+		this.gitCommonDir = gitCommonDir;
+		this.config = null;
+		return self();
+	}
+
+	/**
+	 * Get common dir.
+	 *
+	 * @return common dir; null if not set.
+	 * @since 7.0
+	 */
+	public File getGitCommonDir() {
+		return gitCommonDir;
+	}
+
+	/**
 	 * Set the directory storing the repository's objects.
 	 *
 	 * @param objectDirectory
@@ -396,9 +440,9 @@ public B setInitialBranch(String branch) throws InvalidRefNameException {
 	 * Read standard Git environment variables and configure from those.
 	 * <p>
 	 * This method tries to read the standard Git environment variables, such as
-	 * {@code GIT_DIR} and {@code GIT_WORK_TREE} to configure this builder
-	 * instance. If an environment variable is set, it overrides the value
-	 * already set in this builder.
+	 * {@code GIT_DIR}, {@code GIT_COMMON_DIR}, {@code GIT_WORK_TREE} etc. to
+	 * configure this builder instance. If an environment variable is set, it
+	 * overrides the value already set in this builder.
 	 *
 	 * @return {@code this} (for chaining calls).
 	 */
@@ -410,9 +454,9 @@ public B readEnvironment() {
 	 * Read standard Git environment variables and configure from those.
 	 * <p>
 	 * This method tries to read the standard Git environment variables, such as
-	 * {@code GIT_DIR} and {@code GIT_WORK_TREE} to configure this builder
-	 * instance. If a property is already set in the builder, the environment
-	 * variable is not used.
+	 * {@code GIT_DIR}, {@code GIT_COMMON_DIR}, {@code GIT_WORK_TREE} etc. to
+	 * configure this builder instance. If a property is already set in the
+	 * builder, the environment variable is not used.
 	 *
 	 * @param sr
 	 *            the SystemReader abstraction to access the environment.
@@ -425,6 +469,13 @@ public B readEnvironment(SystemReader sr) {
 				setGitDir(new File(val));
 		}
 
+		if (getGitCommonDir() == null) {
+			String val = sr.getenv(GIT_COMMON_DIR_KEY);
+			if (val != null) {
+				setGitCommonDir(new File(val));
+			}
+		}
+
 		if (getObjectDirectory() == null) {
 			String val = sr.getenv(GIT_OBJECT_DIRECTORY_KEY);
 			if (val != null)
@@ -601,6 +652,7 @@ public B findGitDir(File current) {
 	public B setup() throws IllegalArgumentException, IOException {
 		requireGitDirOrWorkTree();
 		setupGitDir();
+		setupCommonDir();
 		setupWorkTree();
 		setupInternals();
 		return self();
@@ -658,6 +710,20 @@ protected void setupGitDir() throws IOException {
 	}
 
 	/**
+	 * Perform standard common dir initialization.
+	 *
+	 * @throws java.io.IOException
+	 *             the repository could not be accessed
+	 * @since 7.0
+	 */
+	protected void setupCommonDir() throws IOException {
+		// no gitCommonDir? Try to get it from gitDir
+		if (getGitCommonDir() == null) {
+			setGitCommonDir(safeFS().getCommonDir(getGitDir()));
+		}
+	}
+
+	/**
 	 * Perform standard work-tree initialization.
 	 * <p>
 	 * This is a method typically invoked inside of {@link #setup()}, near the
@@ -695,8 +761,12 @@ protected void setupWorkTree() throws IOException {
 	 *             the repository could not be accessed
 	 */
 	protected void setupInternals() throws IOException {
-		if (getObjectDirectory() == null && getGitDir() != null)
-			setObjectDirectory(safeFS().resolve(getGitDir(), Constants.OBJECTS));
+		if (getObjectDirectory() == null) {
+			File commonDir = getGitCommonDir();
+			if (commonDir != null) {
+				setObjectDirectory(safeFS().resolve(commonDir, OBJECTS));
+			}
+		}
 	}
 
 	/**
@@ -723,12 +793,13 @@ protected Config getConfig() throws IOException {
 	 *             the configuration is not available.
 	 */
 	protected Config loadConfig() throws IOException {
-		if (getGitDir() != null) {
+		File commonDir = getGitCommonDir();
+		if (commonDir != null) {
 			// We only want the repository's configuration file, and not
 			// the user file, as these parameters must be unique to this
 			// repository and not inherited from other files.
 			//
-			File path = safeFS().resolve(getGitDir(), Constants.CONFIG);
+			File path = safeFS().resolve(commonDir, CONFIG);
 			FileBasedConfig cfg = new FileBasedConfig(path, safeFS());
 			try {
 				cfg.load();
@@ -749,8 +820,29 @@ private File guessWorkTreeOrFail() throws IOException {
 		//
 		String path = cfg.getString(CONFIG_CORE_SECTION, null,
 				CONFIG_KEY_WORKTREE);
-		if (path != null)
+		if (path != null) {
 			return safeFS().resolve(getGitDir(), path).getCanonicalFile();
+		}
+
+		/*
+		 * We are in worktree's $GIT_DIR folder
+		 * ".git/worktrees/&lt;worktree-name&gt;" and want to get the working
+		 * tree (checkout) path; so here we have an opposite link in file
+		 * "gitdir" showing to the ".git" file located in the working tree read
+		 * it and convert it to absolute path if it's relative
+		 */
+		File gitDirFile = new File(getGitDir(), GITDIR_FILE);
+		if (gitDirFile.isFile()) {
+			String workDirPath = new String(IO.readFully(gitDirFile)).trim();
+			File workTreeDotGitFile = new File(workDirPath);
+			if (!workTreeDotGitFile.isAbsolute()) {
+				workTreeDotGitFile = new File(getGitDir(), workDirPath)
+						.getCanonicalFile();
+			}
+			if (workTreeDotGitFile != null) {
+				return workTreeDotGitFile.getParentFile();
+			}
+		}
 
 		// If core.bare is set, honor its value. Assume workTree is
 		// the parent directory of the repository.
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/CommitBuilder.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/CommitBuilder.java
index ea33082..ad3c2c0 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/CommitBuilder.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/CommitBuilder.java
@@ -194,19 +194,6 @@ public void addParentId(AnyObjectId additionalParent) {
 		}
 	}
 
-	/**
-	 * Set the encoding for the commit information.
-	 *
-	 * @param encodingName
-	 *            the encoding name. See
-	 *            {@link java.nio.charset.Charset#forName(String)}.
-	 * @deprecated use {@link #setEncoding(Charset)} instead.
-	 */
-	@Deprecated
-	public void setEncoding(String encodingName) {
-		setEncoding(Charset.forName(encodingName));
-	}
-
 	@Override
 	public byte[] build() throws UnsupportedEncodingException {
 		ByteArrayOutputStream os = new ByteArrayOutputStream();
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 0edf3c5..acb54d7 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java
@@ -78,6 +78,13 @@ public final class ConfigConstants {
 	public static final String CONFIG_DFS_SECTION = "dfs";
 
 	/**
+	 * The dfs cache subsection prefix.
+	 *
+	 * @since 7.0
+	 */
+	public static final String CONFIG_DFS_CACHE_PREFIX = "dfs.";
+
+	/**
 	 * The "receive" section
 	 * @since 4.6
 	 */
@@ -332,6 +339,13 @@ public final class ConfigConstants {
 	public static final String CONFIG_KEY_DELTA_BASE_CACHE_LIMIT = "deltaBaseCacheLimit";
 
 	/**
+	 * The "packExtensions" key
+	 *
+	 * @since 7.0
+	 **/
+	public static final String CONFIG_KEY_PACK_EXTENSIONS = "packExtensions";
+
+	/**
 	 * The "symlinks" key
 	 * @since 3.3
 	 */
@@ -345,12 +359,6 @@ public final class ConfigConstants {
 	public static final String CONFIG_KEY_STREAM_FILE_THRESHOLD = "streamFileThreshold";
 
 	/**
-	 * @deprecated typo, use CONFIG_KEY_STREAM_FILE_THRESHOLD instead
-	 */
-	@Deprecated(since = "6.8")
-	public static final String CONFIG_KEY_STREAM_FILE_TRESHOLD = CONFIG_KEY_STREAM_FILE_THRESHOLD;
-
-	/**
 	 * The "packedGitMmap" key
 	 * @since 5.1.13
 	 */
@@ -1012,4 +1020,11 @@ public final class ConfigConstants {
 	 * @since 6.7
 	 */
 	public static final String CONFIG_KEY_READ_CHANGED_PATHS = "readChangedPaths";
+
+	/**
+	 * The "useObjectSizeIndex" key
+	 *
+	 * @since 7.0
+	 */
+	public static final String CONFIG_KEY_USE_OBJECT_SIZE_INDEX = "useObjectSizeIndex";
 }
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Constants.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Constants.java
index 1a2f735..997f4ed 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Constants.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Constants.java
@@ -15,7 +15,6 @@
 import static java.nio.charset.StandardCharsets.US_ASCII;
 import static java.nio.charset.StandardCharsets.UTF_8;
 
-import java.nio.charset.Charset;
 import java.nio.CharBuffer;
 import java.nio.charset.CharacterCodingException;
 import java.nio.charset.CharsetEncoder;
@@ -207,24 +206,6 @@ public final class Constants {
 	 */
 	public static final byte[] PACK_SIGNATURE = { 'P', 'A', 'C', 'K' };
 
-	/**
-	 * Native character encoding for commit messages, file names...
-	 *
-	 * @deprecated Use {@link java.nio.charset.StandardCharsets#UTF_8} directly
-	 *             instead.
-	 */
-	@Deprecated
-	public static final Charset CHARSET;
-
-	/**
-	 * Native character encoding for commit messages, file names...
-	 *
-	 * @deprecated Use {@link java.nio.charset.StandardCharsets#UTF_8} directly
-	 *             instead.
-	 */
-	@Deprecated
-	public static final String CHARACTER_ENCODING;
-
 	/** Default main branch name */
 	public static final String MASTER = "master";
 
@@ -277,6 +258,20 @@ public final class Constants {
 	public static final String INFO_REFS = "info/refs";
 
 	/**
+	 * Name of heads folder or file in refs.
+	 *
+	 * @since 7.0
+	 */
+	public static final String HEADS = "heads";
+
+	/**
+	 * Prefix for any log.
+	 *
+	 * @since 7.0
+	 */
+	public static final String L_LOGS = LOGS + "/";
+
+	/**
 	 * Info alternates file (goes under OBJECTS)
 	 * @since 5.5
 	 */
@@ -362,6 +357,14 @@ public final class Constants {
 	public static final String GIT_DIR_KEY = "GIT_DIR";
 
 	/**
+	 * The environment variable that tells us which directory is the common
+	 * ".git" directory.
+	 *
+	 * @since 7.0
+	 */
+	public static final String GIT_COMMON_DIR_KEY = "GIT_COMMON_DIR";
+
+	/**
 	 * The environment variable that tells us which directory is the working
 	 * directory.
 	 */
@@ -463,6 +466,36 @@ public final class Constants {
 	public static final String GITDIR = "gitdir: ";
 
 	/**
+	 * Name of the file (inside gitDir) that references the worktree's .git
+	 * file (opposite link).
+	 *
+	 * .git/worktrees/&lt;worktree-name&gt;/gitdir
+	 *
+	 * A text file containing the absolute path back to the .git file that
+	 * points here. This file is used to verify if the linked repository has been
+	 * manually removed in which case this directory is no longer needed.
+	 * The modification time (mtime) of this file should be updated each time
+	 * the linked repository is accessed.
+	 *
+	 * @since 7.0
+	 */
+	public static final String GITDIR_FILE = "gitdir";
+
+	/**
+	 * Name of the file (inside gitDir) that has reference to $GIT_COMMON_DIR.
+	 *
+	 * .git/worktrees/&lt;worktree-name&gt;/commondir
+	 *
+	 * If this file exists, $GIT_COMMON_DIR will be set to the path specified in
+	 * this file unless it is explicitly set. If the specified path is relative,
+	 * it is relative to $GIT_DIR. The repository with commondir is incomplete
+	 * without the repository pointed by "commondir".
+	 *
+	 * @since 7.0
+	 */
+	public static final String COMMONDIR_FILE = "commondir";
+
+	/**
 	 * Name of the folder (inside gitDir) where submodules are stored
 	 *
 	 * @since 3.6
@@ -498,6 +531,27 @@ public final class Constants {
 	public static final String ATTR_BUILTIN_BINARY_MERGER = "binary"; //$NON-NLS-1$
 
 	/**
+	 * Prefix of a GPG signature.
+	 *
+	 * @since 7.0
+	 */
+	public static final String GPG_SIGNATURE_PREFIX = "-----BEGIN PGP SIGNATURE-----"; //$NON-NLS-1$
+
+	/**
+	 * Prefix of a CMS signature (X.509, S/MIME).
+	 *
+	 * @since 7.0
+	 */
+	public static final String CMS_SIGNATURE_PREFIX = "-----BEGIN SIGNED MESSAGE-----"; //$NON-NLS-1$
+
+	/**
+	 * Prefix of an SSH signature.
+	 *
+	 * @since 7.0
+	 */
+	public static final String SSH_SIGNATURE_PREFIX = "-----BEGIN SSH SIGNATURE-----"; //$NON-NLS-1$
+
+	/**
 	 * Union built-in merge driver
 	 *
 	 * @since 6.10.1
@@ -684,13 +738,12 @@ public static int decodeTypeString(final AnyObjectId id,
 	}
 
 	/**
-	 * Convert a string to a byte array in the standard character encoding.
+	 * Convert a string to a byte array in the standard character encoding UTF8.
 	 *
 	 * @param str
 	 *            the string to convert. May contain any Unicode characters.
 	 * @return a byte array representing the requested string, encoded using the
 	 *         default character encoding (UTF-8).
-	 * @see #CHARACTER_ENCODING
 	 */
 	public static byte[] encode(String str) {
 		return str.getBytes(UTF_8);
@@ -699,8 +752,6 @@ public static int decodeTypeString(final AnyObjectId id,
 	static {
 		if (OBJECT_ID_LENGTH != newMessageDigest().getDigestLength())
 			throw new LinkageError(JGitText.get().incorrectOBJECT_ID_LENGTH);
-		CHARSET = UTF_8;
-		CHARACTER_ENCODING = UTF_8.name();
 	}
 
 	/** name of the file containing the commit msg for a merge commit */
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/CoreConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/CoreConfig.java
index 9fa5d75..49602a7 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/CoreConfig.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/CoreConfig.java
@@ -163,8 +163,6 @@ public enum TrustLooseRefStat {
 
 	private final int packIndexVersion;
 
-	private final LogRefUpdates logAllRefUpdates;
-
 	private final String excludesfile;
 
 	private final String attributesfile;
@@ -205,9 +203,6 @@ private CoreConfig(Config rc) {
 				ConfigConstants.CONFIG_KEY_COMPRESSION, DEFAULT_COMPRESSION);
 		packIndexVersion = rc.getInt(ConfigConstants.CONFIG_PACK_SECTION,
 				ConfigConstants.CONFIG_KEY_INDEXVERSION, 2);
-		logAllRefUpdates = rc.getEnum(ConfigConstants.CONFIG_CORE_SECTION, null,
-				ConfigConstants.CONFIG_KEY_LOGALLREFUPDATES,
-				LogRefUpdates.TRUE);
 		excludesfile = rc.getString(ConfigConstants.CONFIG_CORE_SECTION, null,
 				ConfigConstants.CONFIG_KEY_EXCLUDESFILE);
 		attributesfile = rc.getString(ConfigConstants.CONFIG_CORE_SECTION,
@@ -236,20 +231,6 @@ public int getPackIndexVersion() {
 	}
 
 	/**
-	 * Whether to log all refUpdates
-	 *
-	 * @return whether to log all refUpdates
-	 * @deprecated since 5.6; default value depends on whether the repository is
-	 *             bare. Use
-	 *             {@link Config#getEnum(String, String, String, Enum)}
-	 *             directly.
-	 */
-	@Deprecated
-	public boolean isLogAllRefUpdates() {
-		return !LogRefUpdates.FALSE.equals(logAllRefUpdates);
-	}
-
-	/**
 	 * Get path of excludesfile
 	 *
 	 * @return path of excludesfile
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgConfig.java
index 427a235..fb5c904 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgConfig.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgConfig.java
@@ -24,7 +24,13 @@ public enum GpgFormat implements Config.ConfigEnum {
 		/** Value for openpgp */
 		OPENPGP("openpgp"), //$NON-NLS-1$
 		/** Value for x509 */
-		X509("x509"); //$NON-NLS-1$
+		X509("x509"), //$NON-NLS-1$
+		/**
+		 * Value for ssh.
+		 *
+		 * @since 7.0
+		 */
+		SSH("ssh"); //$NON-NLS-1$
 
 		private final String configValue;
 
@@ -56,27 +62,6 @@ public String toConfigValue() {
 	private final boolean forceAnnotated;
 
 	/**
-	 * Create a {@link GpgConfig} with the given parameters and default
-	 * {@code true} for signing commits and {@code false} for tags.
-	 *
-	 * @param keySpec
-	 *            to use
-	 * @param format
-	 *            to use
-	 * @param gpgProgram
-	 *            to use
-	 * @since 5.11
-	 */
-	public GpgConfig(String keySpec, GpgFormat format, String gpgProgram) {
-		keyFormat = format;
-		signingKey = keySpec;
-		program = gpgProgram;
-		signCommits = true;
-		signAllTags = false;
-		forceAnnotated = false;
-	}
-
-	/**
 	 * Create a new GPG config that reads the configuration from config.
 	 *
 	 * @param config
@@ -91,10 +76,11 @@ public GpgConfig(Config config) {
 
 		String exe = config.getString(ConfigConstants.CONFIG_GPG_SECTION,
 				keyFormat.toConfigValue(), ConfigConstants.CONFIG_KEY_PROGRAM);
-		if (exe == null) {
+		if (exe == null && GpgFormat.OPENPGP.equals(keyFormat)) {
 			exe = config.getString(ConfigConstants.CONFIG_GPG_SECTION, null,
 					ConfigConstants.CONFIG_KEY_PROGRAM);
 		}
+
 		program = exe;
 		signCommits = config.getBoolean(ConfigConstants.CONFIG_COMMIT_SECTION,
 				ConfigConstants.CONFIG_KEY_GPGSIGN, false);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgObjectSigner.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgObjectSigner.java
deleted file mode 100644
index 074f465..0000000
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgObjectSigner.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2020 Thomas Wolf <thomas.wolf@paranor.ch> and others
- *
- * 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.annotations.NonNull;
-import org.eclipse.jgit.annotations.Nullable;
-import org.eclipse.jgit.api.errors.CanceledException;
-import org.eclipse.jgit.api.errors.UnsupportedSigningFormatException;
-import org.eclipse.jgit.transport.CredentialsProvider;
-
-/**
- * Creates GPG signatures for Git objects.
- *
- * @since 5.11
- */
-public interface GpgObjectSigner {
-
-	/**
-	 * Signs the specified object.
-	 *
-	 * <p>
-	 * Implementors should obtain the payload for signing from the specified
-	 * object via {@link ObjectBuilder#build()} and create a proper
-	 * {@link GpgSignature}. The generated signature must be set on the
-	 * specified {@code object} (see
-	 * {@link ObjectBuilder#setGpgSignature(GpgSignature)}).
-	 * </p>
-	 * <p>
-	 * Any existing signature on the object must be discarded prior obtaining
-	 * the payload via {@link ObjectBuilder#build()}.
-	 * </p>
-	 *
-	 * @param object
-	 *            the object to sign (must not be {@code null} and must be
-	 *            complete to allow proper calculation of payload)
-	 * @param gpgSigningKey
-	 *            the signing key to locate (passed as is to the GPG signing
-	 *            tool as is; eg., value of <code>user.signingkey</code>)
-	 * @param committer
-	 *            the signing identity (to help with key lookup in case signing
-	 *            key is not specified)
-	 * @param credentialsProvider
-	 *            provider to use when querying for signing key credentials (eg.
-	 *            passphrase)
-	 * @param config
-	 *            GPG settings from the git config
-	 * @throws CanceledException
-	 *             when signing was canceled (eg., user aborted when entering
-	 *             passphrase)
-	 * @throws UnsupportedSigningFormatException
-	 *             if a config is given and the wanted key format is not
-	 *             supported
-	 */
-	void signObject(@NonNull ObjectBuilder object,
-			@Nullable String gpgSigningKey, @NonNull PersonIdent committer,
-			CredentialsProvider credentialsProvider, GpgConfig config)
-			throws CanceledException, UnsupportedSigningFormatException;
-
-	/**
-	 * Indicates if a signing key is available for the specified committer
-	 * and/or signing key.
-	 *
-	 * @param gpgSigningKey
-	 *            the signing key to locate (passed as is to the GPG signing
-	 *            tool as is; eg., value of <code>user.signingkey</code>)
-	 * @param committer
-	 *            the signing identity (to help with key lookup in case signing
-	 *            key is not specified)
-	 * @param credentialsProvider
-	 *            provider to use when querying for signing key credentials (eg.
-	 *            passphrase)
-	 * @param config
-	 *            GPG settings from the git config
-	 * @return <code>true</code> if a signing key is available,
-	 *         <code>false</code> otherwise
-	 * @throws CanceledException
-	 *             when signing was canceled (eg., user aborted when entering
-	 *             passphrase)
-	 * @throws UnsupportedSigningFormatException
-	 *             if a config is given and the wanted key format is not
-	 *             supported
-	 */
-	public abstract boolean canLocateSigningKey(@Nullable String gpgSigningKey,
-			@NonNull PersonIdent committer,
-			CredentialsProvider credentialsProvider, GpgConfig config)
-			throws CanceledException, UnsupportedSigningFormatException;
-
-}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgSignatureVerifier.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgSignatureVerifier.java
deleted file mode 100644
index 91c9bab..0000000
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgSignatureVerifier.java
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (C) 2021, 2024 Thomas Wolf <twolf@apache.org> and others
- *
- * 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 java.io.IOException;
-import java.util.Date;
-
-import org.eclipse.jgit.annotations.NonNull;
-import org.eclipse.jgit.annotations.Nullable;
-import org.eclipse.jgit.api.errors.JGitInternalException;
-import org.eclipse.jgit.revwalk.RevObject;
-
-/**
- * A {@code GpgSignatureVerifier} can verify GPG signatures on git commits and
- * tags.
- *
- * @since 5.11
- */
-public interface GpgSignatureVerifier {
-
-	/**
-	 * Verifies the signature on a signed commit or tag.
-	 *
-	 * @param object
-	 *            to verify
-	 * @param config
-	 *            the {@link GpgConfig} to use
-	 * @return a {@link SignatureVerification} describing the outcome of the
-	 *         verification, or {@code null} if the object was not signed
-	 * @throws IOException
-	 *             if an error occurs getting a public key
-	 * @throws org.eclipse.jgit.api.errors.JGitInternalException
-	 *             if signature verification fails
-	 */
-	@Nullable
-	SignatureVerification verifySignature(@NonNull RevObject object,
-			@NonNull GpgConfig config) throws IOException;
-
-	/**
-	 * Verifies a given signature for given data.
-	 *
-	 * @param config
-	 *            the {@link GpgConfig}
-	 * @param data
-	 *            the signature is for
-	 * @param signatureData
-	 *            the ASCII-armored signature
-	 * @return a {@link SignatureVerification} describing the outcome
-	 * @throws IOException
-	 *             if the signature cannot be parsed
-	 * @throws JGitInternalException
-	 *             if signature verification fails
-	 * @since 6.9
-	 */
-	default SignatureVerification verify(@NonNull GpgConfig config, byte[] data,
-			byte[] signatureData) throws IOException {
-		// Default implementation for backwards compatibility; override as
-		// appropriate
-		return verify(data, signatureData);
-	}
-
-	/**
-	 * Verifies a given signature for given data.
-	 *
-	 * @param data
-	 *            the signature is for
-	 * @param signatureData
-	 *            the ASCII-armored signature
-	 * @return a {@link SignatureVerification} describing the outcome
-	 * @throws IOException
-	 *             if the signature cannot be parsed
-	 * @throws JGitInternalException
-	 *             if signature verification fails
-	 * @deprecated since 6.9, use {@link #verify(GpgConfig, byte[], byte[])}
-	 *             instead
-	 */
-	@Deprecated
-	public SignatureVerification verify(byte[] data, byte[] signatureData)
-			throws IOException;
-
-	/**
-	 * Retrieves the name of this verifier. This should be a short string
-	 * identifying the engine that verified the signature, like "gpg" if GPG is
-	 * used, or "bc" for a BouncyCastle implementation.
-	 *
-	 * @return the name
-	 */
-	@NonNull
-	String getName();
-
-	/**
-	 * A {@link GpgSignatureVerifier} may cache public keys to speed up
-	 * verifying signatures on multiple objects. This clears this cache, if any.
-	 */
-	void clear();
-
-	/**
-	 * A {@code SignatureVerification} returns data about a (positively or
-	 * negatively) verified signature.
-	 */
-	interface SignatureVerification {
-
-		// Data about the signature.
-
-		@NonNull
-		Date getCreationDate();
-
-		// Data from the signature used to find a public key.
-
-		/**
-		 * Obtains the signer as stored in the signature, if known.
-		 *
-		 * @return the signer, or {@code null} if unknown
-		 */
-		String getSigner();
-
-		/**
-		 * Obtains the short or long fingerprint of the public key as stored in
-		 * the signature, if known.
-		 *
-		 * @return the fingerprint, or {@code null} if unknown
-		 */
-		String getKeyFingerprint();
-
-		// Some information about the found public key.
-
-		/**
-		 * Obtains the OpenPGP user ID associated with the key.
-		 *
-		 * @return the user id, or {@code null} if unknown
-		 */
-		String getKeyUser();
-
-		/**
-		 * Tells whether the public key used for this signature verification was
-		 * expired when the signature was created.
-		 *
-		 * @return {@code true} if the key was expired already, {@code false}
-		 *         otherwise
-		 */
-		boolean isExpired();
-
-		/**
-		 * Obtains the trust level of the public key used to verify the
-		 * signature.
-		 *
-		 * @return the trust level
-		 */
-		@NonNull
-		TrustLevel getTrustLevel();
-
-		// The verification result.
-
-		/**
-		 * Tells whether the signature verification was successful.
-		 *
-		 * @return {@code true} if the signature was verified successfully;
-		 *         {@code false} if not.
-		 */
-		boolean getVerified();
-
-		/**
-		 * Obtains a human-readable message giving additional information about
-		 * the outcome of the verification.
-		 *
-		 * @return the message, or {@code null} if none set.
-		 */
-		String getMessage();
-	}
-
-	/**
-	 * The owner's trust in a public key.
-	 */
-	enum TrustLevel {
-		UNKNOWN, NEVER, MARGINAL, FULL, ULTIMATE
-	}
-}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgSignatureVerifierFactory.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgSignatureVerifierFactory.java
deleted file mode 100644
index 59775c4..0000000
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgSignatureVerifierFactory.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2021, 2022 Thomas Wolf <thomas.wolf@paranor.ch> and others
- *
- * 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 java.util.Iterator;
-import java.util.ServiceConfigurationError;
-import java.util.ServiceLoader;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * A {@code GpgSignatureVerifierFactory} creates {@link GpgSignatureVerifier} instances.
- *
- * @since 5.11
- */
-public abstract class GpgSignatureVerifierFactory {
-
-	private static final Logger LOG = LoggerFactory
-			.getLogger(GpgSignatureVerifierFactory.class);
-
-	private static class DefaultFactory {
-
-		private static volatile GpgSignatureVerifierFactory defaultFactory = loadDefault();
-
-		private static GpgSignatureVerifierFactory loadDefault() {
-			try {
-				ServiceLoader<GpgSignatureVerifierFactory> loader = ServiceLoader
-						.load(GpgSignatureVerifierFactory.class);
-				Iterator<GpgSignatureVerifierFactory> iter = loader.iterator();
-				if (iter.hasNext()) {
-					return iter.next();
-				}
-			} catch (ServiceConfigurationError e) {
-				LOG.error(e.getMessage(), e);
-			}
-			return null;
-		}
-
-		private DefaultFactory() {
-			// No instantiation
-		}
-
-		public static GpgSignatureVerifierFactory getDefault() {
-			return defaultFactory;
-		}
-
-		/**
-		 * Sets the default factory.
-		 *
-		 * @param factory
-		 *            the new default factory
-		 */
-		public static void setDefault(GpgSignatureVerifierFactory factory) {
-			defaultFactory = factory;
-		}
-	}
-
-	/**
-	 * Retrieves the default factory.
-	 *
-	 * @return the default factory or {@code null} if none set
-	 */
-	public static GpgSignatureVerifierFactory getDefault() {
-		return DefaultFactory.getDefault();
-	}
-
-	/**
-	 * Sets the default factory.
-	 *
-	 * @param factory
-	 *            the new default factory
-	 */
-	public static void setDefault(GpgSignatureVerifierFactory factory) {
-		DefaultFactory.setDefault(factory);
-	}
-
-	/**
-	 * Creates a new {@link GpgSignatureVerifier}.
-	 *
-	 * @return the new {@link GpgSignatureVerifier}
-	 */
-	public abstract GpgSignatureVerifier getVerifier();
-
-}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgSigner.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgSigner.java
deleted file mode 100644
index b25a61b..0000000
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgSigner.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (C) 2018, 2022 Salesforce and others
- *
- * 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 java.util.Iterator;
-import java.util.ServiceConfigurationError;
-import java.util.ServiceLoader;
-
-import org.eclipse.jgit.annotations.NonNull;
-import org.eclipse.jgit.annotations.Nullable;
-import org.eclipse.jgit.api.errors.CanceledException;
-import org.eclipse.jgit.transport.CredentialsProvider;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Creates GPG signatures for Git objects.
- *
- * @since 5.3
- */
-public abstract class GpgSigner {
-
-	private static final Logger LOG = LoggerFactory.getLogger(GpgSigner.class);
-
-	private static class DefaultSigner {
-
-		private static volatile GpgSigner defaultSigner = loadGpgSigner();
-
-		private static GpgSigner loadGpgSigner() {
-			try {
-				ServiceLoader<GpgSigner> loader = ServiceLoader
-						.load(GpgSigner.class);
-				Iterator<GpgSigner> iter = loader.iterator();
-				if (iter.hasNext()) {
-					return iter.next();
-				}
-			} catch (ServiceConfigurationError e) {
-				LOG.error(e.getMessage(), e);
-			}
-			return null;
-		}
-
-		private DefaultSigner() {
-			// No instantiation
-		}
-
-		public static GpgSigner getDefault() {
-			return defaultSigner;
-		}
-
-		public static void setDefault(GpgSigner signer) {
-			defaultSigner = signer;
-		}
-	}
-
-	/**
-	 * Get the default signer, or <code>null</code>.
-	 *
-	 * @return the default signer, or <code>null</code>.
-	 */
-	public static GpgSigner getDefault() {
-		return DefaultSigner.getDefault();
-	}
-
-	/**
-	 * Set the default signer.
-	 *
-	 * @param signer
-	 *            the new default signer, may be <code>null</code> to select no
-	 *            default.
-	 */
-	public static void setDefault(GpgSigner signer) {
-		DefaultSigner.setDefault(signer);
-	}
-
-	/**
-	 * Signs the specified commit.
-	 *
-	 * <p>
-	 * Implementors should obtain the payload for signing from the specified
-	 * commit via {@link CommitBuilder#build()} and create a proper
-	 * {@link GpgSignature}. The generated signature must be set on the
-	 * specified {@code commit} (see
-	 * {@link CommitBuilder#setGpgSignature(GpgSignature)}).
-	 * </p>
-	 * <p>
-	 * Any existing signature on the commit must be discarded prior obtaining
-	 * the payload via {@link CommitBuilder#build()}.
-	 * </p>
-	 *
-	 * @param commit
-	 *            the commit to sign (must not be <code>null</code> and must be
-	 *            complete to allow proper calculation of payload)
-	 * @param gpgSigningKey
-	 *            the signing key to locate (passed as is to the GPG signing
-	 *            tool as is; eg., value of <code>user.signingkey</code>)
-	 * @param committer
-	 *            the signing identity (to help with key lookup in case signing
-	 *            key is not specified)
-	 * @param credentialsProvider
-	 *            provider to use when querying for signing key credentials (eg.
-	 *            passphrase)
-	 * @throws CanceledException
-	 *             when signing was canceled (eg., user aborted when entering
-	 *             passphrase)
-	 */
-	public abstract void sign(@NonNull CommitBuilder commit,
-			@Nullable String gpgSigningKey, @NonNull PersonIdent committer,
-			CredentialsProvider credentialsProvider) throws CanceledException;
-
-	/**
-	 * Indicates if a signing key is available for the specified committer
-	 * and/or signing key.
-	 *
-	 * @param gpgSigningKey
-	 *            the signing key to locate (passed as is to the GPG signing
-	 *            tool as is; eg., value of <code>user.signingkey</code>)
-	 * @param committer
-	 *            the signing identity (to help with key lookup in case signing
-	 *            key is not specified)
-	 * @param credentialsProvider
-	 *            provider to use when querying for signing key credentials (eg.
-	 *            passphrase)
-	 * @return <code>true</code> if a signing key is available,
-	 *         <code>false</code> otherwise
-	 * @throws CanceledException
-	 *             when signing was canceled (eg., user aborted when entering
-	 *             passphrase)
-	 */
-	public abstract boolean canLocateSigningKey(@Nullable String gpgSigningKey,
-			@NonNull PersonIdent committer,
-			CredentialsProvider credentialsProvider) throws CanceledException;
-
-}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/IndexDiff.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/IndexDiff.java
index 8e965c5..a99c647 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/IndexDiff.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/IndexDiff.java
@@ -639,7 +639,7 @@ public boolean diff(ProgressMonitor monitor, int estWorkTreeSize,
 							// submodule repository in .git/modules doesn't
 							// exist yet it isn't "missing".
 							File gitDir = new File(
-									new File(repository.getDirectory(),
+									new File(repository.getCommonDirectory(),
 											Constants.MODULES),
 									subRepoPath);
 							if (!gitDir.isDirectory()) {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectId.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectId.java
index 1c31263..1b455b9 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectId.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectId.java
@@ -15,6 +15,7 @@
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
 import java.io.Serializable;
+import java.nio.ByteBuffer;
 
 import org.eclipse.jgit.annotations.Nullable;
 import org.eclipse.jgit.errors.InvalidObjectIdException;
@@ -152,6 +153,22 @@ public static final ObjectId fromRaw(byte[] bs, int p) {
 	}
 
 	/**
+	 * Convert an ObjectId from raw binary representation
+	 *
+	 * @param bb
+	 *            a bytebuffer with the objectid encoded as 5 consecutive ints.
+	 *            This is the reverse of {@link ObjectId#copyRawTo(ByteBuffer)}
+	 *
+	 * @return the converted object id.
+	 *
+	 * @since 7.0
+	 */
+	public static final ObjectId fromRaw(ByteBuffer bb) {
+		return new ObjectId(bb.getInt(), bb.getInt(), bb.getInt(), bb.getInt(),
+				bb.getInt());
+	}
+
+	/**
 	 * Convert an ObjectId from raw binary representation.
 	 *
 	 * @param is
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDatabase.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDatabase.java
index 9e05a39..2cf2418 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDatabase.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDatabase.java
@@ -238,23 +238,6 @@ public boolean performsAtomicTransactions() {
 	}
 
 	/**
-	 * Compatibility synonym for {@link #findRef(String)}.
-	 *
-	 * @param name
-	 *            the name of the reference. May be a short name which must be
-	 *            searched for using the standard {@link #SEARCH_PATH}.
-	 * @return the reference (if it exists); else {@code null}.
-	 * @throws IOException
-	 *             the reference space cannot be accessed.
-	 * @deprecated Use {@link #findRef(String)} instead.
-	 */
-	@Deprecated
-	@Nullable
-	public final Ref getRef(String name) throws IOException {
-		return findRef(name);
-	}
-
-	/**
 	 * Read a single reference.
 	 * <p>
 	 * Aside from taking advantage of {@link #SEARCH_PATH}, this method may be
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java
index 4722e29..0562840 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java
@@ -113,9 +113,12 @@ public static ListenerList getGlobalListenerList() {
 
 	final AtomicLong closedAt = new AtomicLong();
 
-	/** Metadata directory holding the repository's critical files. */
+	/** $GIT_DIR: metadata directory holding the repository's critical files. */
 	private final File gitDir;
 
+	/** $GIT_COMMON_DIR: metadata directory holding the common repository's critical files.  */
+	private final File gitCommonDir;
+
 	/** File abstraction used to resolve paths. */
 	private final FS fs;
 
@@ -137,6 +140,7 @@ public static ListenerList getGlobalListenerList() {
 	 */
 	protected Repository(BaseRepositoryBuilder options) {
 		gitDir = options.getGitDir();
+		gitCommonDir = options.getGitCommonDir();
 		fs = options.getFS();
 		workTree = options.getWorkTree();
 		indexFile = options.getIndexFile();
@@ -220,6 +224,16 @@ public File getDirectory() {
 	public abstract String getIdentifier();
 
 	/**
+	 * Get common dir.
+	 *
+	 * @return $GIT_COMMON_DIR: local common metadata directory;
+	 * @since 7.0
+	 */
+	public File getCommonDirectory() {
+		return gitCommonDir;
+	}
+
+	/**
 	 * Get the object database which stores this repository's data.
 	 *
 	 * @return the object database which stores this repository's data.
@@ -293,25 +307,6 @@ public FS getFS() {
 	}
 
 	/**
-	 * Whether the specified object is stored in this repo or any of the known
-	 * shared repositories.
-	 *
-	 * @param objectId
-	 *            a {@link org.eclipse.jgit.lib.AnyObjectId} object.
-	 * @return true if the specified object is stored in this repo or any of the
-	 *         known shared repositories.
-	 * @deprecated use {@code getObjectDatabase().has(objectId)}
-	 */
-	@Deprecated
-	public boolean hasObject(AnyObjectId objectId) {
-		try {
-			return getObjectDatabase().has(objectId);
-		} catch (IOException e) {
-			throw new UncheckedIOException(e);
-		}
-	}
-
-	/**
 	 * Open an object from this repository.
 	 * <p>
 	 * This is a one-shot call interface which may be faster than allocating a
@@ -1150,11 +1145,9 @@ public Map<String, Ref> getTags() {
 	 *         new Ref object representing the same data as Ref, but isPeeled()
 	 *         will be true and getPeeledObjectId will contain the peeled object
 	 *         (or null).
-	 * @deprecated use {@code getRefDatabase().peel(ref)} instead.
 	 */
-	@Deprecated
 	@NonNull
-	public Ref peel(Ref ref) {
+	private Ref peel(Ref ref) {
 		try {
 			return getRefDatabase().peel(ref);
 		} catch (IOException e) {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCache.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCache.java
index 6288447..1836654 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCache.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCache.java
@@ -450,10 +450,21 @@ public String toString() {
 		 *         Git directory.
 		 */
 		public static boolean isGitRepository(File dir, FS fs) {
-			return fs.resolve(dir, Constants.OBJECTS).exists()
-					&& fs.resolve(dir, "refs").exists() //$NON-NLS-1$
-					&& (fs.resolve(dir, Constants.REFTABLE).exists()
-							|| isValidHead(new File(dir, Constants.HEAD)));
+			// check if common-dir available or fallback to git-dir
+			File commonDir;
+			try {
+				commonDir = fs.getCommonDir(dir);
+			} catch (IOException e) {
+				commonDir = null;
+			}
+			if (commonDir == null) {
+				commonDir = dir;
+			}
+			return fs.resolve(commonDir, Constants.OBJECTS).exists()
+					&& fs.resolve(commonDir, "refs").exists() //$NON-NLS-1$
+					&& (fs.resolve(commonDir, Constants.REFTABLE).exists()
+							|| isValidHead(
+									new File(commonDir, Constants.HEAD)));
 		}
 
 		private static boolean isValidHead(File head) {
@@ -496,15 +507,31 @@ private static String readFirstLine(File head) {
 		 *         null if there is no suitable match.
 		 */
 		public static File resolve(File directory, FS fs) {
-			if (isGitRepository(directory, fs))
+			// the folder itself
+			if (isGitRepository(directory, fs)) {
 				return directory;
-			if (isGitRepository(new File(directory, Constants.DOT_GIT), fs))
-				return new File(directory, Constants.DOT_GIT);
-
-			final String name = directory.getName();
-			final File parent = directory.getParentFile();
-			if (isGitRepository(new File(parent, name + Constants.DOT_GIT_EXT), fs))
-				return new File(parent, name + Constants.DOT_GIT_EXT);
+			}
+			// the .git subfolder or file (reference)
+			File dotDir = new File(directory, Constants.DOT_GIT);
+			if (dotDir.isFile()) {
+				try {
+					File refDir = BaseRepositoryBuilder.getSymRef(directory,
+							dotDir, fs);
+					if (refDir != null && isGitRepository(refDir, fs)) {
+						return refDir;
+					}
+				} catch (IOException ignored) {
+					// Continue searching if gitdir ref isn't found
+				}
+			} else if (isGitRepository(dotDir, fs)) {
+				return dotDir;
+			}
+			// the folder extended with .git (bare)
+			File bareDir = new File(directory.getParentFile(),
+					directory.getName() + Constants.DOT_GIT_EXT);
+			if (isGitRepository(bareDir, fs)) {
+				return bareDir;
+			}
 			return null;
 		}
 	}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/SignatureVerifier.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/SignatureVerifier.java
new file mode 100644
index 0000000..2ce2708
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/SignatureVerifier.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2021, 2024 Thomas Wolf <twolf@apache.org> and others
+ *
+ * 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 java.io.IOException;
+import java.util.Date;
+
+import org.eclipse.jgit.annotations.NonNull;
+import org.eclipse.jgit.api.errors.JGitInternalException;
+
+/**
+ * A {@code SignatureVerifier} can verify signatures on git commits and tags.
+ *
+ * @since 7.0
+ */
+public interface SignatureVerifier {
+
+	/**
+	 * Verifies a given signature for given data.
+	 *
+	 * @param repository
+	 *            the {@link Repository} the data comes from.
+	 * @param config
+	 *            the {@link GpgConfig}
+	 * @param data
+	 *            the signature is for
+	 * @param signatureData
+	 *            the ASCII-armored signature
+	 * @return a {@link SignatureVerification} describing the outcome
+	 * @throws IOException
+	 *             if the signature cannot be parsed
+	 * @throws JGitInternalException
+	 *             if signature verification fails
+	 */
+	SignatureVerification verify(@NonNull Repository repository,
+			@NonNull GpgConfig config, byte[] data, byte[] signatureData)
+			throws IOException;
+
+	/**
+	 * Retrieves the name of this verifier. This should be a short string
+	 * identifying the engine that verified the signature, like "gpg" if GPG is
+	 * used, or "bc" for a BouncyCastle implementation.
+	 *
+	 * @return the name
+	 */
+	@NonNull
+	String getName();
+
+	/**
+	 * A {@link SignatureVerifier} may cache public keys to speed up
+	 * verifying signatures on multiple objects. This clears this cache, if any.
+	 */
+	void clear();
+
+	/**
+	 * A {@code SignatureVerification} returns data about a (positively or
+	 * negatively) verified signature.
+	 *
+	 * @param verifierName
+	 *            the name of the verifier that created this verification result
+	 * @param creationDate
+	 *            date and time the signature was created
+	 * @param signer
+	 *            the signer as stored in the signature, or {@code null} if
+	 *            unknown
+	 * @param keyFingerprint
+	 *            fingerprint of the public key, or {@code null} if unknown
+	 * @param keyUser
+	 *            user associated with the key, or {@code null} if unknown
+	 * @param verified
+	 *            whether the signature verification was successful
+	 * @param expired
+	 *            whether the public key used for this signature verification
+	 *            was expired when the signature was created
+	 * @param trustLevel
+	 *            the trust level of the public key used to verify the signature
+	 * @param message
+	 *            human-readable message giving additional information about the
+	 *            outcome of the verification, possibly {@code null}
+	 */
+	record SignatureVerification(
+			String verifierName,
+			Date creationDate,
+			String signer,
+			String keyFingerprint,
+			String keyUser,
+			boolean verified,
+			boolean expired,
+			@NonNull TrustLevel trustLevel,
+			String message) {
+	}
+
+	/**
+	 * The owner's trust in a public key.
+	 */
+	enum TrustLevel {
+		UNKNOWN, NEVER, MARGINAL, FULL, ULTIMATE
+	}
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/SignatureVerifierFactory.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/SignatureVerifierFactory.java
new file mode 100644
index 0000000..7844aba
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/SignatureVerifierFactory.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2024 Thomas Wolf <twolf@apache.org> and others
+ *
+ * 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.annotations.NonNull;
+
+/**
+ * A factory for {@link SignatureVerifier}s.
+ *
+ * @since 7.0
+ */
+public interface SignatureVerifierFactory {
+
+	/**
+	 * Tells what kind of {@link SignatureVerifier} this factory creates.
+	 *
+	 * @return the {@link GpgConfig.GpgFormat} of the signer
+	 */
+	@NonNull
+	GpgConfig.GpgFormat getType();
+
+	/**
+	 * Creates a new instance of a {@link SignatureVerifier} that can produce
+	 * signatures of type {@link #getType()}.
+	 *
+	 * @return a new {@link SignatureVerifier}
+	 */
+	@NonNull
+	SignatureVerifier create();
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/SignatureVerifiers.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/SignatureVerifiers.java
new file mode 100644
index 0000000..01c8422
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/SignatureVerifiers.java
@@ -0,0 +1,239 @@
+/*
+ * Copyright (C) 2024 Thomas Wolf <twolf@apache.org> and others
+ *
+ * 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 java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.text.MessageFormat;
+import java.util.Arrays;
+import java.util.EnumMap;
+import java.util.Map;
+import java.util.ServiceConfigurationError;
+import java.util.ServiceLoader;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.eclipse.jgit.annotations.NonNull;
+import org.eclipse.jgit.annotations.Nullable;
+import org.eclipse.jgit.internal.JGitText;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevObject;
+import org.eclipse.jgit.revwalk.RevTag;
+import org.eclipse.jgit.util.RawParseUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Manages the available signers.
+ *
+ * @since 7.0
+ */
+public final class SignatureVerifiers {
+
+	private static final Logger LOG = LoggerFactory.getLogger(SignatureVerifiers.class);
+
+	private static final byte[] PGP_PREFIX = Constants.GPG_SIGNATURE_PREFIX
+			.getBytes(StandardCharsets.US_ASCII);
+
+	private static final byte[] X509_PREFIX = Constants.CMS_SIGNATURE_PREFIX
+			.getBytes(StandardCharsets.US_ASCII);
+
+	private static final byte[] SSH_PREFIX = Constants.SSH_SIGNATURE_PREFIX
+			.getBytes(StandardCharsets.US_ASCII);
+
+	private static final Map<GpgConfig.GpgFormat, SignatureVerifierFactory> FACTORIES = loadSignatureVerifiers();
+
+	private static final Map<GpgConfig.GpgFormat, SignatureVerifier> VERIFIERS = new ConcurrentHashMap<>();
+
+	private static Map<GpgConfig.GpgFormat, SignatureVerifierFactory> loadSignatureVerifiers() {
+		Map<GpgConfig.GpgFormat, SignatureVerifierFactory> result = new EnumMap<>(
+				GpgConfig.GpgFormat.class);
+		try {
+			for (SignatureVerifierFactory factory : ServiceLoader
+					.load(SignatureVerifierFactory.class)) {
+				GpgConfig.GpgFormat format = factory.getType();
+				SignatureVerifierFactory existing = result.get(format);
+				if (existing != null) {
+					LOG.warn("{}", //$NON-NLS-1$
+							MessageFormat.format(
+									JGitText.get().signatureServiceConflict,
+									"SignatureVerifierFactory", format, //$NON-NLS-1$
+									existing.getClass().getCanonicalName(),
+									factory.getClass().getCanonicalName()));
+				} else {
+					result.put(format, factory);
+				}
+			}
+		} catch (ServiceConfigurationError e) {
+			LOG.error(e.getMessage(), e);
+		}
+		return result;
+	}
+
+	private SignatureVerifiers() {
+		// No instantiation
+	}
+
+	/**
+	 * Retrieves a {@link Signer} that can produce signatures of the given type
+	 * {@code format}.
+	 *
+	 * @param format
+	 *            {@link GpgConfig.GpgFormat} the signer must support
+	 * @return a {@link Signer}, or {@code null} if none is available
+	 */
+	public static SignatureVerifier get(@NonNull GpgConfig.GpgFormat format) {
+		return VERIFIERS.computeIfAbsent(format, f -> {
+			SignatureVerifierFactory factory = FACTORIES.get(format);
+			if (factory == null) {
+				return null;
+			}
+			return factory.create();
+		});
+	}
+
+	/**
+	 * Sets a specific signature verifier to use for a specific signature type.
+	 *
+	 * @param format
+	 *            signature type to set the {@code verifier} for
+	 * @param verifier
+	 *            the {@link SignatureVerifier} to use for signatures of type
+	 *            {@code format}; if {@code null}, a default implementation, if
+	 *            available, may be used.
+	 */
+	public static void set(@NonNull GpgConfig.GpgFormat format,
+			SignatureVerifier verifier) {
+		SignatureVerifier previous;
+		if (verifier == null) {
+			previous = VERIFIERS.remove(format);
+		} else {
+			previous = VERIFIERS.put(format, verifier);
+		}
+		if (previous != null) {
+			previous.clear();
+		}
+	}
+
+	/**
+	 * Verifies the signature on a signed commit or tag.
+	 *
+	 * @param repository
+	 *            the {@link Repository} the object is from
+	 * @param config
+	 *            the {@link GpgConfig} to use
+	 * @param object
+	 *            to verify
+	 * @return a {@link SignatureVerifier.SignatureVerification} describing the
+	 *         outcome of the verification, or {@code null} if the object does
+	 *         not have a signature of a known type
+	 * @throws IOException
+	 *             if an error occurs getting a public key
+	 * @throws org.eclipse.jgit.api.errors.JGitInternalException
+	 *             if signature verification fails
+	 */
+	@Nullable
+	public static SignatureVerifier.SignatureVerification verify(
+			@NonNull Repository repository, @NonNull GpgConfig config,
+			@NonNull RevObject object) throws IOException {
+		if (object instanceof RevCommit) {
+			RevCommit commit = (RevCommit) object;
+			byte[] signatureData = commit.getRawGpgSignature();
+			if (signatureData == null) {
+				return null;
+			}
+			byte[] raw = commit.getRawBuffer();
+			// Now remove the GPG signature
+			byte[] header = { 'g', 'p', 'g', 's', 'i', 'g' };
+			int start = RawParseUtils.headerStart(header, raw, 0);
+			if (start < 0) {
+				return null;
+			}
+			int end = RawParseUtils.nextLfSkippingSplitLines(raw, start);
+			// start is at the beginning of the header's content
+			start -= header.length + 1;
+			// end is on the terminating LF; we need to skip that, too
+			if (end < raw.length) {
+				end++;
+			}
+			byte[] data = new byte[raw.length - (end - start)];
+			System.arraycopy(raw, 0, data, 0, start);
+			System.arraycopy(raw, end, data, start, raw.length - end);
+			return verify(repository, config, data, signatureData);
+		} else if (object instanceof RevTag) {
+			RevTag tag = (RevTag) object;
+			byte[] signatureData = tag.getRawGpgSignature();
+			if (signatureData == null) {
+				return null;
+			}
+			byte[] raw = tag.getRawBuffer();
+			// The signature is just tacked onto the end of the message, which
+			// is last in the buffer.
+			byte[] data = Arrays.copyOfRange(raw, 0,
+					raw.length - signatureData.length);
+			return verify(repository, config, data, signatureData);
+		}
+		return null;
+	}
+
+	/**
+	 * Verifies a given signature for some give data.
+	 *
+	 * @param repository
+	 *            the {@link Repository} the object is from
+	 * @param config
+	 *            the {@link GpgConfig} to use
+	 * @param data
+	 *            to verify the signature of
+	 * @param signature
+	 *            the given signature of the {@code data}
+	 * @return a {@link SignatureVerifier.SignatureVerification} describing the
+	 *         outcome of the verification, or {@code null} if the signature
+	 *         type is unknown
+	 * @throws IOException
+	 *             if an error occurs getting a public key
+	 * @throws org.eclipse.jgit.api.errors.JGitInternalException
+	 *             if signature verification fails
+	 */
+	@Nullable
+	public static SignatureVerifier.SignatureVerification verify(
+			@NonNull Repository repository, @NonNull GpgConfig config,
+			byte[] data, byte[] signature) throws IOException {
+		GpgConfig.GpgFormat format = getFormat(signature);
+		if (format == null) {
+			return null;
+		}
+		SignatureVerifier verifier = get(format);
+		if (verifier == null) {
+			return null;
+		}
+		return verifier.verify(repository, config, data, signature);
+	}
+
+	/**
+	 * Determines the type of a given signature.
+	 *
+	 * @param signature
+	 *            to get the type of
+	 * @return the signature type, or {@code null} if unknown
+	 */
+	@Nullable
+	public static GpgConfig.GpgFormat getFormat(byte[] signature) {
+		if (RawParseUtils.match(signature, 0, PGP_PREFIX) > 0) {
+			return GpgConfig.GpgFormat.OPENPGP;
+		}
+		if (RawParseUtils.match(signature, 0, X509_PREFIX) > 0) {
+			return GpgConfig.GpgFormat.X509;
+		}
+		if (RawParseUtils.match(signature, 0, SSH_PREFIX) > 0) {
+			return GpgConfig.GpgFormat.SSH;
+		}
+		return null;
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Signer.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Signer.java
new file mode 100644
index 0000000..3bb7464
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Signer.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2024 Thomas Wolf <twolf@apache.org> and others
+ *
+ * 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 java.io.IOException;
+import java.io.UnsupportedEncodingException;
+
+import org.eclipse.jgit.annotations.NonNull;
+import org.eclipse.jgit.api.errors.CanceledException;
+import org.eclipse.jgit.api.errors.JGitInternalException;
+import org.eclipse.jgit.api.errors.UnsupportedSigningFormatException;
+import org.eclipse.jgit.transport.CredentialsProvider;
+
+/**
+ * Creates signatures for Git objects.
+ *
+ * @since 7.0
+ */
+public interface Signer {
+
+	/**
+	 * Signs the specified object.
+	 *
+	 * <p>
+	 * Implementors should obtain the payload for signing from the specified
+	 * object via {@link ObjectBuilder#build()} and create a proper
+	 * {@link GpgSignature}. The generated signature is set on the specified
+	 * {@code object} (see {@link ObjectBuilder#setGpgSignature(GpgSignature)}).
+	 * </p>
+	 * <p>
+	 * Any existing signature on the object must be discarded prior obtaining
+	 * the payload via {@link ObjectBuilder#build()}.
+	 * </p>
+	 *
+	 * @param repository
+	 *            {@link Repository} the object belongs to
+	 * @param config
+	 *            GPG settings from the git config
+	 * @param object
+	 *            the object to sign (must not be {@code null} and must be
+	 *            complete to allow proper calculation of payload)
+	 * @param committer
+	 *            the signing identity (to help with key lookup in case signing
+	 *            key is not specified)
+	 * @param signingKey
+	 *            if non-{@code null} overrides the signing key from the config
+	 * @param credentialsProvider
+	 *            provider to use when querying for signing key credentials (eg.
+	 *            passphrase)
+	 * @throws CanceledException
+	 *             when signing was canceled (eg., user aborted when entering
+	 *             passphrase)
+	 * @throws IOException
+	 *             if an I/O error occurs
+	 * @throws UnsupportedSigningFormatException
+	 *             if a config is given and the wanted key format is not
+	 *             supported
+	 */
+	default void signObject(@NonNull Repository repository,
+			@NonNull GpgConfig config, @NonNull ObjectBuilder object,
+			@NonNull PersonIdent committer, String signingKey,
+			CredentialsProvider credentialsProvider)
+			throws CanceledException, IOException,
+			UnsupportedSigningFormatException {
+		try {
+			object.setGpgSignature(sign(repository, config, object.build(),
+					committer, signingKey, credentialsProvider));
+		} catch (UnsupportedEncodingException e) {
+			throw new JGitInternalException(e.getMessage(), e);
+		}
+	}
+
+	/**
+	 * Signs arbitrary data.
+	 *
+	 * @param repository
+	 *            {@link Repository} the signature is created in
+	 * @param config
+	 *            GPG settings from the git config
+	 * @param data
+	 *            the data to sign
+	 * @param committer
+	 *            the signing identity (to help with key lookup in case signing
+	 *            key is not specified)
+	 * @param signingKey
+	 *            if non-{@code null} overrides the signing key from the config
+	 * @param credentialsProvider
+	 *            provider to use when querying for signing key credentials (eg.
+	 *            passphrase)
+	 * @return the signature for {@code data}
+	 * @throws CanceledException
+	 *             when signing was canceled (eg., user aborted when entering
+	 *             passphrase)
+	 * @throws IOException
+	 *             if an I/O error occurs
+	 * @throws UnsupportedSigningFormatException
+	 *             if a config is given and the wanted key format is not
+	 *             supported
+	 */
+	GpgSignature sign(@NonNull Repository repository, @NonNull GpgConfig config,
+			byte[] data, @NonNull PersonIdent committer, String signingKey,
+			CredentialsProvider credentialsProvider) throws CanceledException,
+			IOException, UnsupportedSigningFormatException;
+
+	/**
+	 * Indicates if a signing key is available for the specified committer
+	 * and/or signing key.
+	 *
+	 * @param repository
+	 *            the current {@link Repository}
+	 * @param config
+	 *            GPG settings from the git config
+	 * @param committer
+	 *            the signing identity (to help with key lookup in case signing
+	 *            key is not specified)
+	 * @param signingKey
+	 *            if non-{@code null} overrides the signing key from the config
+	 * @param credentialsProvider
+	 *            provider to use when querying for signing key credentials (eg.
+	 *            passphrase)
+	 * @return {@code true} if a signing key is available, {@code false}
+	 *         otherwise
+	 * @throws CanceledException
+	 *             when signing was canceled (eg., user aborted when entering
+	 *             passphrase)
+	 */
+	boolean canLocateSigningKey(@NonNull Repository repository,
+			@NonNull GpgConfig config, @NonNull PersonIdent committer,
+			String signingKey, CredentialsProvider credentialsProvider)
+			throws CanceledException;
+
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/SignerFactory.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/SignerFactory.java
new file mode 100644
index 0000000..125d25e
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/SignerFactory.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2024 Thomas Wolf <twolf@apache.org> and others
+ *
+ * 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.annotations.NonNull;
+
+/**
+ * A factory for {@link Signer}s.
+ *
+ * @since 7.0
+ */
+public interface SignerFactory {
+
+	/**
+	 * Tells what kind of {@link Signer} this factory creates.
+	 *
+	 * @return the {@link GpgConfig.GpgFormat} of the signer
+	 */
+	@NonNull
+	GpgConfig.GpgFormat getType();
+
+	/**
+	 * Creates a new instance of a {@link Signer} that can produce signatures of
+	 * type {@link #getType()}.
+	 *
+	 * @return a new {@link Signer}
+	 */
+	@NonNull
+	Signer create();
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Signers.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Signers.java
new file mode 100644
index 0000000..7771b07
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Signers.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2024 Thomas Wolf <twolf@apache.org> and others
+ *
+ * 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 java.text.MessageFormat;
+import java.util.EnumMap;
+import java.util.Map;
+import java.util.ServiceConfigurationError;
+import java.util.ServiceLoader;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.eclipse.jgit.annotations.NonNull;
+import org.eclipse.jgit.internal.JGitText;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Manages the available signers.
+ *
+ * @since 7.0
+ */
+public final class Signers {
+
+	private static final Logger LOG = LoggerFactory.getLogger(Signers.class);
+
+	private static final Map<GpgConfig.GpgFormat, SignerFactory> SIGNER_FACTORIES = loadSigners();
+
+	private static final Map<GpgConfig.GpgFormat, Signer> SIGNERS = new ConcurrentHashMap<>();
+
+	private static Map<GpgConfig.GpgFormat, SignerFactory> loadSigners() {
+		Map<GpgConfig.GpgFormat, SignerFactory> result = new EnumMap<>(
+				GpgConfig.GpgFormat.class);
+		try {
+			for (SignerFactory factory : ServiceLoader
+					.load(SignerFactory.class)) {
+				GpgConfig.GpgFormat format = factory.getType();
+				SignerFactory existing = result.get(format);
+				if (existing != null) {
+					LOG.warn("{}", //$NON-NLS-1$
+							MessageFormat.format(
+									JGitText.get().signatureServiceConflict,
+									"SignerFactory", format, //$NON-NLS-1$
+									existing.getClass().getCanonicalName(),
+									factory.getClass().getCanonicalName()));
+				} else {
+					result.put(format, factory);
+				}
+			}
+		} catch (ServiceConfigurationError e) {
+			LOG.error(e.getMessage(), e);
+		}
+		return result;
+	}
+
+	private Signers() {
+		// No instantiation
+	}
+
+	/**
+	 * Retrieves a {@link Signer} that can produce signatures of the given type
+	 * {@code format}.
+	 *
+	 * @param format
+	 *            {@link GpgConfig.GpgFormat} the signer must support
+	 * @return a {@link Signer}, or {@code null} if none is available
+	 */
+	public static Signer get(@NonNull GpgConfig.GpgFormat format) {
+		return SIGNERS.computeIfAbsent(format, f -> {
+			SignerFactory factory = SIGNER_FACTORIES.get(format);
+			if (factory == null) {
+				return null;
+			}
+			return factory.create();
+		});
+	}
+
+	/**
+	 * Sets a specific signer to use for a specific signature type.
+	 *
+	 * @param format
+	 *            signature type to set the {@code signer} for
+	 * @param signer
+	 *            the {@link Signer} to use for signatures of type
+	 *            {@code format}; if {@code null}, a default implementation, if
+	 *            available, may be used.
+	 */
+	public static void set(@NonNull GpgConfig.GpgFormat format, Signer signer) {
+		if (signer == null) {
+			SIGNERS.remove(format);
+		} else {
+			SIGNERS.put(format, signer);
+		}
+	}
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/TagBuilder.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/TagBuilder.java
index bbc6144..ea73d95 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/TagBuilder.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/TagBuilder.java
@@ -206,23 +206,6 @@ public void setTagger(PersonIdent taggerIdent) {
 		return os.toByteArray();
 	}
 
-	/**
-	 * Format this builder's state as an annotated tag object.
-	 *
-	 * @return this object in the canonical annotated tag format, suitable for
-	 *         storage in a repository, or {@code null} if the tag cannot be
-	 *         encoded
-	 * @deprecated since 5.11; use {@link #build()} instead
-	 */
-	@Deprecated
-	public byte[] toByteArray() {
-		try {
-			return build();
-		} catch (UnsupportedEncodingException e) {
-			return null;
-		}
-	}
-
 	@SuppressWarnings("nls")
 	@Override
 	public String toString() {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeFormatter.java b/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeFormatter.java
index a35b30e..079db4a 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeFormatter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeFormatter.java
@@ -22,37 +22,6 @@
  * A class to convert merge results into a Git conformant textual presentation
  */
 public class MergeFormatter {
-	/**
-	 * Formats the results of a merge of {@link org.eclipse.jgit.diff.RawText}
-	 * objects in a Git conformant way. This method also assumes that the
-	 * {@link org.eclipse.jgit.diff.RawText} objects being merged are line
-	 * oriented files which use LF as delimiter. This method will also use LF to
-	 * separate chunks and conflict metadata, therefore it fits only to texts
-	 * that are LF-separated lines.
-	 *
-	 * @param out
-	 *            the output stream where to write the textual presentation
-	 * @param res
-	 *            the merge result which should be presented
-	 * @param seqName
-	 *            When a conflict is reported each conflicting range will get a
-	 *            name. This name is following the "&lt;&lt;&lt;&lt;&lt;&lt;&lt;
-	 *            " or "&gt;&gt;&gt;&gt;&gt;&gt;&gt; " conflict markers. The
-	 *            names for the sequences are given in this list
-	 * @param charsetName
-	 *            the name of the character set used when writing conflict
-	 *            metadata
-	 * @throws java.io.IOException
-	 *             if an IO error occurred
-	 * @deprecated Use
-	 *             {@link #formatMerge(OutputStream, MergeResult, List, Charset)}
-	 *             instead.
-	 */
-	@Deprecated
-	public void formatMerge(OutputStream out, MergeResult<RawText> res,
-			List<String> seqName, String charsetName) throws IOException {
-		formatMerge(out, res, seqName, Charset.forName(charsetName));
-	}
 
 	/**
 	 * Formats the results of a merge of {@link org.eclipse.jgit.diff.RawText}
@@ -129,40 +98,6 @@ public void formatMergeDiff3(OutputStream out,
 	 *            the name ranges from ours should get
 	 * @param theirsName
 	 *            the name ranges from theirs should get
-	 * @param charsetName
-	 *            the name of the character set used when writing conflict
-	 *            metadata
-	 * @throws java.io.IOException
-	 *             if an IO error occurred
-	 * @deprecated use
-	 *             {@link #formatMerge(OutputStream, MergeResult, String, String, String, Charset)}
-	 *             instead.
-	 */
-	@Deprecated
-	public void formatMerge(OutputStream out, MergeResult res, String baseName,
-			String oursName, String theirsName, String charsetName) throws IOException {
-		formatMerge(out, res, baseName, oursName, theirsName,
-				Charset.forName(charsetName));
-	}
-
-	/**
-	 * Formats the results of a merge of exactly two
-	 * {@link org.eclipse.jgit.diff.RawText} objects in a Git conformant way.
-	 * This convenience method accepts the names for the three sequences (base
-	 * and the two merged sequences) as explicit parameters and doesn't require
-	 * the caller to specify a List
-	 *
-	 * @param out
-	 *            the {@link java.io.OutputStream} where to write the textual
-	 *            presentation
-	 * @param res
-	 *            the merge result which should be presented
-	 * @param baseName
-	 *            the name ranges from the base should get
-	 * @param oursName
-	 *            the name ranges from ours should get
-	 * @param theirsName
-	 *            the name ranges from theirs should get
 	 * @param charset
 	 *            the character set used when writing conflict metadata
 	 * @throws java.io.IOException
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeMessageFormatter.java b/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeMessageFormatter.java
index e0c083f..039d7d8 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeMessageFormatter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeMessageFormatter.java
@@ -92,24 +92,6 @@ public String format(List<Ref> refsToMerge, Ref target) {
 	}
 
 	/**
-	 * Add section with conflicting paths to merge message. Lines are prefixed
-	 * with a hash.
-	 *
-	 * @param message
-	 *            the original merge message
-	 * @param conflictingPaths
-	 *            the paths with conflicts
-	 * @return merge message with conflicting paths added
-	 * @deprecated since 6.1; use
-	 *             {@link #formatWithConflicts(String, Iterable, char)} instead
-	 */
-	@Deprecated
-	public String formatWithConflicts(String message,
-			List<String> conflictingPaths) {
-		return formatWithConflicts(message, conflictingPaths, '#');
-	}
-
-	/**
 	 * Add section with conflicting paths to merge message.
 	 *
 	 * @param message
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/patch/PatchApplier.java b/org.eclipse.jgit/src/org/eclipse/jgit/patch/PatchApplier.java
index cb6cc6e..23e09b9 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/patch/PatchApplier.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/patch/PatchApplier.java
@@ -41,7 +41,6 @@
 
 import org.eclipse.jgit.annotations.Nullable;
 import org.eclipse.jgit.api.errors.FilterFailedException;
-import org.eclipse.jgit.api.errors.PatchFormatException;
 import org.eclipse.jgit.attributes.Attribute;
 import org.eclipse.jgit.attributes.Attributes;
 import org.eclipse.jgit.attributes.FilterCommand;
@@ -290,32 +289,6 @@ private void addErrorWithGitConflict(String msg, String oldFileName,
 	/**
 	 * Applies the given patch
 	 *
-	 * @param patchInput
-	 *            the patch to apply.
-	 * @return the result of the patch
-	 * @throws PatchFormatException
-	 *             if the patch cannot be parsed
-	 * @throws IOException
-	 *             if the patch read fails
-	 * @deprecated use {@link #applyPatch(Patch)} instead
-	 */
-	@Deprecated
-	public Result applyPatch(InputStream patchInput)
-			throws PatchFormatException, IOException {
-		Patch p = new Patch();
-		try (InputStream inStream = patchInput) {
-			p.parse(inStream);
-
-			if (!p.getErrors().isEmpty()) {
-				throw new PatchFormatException(p.getErrors());
-			}
-		}
-		return applyPatch(p);
-	}
-
-	/**
-	 * Applies the given patch
-	 *
 	 * @param p
 	 *            the patch to apply.
 	 * @return the result of the patch
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/ObjectWalk.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/ObjectWalk.java
index 82671d9..7c763bc 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/ObjectWalk.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/ObjectWalk.java
@@ -43,7 +43,7 @@
  * Tree and blob objects reachable from interesting commits are automatically
  * scheduled for inclusion in the results of {@link #nextObject()}, returning
  * each object exactly once. Objects are sorted and returned according to the
- * the commits that reference them and the order they appear within a tree.
+ * commits that reference them and the order they appear within a tree.
  * Ordering can be affected by changing the
  * {@link org.eclipse.jgit.revwalk.RevSort} used to order the commits that are
  * returned first.
@@ -164,29 +164,6 @@ private ObjectWalk(ObjectReader or, boolean closeReader) {
 	}
 
 	/**
-	 * Create an object reachability checker that will use bitmaps if possible.
-	 *
-	 * This reachability checker accepts any object as target. For checks
-	 * exclusively between commits, see
-	 * {@link RevWalk#createReachabilityChecker()}.
-	 *
-	 * @return an object reachability checker, using bitmaps if possible.
-	 *
-	 * @throws IOException
-	 *             when the index fails to load.
-	 *
-	 * @since 5.8
-	 * @deprecated use
-	 *             {@code ObjectReader#createObjectReachabilityChecker(ObjectWalk)}
-	 *             instead.
-	 */
-	@Deprecated
-	public final ObjectReachabilityChecker createObjectReachabilityChecker()
-			throws IOException {
-		return reader.createObjectReachabilityChecker(this);
-	}
-
-	/**
 	 * Mark an object or commit to start graph traversal from.
 	 * <p>
 	 * Callers are encouraged to use
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/ReachabilityChecker.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/ReachabilityChecker.java
index 1a869a0..5afb669 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/ReachabilityChecker.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/ReachabilityChecker.java
@@ -26,40 +26,6 @@
  * @since 5.4
  */
 public interface ReachabilityChecker {
-
-	/**
-	 * Check if all targets are reachable from the {@code starters} commits.
-	 * <p>
-	 * Caller should parse the objectIds (preferably with
-	 * {@code walk.parseCommit()} and handle missing/incorrect type objects
-	 * before calling this method.
-	 *
-	 * @param targets
-	 *            commits to reach.
-	 * @param starters
-	 *            known starting points.
-	 * @return An unreachable target if at least one of the targets is
-	 *         unreachable. An empty optional if all targets are reachable from
-	 *         the starters.
-	 *
-	 * @throws MissingObjectException
-	 *             if any of the incoming objects doesn't exist in the
-	 *             repository.
-	 * @throws IncorrectObjectTypeException
-	 *             if any of the incoming objects is not a commit or a tag.
-	 * @throws IOException
-	 *             if any of the underlying indexes or readers can not be
-	 *             opened.
-	 *
-	 * @deprecated see {{@link #areAllReachable(Collection, Stream)}
-	 */
-	@Deprecated
-	default Optional<RevCommit> areAllReachable(Collection<RevCommit> targets,
-                       Collection<RevCommit> starters) throws MissingObjectException,
-			IncorrectObjectTypeException, IOException {
-		return areAllReachable(targets, starters.stream());
-	}
-
 	/**
 	 * Check if all targets are reachable from the {@code starters} commits.
 	 * <p>
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevTag.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevTag.java
index 75dbd57..0737a78 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevTag.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevTag.java
@@ -38,8 +38,17 @@
  */
 public class RevTag extends RevObject {
 
-	private static final byte[] hSignature = Constants
-			.encodeASCII("-----BEGIN PGP SIGNATURE-----"); //$NON-NLS-1$
+	private static final byte[] SIGNATURE_START = Constants
+			.encodeASCII("-----BEGIN"); //$NON-NLS-1$
+
+	private static final byte[] GPG_SIGNATURE_START = Constants
+			.encodeASCII(Constants.GPG_SIGNATURE_PREFIX);
+
+	private static final byte[] CMS_SIGNATURE_START = Constants
+			.encodeASCII(Constants.CMS_SIGNATURE_PREFIX);
+
+	private static final byte[] SSH_SIGNATURE_START = Constants
+			.encodeASCII(Constants.SSH_SIGNATURE_PREFIX);
 
 	/**
 	 * Parse an annotated tag from its canonical format.
@@ -208,20 +217,27 @@ private int getSignatureStart() {
 			return msgB;
 		}
 		// Find the last signature start and return the rest
-		int start = nextStart(hSignature, raw, msgB);
+		int start = nextStart(SIGNATURE_START, raw, msgB);
 		if (start < 0) {
 			return start;
 		}
 		int next = RawParseUtils.nextLF(raw, start);
 		while (next < raw.length) {
-			int newStart = nextStart(hSignature, raw, next);
+			int newStart = nextStart(SIGNATURE_START, raw, next);
 			if (newStart < 0) {
 				break;
 			}
 			start = newStart;
 			next = RawParseUtils.nextLF(raw, start);
 		}
-		return start;
+		// SIGNATURE_START is just a prefix. Check that it is one of the known
+		// full signature start tags.
+		if (RawParseUtils.match(raw, start, GPG_SIGNATURE_START) > 0
+				|| RawParseUtils.match(raw, start, CMS_SIGNATURE_START) > 0
+				|| RawParseUtils.match(raw, start, SSH_SIGNATURE_START) > 0) {
+			return start;
+		}
+		return -1;
 	}
 
 	/**
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 9714fab..41f98ba 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java
@@ -36,9 +36,9 @@
 import org.eclipse.jgit.errors.MissingObjectException;
 import org.eclipse.jgit.errors.RevWalkException;
 import org.eclipse.jgit.internal.JGitText;
+import org.eclipse.jgit.internal.storage.commitgraph.CommitGraph;
 import org.eclipse.jgit.lib.AnyObjectId;
 import org.eclipse.jgit.lib.AsyncObjectLoaderQueue;
-import org.eclipse.jgit.internal.storage.commitgraph.CommitGraph;
 import org.eclipse.jgit.lib.Constants;
 import org.eclipse.jgit.lib.MutableObjectId;
 import org.eclipse.jgit.lib.NullProgressMonitor;
@@ -284,23 +284,6 @@ public ObjectReader getObjectReader() {
 	}
 
 	/**
-	 * Get a reachability checker for commits over this revwalk.
-	 *
-	 * @return the most efficient reachability checker for this repository.
-	 * @throws IOException
-	 *             if it cannot open any of the underlying indices.
-	 *
-	 * @since 5.4
-	 * @deprecated use {@code ObjectReader#createReachabilityChecker(RevWalk)}
-	 *             instead.
-	 */
-	@Deprecated
-	public final ReachabilityChecker createReachabilityChecker()
-			throws IOException {
-		return reader.createReachabilityChecker(this);
-	}
-
-	/**
 	 * {@inheritDoc}
 	 * <p>
 	 * Release any resources used by this walker's reader.
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/WindowCacheStats.java b/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/WindowCacheStats.java
index 7cb8618..668b92c 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/WindowCacheStats.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/WindowCacheStats.java
@@ -22,27 +22,6 @@
  */
 @MXBean
 public interface WindowCacheStats {
-	/**
-	 * Get number of open files
-	 *
-	 * @return the number of open files.
-	 * @deprecated use {@link #getOpenFileCount()} instead
-	 */
-	@Deprecated
-	public static int getOpenFiles() {
-		return (int) WindowCache.getInstance().getStats().getOpenFileCount();
-	}
-
-	/**
-	 * Get number of open bytes
-	 *
-	 * @return the number of open bytes.
-	 * @deprecated use {@link #getOpenByteCount()} instead
-	 */
-	@Deprecated
-	public static long getOpenBytes() {
-		return WindowCache.getInstance().getStats().getOpenByteCount();
-	}
 
 	/**
 	 * Get cache statistics
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PacketLineIn.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PacketLineIn.java
index ed33eae..614ad88 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PacketLineIn.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PacketLineIn.java
@@ -43,24 +43,13 @@ public class PacketLineIn {
 
 	/**
 	 * Magic return from {@link #readString()} when a flush packet is found.
-	 *
-	 * @deprecated Callers should use {@link #isEnd(String)} to check if a
-	 *             string is the end marker, or
-	 *             {@link PacketLineIn#readStrings()} to iterate over all
-	 *             strings in the input stream until the marker is reached.
 	 */
-	@Deprecated
-	public static final String END = new String(); /* must not string pool */
+	private static final String END = new String(); /* must not string pool */
 
 	/**
 	 * Magic return from {@link #readString()} when a delim packet is found.
-	 *
-	 * @since 5.0
-	 * @deprecated Callers should use {@link #isDelimiter(String)} to check if a
-	 *             string is the delimiter.
 	 */
-	@Deprecated
-	public static final String DELIM = new String(); /* must not string pool */
+	private static final String DELIM = new String(); /* must not string pool */
 
 	enum AckNackResult {
 		/** NAK */
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java
index ddde603..6f211e0 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java
@@ -88,52 +88,6 @@
  * Implements the server side of a push connection, receiving objects.
  */
 public class ReceivePack {
-	/**
-	 * Data in the first line of a request, the line itself plus capabilities.
-	 *
-	 * @deprecated Use {@link FirstCommand} instead.
-	 * @since 5.6
-	 */
-	@Deprecated
-	public static class FirstLine {
-		private final FirstCommand command;
-
-		/**
-		 * Parse the first line of a receive-pack request.
-		 *
-		 * @param line
-		 *            line from the client.
-		 */
-		public FirstLine(String line) {
-			command = FirstCommand.fromLine(line);
-		}
-
-		/**
-		 * Get non-capabilities part of the line
-		 *
-		 * @return non-capabilities part of the line.
-		 */
-		public String getLine() {
-			return command.getLine();
-		}
-
-		/**
-		 * Get capabilities parsed from the line
-		 *
-		 * @return capabilities parsed from the line.
-		 */
-		public Set<String> getCapabilities() {
-			Set<String> reconstructedCapabilites = new HashSet<>();
-			for (Map.Entry<String, String> e : command.getCapabilities()
-					.entrySet()) {
-				String cap = e.getValue() == null ? e.getKey()
-						: e.getKey() + "=" + e.getValue(); //$NON-NLS-1$
-				reconstructedCapabilites.add(cap);
-			}
-
-			return reconstructedCapabilites;
-		}
-	}
 
 	/** Database we write the stored objects into. */
 	private final Repository db;
@@ -2149,22 +2103,6 @@ public void setUnpackErrorHandler(UnpackErrorHandler unpackErrorHandler) {
 	}
 
 	/**
-	 * Set whether this class will report command failures as warning messages
-	 * before sending the command results.
-	 *
-	 * @param echo
-	 *            if true this class will report command failures as warning
-	 *            messages before sending the command results. This is usually
-	 *            not necessary, but may help buggy Git clients that discard the
-	 *            errors when all branches fail.
-	 * @deprecated no widely used Git versions need this any more
-	 */
-	@Deprecated
-	public void setEchoCommandFailures(boolean echo) {
-		// No-op.
-	}
-
-	/**
 	 * Get the client session-id
 	 *
 	 * @return The client session-id.
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/RefAdvertiser.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/RefAdvertiser.java
index f72c421..3d4bea2 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/RefAdvertiser.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/RefAdvertiser.java
@@ -178,7 +178,6 @@ public void setUseProtocolV2(boolean b) {
 	 *
 	 * This method must be invoked prior to any of the following:
 	 * <ul>
-	 * <li>{@link #send(Map)}</li>
 	 * <li>{@link #send(Collection)}</li>
 	 * </ul>
 	 *
@@ -195,7 +194,6 @@ public void setDerefTags(boolean deref) {
 	 * <p>
 	 * This method must be invoked prior to any of the following:
 	 * <ul>
-	 * <li>{@link #send(Map)}</li>
 	 * <li>{@link #send(Collection)}</li>
 	 * <li>{@link #advertiseHave(AnyObjectId)}</li>
 	 * </ul>
@@ -230,7 +228,6 @@ public void advertiseCapability(String name, String value) {
 	 * <p>
 	 * This method must be invoked prior to any of the following:
 	 * <ul>
-	 * <li>{@link #send(Map)}</li>
 	 * <li>{@link #send(Collection)}</li>
 	 * <li>{@link #advertiseHave(AnyObjectId)}</li>
 	 * </ul>
@@ -260,24 +257,6 @@ public void addSymref(String from, String to) {
 	 * @throws java.io.IOException
 	 *             the underlying output stream failed to write out an
 	 *             advertisement record.
-	 * @deprecated use {@link #send(Collection)} instead.
-	 */
-	@Deprecated
-	public Set<ObjectId> send(Map<String, Ref> refs) throws IOException {
-		return send(refs.values());
-	}
-
-	/**
-	 * Format an advertisement for the supplied refs.
-	 *
-	 * @param refs
-	 *            zero or more refs to format for the client. The collection is
-	 *            sorted before display if necessary, and therefore may appear
-	 *            in any order.
-	 * @return set of ObjectIds that were advertised to the client.
-	 * @throws java.io.IOException
-	 *             the underlying output stream failed to write out an
-	 *             advertisement record.
 	 * @since 5.0
 	 */
 	public Set<ObjectId> send(Collection<Ref> refs) throws IOException {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/Transport.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/Transport.java
index b335675..ac76e83 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/Transport.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/Transport.java
@@ -1121,28 +1121,6 @@ public void setRemoveDeletedRefs(boolean remove) {
 	}
 
 	/**
-	 * @return the blob limit value set with {@link #setFilterBlobLimit} or
-	 *         {@link #setFilterSpec(FilterSpec)}, or -1 if no blob limit value
-	 *         was set
-	 * @since 5.0
-	 * @deprecated Use {@link #getFilterSpec()} instead
-	 */
-	@Deprecated
-	public final long getFilterBlobLimit() {
-		return filterSpec.getBlobLimit();
-	}
-
-	/**
-	 * @param bytes exclude blobs of size greater than this
-	 * @since 5.0
-	 * @deprecated Use {@link #setFilterSpec(FilterSpec)} instead
-	 */
-	@Deprecated
-	public final void setFilterBlobLimit(long bytes) {
-		setFilterSpec(FilterSpec.withBlobLimit(bytes));
-	}
-
-	/**
 	 * Get filter spec
 	 *
 	 * @return the last filter spec set with {@link #setFilterSpec(FilterSpec)},
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportGitSsh.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportGitSsh.java
index 0fc9710..f77b041 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportGitSsh.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportGitSsh.java
@@ -254,6 +254,12 @@ private ProcessBuilder createProcess(List<String> args,
 				pb.environment().put(Constants.GIT_DIR_KEY,
 						directory.getPath());
 			}
+			File commonDirectory = local != null ? local.getCommonDirectory()
+					: null;
+			if (commonDirectory != null) {
+				pb.environment().put(Constants.GIT_COMMON_DIR_KEY,
+						commonDirectory.getPath());
+			}
 			return pb;
 		}
 
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportLocal.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportLocal.java
index 3a06ce5..1b9431c 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportLocal.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportLocal.java
@@ -225,6 +225,7 @@ private Process spawn(String cmd,
 			env.remove("GIT_CONFIG"); //$NON-NLS-1$
 			env.remove("GIT_CONFIG_PARAMETERS"); //$NON-NLS-1$
 			env.remove("GIT_DIR"); //$NON-NLS-1$
+			env.remove("GIT_COMMON_DIR"); //$NON-NLS-1$
 			env.remove("GIT_WORK_TREE"); //$NON-NLS-1$
 			env.remove("GIT_GRAFT_FILE"); //$NON-NLS-1$
 			env.remove("GIT_INDEX_FILE"); //$NON-NLS-1$
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java
index fbea704..5ba8270 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java
@@ -30,11 +30,11 @@
 import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_NO_DONE;
 import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_NO_PROGRESS;
 import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_OFS_DELTA;
+import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_SESSION_ID;
 import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_SHALLOW;
 import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_SIDEBAND_ALL;
 import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_SIDE_BAND;
 import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_SIDE_BAND_64K;
-import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_SESSION_ID;
 import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_THIN_PACK;
 import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_WAIT_FOR_DONE;
 import static org.eclipse.jgit.transport.GitProtocolConstants.PACKET_ACK;
@@ -80,7 +80,6 @@
 import org.eclipse.jgit.internal.JGitText;
 import org.eclipse.jgit.internal.storage.pack.CachedPackUriProvider;
 import org.eclipse.jgit.internal.storage.pack.PackWriter;
-import org.eclipse.jgit.internal.transport.parser.FirstWant;
 import org.eclipse.jgit.lib.Constants;
 import org.eclipse.jgit.lib.NullProgressMonitor;
 import org.eclipse.jgit.lib.ObjectId;
@@ -190,52 +189,6 @@ void checkWants(UploadPack up, List<ObjectId> wants)
 				throws PackProtocolException, IOException;
 	}
 
-	/**
-	 * Data in the first line of a want-list, the line itself plus options.
-	 *
-	 * @deprecated Use {@link FirstWant} instead
-	 */
-	@Deprecated
-	public static class FirstLine {
-
-		private final FirstWant firstWant;
-
-		/**
-		 * @param line
-		 *            line from the client.
-		 */
-		public FirstLine(String line) {
-			try {
-				firstWant = FirstWant.fromLine(line);
-			} catch (PackProtocolException e) {
-				throw new UncheckedIOException(e);
-			}
-		}
-
-		/**
-		 * Get non-capabilities part of the line
-		 *
-		 * @return non-capabilities part of the line.
-		 */
-		public String getLine() {
-			return firstWant.getLine();
-		}
-
-		/**
-		 * Get capabilities parsed from the line
-		 *
-		 * @return capabilities parsed from the line.
-		 */
-		public Set<String> getOptions() {
-			if (firstWant.getAgent() != null) {
-				Set<String> caps = new HashSet<>(firstWant.getCapabilities());
-				caps.add(OPTION_AGENT + '=' + firstWant.getAgent());
-				return caps;
-			}
-			return firstWant.getCapabilities();
-		}
-	}
-
 	/*
 	 * {@link java.util.function.Consumer} doesn't allow throwing checked
 	 * exceptions. Define our own to propagate IOExceptions.
@@ -1708,18 +1661,6 @@ public int getDepth() {
 	}
 
 	/**
-	 * Deprecated synonym for {@code getFilterSpec().getBlobLimit()}.
-	 *
-	 * @return filter blob limit requested by the client, or -1 if no limit
-	 * @since 5.3
-	 * @deprecated Use {@link #getFilterSpec()} instead
-	 */
-	@Deprecated
-	public final long getFilterBlobLimit() {
-		return getFilterSpec().getBlobLimit();
-	}
-
-	/**
 	 * Returns the filter spec for the current request. Valid only after
 	 * calling recvWants(). This may be a no-op filter spec, but it won't be
 	 * null.
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UserAgent.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UserAgent.java
index 7b052ad..b23ee97 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UserAgent.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UserAgent.java
@@ -10,10 +10,6 @@
 
 package org.eclipse.jgit.transport;
 
-import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_AGENT;
-
-import java.util.Set;
-
 import org.eclipse.jgit.util.StringUtils;
 
 /**
@@ -91,43 +87,6 @@ public static void set(String agent) {
 		userAgent = StringUtils.isEmptyOrNull(agent) ? null : clean(agent);
 	}
 
-	/**
-	 *
-	 * @param options
-	 *            options
-	 * @param transportAgent
-	 *            name of transport agent
-	 * @return The transport agent.
-	 * @deprecated Capabilities with &lt;key&gt;=&lt;value&gt; shape are now
-	 *             parsed alongside other capabilities in the ReceivePack flow.
-	 */
-	@Deprecated
-	static String getAgent(Set<String> options, String transportAgent) {
-		if (options == null || options.isEmpty()) {
-			return transportAgent;
-		}
-		for (String o : options) {
-			if (o.startsWith(OPTION_AGENT)
-					&& o.length() > OPTION_AGENT.length()
-					&& o.charAt(OPTION_AGENT.length()) == '=') {
-				return o.substring(OPTION_AGENT.length() + 1);
-			}
-		}
-		return transportAgent;
-	}
-
-	/**
-	 *
-	 * @param options
-	 *            options
-	 * @return True if the transport agent is set. False otherwise.
-	 * @deprecated Capabilities with &lt;key&gt;=&lt;value&gt; shape are now
-	 *             parsed alongside other capabilities in the ReceivePack flow.
-	 */
-	@Deprecated
-	static boolean hasAgent(Set<String> options) {
-		return getAgent(options, null) != null;
-	}
 
 	private UserAgent() {
 	}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/FileTreeIterator.java b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/FileTreeIterator.java
index 36fa720..0cac374 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/FileTreeIterator.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/FileTreeIterator.java
@@ -371,12 +371,6 @@ public long getLength() {
 			return attributes.getLength();
 		}
 
-		@Override
-		@Deprecated
-		public long getLastModified() {
-			return attributes.getLastModifiedInstant().toEpochMilli();
-		}
-
 		/**
 		 * @since 5.1.9
 		 */
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java
index 73a3dda..f16d800 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java
@@ -498,6 +498,8 @@ private InputStream filterClean(InputStream in)
 			filterProcessBuilder.directory(repository.getWorkTree());
 			filterProcessBuilder.environment().put(Constants.GIT_DIR_KEY,
 					repository.getDirectory().getAbsolutePath());
+			filterProcessBuilder.environment().put(Constants.GIT_COMMON_DIR_KEY,
+					repository.getCommonDirectory().getAbsolutePath());
 			ExecutionResult result;
 			try {
 				result = fs.execute(filterProcessBuilder, in);
@@ -620,18 +622,6 @@ public long getEntryContentLength() throws IOException {
 	/**
 	 * Get the last modified time of this entry.
 	 *
-	 * @return last modified time of this file, in milliseconds since the epoch
-	 *         (Jan 1, 1970 UTC).
-	 * @deprecated use {@link #getEntryLastModifiedInstant()} instead
-	 */
-	@Deprecated
-	public long getEntryLastModified() {
-		return current().getLastModified();
-	}
-
-	/**
-	 * Get the last modified time of this entry.
-	 *
 	 * @return last modified time of this file
 	 * @since 5.1.9
 	 */
@@ -1229,21 +1219,6 @@ public String toString() {
 		 * needs to compute the value they should cache the reference within an
 		 * instance member instead.
 		 *
-		 * @return time since the epoch (in ms) of the last change.
-		 * @deprecated use {@link #getLastModifiedInstant()} instead
-		 */
-		@Deprecated
-		public abstract long getLastModified();
-
-		/**
-		 * Get the last modified time of this entry.
-		 * <p>
-		 * <b>Note: Efficient implementation required.</b>
-		 * <p>
-		 * The implementation of this method must be efficient. If a subclass
-		 * needs to compute the value they should cache the reference within an
-		 * instance member instead.
-		 *
 		 * @return time of the last change.
 		 * @since 5.1.9
 		 */
@@ -1332,7 +1307,7 @@ IgnoreNode load(IgnoreNode parent) throws IOException {
 
 			IgnoreNode infoExclude = new IgnoreNodeWithParent(
 					coreExclude);
-			File exclude = fs.resolve(repository.getDirectory(),
+			File exclude = fs.resolve(repository.getCommonDirectory(),
 					Constants.INFO_EXCLUDE);
 			if (fs.exists(exclude)) {
 				loadRulesFromFile(infoExclude, exclude);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java
index a8e1dae..860c1c9 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java
@@ -898,21 +898,6 @@ public static FS detect() {
 	}
 
 	/**
-	 * Whether FileStore attributes should be determined asynchronously
-	 *
-	 * @param asynch
-	 *            whether FileStore attributes should be determined
-	 *            asynchronously. If false access to cached attributes may block
-	 *            for some seconds for the first call per FileStore
-	 * @since 5.1.9
-	 * @deprecated Use {@link FileStoreAttributes#setBackground} instead
-	 */
-	@Deprecated
-	public static void setAsyncFileStoreAttributes(boolean asynch) {
-		FileStoreAttributes.setBackground(asynch);
-	}
-
-	/**
 	 * Auto-detect the appropriate file system abstraction, taking into account
 	 * the presence of a Cygwin installation on the system. Using jgit in
 	 * combination with Cygwin requires a more elaborate (and possibly slower)
@@ -1085,24 +1070,6 @@ private void detectSymlinkSupport() {
 	 * symbolic links, the modification time of the link is returned, rather
 	 * than that of the link target.
 	 *
-	 * @param f
-	 *            a {@link java.io.File} object.
-	 * @return last modified time of f
-	 * @throws java.io.IOException
-	 *             if an IO error occurred
-	 * @since 3.0
-	 * @deprecated use {@link #lastModifiedInstant(Path)} instead
-	 */
-	@Deprecated
-	public long lastModified(File f) throws IOException {
-		return FileUtils.lastModified(f);
-	}
-
-	/**
-	 * Get the last modified time of a file system object. If the OS/JRE support
-	 * symbolic links, the modification time of the link is returned, rather
-	 * than that of the link target.
-	 *
 	 * @param p
 	 *            a {@link Path} object.
 	 * @return last modified time of p
@@ -1131,25 +1098,6 @@ public Instant lastModifiedInstant(File f) {
 	 * <p>
 	 * For symlinks it sets the modified time of the link target.
 	 *
-	 * @param f
-	 *            a {@link java.io.File} object.
-	 * @param time
-	 *            last modified time
-	 * @throws java.io.IOException
-	 *             if an IO error occurred
-	 * @since 3.0
-	 * @deprecated use {@link #setLastModified(Path, Instant)} instead
-	 */
-	@Deprecated
-	public void setLastModified(File f, long time) throws IOException {
-		FileUtils.setLastModified(f, time);
-	}
-
-	/**
-	 * Set the last modified time of a file system object.
-	 * <p>
-	 * For symlinks it sets the modified time of the link target.
-	 *
 	 * @param p
 	 *            a {@link Path} object.
 	 * @param time
@@ -1800,25 +1748,6 @@ public void createSymLink(File path, String target) throws IOException {
 	}
 
 	/**
-	 * Create a new file. See {@link java.io.File#createNewFile()}. Subclasses
-	 * of this class may take care to provide a safe implementation for this
-	 * even if {@link #supportsAtomicCreateNewFile()} is <code>false</code>
-	 *
-	 * @param path
-	 *            the file to be created
-	 * @return <code>true</code> if the file was created, <code>false</code> if
-	 *         the file already existed
-	 * @throws java.io.IOException
-	 *             if an IO error occurred
-	 * @deprecated use {@link #createNewFileAtomic(File)} instead
-	 * @since 4.5
-	 */
-	@Deprecated
-	public boolean createNewFile(File path) throws IOException {
-		return path.createNewFile();
-	}
-
-	/**
 	 * A token representing a file created by
 	 * {@link #createNewFileAtomic(File)}. The token must be retained until the
 	 * file has been deleted in order to guarantee that the unique file was
@@ -2042,6 +1971,8 @@ protected ProcessResult internalRunHookIfPresent(Repository repository,
 		environment.put(Constants.GIT_DIR_KEY,
 				repository.getDirectory().getAbsolutePath());
 		if (!repository.isBare()) {
+			environment.put(Constants.GIT_COMMON_DIR_KEY,
+					repository.getCommonDirectory().getAbsolutePath());
 			environment.put(Constants.GIT_WORK_TREE_KEY,
 					repository.getWorkTree().getAbsolutePath());
 		}
@@ -2137,7 +2068,7 @@ private File getRunDirectory(Repository repository,
 		case "post-receive": //$NON-NLS-1$
 		case "post-update": //$NON-NLS-1$
 		case "push-to-checkout": //$NON-NLS-1$
-			return repository.getDirectory();
+			return repository.getCommonDirectory();
 		default:
 			return repository.getWorkTree();
 		}
@@ -2150,7 +2081,7 @@ private File getHooksDirectory(Repository repository) {
 		if (hooksDir != null) {
 			return new File(hooksDir);
 		}
-		File dir = repository.getDirectory();
+		File dir = repository.getCommonDirectory();
 		return dir == null ? null : new File(dir, Constants.HOOKS);
 	}
 
@@ -2424,19 +2355,6 @@ public long getCreationTime() {
 		}
 
 		/**
-		 * Get the time when the file was last modified in milliseconds since
-		 * the epoch
-		 *
-		 * @return the time (milliseconds since 1970-01-01) when this object was
-		 *         last modified
-		 * @deprecated use getLastModifiedInstant instead
-		 */
-		@Deprecated
-		public long getLastModifiedTime() {
-			return lastModifiedInstant.toEpochMilli();
-		}
-
-		/**
 		 * Get the time when this object was last modified
 		 *
 		 * @return the time when this object was last modified
@@ -2578,6 +2496,33 @@ public String normalize(String name) {
 	}
 
 	/**
+	 * Get common dir path.
+	 *
+	 * @param dir
+	 *            the .git folder
+	 * @return common dir path
+	 * @throws IOException
+	 *             if commondir file can't be read
+	 *
+	 * @since 7.0
+	 */
+	public File getCommonDir(File dir) throws IOException {
+		// first the GIT_COMMON_DIR is same as GIT_DIR
+		File commonDir = dir;
+		// now check if commondir file exists (e.g. worktree repository)
+		File commonDirFile = new File(dir, Constants.COMMONDIR_FILE);
+		if (commonDirFile.isFile()) {
+			String commonDirPath = new String(IO.readFully(commonDirFile))
+					.trim();
+			commonDir = new File(commonDirPath);
+			if (!commonDir.isAbsolute()) {
+				commonDir = new File(dir, commonDirPath).getCanonicalFile();
+			}
+		}
+		return commonDir;
+	}
+
+	/**
 	 * This runnable will consume an input stream's content into an output
 	 * stream as soon as it gets available.
 	 * <p>
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX.java
index e73095f..db2b5b4 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX.java
@@ -341,73 +341,6 @@ public boolean supportsAtomicCreateNewFile() {
 		return supportsAtomicFileCreation == AtomicFileCreation.SUPPORTED;
 	}
 
-	@Override
-	@SuppressWarnings("boxing")
-	/**
-	 * {@inheritDoc}
-	 * <p>
-	 * An implementation of the File#createNewFile() semantics which works also
-	 * on NFS. If the config option
-	 * {@code core.supportsAtomicCreateNewFile = true} (which is the default)
-	 * then simply File#createNewFile() is called.
-	 *
-	 * But if {@code core.supportsAtomicCreateNewFile = false} then after
-	 * successful creation of the lock file a hard link to that lock file is
-	 * created and the attribute nlink of the lock file is checked to be 2. If
-	 * multiple clients manage to create the same lock file nlink would be
-	 * greater than 2 showing the error.
-	 *
-	 * @see "https://www.time-travellers.org/shane/papers/NFS_considered_harmful.html"
-	 *
-	 * @deprecated use {@link FS_POSIX#createNewFileAtomic(File)} instead
-	 * @since 4.5
-	 */
-	@Deprecated
-	public boolean createNewFile(File lock) throws IOException {
-		if (!lock.createNewFile()) {
-			return false;
-		}
-		if (supportsAtomicCreateNewFile()) {
-			return true;
-		}
-		Path lockPath = lock.toPath();
-		Path link = null;
-		FileStore store = null;
-		try {
-			store = Files.getFileStore(lockPath);
-		} catch (SecurityException e) {
-			return true;
-		}
-		try {
-			Boolean canLink = CAN_HARD_LINK.computeIfAbsent(store,
-					s -> Boolean.TRUE);
-			if (Boolean.FALSE.equals(canLink)) {
-				return true;
-			}
-			link = Files.createLink(
-					Paths.get(lock.getAbsolutePath() + ".lnk"), //$NON-NLS-1$
-					lockPath);
-			Integer nlink = (Integer) Files.getAttribute(lockPath,
-					"unix:nlink"); //$NON-NLS-1$
-			if (nlink > 2) {
-				LOG.warn(MessageFormat.format(
-						JGitText.get().failedAtomicFileCreation, lockPath,
-						nlink));
-				return false;
-			} else if (nlink < 2) {
-				CAN_HARD_LINK.put(store, Boolean.FALSE);
-			}
-			return true;
-		} catch (UnsupportedOperationException | IllegalArgumentException e) {
-			CAN_HARD_LINK.put(store, Boolean.FALSE);
-			return true;
-		} finally {
-			if (link != null) {
-				Files.delete(link);
-			}
-		}
-	}
-
 	/**
 	 * {@inheritDoc}
 	 * <p>
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java
index cab0e6a..39c67f1 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java
@@ -771,24 +771,6 @@ static boolean isSymlink(File file) {
 	}
 
 	/**
-	 * Get the lastModified attribute for a given file
-	 *
-	 * @param file
-	 *            the file
-	 * @return lastModified attribute for given file, not following symbolic
-	 *         links
-	 * @throws IOException
-	 *             if an IO error occurred
-	 * @deprecated use {@link #lastModifiedInstant(Path)} instead which returns
-	 *             FileTime
-	 */
-	@Deprecated
-	static long lastModified(File file) throws IOException {
-		return Files.getLastModifiedTime(toPath(file), LinkOption.NOFOLLOW_LINKS)
-				.toMillis();
-	}
-
-	/**
 	 * Get last modified timestamp of a file
 	 *
 	 * @param path
@@ -830,21 +812,6 @@ static BasicFileAttributes fileAttributes(File file) throws IOException {
 	/**
 	 * Set the last modified time of a file system object.
 	 *
-	 * @param file
-	 *            the file
-	 * @param time
-	 *            last modified timestamp
-	 * @throws IOException
-	 *             if an IO error occurred
-	 */
-	@Deprecated
-	static void setLastModified(File file, long time) throws IOException {
-		Files.setLastModifiedTime(toPath(file), FileTime.fromMillis(time));
-	}
-
-	/**
-	 * Set the last modified time of a file system object.
-	 *
 	 * @param path
 	 *            file path
 	 * @param time
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/RawParseUtils.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/RawParseUtils.java
index 46d0bc8..2ce8690 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/RawParseUtils.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/RawParseUtils.java
@@ -44,14 +44,6 @@
  * Handy utility functions to parse raw object contents.
  */
 public final class RawParseUtils {
-	/**
-	 * UTF-8 charset constant.
-	 *
-	 * @since 2.2
-	 * @deprecated use {@link java.nio.charset.StandardCharsets#UTF_8} instead
-	 */
-	@Deprecated
-	public static final Charset UTF8_CHARSET = UTF_8;
 
 	private static final byte[] digits10;
 
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/SignatureUtils.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/SignatureUtils.java
index cf06172..90524db 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/SignatureUtils.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/SignatureUtils.java
@@ -13,8 +13,8 @@
 import java.util.Locale;
 
 import org.eclipse.jgit.internal.JGitText;
-import org.eclipse.jgit.lib.GpgSignatureVerifier.SignatureVerification;
-import org.eclipse.jgit.lib.GpgSignatureVerifier.TrustLevel;
+import org.eclipse.jgit.lib.SignatureVerifier.SignatureVerification;
+import org.eclipse.jgit.lib.SignatureVerifier.TrustLevel;
 import org.eclipse.jgit.lib.PersonIdent;
 
 /**
@@ -39,29 +39,31 @@ private SignatureUtils() {
 	 *            to use for dates
 	 * @return a textual representation of the {@link SignatureVerification},
 	 *         using LF as line separator
+	 *
+	 * @since 7.0
 	 */
 	public static String toString(SignatureVerification verification,
 			PersonIdent creator, GitDateFormatter formatter) {
 		StringBuilder result = new StringBuilder();
 		// Use the creator's timezone for the signature date
 		PersonIdent dateId = new PersonIdent(creator,
-				verification.getCreationDate());
+				verification.creationDate());
 		result.append(MessageFormat.format(JGitText.get().verifySignatureMade,
 				formatter.formatDate(dateId)));
 		result.append('\n');
 		result.append(MessageFormat.format(
 				JGitText.get().verifySignatureKey,
-				verification.getKeyFingerprint().toUpperCase(Locale.ROOT)));
+				verification.keyFingerprint().toUpperCase(Locale.ROOT)));
 		result.append('\n');
-		if (!StringUtils.isEmptyOrNull(verification.getSigner())) {
+		if (!StringUtils.isEmptyOrNull(verification.signer())) {
 			result.append(
 					MessageFormat.format(JGitText.get().verifySignatureIssuer,
-							verification.getSigner()));
+							verification.signer()));
 			result.append('\n');
 		}
 		String msg;
-		if (verification.getVerified()) {
-			if (verification.isExpired()) {
+		if (verification.verified()) {
+			if (verification.expired()) {
 				msg = JGitText.get().verifySignatureExpired;
 			} else {
 				msg = JGitText.get().verifySignatureGood;
@@ -69,14 +71,14 @@ public static String toString(SignatureVerification verification,
 		} else {
 			msg = JGitText.get().verifySignatureBad;
 		}
-		result.append(MessageFormat.format(msg, verification.getKeyUser()));
-		if (!TrustLevel.UNKNOWN.equals(verification.getTrustLevel())) {
+		result.append(MessageFormat.format(msg, verification.keyUser()));
+		if (!TrustLevel.UNKNOWN.equals(verification.trustLevel())) {
 			result.append(' ' + MessageFormat
 					.format(JGitText.get().verifySignatureTrust, verification
-							.getTrustLevel().name().toLowerCase(Locale.ROOT)));
+							.trustLevel().name().toLowerCase(Locale.ROOT)));
 		}
 		result.append('\n');
-		msg = verification.getMessage();
+		msg = verification.message();
 		if (!StringUtils.isEmptyOrNull(msg)) {
 			result.append(msg);
 			result.append('\n');
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/io/AutoLFInputStream.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/io/AutoLFInputStream.java
index 2385865..4b9706a 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/io/AutoLFInputStream.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/io/AutoLFInputStream.java
@@ -147,44 +147,6 @@ public AutoLFInputStream(InputStream in, Set<StreamFlag> flags) {
 				&& flags.contains(StreamFlag.FOR_CHECKOUT);
 	}
 
-	/**
-	 * Creates a new InputStream, wrapping the specified stream.
-	 *
-	 * @param in
-	 *            raw input stream
-	 * @param detectBinary
-	 *            whether binaries should be detected
-	 * @since 2.0
-	 * @deprecated since 5.9, use {@link #create(InputStream, StreamFlag...)}
-	 *             instead
-	 */
-	@Deprecated
-	public AutoLFInputStream(InputStream in, boolean detectBinary) {
-		this(in, detectBinary, false);
-	}
-
-	/**
-	 * Creates a new InputStream, wrapping the specified stream.
-	 *
-	 * @param in
-	 *            raw input stream
-	 * @param detectBinary
-	 *            whether binaries should be detected
-	 * @param abortIfBinary
-	 *            throw an IOException if the file is binary
-	 * @since 3.3
-	 * @deprecated since 5.9, use {@link #create(InputStream, StreamFlag...)}
-	 *             instead
-	 */
-	@Deprecated
-	public AutoLFInputStream(InputStream in, boolean detectBinary,
-			boolean abortIfBinary) {
-		this.in = in;
-		this.detectBinary = detectBinary;
-		this.abortIfBinary = abortIfBinary;
-		this.forCheckout = false;
-	}
-
 	@Override
 	public int read() throws IOException {
 		final int read = read(single, 0, 1);
diff --git a/pom.xml b/pom.xml
index 0762920..ef6018b 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>6.10.2-SNAPSHOT</version>
+  <version>7.0.2-SNAPSHOT</version>
 
   <name>JGit - Parent</name>
   <url>${jgit-url}</url>
@@ -33,8 +33,8 @@
   </description>
 
   <scm>
-    <url>https://git.eclipse.org/r/plugins/gitiles/jgit/jgit</url>
-    <connection>scm:git:https://git.eclipse.org/r/jgit/jgit</connection>
+    <url>https://eclipse.gerrithub.io/plugins/gitiles/eclipse-jgit/jgit</url>
+    <connection>scm:git:https://eclipse.gerrithub.io/eclipse-jgit/jgit</connection>
   </scm>
 
   <ciManagement>
@@ -95,8 +95,8 @@
   </mailingLists>
 
   <issueManagement>
-    <url>https://bugs.eclipse.org/bugs/buglist.cgi?query_format=advanced;component=JGit;product=JGit;classification=Technology</url>
-    <system>Bugzilla</system>
+    <url>https://github.com/eclipse-jgit/jgit/issues</url>
+    <system>GitHub Issues</system>
   </issueManagement>
 
   <licenses>
@@ -113,12 +113,12 @@
 
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
     <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
-    <java.version>11</java.version>
+    <java.version>17</java.version>
     <bundle-manifest>${project.build.directory}/META-INF/MANIFEST.MF</bundle-manifest>
 
     <project.build.outputTimestamp>${commit.time.iso}</project.build.outputTimestamp>
 
-    <jgit-last-release-version>6.9.0.202403050737-r</jgit-last-release-version>
+    <jgit-last-release-version>6.10.0.202406032230-r</jgit-last-release-version>
     <ant-version>1.10.14</ant-version>
     <apache-sshd-version>2.14.0</apache-sshd-version>
     <jsch-version>0.1.55</jsch-version>
@@ -127,10 +127,10 @@
     <junit-version>4.13.2</junit-version>
     <test-fork-count>1C</test-fork-count>
     <args4j-version>2.37</args4j-version>
-    <commons-compress-version>1.26.2</commons-compress-version>
+    <commons-compress-version>1.27.1</commons-compress-version>
     <osgi-core-version>6.0.0</osgi-core-version>
-    <servlet-api-version>4.0.4</servlet-api-version>
-    <jetty-version>10.0.21</jetty-version>
+    <servlet-api-version>6.1.0</servlet-api-version>
+    <jetty-version>12.0.12</jetty-version>
     <japicmp-version>0.21.2</japicmp-version>
     <httpclient-version>4.5.14</httpclient-version>
     <httpcore-version>4.4.16</httpcore-version>
@@ -146,9 +146,9 @@
     <maven-compiler-plugin-version>3.13.0</maven-compiler-plugin-version>
     <plexus-compiler-version>2.13.0</plexus-compiler-version>
     <hamcrest-version>2.2</hamcrest-version>
-    <assertj-version>3.26.0</assertj-version>
+    <assertj-version>3.26.3</assertj-version>
     <jna-version>5.14.0</jna-version>
-    <byte-buddy-version>1.14.16</byte-buddy-version>
+    <byte-buddy-version>1.15.0</byte-buddy-version>
 
     <!-- Properties to enable jacoco code coverage analysis -->
     <sonar.core.codeCoveragePlugin>jacoco</sonar.core.codeCoveragePlugin>
@@ -492,7 +492,7 @@
           <failOnWarnings>true</failOnWarnings>
           <excludePackageNames>org.eclipse.jgit.http.test</excludePackageNames>
           <links>
-            <link>https://docs.oracle.com/en/java/javase/11/docs/api</link>
+            <link>https://docs.oracle.com/en/java/javase/17/docs/api</link>
           </links>
           <tags>
             <tag>
@@ -766,7 +766,7 @@
           <failOnWarnings>false</failOnWarnings>
           <excludePackageNames>org.eclipse.jgit.http.test</excludePackageNames>
           <links>
-            <link>https://docs.oracle.com/en/java/javase/11/docs/api</link>
+            <link>https://docs.oracle.com/en/java/javase/17/docs/api</link>
           </links>
           <tags>
             <tag>
@@ -899,7 +899,7 @@
       <dependency>
         <groupId>commons-codec</groupId>
         <artifactId>commons-codec</artifactId>
-        <version>1.17.0</version>
+        <version>1.17.1</version>
       </dependency>
 
       <dependency>
@@ -917,19 +917,25 @@
       <dependency>
         <groupId>commons-logging</groupId>
         <artifactId>commons-logging</artifactId>
-        <version>1.3.2</version>
+        <version>1.3.4</version>
       </dependency>
 
       <dependency>
         <groupId>org.tukaani</groupId>
         <artifactId>xz</artifactId>
-        <version>1.9</version>
+        <version>1.10</version>
         <optional>true</optional>
       </dependency>
 
       <dependency>
+        <groupId>org.eclipse.jetty.ee10</groupId>
+        <artifactId>jetty-ee10-servlet</artifactId>
+        <version>${jetty-version}</version>
+      </dependency>
+
+      <dependency>
         <groupId>org.eclipse.jetty</groupId>
-        <artifactId>jetty-servlet</artifactId>
+        <artifactId>jetty-session</artifactId>
         <version>${jetty-version}</version>
       </dependency>
 
@@ -1123,7 +1129,7 @@
               <dependency>
                 <groupId>org.eclipse.jdt</groupId>
                 <artifactId>ecj</artifactId>
-                <version>3.37.0</version>
+                <version>3.38.0</version>
               </dependency>
             </dependencies>
           </plugin>
diff --git a/tools/BUILD b/tools/BUILD
index c7ec638..8c424b3 100644
--- a/tools/BUILD
+++ b/tools/BUILD
@@ -5,16 +5,6 @@
 load("@rules_java//java:defs.bzl", "java_package_configuration")
 
 default_java_toolchain(
-    name = "error_prone_warnings_toolchain_java11",
-    package_configuration = [
-        ":error_prone",
-    ],
-    source_version = "11",
-    target_version = "11",
-    visibility = ["//visibility:public"],
-)
-
-default_java_toolchain(
     name = "error_prone_warnings_toolchain_java17",
     configuration = dict(),
     java_runtime = "@rules_java//toolchains:remotejdk_17",
diff --git a/tools/workspace_status.py b/tools/workspace_status.py
index ca9e0a9..1186a4a 100644
--- a/tools/workspace_status.py
+++ b/tools/workspace_status.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 # Copyright (C) 2020, David Ostrovsky <david@ostrovsky.org> and others
 #
 # This program and the accompanying materials are made available under the