Merge "Gc#deleteOrphans: avoid dependence on PackExt alphabetical ordering"
diff --git a/WORKSPACE b/WORKSPACE
index ceb0e48..106d1fb 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -214,55 +214,55 @@
     sha1 = "02cc2131b98ebfb04e2b2c7dfb84431f4045096b",
 )
 
-JETTY_VER = "10.0.6"
+JETTY_VER = "10.0.13"
 
 maven_jar(
     name = "jetty-servlet",
     artifact = "org.eclipse.jetty:jetty-servlet:" + JETTY_VER,
-    sha1 = "482165726bf54dd10ee7e2aeb4ae9481eee0c878",
-    src_sha1 = "8a8173a0bc6c0d215fc9fb9ba5fd50bae1690f9c",
+    sha1 = "a6ee6e48e98377863aa80f41ea979df678b17966",
+    src_sha1 = "5a01db2e1bae632879e9b90e845ae946059b46c9",
 )
 
 maven_jar(
     name = "jetty-security",
     artifact = "org.eclipse.jetty:jetty-security:" + JETTY_VER,
-    sha1 = "513f44ed9636ca5e0adefa0c0b81511065dfddd2",
-    src_sha1 = "2e7eb2edbf1592e15b338096651e379fea860859",
+    sha1 = "6d4c88cf068709d9f2499ca417b23f3f835b0c43",
+    src_sha1 = "887e7a7c457e149df9c23db89c7d2425c4444ccf",
 )
 
 maven_jar(
     name = "jetty-server",
     artifact = "org.eclipse.jetty:jetty-server:" + JETTY_VER,
-    sha1 = "125ee07e4d8182a6afca00d543f6a4dcc84f2678",
-    src_sha1 = "5c0789872ec6743ae893131ae81262aaefc87fe6",
+    sha1 = "f472705ebfce7e9a5b6cb8cbb84e73767e35fad7",
+    src_sha1 = "2689f8e616282b19f34d43f89800f67490ae65fa",
 )
 
 maven_jar(
     name = "jetty-http",
     artifact = "org.eclipse.jetty:jetty-http:" + JETTY_VER,
-    sha1 = "4c8eed25d577002a6c0f9f3ef340eb581390f696",
-    src_sha1 = "ac7214d6202ee0cbc4bdbcf90c7906ca716e84e5",
+    sha1 = "b3dc7ec1da090106031dd36cb1e2637a7fb6ce1c",
+    src_sha1 = "1bbb620e34218584bfdf11542e2b46781437335d",
 )
 
 maven_jar(
     name = "jetty-io",
     artifact = "org.eclipse.jetty:jetty-io:" + JETTY_VER,
-    sha1 = "1ab82ae5dfdbb07f0ffa07f28274fdf30e3e96ee",
-    src_sha1 = "c59082f3a09c024fafc281f432b67432d398b8c0",
+    sha1 = "be9d7f226022b02e174a83d597d088e22e12d365",
+    src_sha1 = "48f5b1ce8570a9d560e62c39170e754288a1d290",
 )
 
 maven_jar(
     name = "jetty-util",
     artifact = "org.eclipse.jetty:jetty-util:" + JETTY_VER,
-    sha1 = "4e2935749ea1c9fcabba61a857f8283c7f5f9885",
-    src_sha1 = "6baba651899c044e14ba37d43934950670d2aa4e",
+    sha1 = "35caf3afb3cca22ca4bc36908bf82e6d973c5be4",
+    src_sha1 = "9d7c19deb76c0247ad0d25afce6e4c0d681d2af0",
 )
 
 maven_jar(
     name = "jetty-util-ajax",
     artifact = "org.eclipse.jetty:jetty-util-ajax:" + JETTY_VER,
-    sha1 = "a801d4b5f5e906f134713ae82fd1ea10a15902c6",
-    src_sha1 = "f35f5525a5d30dc1237b85457d758d578e3ce8d0",
+    sha1 = "bc52bc38cb76b5c260ec109661ebcb02393d83a7",
+    src_sha1 = "b229198672cfb765ce7571e5e0e855e01170f881",
 )
 
 BOUNCYCASTLE_VER = "1.72"
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.17.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.17.target
index d5ee87b..b129fa8 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.17.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.17.target
@@ -1,26 +1,17 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <?pde?>
 <!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
-<target name="jgit-4.17" sequenceNumber="1669195943">
+<target name="jgit-4.17" sequenceNumber="1670938799">
   <locations>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
-      <unit id="jakarta.servlet-api" version="4.0.0"/>
-      <unit id="jakarta.servlet-api.source" version="4.0.0"/>
-      <unit id="org.eclipse.jetty.http" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.http.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.io" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.io.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.security" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.security.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.server" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.server.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.servlet" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.servlet.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.util" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.util.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.util.ajax" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.util.ajax.source" version="10.0.6"/>
-      <repository id="jetty-10.0.x" location="https://download.eclipse.org/eclipse/jetty/10.0.6/"/>
+      <unit id="org.eclipse.jetty.http" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.io" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.security" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.server" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.servlet" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.util" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.util.ajax" version="10.0.13"/>
+      <repository id="jetty-10.0.x" location="https://download.eclipse.org/oomph/jetty/release/10.0.13/"/>
     </location>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
       <unit id="com.google.gson" version="2.9.1.v20220915-1632"/>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.18.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.18.target
index 36e37b1..bdbdeb7 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.18.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.18.target
@@ -1,26 +1,17 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <?pde?>
 <!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
-<target name="jgit-4.18" sequenceNumber="1669195943">
+<target name="jgit-4.18" sequenceNumber="1670938799">
   <locations>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
-      <unit id="jakarta.servlet-api" version="4.0.0"/>
-      <unit id="jakarta.servlet-api.source" version="4.0.0"/>
-      <unit id="org.eclipse.jetty.http" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.http.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.io" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.io.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.security" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.security.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.server" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.server.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.servlet" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.servlet.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.util" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.util.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.util.ajax" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.util.ajax.source" version="10.0.6"/>
-      <repository id="jetty-10.0.x" location="https://download.eclipse.org/eclipse/jetty/10.0.6/"/>
+      <unit id="org.eclipse.jetty.http" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.io" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.security" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.server" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.servlet" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.util" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.util.ajax" version="10.0.13"/>
+      <repository id="jetty-10.0.x" location="https://download.eclipse.org/oomph/jetty/release/10.0.13/"/>
     </location>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
       <unit id="com.google.gson" version="2.9.1.v20220915-1632"/>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.19.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.19.target
index 2966e88..5d93be8 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.19.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.19.target
@@ -1,26 +1,17 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <?pde?>
 <!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
-<target name="jgit-4.19-staging" sequenceNumber="1669195941">
+<target name="jgit-4.19-staging" sequenceNumber="1670938799">
   <locations>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
-      <unit id="jakarta.servlet-api" version="4.0.0"/>
-      <unit id="jakarta.servlet-api.source" version="4.0.0"/>
-      <unit id="org.eclipse.jetty.http" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.http.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.io" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.io.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.security" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.security.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.server" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.server.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.servlet" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.servlet.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.util" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.util.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.util.ajax" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.util.ajax.source" version="10.0.6"/>
-      <repository id="jetty-10.0.x" location="https://download.eclipse.org/eclipse/jetty/10.0.6/"/>
+      <unit id="org.eclipse.jetty.http" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.io" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.security" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.server" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.servlet" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.util" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.util.ajax" version="10.0.13"/>
+      <repository id="jetty-10.0.x" location="https://download.eclipse.org/oomph/jetty/release/10.0.13/"/>
     </location>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
       <unit id="com.google.gson" version="2.9.1.v20220915-1632"/>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.20.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.20.target
index 6e6e7fb..46a909d 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.20.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.20.target
@@ -1,26 +1,17 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <?pde?>
 <!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
-<target name="jgit-4.20" sequenceNumber="1669195941">
+<target name="jgit-4.20" sequenceNumber="1670938799">
   <locations>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
-      <unit id="jakarta.servlet-api" version="4.0.0"/>
-      <unit id="jakarta.servlet-api.source" version="4.0.0"/>
-      <unit id="org.eclipse.jetty.http" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.http.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.io" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.io.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.security" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.security.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.server" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.server.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.servlet" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.servlet.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.util" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.util.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.util.ajax" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.util.ajax.source" version="10.0.6"/>
-      <repository id="jetty-10.0.x" location="https://download.eclipse.org/eclipse/jetty/10.0.6/"/>
+      <unit id="org.eclipse.jetty.http" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.io" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.security" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.server" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.servlet" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.util" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.util.ajax" version="10.0.13"/>
+      <repository id="jetty-10.0.x" location="https://download.eclipse.org/oomph/jetty/release/10.0.13/"/>
     </location>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
       <unit id="com.google.gson" version="2.9.1.v20220915-1632"/>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.21.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.21.target
index edfc027..5c12e64 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.21.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.21.target
@@ -1,26 +1,17 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <?pde?>
 <!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
-<target name="jgit-4.21" sequenceNumber="1669195941">
+<target name="jgit-4.21" sequenceNumber="1670938799">
   <locations>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
-      <unit id="jakarta.servlet-api" version="4.0.0"/>
-      <unit id="jakarta.servlet-api.source" version="4.0.0"/>
-      <unit id="org.eclipse.jetty.http" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.http.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.io" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.io.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.security" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.security.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.server" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.server.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.servlet" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.servlet.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.util" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.util.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.util.ajax" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.util.ajax.source" version="10.0.6"/>
-      <repository id="jetty-10.0.x" location="https://download.eclipse.org/eclipse/jetty/10.0.6/"/>
+      <unit id="org.eclipse.jetty.http" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.io" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.security" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.server" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.servlet" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.util" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.util.ajax" version="10.0.13"/>
+      <repository id="jetty-10.0.x" location="https://download.eclipse.org/oomph/jetty/release/10.0.13/"/>
     </location>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
       <unit id="com.google.gson" version="2.9.1.v20220915-1632"/>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.22.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.22.target
index f5efb8c..d789653 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.22.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.22.target
@@ -1,26 +1,17 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <?pde?>
 <!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
-<target name="jgit-4.22" sequenceNumber="1669195941">
+<target name="jgit-4.22" sequenceNumber="1670938799">
   <locations>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
-      <unit id="jakarta.servlet-api" version="4.0.0"/>
-      <unit id="jakarta.servlet-api.source" version="4.0.0"/>
-      <unit id="org.eclipse.jetty.http" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.http.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.io" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.io.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.security" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.security.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.server" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.server.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.servlet" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.servlet.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.util" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.util.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.util.ajax" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.util.ajax.source" version="10.0.6"/>
-      <repository id="jetty-10.0.x" location="https://download.eclipse.org/eclipse/jetty/10.0.6/"/>
+      <unit id="org.eclipse.jetty.http" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.io" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.security" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.server" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.servlet" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.util" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.util.ajax" version="10.0.13"/>
+      <repository id="jetty-10.0.x" location="https://download.eclipse.org/oomph/jetty/release/10.0.13/"/>
     </location>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
       <unit id="com.google.gson" version="2.9.1.v20220915-1632"/>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.23.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.23.target
index 1100bf2..1721bd6 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.23.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.23.target
@@ -1,26 +1,17 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <?pde?>
 <!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
-<target name="jgit-4.23" sequenceNumber="1669195941">
+<target name="jgit-4.23" sequenceNumber="1670938799">
   <locations>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
-      <unit id="jakarta.servlet-api" version="4.0.0"/>
-      <unit id="jakarta.servlet-api.source" version="4.0.0"/>
-      <unit id="org.eclipse.jetty.http" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.http.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.io" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.io.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.security" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.security.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.server" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.server.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.servlet" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.servlet.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.util" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.util.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.util.ajax" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.util.ajax.source" version="10.0.6"/>
-      <repository id="jetty-10.0.x" location="https://download.eclipse.org/eclipse/jetty/10.0.6/"/>
+      <unit id="org.eclipse.jetty.http" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.io" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.security" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.server" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.servlet" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.util" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.util.ajax" version="10.0.13"/>
+      <repository id="jetty-10.0.x" location="https://download.eclipse.org/oomph/jetty/release/10.0.13/"/>
     </location>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
       <unit id="com.google.gson" version="2.9.1.v20220915-1632"/>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.24.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.24.target
index ccd8d23..b44842d 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.24.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.24.target
@@ -1,26 +1,17 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <?pde?>
 <!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
-<target name="jgit-4.24" sequenceNumber="1669195941">
+<target name="jgit-4.24" sequenceNumber="1670938799">
   <locations>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
-      <unit id="jakarta.servlet-api" version="4.0.0"/>
-      <unit id="jakarta.servlet-api.source" version="4.0.0"/>
-      <unit id="org.eclipse.jetty.http" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.http.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.io" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.io.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.security" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.security.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.server" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.server.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.servlet" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.servlet.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.util" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.util.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.util.ajax" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.util.ajax.source" version="10.0.6"/>
-      <repository id="jetty-10.0.x" location="https://download.eclipse.org/eclipse/jetty/10.0.6/"/>
+      <unit id="org.eclipse.jetty.http" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.io" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.security" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.server" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.servlet" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.util" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.util.ajax" version="10.0.13"/>
+      <repository id="jetty-10.0.x" location="https://download.eclipse.org/oomph/jetty/release/10.0.13/"/>
     </location>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
       <unit id="com.google.gson" version="2.9.1.v20220915-1632"/>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.25.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.25.target
index 364f49e..60f8075 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.25.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.25.target
@@ -1,26 +1,17 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <?pde?>
 <!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
-<target name="jgit-4.25" sequenceNumber="1669195941">
+<target name="jgit-4.25" sequenceNumber="1670938799">
   <locations>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
-      <unit id="jakarta.servlet-api" version="4.0.0"/>
-      <unit id="jakarta.servlet-api.source" version="4.0.0"/>
-      <unit id="org.eclipse.jetty.http" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.http.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.io" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.io.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.security" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.security.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.server" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.server.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.servlet" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.servlet.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.util" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.util.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.util.ajax" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.util.ajax.source" version="10.0.6"/>
-      <repository id="jetty-10.0.x" location="https://download.eclipse.org/eclipse/jetty/10.0.6/"/>
+      <unit id="org.eclipse.jetty.http" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.io" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.security" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.server" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.servlet" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.util" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.util.ajax" version="10.0.13"/>
+      <repository id="jetty-10.0.x" location="https://download.eclipse.org/oomph/jetty/release/10.0.13/"/>
     </location>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
       <unit id="com.google.gson" version="2.9.1.v20220915-1632"/>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.26.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.26.target
index 257f45e..f6015d8 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.26.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.26.target
@@ -1,26 +1,17 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <?pde?>
 <!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
-<target name="jgit-4.25" sequenceNumber="1669195949">
+<target name="jgit-4.25" sequenceNumber="1670938729">
   <locations>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
-      <unit id="jakarta.servlet-api" version="4.0.0"/>
-      <unit id="jakarta.servlet-api.source" version="4.0.0"/>
-      <unit id="org.eclipse.jetty.http" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.http.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.io" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.io.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.security" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.security.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.server" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.server.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.servlet" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.servlet.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.util" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.util.source" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.util.ajax" version="10.0.6"/>
-      <unit id="org.eclipse.jetty.util.ajax.source" version="10.0.6"/>
-      <repository id="jetty-10.0.x" location="https://download.eclipse.org/eclipse/jetty/10.0.6/"/>
+      <unit id="org.eclipse.jetty.http" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.io" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.security" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.server" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.servlet" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.util" version="10.0.13"/>
+      <unit id="org.eclipse.jetty.util.ajax" version="10.0.13"/>
+      <repository id="jetty-10.0.x" location="https://download.eclipse.org/oomph/jetty/release/10.0.13/"/>
     </location>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
       <unit id="com.google.gson" version="2.9.1.v20220915-1632"/>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/projects/jetty-10.0.x.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/projects/jetty-10.0.x.tpd
index 6c3ee18..9fe89e2 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/projects/jetty-10.0.x.tpd
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/projects/jetty-10.0.x.tpd
@@ -1,20 +1,11 @@
 target "jetty-10.0.x" with source configurePhase
 
-location jetty-10.0.x "https://download.eclipse.org/eclipse/jetty/10.0.6/" {
-	jakarta.servlet-api [4.0.0, 5.0.0)
-	jakarta.servlet-api.source [4.0.0, 5.0.0)
-	org.eclipse.jetty.http [10.0.6,10.0.6]
-	org.eclipse.jetty.http.source [10.0.6,10.0.6]
-	org.eclipse.jetty.io [10.0.6,10.0.6]
-	org.eclipse.jetty.io.source [10.0.6,10.0.6]
-	org.eclipse.jetty.security [10.0.6,10.0.6]
-	org.eclipse.jetty.security.source [10.0.6,10.0.6]
-	org.eclipse.jetty.server [10.0.6,10.0.6]
-	org.eclipse.jetty.server.source [10.0.6,10.0.6]
-	org.eclipse.jetty.servlet [10.0.6,10.0.6]
-	org.eclipse.jetty.servlet.source [10.0.6,10.0.6]
-	org.eclipse.jetty.util [10.0.6,10.0.6]
-	org.eclipse.jetty.util.source [10.0.6,10.0.6]
-	org.eclipse.jetty.util.ajax [10.0.6,10.0.6]
-	org.eclipse.jetty.util.ajax.source [10.0.6,10.0.6]
+location jetty-10.0.x "https://download.eclipse.org/oomph/jetty/release/10.0.13/" {
+	org.eclipse.jetty.http [10.0.13,10.0.14]
+	org.eclipse.jetty.io [10.0.13,10.0.14]
+	org.eclipse.jetty.security [10.0.13,10.0.14]
+	org.eclipse.jetty.server [10.0.13,10.0.14]
+	org.eclipse.jetty.servlet [10.0.13,10.0.14]
+	org.eclipse.jetty.util [10.0.13,10.0.14]
+	org.eclipse.jetty.util.ajax [10.0.13,10.0.14]
 }
diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/commit-graph.v1 b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/commit-graph.v1
new file mode 100644
index 0000000..941c0a7
--- /dev/null
+++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/commit-graph.v1
Binary files differ
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/commitgraph/CommitGraphBuilderTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/commitgraph/CommitGraphBuilderTest.java
new file mode 100644
index 0000000..8ecf5df
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/commitgraph/CommitGraphBuilderTest.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2022, Tencent.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+package org.eclipse.jgit.internal.storage.commitgraph;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
+
+import org.junit.Test;
+
+public class CommitGraphBuilderTest {
+
+	@Test
+	public void testRepeatedChunk() throws Exception {
+		byte[] buffer = new byte[2048];
+
+		CommitGraphBuilder builder1 = CommitGraphBuilder.builder();
+		builder1.addOidFanout(buffer);
+		Exception e1 = assertThrows(CommitGraphFormatException.class, () -> {
+			builder1.addOidFanout(buffer);
+		});
+		assertEquals("commit-graph chunk id 0x4f494446 appears multiple times",
+				e1.getMessage());
+
+		CommitGraphBuilder builder2 = CommitGraphBuilder.builder();
+		builder2.addOidLookUp(buffer);
+		Exception e2 = assertThrows(CommitGraphFormatException.class, () -> {
+			builder2.addOidLookUp(buffer);
+		});
+		assertEquals("commit-graph chunk id 0x4f49444c appears multiple times",
+				e2.getMessage());
+
+		CommitGraphBuilder builder3 = CommitGraphBuilder.builder();
+		builder3.addCommitData(buffer);
+		Exception e3 = assertThrows(CommitGraphFormatException.class, () -> {
+			builder3.addCommitData(buffer);
+		});
+		assertEquals("commit-graph chunk id 0x43444154 appears multiple times",
+				e3.getMessage());
+
+		CommitGraphBuilder builder4 = CommitGraphBuilder.builder();
+		builder4.addExtraList(buffer);
+		Exception e4 = assertThrows(CommitGraphFormatException.class, () -> {
+			builder4.addExtraList(buffer);
+		});
+		assertEquals("commit-graph chunk id 0x45444745 appears multiple times",
+				e4.getMessage());
+	}
+
+	@Test
+	public void testNeededChunk() {
+		byte[] buffer = new byte[2048];
+
+		Exception e1 = assertThrows(CommitGraphFormatException.class, () -> {
+			CommitGraphBuilder.builder().addOidLookUp(buffer)
+					.addCommitData(buffer).build();
+		});
+		assertEquals("commit-graph 0x4f494446 chunk has not been loaded",
+				e1.getMessage());
+
+		Exception e2 = assertThrows(CommitGraphFormatException.class, () -> {
+			CommitGraphBuilder.builder().addOidFanout(buffer)
+					.addCommitData(buffer).build();
+		});
+		assertEquals("commit-graph 0x4f49444c chunk has not been loaded",
+				e2.getMessage());
+
+		Exception e3 = assertThrows(CommitGraphFormatException.class, () -> {
+			CommitGraphBuilder.builder().addOidFanout(buffer)
+					.addOidLookUp(buffer).build();
+		});
+		assertEquals("commit-graph 0x43444154 chunk has not been loaded",
+				e3.getMessage());
+	}
+}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/commitgraph/CommitGraphLoaderTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/commitgraph/CommitGraphLoaderTest.java
new file mode 100644
index 0000000..fd427a1
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/commitgraph/CommitGraphLoaderTest.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2022, Tencent.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+package org.eclipse.jgit.internal.storage.commitgraph;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import org.eclipse.jgit.internal.storage.commitgraph.CommitGraph.CommitData;
+import org.eclipse.jgit.junit.JGitTestUtil;
+import org.eclipse.jgit.lib.ObjectId;
+import org.junit.Test;
+
+/**
+ * Test CommitGraphLoader by reading the commit-graph file generated by Cgit.
+ */
+public class CommitGraphLoaderTest {
+
+	private CommitGraph commitGraph;
+
+	@Test
+	public void readCommitGraphV1() throws Exception {
+		commitGraph = CommitGraphLoader
+				.open(JGitTestUtil.getTestResourceFile("commit-graph.v1"));
+		assertNotNull(commitGraph);
+		assertEquals(10, commitGraph.getCommitCnt());
+		verifyGraphObjectIndex();
+
+		assertCommitData("85b0176af27fa1640868f061f224d01e0b295f59",
+				new int[] { 5, 6 }, 1670570408L, 3, 0);
+		assertCommitData("d4f7c00aab3f0160168c9e5991abb6194a4e0d9e",
+				new int[] {}, 1670569901L, 1, 1);
+		assertCommitData("4d03aaf9c20c97d6ccdc05cb7f146b1deb6c01d5",
+				new int[] { 5 }, 1670570119L, 3, 2);
+		assertCommitData("a2f409b753880bf83b18bfb433dd340a6185e8be",
+				new int[] { 7 }, 1670569935L, 3, 3);
+		assertCommitData("431343847343979bbe31127ed905a24fed9a636c",
+				new int[] { 3, 2, 8 }, 1670570644L, 4, 4);
+		assertCommitData("c3f745ad8928ef56b5dbf33740fc8ede6b598290",
+				new int[] { 1 }, 1670570106L, 2, 5);
+		assertCommitData("95b12422c8ea4371e54cd58925eeed9d960ff1f0",
+				new int[] { 1 }, 1670570163L, 2, 6);
+		assertCommitData("de0ea882503cdd9c984c0a43238014569a123cac",
+				new int[] { 1 }, 1670569921L, 2, 7);
+		assertCommitData("102c9d6481559b1a113eb66bf55085903de6fb00",
+				new int[] { 6 }, 1670570616L, 3, 8);
+		assertCommitData("b5de2a84867f8ffc6321649dabf8c0680661ec03",
+				new int[] { 7, 5 }, 1670570364L, 3, 9);
+	}
+
+	private void verifyGraphObjectIndex() {
+		for (int i = 0; i < commitGraph.getCommitCnt(); i++) {
+			ObjectId id = commitGraph.getObjectId(i);
+			int pos = commitGraph.findGraphPosition(id);
+			assertEquals(i, pos);
+		}
+	}
+
+	private void assertCommitData(String expectedTree, int[] expectedParents,
+			long expectedCommitTime, int expectedGeneration, int graphPos) {
+		CommitData commitData = commitGraph.getCommitData(graphPos);
+		assertEquals(ObjectId.fromString(expectedTree), commitData.getTree());
+		assertArrayEquals(expectedParents, commitData.getParents());
+		assertEquals(expectedCommitTime, commitData.getCommitTime());
+		assertEquals(expectedGeneration, commitData.getGeneration());
+	}
+}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/commitgraph/CommitGraphTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/commitgraph/CommitGraphTest.java
new file mode 100644
index 0000000..9797656
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/commitgraph/CommitGraphTest.java
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2022, Tencent.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+package org.eclipse.jgit.internal.storage.commitgraph;
+
+import static org.eclipse.jgit.lib.Constants.COMMIT_GENERATION_UNKNOWN;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.eclipse.jgit.internal.storage.file.FileRepository;
+import org.eclipse.jgit.junit.RepositoryTestCase;
+import org.eclipse.jgit.junit.TestRepository;
+import org.eclipse.jgit.lib.NullProgressMonitor;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevWalk;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Test writing and then reading the commit-graph.
+ */
+public class CommitGraphTest extends RepositoryTestCase {
+
+	private TestRepository<FileRepository> tr;
+
+	private CommitGraph commitGraph;
+
+	@Override
+	@Before
+	public void setUp() throws Exception {
+		super.setUp();
+		tr = new TestRepository<>(db, new RevWalk(db), mockSystemReader);
+	}
+
+	@Test
+	public void testGraphWithSingleCommit() throws Exception {
+		RevCommit root = commit();
+		writeAndReadCommitGraph(Collections.singleton(root));
+		verifyCommitGraph();
+		assertEquals(1, getGenerationNumber(root));
+	}
+
+	@Test
+	public void testGraphWithManyParents() throws Exception {
+		int parentsNum = 40;
+		RevCommit root = commit();
+
+		RevCommit[] parents = new RevCommit[parentsNum];
+		for (int i = 0; i < parents.length; i++) {
+			parents[i] = commit(root);
+		}
+		RevCommit tip = commit(parents);
+
+		Set<ObjectId> wants = Collections.singleton(tip);
+		writeAndReadCommitGraph(wants);
+		assertEquals(parentsNum + 2, commitGraph.getCommitCnt());
+		verifyCommitGraph();
+
+		assertEquals(1, getGenerationNumber(root));
+		for (RevCommit parent : parents) {
+			assertEquals(2, getGenerationNumber(parent));
+		}
+		assertEquals(3, getGenerationNumber(tip));
+	}
+
+	@Test
+	public void testGraphLinearHistory() throws Exception {
+		int commitNum = 20;
+		RevCommit[] commits = new RevCommit[commitNum];
+		for (int i = 0; i < commitNum; i++) {
+			if (i == 0) {
+				commits[i] = commit();
+			} else {
+				commits[i] = commit(commits[i - 1]);
+			}
+		}
+
+		Set<ObjectId> wants = Collections.singleton(commits[commitNum - 1]);
+		writeAndReadCommitGraph(wants);
+		assertEquals(commitNum, commitGraph.getCommitCnt());
+		verifyCommitGraph();
+		for (int i = 0; i < commitNum; i++) {
+			assertEquals(i + 1, getGenerationNumber(commits[i]));
+		}
+	}
+
+	@Test
+	public void testGraphWithMerges() throws Exception {
+		RevCommit c1 = commit();
+		RevCommit c2 = commit(c1);
+		RevCommit c3 = commit(c2);
+		RevCommit c4 = commit(c1);
+		RevCommit c5 = commit(c4);
+		RevCommit c6 = commit(c1);
+		RevCommit c7 = commit(c6);
+
+		RevCommit m1 = commit(c2, c4);
+		RevCommit m2 = commit(c4, c6);
+		RevCommit m3 = commit(c3, c5, c7);
+
+		Set<ObjectId> wants = new HashSet<>();
+
+		/*
+		 * <pre>
+		 * current graph structure:
+		 *    M1
+		 *   /  \
+		 *  2    4
+		 *  |___/
+		 *  1
+		 * </pre>
+		 */
+		wants.add(m1);
+		writeAndReadCommitGraph(wants);
+		assertEquals(4, commitGraph.getCommitCnt());
+		verifyCommitGraph();
+
+		/*
+		 * <pre>
+		 * current graph structure:
+		 *    M1   M2
+		 *   /  \ /  \
+		 *  2    4    6
+		 *  |___/____/
+		 *  1
+		 * </pre>
+		 */
+		wants.add(m2);
+		writeAndReadCommitGraph(wants);
+		assertEquals(6, commitGraph.getCommitCnt());
+		verifyCommitGraph();
+
+		/*
+		 * <pre>
+		 * current graph structure:
+		 *
+		 *    __M3___
+		 *   /   |   \
+		 *  3 M1 5 M2 7
+		 *  |/  \|/  \|
+		 *  2    4    6
+		 *  |___/____/
+		 *  1
+		 * </pre>
+		 */
+		wants.add(m3);
+		writeAndReadCommitGraph(wants);
+		assertEquals(10, commitGraph.getCommitCnt());
+		verifyCommitGraph();
+
+		/*
+		 * <pre>
+		 * current graph structure:
+		 *       8
+		 *       |
+		 *    __M3___
+		 *   /   |   \
+		 *  3 M1 5 M2 7
+		 *  |/  \|/  \|
+		 *  2    4    6
+		 *  |___/____/
+		 *  1
+		 * </pre>
+		 */
+		RevCommit c8 = commit(m3);
+		wants.add(c8);
+		writeAndReadCommitGraph(wants);
+		assertEquals(11, commitGraph.getCommitCnt());
+		verifyCommitGraph();
+
+		assertEquals(getGenerationNumber(c1), 1);
+		assertEquals(getGenerationNumber(c2), 2);
+		assertEquals(getGenerationNumber(c4), 2);
+		assertEquals(getGenerationNumber(c6), 2);
+		assertEquals(getGenerationNumber(c3), 3);
+		assertEquals(getGenerationNumber(c5), 3);
+		assertEquals(getGenerationNumber(c7), 3);
+		assertEquals(getGenerationNumber(m1), 3);
+		assertEquals(getGenerationNumber(m2), 3);
+		assertEquals(getGenerationNumber(m3), 4);
+		assertEquals(getGenerationNumber(c8), 5);
+	}
+
+	void writeAndReadCommitGraph(Set<ObjectId> wants) throws Exception {
+		NullProgressMonitor m = NullProgressMonitor.INSTANCE;
+		try (RevWalk walk = new RevWalk(db)) {
+			CommitGraphWriter writer = new CommitGraphWriter(
+					GraphCommits.fromWalk(m, wants, walk));
+			ByteArrayOutputStream os = new ByteArrayOutputStream();
+			writer.write(m, os);
+			InputStream inputStream = new ByteArrayInputStream(
+					os.toByteArray());
+			commitGraph = CommitGraphLoader.read(inputStream);
+		}
+	}
+
+	void verifyCommitGraph() throws Exception {
+		try (RevWalk walk = new RevWalk(db)) {
+			for (int i = 0; i < commitGraph.getCommitCnt(); i++) {
+				ObjectId objId = commitGraph.getObjectId(i);
+
+				// check the objectId index of commit-graph
+				int pos = commitGraph.findGraphPosition(objId);
+				assertEquals(i, pos);
+
+				// check the commit meta of commit-graph
+				CommitGraph.CommitData commit = commitGraph.getCommitData(i);
+				int[] pList = commit.getParents();
+
+				RevCommit expect = walk.lookupCommit(objId);
+				walk.parseBody(expect);
+
+				assertEquals(expect.getCommitTime(), commit.getCommitTime());
+				assertEquals(expect.getTree(), commit.getTree());
+				assertEquals(expect.getParentCount(), pList.length);
+
+				if (pList.length > 0) {
+					ObjectId[] parents = new ObjectId[pList.length];
+					for (int j = 0; j < parents.length; j++) {
+						parents[j] = commitGraph.getObjectId(pList[j]);
+					}
+					assertArrayEquals(expect.getParents(), parents);
+				}
+			}
+		}
+	}
+
+	int getGenerationNumber(ObjectId id) {
+		int graphPos = commitGraph.findGraphPosition(id);
+		CommitGraph.CommitData commitData = commitGraph.getCommitData(graphPos);
+		if (commitData != null) {
+			return commitData.getGeneration();
+		}
+		return COMMIT_GENERATION_UNKNOWN;
+	}
+
+	RevCommit commit(RevCommit... parents) throws Exception {
+		return tr.commit(parents);
+	}
+}
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 9b9e6d5..9c918ad 100644
--- a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
+++ b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
@@ -143,6 +143,10 @@
 commandClosedStderrButDidntExit=Command {0} closed stderr stream but didn''t exit within timeout {1} seconds
 commandRejectedByHook=Rejected by "{0}" hook.\n{1}
 commandWasCalledInTheWrongState=Command {0} was called in the wrong state
+commitGraphChunkNeeded=commit-graph 0x{0} chunk has not been loaded
+commitGraphChunkRepeated=commit-graph chunk id 0x{0} appears multiple times
+commitGraphChunkUnknown=unknown commit-graph chunk: 0x{0}
+commitGraphFileIsTooLargeForJgit=commit-graph file is too large for jgit
 commitGraphWritingCancelled=commit-graph writing was canceled
 commitMessageNotSpecified=commit message not specified
 commitOnRepoWithoutHEADCurrentlyNotSupported=Commit on repo without HEAD currently not supported
@@ -385,6 +389,7 @@
 invalidEncoding=Invalid encoding from git config i18n.commitEncoding: {0}
 invalidEncryption=Invalid encryption
 invalidExpandWildcard=ExpandFromSource on a refspec that can have mismatched wildcards does not make sense.
+invalidExtraEdgeListPosition=Invalid position in Extra Edge List chunk: {0}
 invalidFilter=Invalid filter: {0}
 invalidGitdirRef = Invalid .git reference in file ''{0}''
 invalidGitModules=Invalid .gitmodules file
@@ -515,6 +520,7 @@
 noSuchSubmodule=no such submodule {0}
 notABoolean=Not a boolean: {0}
 notABundle=not a bundle
+notACommitGraph=not a commit-graph
 notADIRCFile=Not a DIRC file.
 notAGitDirectory=not a git directory
 notAPACKFile=Not a PACK file.
@@ -797,6 +803,7 @@
 unmergedPath=Unmerged path: {0}
 unmergedPaths=Repository contains unmerged paths
 unpackException=Exception while parsing pack stream
+unreadableCommitGraph=Unreadable commit-graph: {0}
 unreadablePackIndex=Unreadable pack index: {0}
 unrecognizedPackExtension=Unrecognized pack extension: {0}
 unrecognizedRef=Unrecognized ref: {0}
@@ -804,6 +811,7 @@
 unsupportedAlternates=Alternates not supported
 unsupportedArchiveFormat=Unknown archive format ''{0}''
 unsupportedCommand0=unsupported command 0
+unsupportedCommitGraphVersion=Unsupported commit-graph version: {0}
 unsupportedEncryptionAlgorithm=Unsupported encryption algorithm: {0}
 unsupportedEncryptionVersion=Unsupported encryption version: {0}
 unsupportedGC=Unsupported garbage collector for repository type: {0}
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 7e741e0..3300742 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
@@ -171,6 +171,10 @@ public static JGitText get() {
 	/***/ public String commandClosedStderrButDidntExit;
 	/***/ public String commandRejectedByHook;
 	/***/ public String commandWasCalledInTheWrongState;
+	/***/ public String commitGraphChunkNeeded;
+	/***/ public String commitGraphChunkRepeated;
+	/***/ public String commitGraphChunkUnknown;
+	/***/ public String commitGraphFileIsTooLargeForJgit;
 	/***/ public String commitGraphWritingCancelled;
 	/***/ public String commitMessageNotSpecified;
 	/***/ public String commitOnRepoWithoutHEADCurrentlyNotSupported;
@@ -413,6 +417,7 @@ public static JGitText get() {
 	/***/ public String invalidEncoding;
 	/***/ public String invalidEncryption;
 	/***/ public String invalidExpandWildcard;
+	/***/ public String invalidExtraEdgeListPosition;
 	/***/ public String invalidFilter;
 	/***/ public String invalidGitdirRef;
 	/***/ public String invalidGitModules;
@@ -543,6 +548,7 @@ public static JGitText get() {
 	/***/ public String noSuchSubmodule;
 	/***/ public String notABoolean;
 	/***/ public String notABundle;
+	/***/ public String notACommitGraph;
 	/***/ public String notADIRCFile;
 	/***/ public String notAGitDirectory;
 	/***/ public String notAPACKFile;
@@ -825,6 +831,7 @@ public static JGitText get() {
 	/***/ public String unmergedPath;
 	/***/ public String unmergedPaths;
 	/***/ public String unpackException;
+	/***/ public String unreadableCommitGraph;
 	/***/ public String unreadablePackIndex;
 	/***/ public String unrecognizedPackExtension;
 	/***/ public String unrecognizedRef;
@@ -832,6 +839,7 @@ public static JGitText get() {
 	/***/ public String unsupportedAlternates;
 	/***/ public String unsupportedArchiveFormat;
 	/***/ public String unsupportedCommand0;
+	/***/ public String unsupportedCommitGraphVersion;
 	/***/ public String unsupportedEncryptionAlgorithm;
 	/***/ public String unsupportedEncryptionVersion;
 	/***/ public String unsupportedGC;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/commitgraph/CommitGraph.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/commitgraph/CommitGraph.java
new file mode 100644
index 0000000..162e0e2
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/commitgraph/CommitGraph.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2022, Tencent.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+package org.eclipse.jgit.internal.storage.commitgraph;
+
+import org.eclipse.jgit.lib.AnyObjectId;
+import org.eclipse.jgit.lib.ObjectId;
+
+/**
+ * The CommitGraph is a supplemental data structure that accelerates commit
+ * graph walks.
+ * <p>
+ * If a user downgrades or disables the <code>core.commitGraph</code> config
+ * setting, then the existing object database is sufficient.
+ * </p>
+ * <p>
+ * It stores the commit graph structure along with some extra metadata to speed
+ * up graph walks. By listing commit OIDs in lexicographic order, we can
+ * identify an integer position for each commit and refer to the parents of a
+ * commit using those integer positions. We use binary search to find initial
+ * commits and then use the integer positions for fast lookups during the walk.
+ * </p>
+ */
+public interface CommitGraph {
+
+	/**
+	 * Find the position in the commit-graph of the commit.
+	 * <p>
+	 * The position can only be used within the CommitGraph Instance you got it
+	 * from. That's because the graph position of the same commit may be
+	 * different in CommitGraph obtained at different times (eg., regenerated
+	 * new commit-graph).
+	 *
+	 * @param commit
+	 *            the commit for which the commit-graph position will be found.
+	 * @return the commit-graph position or -1 if the object was not found.
+	 */
+	int findGraphPosition(AnyObjectId commit);
+
+	/**
+	 * Get the metadata of a commit。
+	 * <p>
+	 * This function runs in time O(1).
+	 * <p>
+	 * In the process of commit history traversal,
+	 * {@link CommitData#getParents()} makes us get the graphPos of the commit's
+	 * parents in advance, so that we can avoid O(logN) lookup and use O(1)
+	 * lookup instead.
+	 *
+	 * @param graphPos
+	 *            the position in the commit-graph of the object.
+	 * @return the metadata of a commit or null if it's not found.
+	 */
+	CommitData getCommitData(int graphPos);
+
+	/**
+	 * Get the object at the commit-graph position.
+	 *
+	 * @param graphPos
+	 *            the position in the commit-graph of the object.
+	 * @return the ObjectId or null if it's not found.
+	 */
+	ObjectId getObjectId(int graphPos);
+
+	/**
+	 * Obtain the total number of commits described by this commit-graph.
+	 *
+	 * @return number of commits in this commit-graph.
+	 */
+	long getCommitCnt();
+
+	/**
+	 * Metadata of a commit in commit data chunk.
+	 */
+	interface CommitData {
+
+		/**
+		 * Get a reference to this commit's tree.
+		 *
+		 * @return tree of this commit.
+		 */
+		ObjectId getTree();
+
+		/**
+		 * Obtain an array of all parents.
+		 * <p>
+		 * The method only provides the graph positions of parents in
+		 * commit-graph, call {@link CommitGraph#getObjectId(int)} to get the
+		 * real objectId.
+		 *
+		 * @return the array of parents.
+		 */
+		int[] getParents();
+
+		/**
+		 * Time from the "committer" line.
+		 *
+		 * @return the commit time in seconds since EPOCH.
+		 */
+		long getCommitTime();
+
+		/**
+		 * Get the generation number (the distance from the root) of the commit.
+		 *
+		 * @return the generation number or
+		 *         {@link org.eclipse.jgit.lib.Constants#COMMIT_GENERATION_NOT_COMPUTED}
+		 *         if the writer didn't calculate it.
+		 */
+		int getGeneration();
+	}
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/commitgraph/CommitGraphBuilder.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/commitgraph/CommitGraphBuilder.java
new file mode 100644
index 0000000..a6af3bc
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/commitgraph/CommitGraphBuilder.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2022, Tencent.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+package org.eclipse.jgit.internal.storage.commitgraph;
+
+import static org.eclipse.jgit.internal.storage.commitgraph.CommitGraphConstants.CHUNK_ID_COMMIT_DATA;
+import static org.eclipse.jgit.internal.storage.commitgraph.CommitGraphConstants.CHUNK_ID_EXTRA_EDGE_LIST;
+import static org.eclipse.jgit.internal.storage.commitgraph.CommitGraphConstants.CHUNK_ID_OID_FANOUT;
+import static org.eclipse.jgit.internal.storage.commitgraph.CommitGraphConstants.CHUNK_ID_OID_LOOKUP;
+import static org.eclipse.jgit.lib.Constants.OBJECT_ID_LENGTH;
+
+import java.text.MessageFormat;
+
+import org.eclipse.jgit.internal.JGitText;
+
+/**
+ * Builder for {@link CommitGraph}.
+ */
+class CommitGraphBuilder {
+
+	private final int hashLength;
+
+	private byte[] oidFanout;
+
+	private byte[] oidLookup;
+
+	private byte[] commitData;
+
+	private byte[] extraList;
+
+	/** @return A builder of {@link CommitGraph}. */
+	static CommitGraphBuilder builder() {
+		return new CommitGraphBuilder(OBJECT_ID_LENGTH);
+	}
+
+	private CommitGraphBuilder(int hashLength) {
+		this.hashLength = hashLength;
+	}
+
+	CommitGraphBuilder addOidFanout(byte[] buffer)
+			throws CommitGraphFormatException {
+		assertChunkNotSeenYet(oidFanout, CHUNK_ID_OID_FANOUT);
+		oidFanout = buffer;
+		return this;
+	}
+
+	CommitGraphBuilder addOidLookUp(byte[] buffer)
+			throws CommitGraphFormatException {
+		assertChunkNotSeenYet(oidLookup, CHUNK_ID_OID_LOOKUP);
+		oidLookup = buffer;
+		return this;
+	}
+
+	CommitGraphBuilder addCommitData(byte[] buffer)
+			throws CommitGraphFormatException {
+		assertChunkNotSeenYet(commitData, CHUNK_ID_COMMIT_DATA);
+		commitData = buffer;
+		return this;
+	}
+
+	CommitGraphBuilder addExtraList(byte[] buffer)
+			throws CommitGraphFormatException {
+		assertChunkNotSeenYet(extraList, CHUNK_ID_EXTRA_EDGE_LIST);
+		extraList = buffer;
+		return this;
+	}
+
+	CommitGraph build() throws CommitGraphFormatException {
+		assertChunkNotNull(oidFanout, CHUNK_ID_OID_FANOUT);
+		assertChunkNotNull(oidLookup, CHUNK_ID_OID_LOOKUP);
+		assertChunkNotNull(commitData, CHUNK_ID_COMMIT_DATA);
+
+		GraphObjectIndex index = new GraphObjectIndex(hashLength, oidFanout,
+				oidLookup);
+		GraphCommitData commitDataChunk = new GraphCommitData(hashLength,
+				commitData, extraList);
+		return new CommitGraphV1(index, commitDataChunk);
+	}
+
+	private void assertChunkNotNull(Object object, int chunkId)
+			throws CommitGraphFormatException {
+		if (object == null) {
+			throw new CommitGraphFormatException(
+					MessageFormat.format(JGitText.get().commitGraphChunkNeeded,
+							Integer.toHexString(chunkId)));
+		}
+	}
+
+	private void assertChunkNotSeenYet(Object object, int chunkId)
+			throws CommitGraphFormatException {
+		if (object != null) {
+			throw new CommitGraphFormatException(MessageFormat.format(
+					JGitText.get().commitGraphChunkRepeated,
+					Integer.toHexString(chunkId)));
+		}
+	}
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/commitgraph/CommitGraphFormatException.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/commitgraph/CommitGraphFormatException.java
new file mode 100644
index 0000000..352bf4b
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/commitgraph/CommitGraphFormatException.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2022, Tencent.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+package org.eclipse.jgit.internal.storage.commitgraph;
+
+import java.io.IOException;
+
+/**
+ * Thrown when a commit-graph file's format is different from we expected
+ */
+public class CommitGraphFormatException extends IOException {
+
+	private static final long serialVersionUID = 1L;
+
+	/**
+	 * Construct an exception.
+	 *
+	 * @param why
+	 *            description of the type of error.
+	 */
+	CommitGraphFormatException(String why) {
+		super(why);
+	}
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/commitgraph/CommitGraphLoader.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/commitgraph/CommitGraphLoader.java
new file mode 100644
index 0000000..571f5f4
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/commitgraph/CommitGraphLoader.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2022, Tencent.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+package org.eclipse.jgit.internal.storage.commitgraph;
+
+import static org.eclipse.jgit.internal.storage.commitgraph.CommitGraphConstants.CHUNK_ID_COMMIT_DATA;
+import static org.eclipse.jgit.internal.storage.commitgraph.CommitGraphConstants.CHUNK_ID_EXTRA_EDGE_LIST;
+import static org.eclipse.jgit.internal.storage.commitgraph.CommitGraphConstants.CHUNK_ID_OID_FANOUT;
+import static org.eclipse.jgit.internal.storage.commitgraph.CommitGraphConstants.CHUNK_ID_OID_LOOKUP;
+import static org.eclipse.jgit.internal.storage.commitgraph.CommitGraphConstants.CHUNK_LOOKUP_WIDTH;
+import static org.eclipse.jgit.internal.storage.commitgraph.CommitGraphConstants.COMMIT_GRAPH_MAGIC;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jgit.internal.JGitText;
+import org.eclipse.jgit.util.IO;
+import org.eclipse.jgit.util.NB;
+import org.eclipse.jgit.util.io.SilentFileInputStream;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The loader returns the representation of the commit-graph file content.
+ */
+public class CommitGraphLoader {
+
+	private final static Logger LOG = LoggerFactory
+			.getLogger(CommitGraphLoader.class);
+
+	/**
+	 * Open an existing commit-graph file for reading.
+	 * <p>
+	 * The format of the file will be automatically detected and a proper access
+	 * implementation for that format will be constructed and returned to the
+	 * caller. The file may or may not be held open by the returned instance.
+	 *
+	 * @param graphFile
+	 *            existing commit-graph to read.
+	 * @return a copy of the commit-graph file in memory
+	 * @throws FileNotFoundException
+	 *             the file does not exist.
+	 * @throws CommitGraphFormatException
+	 *             commit-graph file's format is different from we expected.
+	 * @throws java.io.IOException
+	 *             the file exists but could not be read due to security errors
+	 *             or unexpected data corruption.
+	 */
+	public static CommitGraph open(File graphFile) throws FileNotFoundException,
+			CommitGraphFormatException, IOException {
+		try (SilentFileInputStream fd = new SilentFileInputStream(graphFile)) {
+			try {
+				return read(fd);
+			} catch (CommitGraphFormatException fe) {
+				throw fe;
+			} catch (IOException ioe) {
+				throw new IOException(MessageFormat.format(
+						JGitText.get().unreadableCommitGraph,
+						graphFile.getAbsolutePath()), ioe);
+			}
+		}
+	}
+
+	/**
+	 * Read an existing commit-graph file from a buffered stream.
+	 * <p>
+	 * The format of the file will be automatically detected and a proper access
+	 * implementation for that format will be constructed and returned to the
+	 * caller. The file may or may not be held open by the returned instance.
+	 *
+	 * @param fd
+	 *            stream to read the commit-graph file from. The stream must be
+	 *            buffered as some small IOs are performed against the stream.
+	 *            The caller is responsible for closing the stream.
+	 *
+	 * @return a copy of the commit-graph file in memory
+	 * @throws CommitGraphFormatException
+	 *             the commit-graph file's format is different from we expected.
+	 * @throws java.io.IOException
+	 *             the stream cannot be read.
+	 */
+	public static CommitGraph read(InputStream fd)
+			throws CommitGraphFormatException, IOException {
+		byte[] hdr = new byte[8];
+		IO.readFully(fd, hdr, 0, hdr.length);
+
+		int magic = NB.decodeInt32(hdr, 0);
+		if (magic != COMMIT_GRAPH_MAGIC) {
+			throw new CommitGraphFormatException(
+					JGitText.get().notACommitGraph);
+		}
+
+		// Read the hash version (1 byte)
+		// 1 => SHA-1
+		// 2 => SHA-256 nonsupport now
+		int hashVersion = hdr[5];
+		if (hashVersion != 1) {
+			throw new CommitGraphFormatException(
+					JGitText.get().incorrectOBJECT_ID_LENGTH);
+		}
+
+		// Check commit-graph version
+		int v = hdr[4];
+		if (v != 1) {
+			throw new CommitGraphFormatException(MessageFormat.format(
+					JGitText.get().unsupportedCommitGraphVersion,
+					Integer.valueOf(v)));
+		}
+
+		// Read the number of "chunkOffsets" (1 byte)
+		int numberOfChunks = hdr[6];
+
+		// hdr[7] is the number of base commit-graphs, which is not supported in
+		// current version
+
+		byte[] lookupBuffer = new byte[CHUNK_LOOKUP_WIDTH
+				* (numberOfChunks + 1)];
+		IO.readFully(fd, lookupBuffer, 0, lookupBuffer.length);
+		List<ChunkSegment> chunks = new ArrayList<>(numberOfChunks + 1);
+		for (int i = 0; i <= numberOfChunks; i++) {
+			// chunks[numberOfChunks] is just a marker, in order to record the
+			// length of the last chunk.
+			int id = NB.decodeInt32(lookupBuffer, i * 12);
+			long offset = NB.decodeInt64(lookupBuffer, i * 12 + 4);
+			chunks.add(new ChunkSegment(id, offset));
+		}
+
+		CommitGraphBuilder builder = CommitGraphBuilder.builder();
+		for (int i = 0; i < numberOfChunks; i++) {
+			long chunkOffset = chunks.get(i).offset;
+			int chunkId = chunks.get(i).id;
+			long len = chunks.get(i + 1).offset - chunkOffset;
+
+			if (len > Integer.MAX_VALUE - 8) { // http://stackoverflow.com/a/8381338
+				throw new CommitGraphFormatException(
+						JGitText.get().commitGraphFileIsTooLargeForJgit);
+			}
+
+			byte buffer[] = new byte[(int) len];
+			IO.readFully(fd, buffer, 0, buffer.length);
+
+			switch (chunkId) {
+			case CHUNK_ID_OID_FANOUT:
+				builder.addOidFanout(buffer);
+				break;
+			case CHUNK_ID_OID_LOOKUP:
+				builder.addOidLookUp(buffer);
+				break;
+			case CHUNK_ID_COMMIT_DATA:
+				builder.addCommitData(buffer);
+				break;
+			case CHUNK_ID_EXTRA_EDGE_LIST:
+				builder.addExtraList(buffer);
+				break;
+			default:
+				LOG.warn(MessageFormat.format(
+						JGitText.get().commitGraphChunkUnknown,
+						Integer.toHexString(chunkId)));
+			}
+		}
+		return builder.build();
+	}
+
+	private static class ChunkSegment {
+		final int id;
+
+		final long offset;
+
+		private ChunkSegment(int id, long offset) {
+			this.id = id;
+			this.offset = offset;
+		}
+	}
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/commitgraph/CommitGraphV1.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/commitgraph/CommitGraphV1.java
new file mode 100644
index 0000000..da17219
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/commitgraph/CommitGraphV1.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2022, Tencent.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+package org.eclipse.jgit.internal.storage.commitgraph;
+
+import org.eclipse.jgit.lib.AnyObjectId;
+import org.eclipse.jgit.lib.ObjectId;
+
+/**
+ * Support for the commit-graph v1 format.
+ *
+ * @see CommitGraph
+ */
+class CommitGraphV1 implements CommitGraph {
+
+	private final GraphObjectIndex idx;
+
+	private final GraphCommitData commitData;
+
+	CommitGraphV1(GraphObjectIndex index, GraphCommitData commitData) {
+		this.idx = index;
+		this.commitData = commitData;
+	}
+
+	/** {@inheritDoc} */
+	@Override
+	public int findGraphPosition(AnyObjectId commit) {
+		return idx.findGraphPosition(commit);
+	}
+
+	/** {@inheritDoc} */
+	@Override
+	public CommitData getCommitData(int graphPos) {
+		if (graphPos < 0 || graphPos >= getCommitCnt()) {
+			return null;
+		}
+		return commitData.getCommitData(graphPos);
+	}
+
+	/** {@inheritDoc} */
+	@Override
+	public ObjectId getObjectId(int graphPos) {
+		return idx.getObjectId(graphPos);
+	}
+
+	/** {@inheritDoc} */
+	@Override
+	public long getCommitCnt() {
+		return idx.getCommitCnt();
+	}
+}
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 2f96c4d..a58a9eb 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
@@ -103,7 +103,8 @@ public void write(@NonNull ProgressMonitor monitor,
 			writeChunks(monitor, out, chunks);
 			writeCheckSum(out);
 		} catch (InterruptedIOException e) {
-			throw new IOException(JGitText.get().commitGraphWritingCancelled);
+			throw new IOException(JGitText.get().commitGraphWritingCancelled,
+					e);
 		} finally {
 			monitor.endTask();
 		}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/commitgraph/GraphCommitData.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/commitgraph/GraphCommitData.java
new file mode 100644
index 0000000..6ae40ff
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/commitgraph/GraphCommitData.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2022, Tencent.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+package org.eclipse.jgit.internal.storage.commitgraph;
+
+import static org.eclipse.jgit.internal.storage.commitgraph.CommitGraphConstants.COMMIT_DATA_WIDTH;
+import static org.eclipse.jgit.internal.storage.commitgraph.CommitGraphConstants.GRAPH_EDGE_LAST_MASK;
+import static org.eclipse.jgit.internal.storage.commitgraph.CommitGraphConstants.GRAPH_EXTRA_EDGES_NEEDED;
+import static org.eclipse.jgit.internal.storage.commitgraph.CommitGraphConstants.GRAPH_LAST_EDGE;
+import static org.eclipse.jgit.internal.storage.commitgraph.CommitGraphConstants.GRAPH_NO_PARENT;
+
+import java.text.MessageFormat;
+import java.util.Arrays;
+
+import org.eclipse.jgit.annotations.NonNull;
+import org.eclipse.jgit.internal.JGitText;
+import org.eclipse.jgit.internal.storage.commitgraph.CommitGraph.CommitData;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.util.NB;
+
+/**
+ * Represent the collection of {@link CommitData}.
+ */
+class GraphCommitData {
+
+	private static final int[] NO_PARENTS = {};
+
+	private final byte[] data;
+
+	private final byte[] extraList;
+
+	private final int hashLength;
+
+	private final int commitDataLength;
+
+	/**
+	 * Initialize the GraphCommitData.
+	 *
+	 * @param hashLength
+	 *            length of object hash.
+	 * @param commitData
+	 *            content of CommitData Chunk.
+	 * @param extraList
+	 *            content of Extra Edge List Chunk.
+	 */
+	GraphCommitData(int hashLength, @NonNull byte[] commitData,
+			byte[] extraList) {
+		this.data = commitData;
+		this.extraList = extraList;
+		this.hashLength = hashLength;
+		this.commitDataLength = hashLength + COMMIT_DATA_WIDTH;
+	}
+
+	/**
+	 * Get the metadata of a commit。
+	 *
+	 * @param graphPos
+	 *            the position in the commit-graph of the object.
+	 * @return the metadata of a commit or null if not found.
+	 */
+	CommitData getCommitData(int graphPos) {
+		int dataIdx = commitDataLength * graphPos;
+
+		// parse tree
+		ObjectId tree = ObjectId.fromRaw(data, dataIdx);
+
+		// parse date
+		long dateHigh = NB.decodeUInt32(data, dataIdx + hashLength + 8) & 0x3;
+		long dateLow = NB.decodeUInt32(data, dataIdx + hashLength + 12);
+		long commitTime = dateHigh << 32 | dateLow;
+
+		// parse generation
+		int generation = NB.decodeInt32(data, dataIdx + hashLength + 8) >> 2;
+
+		// parse first parent
+		int parent1 = NB.decodeInt32(data, dataIdx + hashLength);
+		if (parent1 == GRAPH_NO_PARENT) {
+			return new CommitDataImpl(tree, NO_PARENTS, commitTime, generation);
+		}
+
+		// parse second parent
+		int parent2 = NB.decodeInt32(data, dataIdx + hashLength + 4);
+		if (parent2 == GRAPH_NO_PARENT) {
+			return new CommitDataImpl(tree, new int[] { parent1 }, commitTime,
+					generation);
+		}
+
+		if ((parent2 & GRAPH_EXTRA_EDGES_NEEDED) == 0) {
+			return new CommitDataImpl(tree, new int[] { parent1, parent2 },
+					commitTime, generation);
+		}
+
+		// parse parents for octopus merge
+		return new CommitDataImpl(tree,
+				findParentsForOctopusMerge(parent1,
+						parent2 & GRAPH_EDGE_LAST_MASK),
+				commitTime, generation);
+	}
+
+	private int[] findParentsForOctopusMerge(int parent1, int extraEdgePos) {
+		int maxOffset = extraList.length - 4;
+		int offset = extraEdgePos * 4;
+		if (offset < 0 || offset > maxOffset) {
+			throw new IllegalArgumentException(MessageFormat.format(
+					JGitText.get().invalidExtraEdgeListPosition,
+					Integer.valueOf(extraEdgePos)));
+		}
+		int[] pList = new int[32];
+		pList[0] = parent1;
+		int count = 1;
+		int parentPosition;
+		for (; offset <= maxOffset; offset += 4) {
+			if (count >= pList.length) {
+				// expand the pList
+				pList = Arrays.copyOf(pList, pList.length + 32);
+			}
+			parentPosition = NB.decodeInt32(extraList, offset);
+			if ((parentPosition & GRAPH_LAST_EDGE) != 0) {
+				pList[count++] = parentPosition & GRAPH_EDGE_LAST_MASK;
+				break;
+			}
+			pList[count++] = parentPosition;
+		}
+		return Arrays.copyOf(pList, count);
+	}
+
+	private static class CommitDataImpl implements CommitData {
+
+		private final ObjectId tree;
+
+		private final int[] parents;
+
+		private final long commitTime;
+
+		private final int generation;
+
+		public CommitDataImpl(ObjectId tree, int[] parents, long commitTime,
+				int generation) {
+			this.tree = tree;
+			this.parents = parents;
+			this.commitTime = commitTime;
+			this.generation = generation;
+		}
+
+		@Override
+		public ObjectId getTree() {
+			return tree;
+		}
+
+		@Override
+		public int[] getParents() {
+			return parents;
+		}
+
+		@Override
+		public long getCommitTime() {
+			return commitTime;
+		}
+
+		@Override
+		public int getGeneration() {
+			return generation;
+		}
+	}
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/commitgraph/GraphCommits.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/commitgraph/GraphCommits.java
index 23234f9..ccf6d0e 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/commitgraph/GraphCommits.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/commitgraph/GraphCommits.java
@@ -116,13 +116,6 @@ int getOidPosition(RevCommit c) throws MissingObjectException {
 		return commitWithPosition.position;
 	}
 
-	RevCommit getCommit(int oidPos) {
-		if (oidPos < 0 || oidPos >= sortedCommits.size()) {
-			return null;
-		}
-		return sortedCommits.get(oidPos);
-	}
-
 	int getExtraEdgeCnt() {
 		return extraEdgeCnt;
 	}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/commitgraph/GraphObjectIndex.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/commitgraph/GraphObjectIndex.java
new file mode 100644
index 0000000..b0df467
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/commitgraph/GraphObjectIndex.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2022, Tencent.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+package org.eclipse.jgit.internal.storage.commitgraph;
+
+import org.eclipse.jgit.annotations.NonNull;
+import org.eclipse.jgit.internal.JGitText;
+import org.eclipse.jgit.lib.AnyObjectId;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.util.NB;
+
+/**
+ * The index which are used by the commit-graph to:
+ * <ul>
+ * <li>Get the object in commit-graph by using a specific position.</li>
+ * <li>Get the position of a specific object in commit-graph.</li>
+ * </ul>
+ */
+class GraphObjectIndex {
+
+	private static final int FANOUT = 256;
+
+	private final int hashLength;
+
+	private final int[] fanoutTable;
+
+	private final byte[] oidLookup;
+
+	private final long commitCnt;
+
+	/**
+	 * Initialize the GraphObjectIndex.
+	 *
+	 * @param hashLength
+	 *            length of object hash.
+	 * @param oidFanout
+	 *            content of OID Fanout Chunk.
+	 * @param oidLookup
+	 *            content of OID Lookup Chunk.
+	 * @throws CommitGraphFormatException
+	 *             commit-graph file's format is different from we expected.
+	 */
+	GraphObjectIndex(int hashLength, @NonNull byte[] oidFanout,
+			@NonNull byte[] oidLookup) throws CommitGraphFormatException {
+		this.hashLength = hashLength;
+		this.oidLookup = oidLookup;
+
+		int[] table = new int[FANOUT];
+		long uint32;
+		for (int k = 0; k < table.length; k++) {
+			uint32 = NB.decodeUInt32(oidFanout, k * 4);
+			if (table[k] > Integer.MAX_VALUE) {
+				throw new CommitGraphFormatException(
+						JGitText.get().commitGraphFileIsTooLargeForJgit);
+			}
+			table[k] = (int) uint32;
+		}
+		this.fanoutTable = table;
+		this.commitCnt = table[FANOUT - 1];
+	}
+
+	/**
+	 * Find the position in the commit-graph of the specified id.
+	 *
+	 * @param id
+	 *            the id for which the commit-graph position will be found.
+	 * @return the commit-graph position or -1 if the object was not found.
+	 */
+	int findGraphPosition(AnyObjectId id) {
+		int levelOne = id.getFirstByte();
+		int high = fanoutTable[levelOne];
+		int low = 0;
+		if (levelOne > 0) {
+			low = fanoutTable[levelOne - 1];
+		}
+		do {
+			int mid = (low + high) >>> 1;
+			int pos = objIdOffset(mid);
+			int cmp = id.compareTo(oidLookup, pos);
+			if (cmp < 0) {
+				high = mid;
+			} else if (cmp == 0) {
+				return mid;
+			} else {
+				low = mid + 1;
+			}
+		} while (low < high);
+		return -1;
+	}
+
+	/**
+	 * Get the object at the commit-graph position.
+	 *
+	 * @param graphPos
+	 *            the position in the commit-graph of the object.
+	 * @return the ObjectId or null if it's not found.
+	 */
+	ObjectId getObjectId(int graphPos) {
+		if (graphPos < 0 || graphPos >= commitCnt) {
+			return null;
+		}
+		return ObjectId.fromRaw(oidLookup, objIdOffset(graphPos));
+	}
+
+	long getCommitCnt() {
+		return commitCnt;
+	}
+
+	private int objIdOffset(int pos) {
+		return hashLength * pos;
+	}
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkPushConnection.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkPushConnection.java
index 03ef852..a54fd8e 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkPushConnection.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkPushConnection.java
@@ -230,7 +230,7 @@ private void sendpack(final List<RemoteRefUpdate> updates,
 				// offsets from appearing to clients.
 				//
 				dest.writeInfoPacks(packNames.keySet());
-				dest.deleteFile(idx.getPath());
+				dest.deleteFile(sanitizedPath(idx));
 			}
 
 			// Write the pack file, then the index, as readers look the
@@ -238,13 +238,13 @@ private void sendpack(final List<RemoteRefUpdate> updates,
 			//
 			String wt = "Put " + pack.getName().substring(0, 12); //$NON-NLS-1$
 			try (OutputStream os = new BufferedOutputStream(
-					dest.writeFile(pack.getPath(), monitor,
+					dest.writeFile(sanitizedPath(pack), monitor,
 							wt + "." + pack.getPackExt().getExtension()))) { //$NON-NLS-1$
 				writer.writePack(monitor, monitor, os);
 			}
 
 			try (OutputStream os = new BufferedOutputStream(
-					dest.writeFile(idx.getPath(), monitor,
+					dest.writeFile(sanitizedPath(idx), monitor,
 							wt + "." + idx.getPackExt().getExtension()))) { //$NON-NLS-1$
 				writer.writeIndex(os);
 			}
@@ -269,7 +269,7 @@ private void sendpack(final List<RemoteRefUpdate> updates,
 	private void safeDelete(File path) {
 		if (path != null) {
 			try {
-				dest.deleteFile(path.getPath());
+				dest.deleteFile(sanitizedPath(path));
 			} catch (IOException cleanupFailure) {
 				// Ignore the deletion failure. We probably are
 				// already failing and were just trying to pick
@@ -366,4 +366,13 @@ private static String pickHEAD(List<RemoteRefUpdate> updates) {
 		}
 		return updates.get(0).getRemoteName();
 	}
+
+	private static String sanitizedPath(File file) {
+		String path = file.getPath();
+		if (File.separatorChar != '/') {
+			path = path.replace(File.separatorChar, '/');
+		}
+		return path;
+	}
+
 }
diff --git a/pom.xml b/pom.xml
index 4b25f21..d8e5ad3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -162,7 +162,7 @@
     <commons-compress-version>1.21</commons-compress-version>
     <osgi-core-version>6.0.0</osgi-core-version>
     <servlet-api-version>4.0.0</servlet-api-version>
-    <jetty-version>10.0.6</jetty-version>
+    <jetty-version>10.0.13</jetty-version>
     <japicmp-version>0.15.3</japicmp-version>
     <httpclient-version>4.5.13</httpclient-version>
     <httpcore-version>4.4.15</httpcore-version>