Merge "[spotbugs]: Fix potential NPE in FileSnapshot constructor"
diff --git a/WORKSPACE b/WORKSPACE
index ad04d14..768682d 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -233,52 +233,59 @@
 
 maven_jar(
     name = "gson",
-    artifact = "com.google.code.gson:gson:2.8.2",
-    sha1 = "3edcfe49d2c6053a70a2a47e4e1c2f94998a49cf",
+    artifact = "com.google.code.gson:gson:2.8.6",
+    sha1 = "9180733b7df8542621dc12e21e87557e8c99b8cb",
 )
 
-JETTY_VER = "9.4.30.v20200611"
+JETTY_VER = "9.4.35.v20201120"
 
 maven_jar(
     name = "jetty-servlet",
     artifact = "org.eclipse.jetty:jetty-servlet:" + JETTY_VER,
-    sha1 = "ca3dea2cd34ee88cec017001603af0c9e74781d6",
-    src_sha1 = "6908f24428060bd542bddfa3e89e03d0dbbc2a6d",
+    sha1 = "3e61bcb471e1bfc545ce866cbbe33c3aedeec9b1",
+    src_sha1 = "e237af9dd6556756736fcdc7da00194fa00d3c2b",
 )
 
 maven_jar(
     name = "jetty-security",
     artifact = "org.eclipse.jetty:jetty-security:" + JETTY_VER,
-    sha1 = "1a5261f6ad4081ad9e9bb01416d639931d391273",
-    src_sha1 = "6ca41b34aa4f84c267603edd4b069122bd5f17d3",
+    sha1 = "80dc2f422789c78315de76d289b7a5b36c3232d5",
+    src_sha1 = "3c0d03191fdffd9cf1e46fa206d79eeb9e3adb90",
 )
 
 maven_jar(
     name = "jetty-server",
     artifact = "org.eclipse.jetty:jetty-server:" + JETTY_VER,
-    sha1 = "e5ede3724d062717d0c04e4c77f74fe8115c2a6f",
-    src_sha1 = "c8b02a47a35c1f083b310cbd202738cf08bc1d55",
+    sha1 = "513502352fd689d4730b2935421b990ada8cc818",
+    src_sha1 = "760d3574ebc7f9b9b1ba51242b9c1dda6fe5505b",
 )
 
 maven_jar(
     name = "jetty-http",
     artifact = "org.eclipse.jetty:jetty-http:" + JETTY_VER,
-    sha1 = "cd6223382e4f82b9ea807d8cdb04a23e5d629f1c",
-    src_sha1 = "00520c04b10609b981159b5ca284b5a158c077a9",
+    sha1 = "45d35131a35a1e76991682174421e8cdf765fb9f",
+    src_sha1 = "491cd5b8abe8fe6f3db0086907a3f12440188e73",
 )
 
 maven_jar(
     name = "jetty-io",
     artifact = "org.eclipse.jetty:jetty-io:" + JETTY_VER,
-    sha1 = "9c360d08e903b2dbd5d1f8e889a32046948628ce",
-    src_sha1 = "dac8f8a3f84afdd3686d36f58b5ccb276961b8ce",
+    sha1 = "eb9460700b99b71ecd82a53697f5ff99f69b9e1c",
+    src_sha1 = "fed96a4559a49e7173dbe2d9d8e100d72aee2a10",
 )
 
 maven_jar(
     name = "jetty-util",
     artifact = "org.eclipse.jetty:jetty-util:" + JETTY_VER,
-    sha1 = "39ec6aa4745952077f5407cb1394d8ba2db88b13",
-    src_sha1 = "f41f9391f91884a79350f3ad9b09b8e46c9be0ec",
+    sha1 = "ef61b83f9715c3b5355b633d9f01d2834f908ece",
+    src_sha1 = "8f178bebeb34c8365a06d854daa9b22da1b301d7",
+)
+
+maven_jar(
+    name = "jetty-util-ajax",
+    artifact = "org.eclipse.jetty:jetty-util-ajax:" + JETTY_VER,
+    sha1 = "ebbb43912c6423bedb3458e44aee28eeb4d66f27",
+    src_sha1 = "b3acea974a17493afb125a9dfbe783870ce1d2f9",
 )
 
 BOUNCYCASTLE_VER = "1.65"
diff --git a/lib/BUILD b/lib/BUILD
index 7720696..b56ba2f 100644
--- a/lib/BUILD
+++ b/lib/BUILD
@@ -132,7 +132,10 @@
     name = "jetty-servlet",
     # TODO: This should be testonly but org.eclipse.jgit.pgm depends on it.
     visibility = ["//visibility:public"],
-    exports = ["@jetty-servlet//jar"],
+    exports = [
+        "@jetty-servlet//jar",
+        "@jetty-util-ajax//jar",
+    ],
 )
 
 java_library(
diff --git a/org.eclipse.jgit.http.apache/resources/org/eclipse/jgit/transport/http/apache/internal/HttpApacheText.properties b/org.eclipse.jgit.http.apache/resources/org/eclipse/jgit/transport/http/apache/internal/HttpApacheText.properties
index d2e5216..b7b9af0 100644
--- a/org.eclipse.jgit.http.apache/resources/org/eclipse/jgit/transport/http/apache/internal/HttpApacheText.properties
+++ b/org.eclipse.jgit.http.apache/resources/org/eclipse/jgit/transport/http/apache/internal/HttpApacheText.properties
@@ -1 +1,2 @@
+httpWrongConnectionType=Wrong connection type: expected {0}, got {1}.
 unexpectedSSLContextException=unexpected exception when searching for the TLS protocol
diff --git a/org.eclipse.jgit.http.apache/src/org/eclipse/jgit/transport/http/apache/HttpClientConnection.java b/org.eclipse.jgit.http.apache/src/org/eclipse/jgit/transport/http/apache/HttpClientConnection.java
index ed05f0a..90348f5 100644
--- a/org.eclipse.jgit.http.apache/src/org/eclipse/jgit/transport/http/apache/HttpClientConnection.java
+++ b/org.eclipse.jgit.http.apache/src/org/eclipse/jgit/transport/http/apache/HttpClientConnection.java
@@ -57,9 +57,7 @@
 import org.apache.http.config.RegistryBuilder;
 import org.apache.http.conn.socket.ConnectionSocketFactory;
 import org.apache.http.conn.socket.PlainConnectionSocketFactory;
-import org.apache.http.conn.ssl.DefaultHostnameVerifier;
 import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
-import org.apache.http.conn.util.PublicSuffixMatcherLoader;
 import org.apache.http.impl.client.HttpClientBuilder;
 import org.apache.http.impl.client.HttpClients;
 import org.apache.http.impl.client.SystemDefaultCredentialsProvider;
@@ -103,7 +101,11 @@
 
 	private HostnameVerifier hostnameverifier;
 
-	SSLContext ctx;
+	private SSLContext ctx;
+
+	private SSLConnectionSocketFactory socketFactory;
+
+	private boolean usePooling = true;
 
 	private HttpClient getClient() {
 		if (client == null) {
@@ -125,11 +127,18 @@
 				configBuilder
 						.setRedirectsEnabled(followRedirects.booleanValue());
 			}
-			SSLConnectionSocketFactory sslConnectionFactory = getSSLSocketFactory();
+			boolean pooled = true;
+			SSLConnectionSocketFactory sslConnectionFactory;
+			if (socketFactory != null) {
+				pooled = usePooling;
+				sslConnectionFactory = socketFactory;
+			} else {
+				// Legacy implementation.
+				pooled = (hostnameverifier == null);
+				sslConnectionFactory = getSSLSocketFactory();
+			}
 			clientBuilder.setSSLSocketFactory(sslConnectionFactory);
-			if (hostnameverifier != null) {
-				// Using a custom verifier: we don't want pooled connections
-				// with this.
+			if (!pooled) {
 				Registry<ConnectionSocketFactory> registry = RegistryBuilder
 						.<ConnectionSocketFactory> create()
 						.register("https", sslConnectionFactory)
@@ -147,14 +156,19 @@
 		return client;
 	}
 
+	void setSSLSocketFactory(@NonNull SSLConnectionSocketFactory factory,
+			boolean isDefault) {
+		socketFactory = factory;
+		usePooling = isDefault;
+	}
+
 	private SSLConnectionSocketFactory getSSLSocketFactory() {
 		HostnameVerifier verifier = hostnameverifier;
 		SSLContext context;
 		if (verifier == null) {
 			// Use defaults
-			context = SSLContexts.createDefault();
-			verifier = new DefaultHostnameVerifier(
-					PublicSuffixMatcherLoader.getDefault());
+			context = SSLContexts.createSystemDefault();
+			verifier = SSLConnectionSocketFactory.getDefaultHostnameVerifier();
 		} else {
 			// Using a custom verifier. Attention: configure() must have been
 			// called already, otherwise one gets a "context not initialized"
diff --git a/org.eclipse.jgit.http.apache/src/org/eclipse/jgit/transport/http/apache/HttpClientConnectionFactory.java b/org.eclipse.jgit.http.apache/src/org/eclipse/jgit/transport/http/apache/HttpClientConnectionFactory.java
index 3c05cde..4de3e47 100644
--- a/org.eclipse.jgit.http.apache/src/org/eclipse/jgit/transport/http/apache/HttpClientConnectionFactory.java
+++ b/org.eclipse.jgit.http.apache/src/org/eclipse/jgit/transport/http/apache/HttpClientConnectionFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Christian Halstrick <christian.halstrick@sap.com> and others
+ * Copyright (C) 2013, 2020 Christian Halstrick <christian.halstrick@sap.com> 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
@@ -12,27 +12,100 @@
 import java.io.IOException;
 import java.net.Proxy;
 import java.net.URL;
+import java.security.GeneralSecurityException;
+import java.text.MessageFormat;
 
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.TrustManager;
+
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
 import org.eclipse.jgit.transport.http.HttpConnection;
-import org.eclipse.jgit.transport.http.HttpConnectionFactory;
+import org.eclipse.jgit.transport.http.HttpConnectionFactory2;
+import org.eclipse.jgit.transport.http.NoCheckX509TrustManager;
+import org.eclipse.jgit.transport.http.apache.internal.HttpApacheText;
+import org.eclipse.jgit.util.HttpSupport;
 
 /**
- * A factory returning instances of
- * {@link org.eclipse.jgit.transport.http.apache.HttpClientConnection}
+ * A factory returning instances of {@link HttpClientConnection}.
  *
  * @since 3.3
  */
-public class HttpClientConnectionFactory implements HttpConnectionFactory {
-	/** {@inheritDoc} */
+public class HttpClientConnectionFactory implements HttpConnectionFactory2 {
+
 	@Override
 	public HttpConnection create(URL url) throws IOException {
 		return new HttpClientConnection(url.toString());
 	}
 
-	/** {@inheritDoc} */
 	@Override
-	public HttpConnection create(URL url, Proxy proxy)
-			throws IOException {
+	public HttpConnection create(URL url, Proxy proxy) throws IOException {
 		return new HttpClientConnection(url.toString(), proxy);
 	}
+
+	@Override
+	public GitSession newSession() {
+		return new HttpClientSession();
+	}
+
+	private static class HttpClientSession implements GitSession {
+
+		private SSLContext securityContext;
+
+		private SSLConnectionSocketFactory socketFactory;
+
+		private boolean isDefault;
+
+		@Override
+		public HttpClientConnection configure(HttpConnection connection,
+				boolean sslVerify)
+				throws IOException, GeneralSecurityException {
+			if (!(connection instanceof HttpClientConnection)) {
+				throw new IllegalArgumentException(MessageFormat.format(
+						HttpApacheText.get().httpWrongConnectionType,
+						HttpClientConnection.class.getName(),
+						connection.getClass().getName()));
+			}
+			HttpClientConnection conn = (HttpClientConnection) connection;
+			String scheme = conn.getURL().getProtocol();
+			if (!"https".equals(scheme)) { //$NON-NLS-1$
+				return conn;
+			}
+			if (securityContext == null || isDefault != sslVerify) {
+				isDefault = sslVerify;
+				HostnameVerifier verifier;
+				if (sslVerify) {
+					securityContext = SSLContext.getDefault();
+					verifier = SSLConnectionSocketFactory
+							.getDefaultHostnameVerifier();
+				} else {
+					securityContext = SSLContext.getInstance("TLS");
+					TrustManager[] trustAllCerts = {
+							new NoCheckX509TrustManager() };
+					securityContext.init(null, trustAllCerts, null);
+					verifier = (name, session) -> true;
+				}
+				socketFactory = new SSLConnectionSocketFactory(securityContext,
+						verifier) {
+
+					@Override
+					protected void prepareSocket(SSLSocket socket)
+							throws IOException {
+						super.prepareSocket(socket);
+						HttpSupport.configureTLS(socket);
+					}
+				};
+			}
+			conn.setSSLSocketFactory(socketFactory, isDefault);
+			return conn;
+		}
+
+		@Override
+		public void close() {
+			securityContext = null;
+			socketFactory = null;
+		}
+
+	}
 }
diff --git a/org.eclipse.jgit.http.apache/src/org/eclipse/jgit/transport/http/apache/internal/HttpApacheText.java b/org.eclipse.jgit.http.apache/src/org/eclipse/jgit/transport/http/apache/internal/HttpApacheText.java
index 907ab98..677d7d7 100644
--- a/org.eclipse.jgit.http.apache/src/org/eclipse/jgit/transport/http/apache/internal/HttpApacheText.java
+++ b/org.eclipse.jgit.http.apache/src/org/eclipse/jgit/transport/http/apache/internal/HttpApacheText.java
@@ -27,5 +27,6 @@
 	}
 
 	// @formatter:off
+	/***/ public String httpWrongConnectionType;
 	/***/ public String unexpectedSSLContextException;
 }
diff --git a/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF
index 44ce9c4..0bcc57c 100644
--- a/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF
@@ -28,6 +28,7 @@
  org.eclipse.jetty.util.log;version="[9.4.5,10.0.0)",
  org.eclipse.jetty.util.security;version="[9.4.5,10.0.0)",
  org.eclipse.jetty.util.thread;version="[9.4.5,10.0.0)",
+ org.eclipse.jgit.api;version="[5.11.0,5.12.0)",
  org.eclipse.jgit.errors;version="[5.11.0,5.12.0)",
  org.eclipse.jgit.http.server;version="[5.11.0,5.12.0)",
  org.eclipse.jgit.http.server.glue;version="[5.11.0,5.12.0)",
diff --git a/org.eclipse.jgit.http.test/build.properties b/org.eclipse.jgit.http.test/build.properties
index e8bacac..a909f13 100644
--- a/org.eclipse.jgit.http.test/build.properties
+++ b/org.eclipse.jgit.http.test/build.properties
@@ -4,3 +4,5 @@
 bin.includes = META-INF/,\
                .,\
                plugin.properties
+additional.bundles = org.apache.log4j,\
+                     org.slf4j.binding.log4j12
diff --git a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/AllProtocolsHttpTestCase.java b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/AllProtocolsHttpTestCase.java
new file mode 100644
index 0000000..c6931ad
--- /dev/null
+++ b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/AllProtocolsHttpTestCase.java
@@ -0,0 +1,99 @@
+/*
+ * 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.http.test;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.eclipse.jgit.junit.http.HttpTestCase;
+import org.eclipse.jgit.transport.HttpTransport;
+import org.eclipse.jgit.transport.http.HttpConnectionFactory;
+import org.eclipse.jgit.transport.http.JDKHttpConnectionFactory;
+import org.eclipse.jgit.transport.http.apache.HttpClientConnectionFactory;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+/**
+ * Abstract test base class for running HTTP-related tests with all connection
+ * factories provided in JGit and with both protocol V0 and V2.
+ */
+@Ignore
+@RunWith(Parameterized.class)
+public abstract class AllProtocolsHttpTestCase extends HttpTestCase {
+
+	protected static class TestParameters {
+
+		public final HttpConnectionFactory factory;
+
+		public final boolean enableProtocolV2;
+
+		public TestParameters(HttpConnectionFactory factory,
+				boolean enableProtocolV2) {
+			this.factory = factory;
+			this.enableProtocolV2 = enableProtocolV2;
+		}
+
+		@Override
+		public String toString() {
+			return factory.toString() + " protocol "
+					+ (enableProtocolV2 ? "V2" : "V0");
+		}
+	}
+
+	@Parameters(name = "{0}")
+	public static Collection<TestParameters> data() {
+		// run all tests with both connection factories we have
+		HttpConnectionFactory[] factories = new HttpConnectionFactory[] {
+				new JDKHttpConnectionFactory() {
+
+					@Override
+					public String toString() {
+						return this.getClass().getSuperclass().getName();
+					}
+				}, new HttpClientConnectionFactory() {
+
+					@Override
+					public String toString() {
+						return this.getClass().getSuperclass().getName();
+					}
+				} };
+		List<TestParameters> result = new ArrayList<>();
+		for (HttpConnectionFactory factory : factories) {
+			result.add(new TestParameters(factory, false));
+			result.add(new TestParameters(factory, true));
+		}
+		return result;
+	}
+
+	protected final boolean enableProtocolV2;
+
+	protected AllProtocolsHttpTestCase(TestParameters params) {
+		HttpTransport.setConnectionFactory(params.factory);
+		enableProtocolV2 = params.enableProtocolV2;
+	}
+
+	private static HttpConnectionFactory originalFactory;
+
+	@BeforeClass
+	public static void saveConnectionFactory() {
+		originalFactory = HttpTransport.getConnectionFactory();
+	}
+
+	@AfterClass
+	public static void restoreConnectionFactory() {
+		HttpTransport.setConnectionFactory(originalFactory);
+	}
+
+}
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 6da5f86..8b28c42 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
@@ -35,6 +35,7 @@
 import org.eclipse.jgit.lib.NullProgressMonitor;
 import org.eclipse.jgit.lib.Ref;
 import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.StoredConfig;
 import org.eclipse.jgit.revwalk.RevBlob;
 import org.eclipse.jgit.revwalk.RevCommit;
 import org.eclipse.jgit.transport.FetchConnection;
@@ -77,6 +78,9 @@
 
 		remoteRepository = src.getRepository();
 		remoteURI = toURIish(app, srcGit.getName());
+		StoredConfig cfg = remoteRepository.getConfig();
+		cfg.setInt("protocol", null, "version", 0);
+		cfg.save();
 
 		A_txt = src.blob("A");
 		A = src.commit().add("A_txt", A_txt).create();
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 ccde1fe..986b5ca 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
@@ -35,6 +35,7 @@
 import org.eclipse.jgit.lib.NullProgressMonitor;
 import org.eclipse.jgit.lib.Ref;
 import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.StoredConfig;
 import org.eclipse.jgit.revwalk.RevBlob;
 import org.eclipse.jgit.revwalk.RevCommit;
 import org.eclipse.jgit.transport.FetchConnection;
@@ -42,11 +43,10 @@
 import org.eclipse.jgit.transport.Transport;
 import org.eclipse.jgit.transport.TransportHttp;
 import org.eclipse.jgit.transport.URIish;
-import org.eclipse.jgit.transport.http.HttpConnectionFactory;
 import org.junit.Before;
 import org.junit.Test;
 
-public class DumbClientSmartServerTest extends AllFactoriesHttpTestCase {
+public class DumbClientSmartServerTest extends AllProtocolsHttpTestCase {
 	private Repository remoteRepository;
 
 	private URIish remoteURI;
@@ -55,8 +55,8 @@
 
 	private RevCommit A, B;
 
-	public DumbClientSmartServerTest(HttpConnectionFactory cf) {
-		super(cf);
+	public DumbClientSmartServerTest(TestParameters params) {
+		super(params);
 	}
 
 	@Override
@@ -76,6 +76,9 @@
 
 		remoteRepository = src.getRepository();
 		remoteURI = toURIish(app, srcName);
+		StoredConfig cfg = remoteRepository.getConfig();
+		cfg.setInt("protocol", null, "version", enableProtocolV2 ? 2 : 0);
+		cfg.save();
 
 		A_txt = src.blob("A");
 		A = src.commit().add("A_txt", A_txt).create();
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 26a453b..df093c1 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
@@ -38,7 +38,6 @@
 import org.eclipse.jgit.junit.TestRepository;
 import org.eclipse.jgit.junit.http.AccessEvent;
 import org.eclipse.jgit.junit.http.AppServer;
-import org.eclipse.jgit.lib.ConfigConstants;
 import org.eclipse.jgit.lib.Constants;
 import org.eclipse.jgit.lib.Ref;
 import org.eclipse.jgit.lib.RefUpdate;
@@ -50,7 +49,6 @@
 import org.eclipse.jgit.transport.PacketLineIn;
 import org.eclipse.jgit.transport.PacketLineOut;
 import org.eclipse.jgit.transport.Transport;
-import org.eclipse.jgit.transport.TransferConfig;
 import org.eclipse.jgit.transport.URIish;
 import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
 import org.eclipse.jgit.transport.http.HttpConnection;
@@ -326,7 +324,22 @@
 	}
 
 	@Test
-	public void testHttpClientWantsV2ButServerNotConfigured() throws Exception {
+	public void testHttpClientWantsV2AndServerNotConfigured() throws Exception {
+		String url = smartAuthNoneURI.toString() + "/info/refs?service=git-upload-pack";
+		HttpConnection c = HttpTransport.getConnectionFactory()
+				.create(new URL(url));
+		c.setRequestMethod("GET");
+		c.setRequestProperty("Git-Protocol", "version=2");
+		assertEquals(200, c.getResponseCode());
+
+		PacketLineIn pckIn = new PacketLineIn(c.getInputStream());
+		assertThat(pckIn.readString(), is("version 2"));
+	}
+
+	@Test
+	public void testHttpServerConfiguredToV0() throws Exception {
+		remoteRepository.getRepository().getConfig().setInt(
+			"protocol", null, "version", 0);
 		String url = smartAuthNoneURI.toString() + "/info/refs?service=git-upload-pack";
 		HttpConnection c = HttpTransport.getConnectionFactory()
 				.create(new URL(url));
@@ -344,11 +357,6 @@
 
 	@Test
 	public void testV2HttpFirstResponse() throws Exception {
-		remoteRepository.getRepository().getConfig().setString(
-				ConfigConstants.CONFIG_PROTOCOL_SECTION, null,
-				ConfigConstants.CONFIG_KEY_VERSION,
-				TransferConfig.ProtocolVersion.V2.version());
-
 		String url = smartAuthNoneURI.toString() + "/info/refs?service=git-upload-pack";
 		HttpConnection c = HttpTransport.getConnectionFactory()
 				.create(new URL(url));
@@ -368,11 +376,6 @@
 
 	@Test
 	public void testV2HttpSubsequentResponse() throws Exception {
-		remoteRepository.getRepository().getConfig().setString(
-				ConfigConstants.CONFIG_PROTOCOL_SECTION, null,
-				ConfigConstants.CONFIG_KEY_VERSION,
-				TransferConfig.ProtocolVersion.V2.version());
-
 		String url = smartAuthNoneURI.toString() + "/git-upload-pack";
 		HttpConnection c = HttpTransport.getConnectionFactory()
 				.create(new URL(url));
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 597fb2e..7bc50ca 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
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 Thomas Wolf <thomas.wolf@paranor.ch> and others
+ * Copyright (C) 2017, 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
@@ -41,6 +41,7 @@
 import org.eclipse.jgit.lib.ConfigConstants;
 import org.eclipse.jgit.lib.NullProgressMonitor;
 import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.StoredConfig;
 import org.eclipse.jgit.revwalk.RevBlob;
 import org.eclipse.jgit.revwalk.RevCommit;
 import org.eclipse.jgit.transport.CredentialItem;
@@ -48,7 +49,6 @@
 import org.eclipse.jgit.transport.Transport;
 import org.eclipse.jgit.transport.URIish;
 import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
-import org.eclipse.jgit.transport.http.HttpConnectionFactory;
 import org.eclipse.jgit.util.HttpSupport;
 import org.junit.Before;
 import org.junit.Test;
@@ -56,7 +56,7 @@
 import org.junit.runners.Parameterized;
 
 @RunWith(Parameterized.class)
-public class SmartClientSmartServerSslTest extends AllFactoriesHttpTestCase {
+public class SmartClientSmartServerSslTest extends AllProtocolsHttpTestCase {
 
 	// We run these tests with a server on localhost with a self-signed
 	// certificate. We don't do authentication tests here, so there's no need
@@ -112,8 +112,8 @@
 
 	private RevCommit A, B;
 
-	public SmartClientSmartServerSslTest(HttpConnectionFactory cf) {
-		super(cf);
+	public SmartClientSmartServerSslTest(TestParameters params) {
+		super(params);
 	}
 
 	@Override
@@ -128,10 +128,11 @@
 
 		final TestRepository<Repository> src = createTestRepository();
 		final String srcName = src.getRepository().getDirectory().getName();
-		src.getRepository()
-				.getConfig()
-				.setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null,
-						ConfigConstants.CONFIG_KEY_LOGALLREFUPDATES, true);
+		StoredConfig cfg = src.getRepository().getConfig();
+		cfg.setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null,
+				ConfigConstants.CONFIG_KEY_LOGALLREFUPDATES, true);
+		cfg.setInt("protocol", null, "version", enableProtocolV2 ? 2 : 0);
+		cfg.save();
 
 		GitServlet gs = new GitServlet();
 
@@ -238,7 +239,7 @@
 		fsck(dst, B);
 
 		List<AccessEvent> requests = getRequests();
-		assertEquals(2, requests.size());
+		assertEquals(enableProtocolV2 ? 3 : 2, requests.size());
 	}
 
 	@Test
@@ -256,7 +257,7 @@
 		fsck(dst, B);
 
 		List<AccessEvent> requests = getRequests();
-		assertEquals(3, requests.size());
+		assertEquals(enableProtocolV2 ? 4 : 3, requests.size());
 	}
 
 	@Test
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 8d1870a..887e970 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
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010, 2017 Google Inc. and others
+ * Copyright (C) 2010, 2020 Google Inc. 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
@@ -22,10 +22,17 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
+import java.io.ByteArrayOutputStream;
+import java.io.File;
 import java.io.IOException;
+import java.io.OutputStreamWriter;
 import java.io.PrintWriter;
+import java.io.Writer;
+import java.net.Proxy;
 import java.net.URI;
 import java.net.URISyntaxException;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
 import java.text.MessageFormat;
 import java.util.Collections;
 import java.util.EnumSet;
@@ -48,6 +55,8 @@
 import org.eclipse.jetty.servlet.FilterHolder;
 import org.eclipse.jetty.servlet.ServletContextHandler;
 import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.TransportConfigCallback;
 import org.eclipse.jgit.errors.RemoteRepositoryException;
 import org.eclipse.jgit.errors.TransportException;
 import org.eclipse.jgit.errors.UnsupportedCredentialItem;
@@ -70,6 +79,7 @@
 import org.eclipse.jgit.lib.ReflogReader;
 import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.lib.StoredConfig;
+import org.eclipse.jgit.lib.TextProgressMonitor;
 import org.eclipse.jgit.revwalk.RevBlob;
 import org.eclipse.jgit.revwalk.RevCommit;
 import org.eclipse.jgit.revwalk.RevWalk;
@@ -86,13 +96,14 @@
 import org.eclipse.jgit.transport.URIish;
 import org.eclipse.jgit.transport.UploadPack;
 import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
+import org.eclipse.jgit.transport.http.HttpConnection;
 import org.eclipse.jgit.transport.http.HttpConnectionFactory;
 import org.eclipse.jgit.util.HttpSupport;
 import org.eclipse.jgit.util.SystemReader;
 import org.junit.Before;
 import org.junit.Test;
 
-public class SmartClientSmartServerTest extends AllFactoriesHttpTestCase {
+public class SmartClientSmartServerTest extends AllProtocolsHttpTestCase {
 	private static final String HDR_TRANSFER_ENCODING = "Transfer-Encoding";
 
 	private AdvertiseRefsHook advertiseRefsHook;
@@ -120,8 +131,8 @@
 
 	private RevCommit A, B, unreachableCommit;
 
-	public SmartClientSmartServerTest(HttpConnectionFactory cf) {
-		super(cf);
+	public SmartClientSmartServerTest(TestParameters params) {
+		super(params);
 	}
 
 	@Override
@@ -131,10 +142,11 @@
 
 		final TestRepository<Repository> src = createTestRepository();
 		final String srcName = src.getRepository().getDirectory().getName();
-		src.getRepository()
-				.getConfig()
-				.setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null,
-						ConfigConstants.CONFIG_KEY_LOGALLREFUPDATES, true);
+		StoredConfig cfg = src.getRepository().getConfig();
+		cfg.setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null,
+				ConfigConstants.CONFIG_KEY_LOGALLREFUPDATES, true);
+		cfg.setInt("protocol", null, "version", enableProtocolV2 ? 2 : 0);
+		cfg.save();
 
 		GitServlet gs = new GitServlet();
 		gs.setUploadPackFactory((HttpServletRequest req, Repository db) -> {
@@ -448,7 +460,7 @@
 		assertEquals(B, map.get(Constants.HEAD).getObjectId());
 
 		List<AccessEvent> requests = getRequests();
-		assertEquals(1, requests.size());
+		assertEquals(enableProtocolV2 ? 2 : 1, requests.size());
 
 		AccessEvent info = requests.get(0);
 		assertEquals("GET", info.getMethod());
@@ -458,7 +470,22 @@
 		assertEquals(200, info.getStatus());
 		assertEquals("application/x-git-upload-pack-advertisement", info
 				.getResponseHeader(HDR_CONTENT_TYPE));
-		assertEquals("gzip", info.getResponseHeader(HDR_CONTENT_ENCODING));
+		if (!enableProtocolV2) {
+			assertEquals("gzip", info.getResponseHeader(HDR_CONTENT_ENCODING));
+		} else {
+			AccessEvent lsRefs = requests.get(1);
+			assertEquals("POST", lsRefs.getMethod());
+			assertEquals(join(remoteURI, "git-upload-pack"), lsRefs.getPath());
+			assertEquals(0, lsRefs.getParameters().size());
+			assertNotNull("has content-length",
+					lsRefs.getRequestHeader(HDR_CONTENT_LENGTH));
+			assertNull("not chunked",
+					lsRefs.getRequestHeader(HDR_TRANSFER_ENCODING));
+			assertEquals("version=2", lsRefs.getRequestHeader("Git-Protocol"));
+			assertEquals(200, lsRefs.getStatus());
+			assertEquals("application/x-git-upload-pack-result",
+					lsRefs.getResponseHeader(HDR_CONTENT_TYPE));
+		}
 	}
 
 	@Test
@@ -576,9 +603,10 @@
 		}
 
 		List<AccessEvent> requests = getRequests();
-		assertEquals(2, requests.size());
+		assertEquals(enableProtocolV2 ? 3 : 2, requests.size());
 
-		AccessEvent info = requests.get(0);
+		int requestNumber = 0;
+		AccessEvent info = requests.get(requestNumber++);
 		assertEquals("GET", info.getMethod());
 		assertEquals(join(remoteURI, "info/refs"), info.getPath());
 		assertEquals(1, info.getParameters().size());
@@ -586,9 +614,24 @@
 		assertEquals(200, info.getStatus());
 		assertEquals("application/x-git-upload-pack-advertisement", info
 				.getResponseHeader(HDR_CONTENT_TYPE));
-		assertEquals("gzip", info.getResponseHeader(HDR_CONTENT_ENCODING));
+		if (!enableProtocolV2) {
+			assertEquals("gzip", info.getResponseHeader(HDR_CONTENT_ENCODING));
+		} else {
+			AccessEvent lsRefs = requests.get(requestNumber++);
+			assertEquals("POST", lsRefs.getMethod());
+			assertEquals(join(remoteURI, "git-upload-pack"), lsRefs.getPath());
+			assertEquals(0, lsRefs.getParameters().size());
+			assertNotNull("has content-length",
+					lsRefs.getRequestHeader(HDR_CONTENT_LENGTH));
+			assertNull("not chunked",
+					lsRefs.getRequestHeader(HDR_TRANSFER_ENCODING));
+			assertEquals("version=2", lsRefs.getRequestHeader("Git-Protocol"));
+			assertEquals(200, lsRefs.getStatus());
+			assertEquals("application/x-git-upload-pack-result",
+					lsRefs.getResponseHeader(HDR_CONTENT_TYPE));
+		}
 
-		AccessEvent service = requests.get(1);
+		AccessEvent service = requests.get(requestNumber);
 		assertEquals("POST", service.getMethod());
 		assertEquals(join(remoteURI, "git-upload-pack"), service.getPath());
 		assertEquals(0, service.getParameters().size());
@@ -602,6 +645,63 @@
 				.getResponseHeader(HDR_CONTENT_TYPE));
 	}
 
+	@Test
+	public void test_CloneWithCustomFactory() throws Exception {
+		HttpConnectionFactory globalFactory = HttpTransport
+				.getConnectionFactory();
+		HttpConnectionFactory failingConnectionFactory = new HttpConnectionFactory() {
+
+			@Override
+			public HttpConnection create(URL url) throws IOException {
+				throw new IOException("Should not be reached");
+			}
+
+			@Override
+			public HttpConnection create(URL url, Proxy proxy)
+					throws IOException {
+				throw new IOException("Should not be reached");
+			}
+		};
+		HttpTransport.setConnectionFactory(failingConnectionFactory);
+		try {
+			File tmp = createTempDirectory("cloneViaApi");
+			boolean[] localFactoryUsed = { false };
+			TransportConfigCallback callback = new TransportConfigCallback() {
+
+				@Override
+				public void configure(Transport transport) {
+					if (transport instanceof TransportHttp) {
+						((TransportHttp) transport).setHttpConnectionFactory(
+								new HttpConnectionFactory() {
+
+									@Override
+									public HttpConnection create(URL url)
+											throws IOException {
+										localFactoryUsed[0] = true;
+										return globalFactory.create(url);
+									}
+
+									@Override
+									public HttpConnection create(URL url,
+											Proxy proxy) throws IOException {
+										localFactoryUsed[0] = true;
+										return globalFactory.create(url, proxy);
+									}
+								});
+					}
+				}
+			};
+			try (Git git = Git.cloneRepository().setDirectory(tmp)
+					.setTransportConfigCallback(callback)
+					.setURI(remoteURI.toPrivateString()).call()) {
+				assertTrue("Should have used the local HttpConnectionFactory",
+						localFactoryUsed[0]);
+			}
+		} finally {
+			HttpTransport.setConnectionFactory(globalFactory);
+		}
+	}
+
 	private void initialClone_Redirect(int nofRedirects, int code)
 			throws Exception {
 		initialClone_Redirect(nofRedirects, code, false);
@@ -628,7 +728,8 @@
 		}
 
 		List<AccessEvent> requests = getRequests();
-		assertEquals(2 + nofRedirects, requests.size());
+		assertEquals((enableProtocolV2 ? 3 : 2) + nofRedirects,
+				requests.size());
 
 		int n = 0;
 		while (n < nofRedirects) {
@@ -644,7 +745,22 @@
 		assertEquals(200, info.getStatus());
 		assertEquals("application/x-git-upload-pack-advertisement",
 				info.getResponseHeader(HDR_CONTENT_TYPE));
-		assertEquals("gzip", info.getResponseHeader(HDR_CONTENT_ENCODING));
+		if (!enableProtocolV2) {
+			assertEquals("gzip", info.getResponseHeader(HDR_CONTENT_ENCODING));
+		} else {
+			AccessEvent lsRefs = requests.get(n++);
+			assertEquals("POST", lsRefs.getMethod());
+			assertEquals(join(remoteURI, "git-upload-pack"), lsRefs.getPath());
+			assertEquals(0, lsRefs.getParameters().size());
+			assertNotNull("has content-length",
+					lsRefs.getRequestHeader(HDR_CONTENT_LENGTH));
+			assertNull("not chunked",
+					lsRefs.getRequestHeader(HDR_TRANSFER_ENCODING));
+			assertEquals("version=2", lsRefs.getRequestHeader("Git-Protocol"));
+			assertEquals(200, lsRefs.getStatus());
+			assertEquals("application/x-git-upload-pack-result",
+					lsRefs.getResponseHeader(HDR_CONTENT_TYPE));
+		}
 
 		AccessEvent service = requests.get(n++);
 		assertEquals("POST", service.getMethod());
@@ -756,7 +872,7 @@
 		}
 
 		List<AccessEvent> requests = getRequests();
-		assertEquals(3, requests.size());
+		assertEquals(enableProtocolV2 ? 4 : 3, requests.size());
 
 		AccessEvent info = requests.get(0);
 		assertEquals("GET", info.getMethod());
@@ -766,24 +882,27 @@
 		assertEquals(200, info.getStatus());
 		assertEquals("application/x-git-upload-pack-advertisement",
 				info.getResponseHeader(HDR_CONTENT_TYPE));
-		assertEquals("gzip", info.getResponseHeader(HDR_CONTENT_ENCODING));
+		if (!enableProtocolV2) {
+			assertEquals("gzip", info.getResponseHeader(HDR_CONTENT_ENCODING));
+		}
 
 		AccessEvent redirect = requests.get(1);
 		assertEquals("POST", redirect.getMethod());
 		assertEquals(301, redirect.getStatus());
 
-		AccessEvent service = requests.get(2);
-		assertEquals("POST", service.getMethod());
-		assertEquals(join(remoteURI, "git-upload-pack"), service.getPath());
-		assertEquals(0, service.getParameters().size());
-		assertNotNull("has content-length",
-				service.getRequestHeader(HDR_CONTENT_LENGTH));
-		assertNull("not chunked",
-				service.getRequestHeader(HDR_TRANSFER_ENCODING));
-
-		assertEquals(200, service.getStatus());
-		assertEquals("application/x-git-upload-pack-result",
-				service.getResponseHeader(HDR_CONTENT_TYPE));
+		for (int i = 2; i < requests.size(); i++) {
+			AccessEvent service = requests.get(i);
+			assertEquals("POST", service.getMethod());
+			assertEquals(join(remoteURI, "git-upload-pack"), service.getPath());
+			assertEquals(0, service.getParameters().size());
+			assertNotNull("has content-length",
+					service.getRequestHeader(HDR_CONTENT_LENGTH));
+			assertNull("not chunked",
+					service.getRequestHeader(HDR_TRANSFER_ENCODING));
+			assertEquals(200, service.getStatus());
+			assertEquals("application/x-git-upload-pack-result",
+					service.getResponseHeader(HDR_CONTENT_TYPE));
+		}
 	}
 
 	@Test
@@ -817,6 +936,35 @@
 		}
 	}
 
+	private void assertFetchRequests(List<AccessEvent> requests, int index) {
+		AccessEvent info = requests.get(index++);
+		assertEquals("GET", info.getMethod());
+		assertEquals(join(authURI, "info/refs"), info.getPath());
+		assertEquals(1, info.getParameters().size());
+		assertEquals("git-upload-pack", info.getParameter("service"));
+		assertEquals(200, info.getStatus());
+		assertEquals("application/x-git-upload-pack-advertisement",
+				info.getResponseHeader(HDR_CONTENT_TYPE));
+		if (!enableProtocolV2) {
+			assertEquals("gzip", info.getResponseHeader(HDR_CONTENT_ENCODING));
+		}
+
+		for (int i = index; i < requests.size(); i++) {
+			AccessEvent service = requests.get(i);
+			assertEquals("POST", service.getMethod());
+			assertEquals(join(authURI, "git-upload-pack"), service.getPath());
+			assertEquals(0, service.getParameters().size());
+			assertNotNull("has content-length",
+					service.getRequestHeader(HDR_CONTENT_LENGTH));
+			assertNull("not chunked",
+					service.getRequestHeader(HDR_TRANSFER_ENCODING));
+
+			assertEquals(200, service.getStatus());
+			assertEquals("application/x-git-upload-pack-result",
+					service.getResponseHeader(HDR_CONTENT_TYPE));
+		}
+	}
+
 	@Test
 	public void testInitialClone_WithAuthentication() throws Exception {
 		try (Repository dst = createBareRepository();
@@ -830,34 +978,167 @@
 		}
 
 		List<AccessEvent> requests = getRequests();
-		assertEquals(3, requests.size());
+		assertEquals(enableProtocolV2 ? 4 : 3, requests.size());
 
 		AccessEvent info = requests.get(0);
 		assertEquals("GET", info.getMethod());
 		assertEquals(401, info.getStatus());
 
-		info = requests.get(1);
+		assertFetchRequests(requests, 1);
+	}
+
+	@Test
+	public void testInitialClone_WithPreAuthentication() throws Exception {
+		try (Repository dst = createBareRepository();
+				Transport t = Transport.open(dst, authURI)) {
+			assertFalse(dst.getObjectDatabase().has(A_txt));
+			((TransportHttp) t).setPreemptiveBasicAuthentication(
+					AppServer.username, AppServer.password);
+			t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
+			assertTrue(dst.getObjectDatabase().has(A_txt));
+			assertEquals(B, dst.exactRef(master).getObjectId());
+			fsck(dst, B);
+		}
+
+		List<AccessEvent> requests = getRequests();
+		assertEquals(enableProtocolV2 ? 3 : 2, requests.size());
+
+		assertFetchRequests(requests, 0);
+	}
+
+	@Test
+	public void testInitialClone_WithPreAuthenticationCleared()
+			throws Exception {
+		try (Repository dst = createBareRepository();
+				Transport t = Transport.open(dst, authURI)) {
+			assertFalse(dst.getObjectDatabase().has(A_txt));
+			((TransportHttp) t).setPreemptiveBasicAuthentication(
+					AppServer.username, AppServer.password);
+			((TransportHttp) t).setPreemptiveBasicAuthentication(null, null);
+			t.setCredentialsProvider(testCredentials);
+			t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
+			assertTrue(dst.getObjectDatabase().has(A_txt));
+			assertEquals(B, dst.exactRef(master).getObjectId());
+			fsck(dst, B);
+		}
+
+		List<AccessEvent> requests = getRequests();
+		assertEquals(enableProtocolV2 ? 4 : 3, requests.size());
+
+		AccessEvent info = requests.get(0);
 		assertEquals("GET", info.getMethod());
-		assertEquals(join(authURI, "info/refs"), info.getPath());
-		assertEquals(1, info.getParameters().size());
-		assertEquals("git-upload-pack", info.getParameter("service"));
-		assertEquals(200, info.getStatus());
-		assertEquals("application/x-git-upload-pack-advertisement",
-				info.getResponseHeader(HDR_CONTENT_TYPE));
-		assertEquals("gzip", info.getResponseHeader(HDR_CONTENT_ENCODING));
+		assertEquals(401, info.getStatus());
 
-		AccessEvent service = requests.get(2);
-		assertEquals("POST", service.getMethod());
-		assertEquals(join(authURI, "git-upload-pack"), service.getPath());
-		assertEquals(0, service.getParameters().size());
-		assertNotNull("has content-length",
-				service.getRequestHeader(HDR_CONTENT_LENGTH));
-		assertNull("not chunked",
-				service.getRequestHeader(HDR_TRANSFER_ENCODING));
+		assertFetchRequests(requests, 1);
+	}
 
-		assertEquals(200, service.getStatus());
-		assertEquals("application/x-git-upload-pack-result",
-				service.getResponseHeader(HDR_CONTENT_TYPE));
+	@Test
+	public void testInitialClone_PreAuthenticationTooLate() throws Exception {
+		try (Repository dst = createBareRepository();
+				Transport t = Transport.open(dst, authURI)) {
+			assertFalse(dst.getObjectDatabase().has(A_txt));
+			((TransportHttp) t).setPreemptiveBasicAuthentication(
+					AppServer.username, AppServer.password);
+			t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
+			assertTrue(dst.getObjectDatabase().has(A_txt));
+			assertEquals(B, dst.exactRef(master).getObjectId());
+			fsck(dst, B);
+			List<AccessEvent> requests = getRequests();
+			assertEquals(enableProtocolV2 ? 3 : 2, requests.size());
+			assertFetchRequests(requests, 0);
+			assertThrows(IllegalStateException.class,
+					() -> ((TransportHttp) t).setPreemptiveBasicAuthentication(
+							AppServer.username, AppServer.password));
+			assertThrows(IllegalStateException.class, () -> ((TransportHttp) t)
+					.setPreemptiveBasicAuthentication(null, null));
+		}
+	}
+
+	@Test
+	public void testInitialClone_WithWrongPreAuthenticationAndCredentialProvider()
+			throws Exception {
+		try (Repository dst = createBareRepository();
+				Transport t = Transport.open(dst, authURI)) {
+			assertFalse(dst.getObjectDatabase().has(A_txt));
+			((TransportHttp) t).setPreemptiveBasicAuthentication(
+					AppServer.username, AppServer.password + 'x');
+			t.setCredentialsProvider(testCredentials);
+			t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
+			assertTrue(dst.getObjectDatabase().has(A_txt));
+			assertEquals(B, dst.exactRef(master).getObjectId());
+			fsck(dst, B);
+		}
+
+		List<AccessEvent> requests = getRequests();
+		assertEquals(enableProtocolV2 ? 4 : 3, requests.size());
+
+		AccessEvent info = requests.get(0);
+		assertEquals("GET", info.getMethod());
+		assertEquals(401, info.getStatus());
+
+		assertFetchRequests(requests, 1);
+	}
+
+	@Test
+	public void testInitialClone_WithWrongPreAuthentication() throws Exception {
+		try (Repository dst = createBareRepository();
+				Transport t = Transport.open(dst, authURI)) {
+			assertFalse(dst.getObjectDatabase().has(A_txt));
+			((TransportHttp) t).setPreemptiveBasicAuthentication(
+					AppServer.username, AppServer.password + 'x');
+			TransportException e = assertThrows(TransportException.class,
+					() -> t.fetch(NullProgressMonitor.INSTANCE,
+							mirror(master)));
+			String msg = e.getMessage();
+			assertTrue("Unexpected exception message: " + msg,
+					msg.contains("no CredentialsProvider"));
+		}
+		List<AccessEvent> requests = getRequests();
+		assertEquals(1, requests.size());
+
+		AccessEvent info = requests.get(0);
+		assertEquals("GET", info.getMethod());
+		assertEquals(401, info.getStatus());
+	}
+
+	@Test
+	public void testInitialClone_WithUserInfo() throws Exception {
+		URIish withUserInfo = authURI.setUser(AppServer.username)
+				.setPass(AppServer.password);
+		try (Repository dst = createBareRepository();
+				Transport t = Transport.open(dst, withUserInfo)) {
+			assertFalse(dst.getObjectDatabase().has(A_txt));
+			t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
+			assertTrue(dst.getObjectDatabase().has(A_txt));
+			assertEquals(B, dst.exactRef(master).getObjectId());
+			fsck(dst, B);
+		}
+
+		List<AccessEvent> requests = getRequests();
+		assertEquals(enableProtocolV2 ? 3 : 2, requests.size());
+
+		assertFetchRequests(requests, 0);
+	}
+
+	@Test
+	public void testInitialClone_PreAuthOverridesUserInfo() throws Exception {
+		URIish withUserInfo = authURI.setUser(AppServer.username)
+				.setPass(AppServer.password + 'x');
+		try (Repository dst = createBareRepository();
+				Transport t = Transport.open(dst, withUserInfo)) {
+			assertFalse(dst.getObjectDatabase().has(A_txt));
+			((TransportHttp) t).setPreemptiveBasicAuthentication(
+					AppServer.username, AppServer.password);
+			t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
+			assertTrue(dst.getObjectDatabase().has(A_txt));
+			assertEquals(B, dst.exactRef(master).getObjectId());
+			fsck(dst, B);
+		}
+
+		List<AccessEvent> requests = getRequests();
+		assertEquals(enableProtocolV2 ? 3 : 2, requests.size());
+
+		assertFetchRequests(requests, 0);
 	}
 
 	@Test
@@ -937,19 +1218,20 @@
 		}
 
 		List<AccessEvent> requests = getRequests();
-		assertEquals(4, requests.size());
+		assertEquals(enableProtocolV2 ? 5 : 4, requests.size());
 
-		AccessEvent redirect = requests.get(0);
+		int requestNumber = 0;
+		AccessEvent redirect = requests.get(requestNumber++);
 		assertEquals("GET", redirect.getMethod());
 		assertEquals(join(cloneFrom, "info/refs"), redirect.getPath());
 		assertEquals(301, redirect.getStatus());
 
-		AccessEvent info = requests.get(1);
+		AccessEvent info = requests.get(requestNumber++);
 		assertEquals("GET", info.getMethod());
 		assertEquals(join(authURI, "info/refs"), info.getPath());
 		assertEquals(401, info.getStatus());
 
-		info = requests.get(2);
+		info = requests.get(requestNumber++);
 		assertEquals("GET", info.getMethod());
 		assertEquals(join(authURI, "info/refs"), info.getPath());
 		assertEquals(1, info.getParameters().size());
@@ -957,9 +1239,24 @@
 		assertEquals(200, info.getStatus());
 		assertEquals("application/x-git-upload-pack-advertisement",
 				info.getResponseHeader(HDR_CONTENT_TYPE));
-		assertEquals("gzip", info.getResponseHeader(HDR_CONTENT_ENCODING));
+		if (!enableProtocolV2) {
+			assertEquals("gzip", info.getResponseHeader(HDR_CONTENT_ENCODING));
+		} else {
+			AccessEvent lsRefs = requests.get(requestNumber++);
+			assertEquals("POST", lsRefs.getMethod());
+			assertEquals(join(authURI, "git-upload-pack"), lsRefs.getPath());
+			assertEquals(0, lsRefs.getParameters().size());
+			assertNotNull("has content-length",
+					lsRefs.getRequestHeader(HDR_CONTENT_LENGTH));
+			assertNull("not chunked",
+					lsRefs.getRequestHeader(HDR_TRANSFER_ENCODING));
+			assertEquals("version=2", lsRefs.getRequestHeader("Git-Protocol"));
+			assertEquals(200, lsRefs.getStatus());
+			assertEquals("application/x-git-upload-pack-result",
+					lsRefs.getResponseHeader(HDR_CONTENT_TYPE));
+		}
 
-		AccessEvent service = requests.get(3);
+		AccessEvent service = requests.get(requestNumber);
 		assertEquals("POST", service.getMethod());
 		assertEquals(join(authURI, "git-upload-pack"), service.getPath());
 		assertEquals(0, service.getParameters().size());
@@ -987,7 +1284,7 @@
 		}
 
 		List<AccessEvent> requests = getRequests();
-		assertEquals(3, requests.size());
+		assertEquals(enableProtocolV2 ? 4 : 3, requests.size());
 
 		AccessEvent info = requests.get(0);
 		assertEquals("GET", info.getMethod());
@@ -997,25 +1294,30 @@
 		assertEquals(200, info.getStatus());
 		assertEquals("application/x-git-upload-pack-advertisement",
 				info.getResponseHeader(HDR_CONTENT_TYPE));
-		assertEquals("gzip", info.getResponseHeader(HDR_CONTENT_ENCODING));
+		if (!enableProtocolV2) {
+			assertEquals("gzip", info.getResponseHeader(HDR_CONTENT_ENCODING));
+		}
 
 		AccessEvent service = requests.get(1);
 		assertEquals("POST", service.getMethod());
 		assertEquals(join(authOnPostURI, "git-upload-pack"), service.getPath());
 		assertEquals(401, service.getStatus());
 
-		service = requests.get(2);
-		assertEquals("POST", service.getMethod());
-		assertEquals(join(authOnPostURI, "git-upload-pack"), service.getPath());
-		assertEquals(0, service.getParameters().size());
-		assertNotNull("has content-length",
-				service.getRequestHeader(HDR_CONTENT_LENGTH));
-		assertNull("not chunked",
-				service.getRequestHeader(HDR_TRANSFER_ENCODING));
+		for (int i = 2; i < requests.size(); i++) {
+			service = requests.get(i);
+			assertEquals("POST", service.getMethod());
+			assertEquals(join(authOnPostURI, "git-upload-pack"),
+					service.getPath());
+			assertEquals(0, service.getParameters().size());
+			assertNotNull("has content-length",
+					service.getRequestHeader(HDR_CONTENT_LENGTH));
+			assertNull("not chunked",
+					service.getRequestHeader(HDR_TRANSFER_ENCODING));
 
-		assertEquals(200, service.getStatus());
-		assertEquals("application/x-git-upload-pack-result",
-				service.getResponseHeader(HDR_CONTENT_TYPE));
+			assertEquals(200, service.getStatus());
+			assertEquals("application/x-git-upload-pack-result",
+					service.getResponseHeader(HDR_CONTENT_TYPE));
+		}
 	}
 
 	@Test
@@ -1052,9 +1354,11 @@
 
 		List<AccessEvent> requests = getRequests();
 		requests.removeAll(cloneRequests);
-		assertEquals(2, requests.size());
 
-		AccessEvent info = requests.get(0);
+		assertEquals(enableProtocolV2 ? 3 : 2, requests.size());
+
+		int requestNumber = 0;
+		AccessEvent info = requests.get(requestNumber++);
 		assertEquals("GET", info.getMethod());
 		assertEquals(join(remoteURI, "info/refs"), info.getPath());
 		assertEquals(1, info.getParameters().size());
@@ -1063,9 +1367,24 @@
 		assertEquals("application/x-git-upload-pack-advertisement",
 				info.getResponseHeader(HDR_CONTENT_TYPE));
 
+		if (enableProtocolV2) {
+			AccessEvent lsRefs = requests.get(requestNumber++);
+			assertEquals("POST", lsRefs.getMethod());
+			assertEquals(join(remoteURI, "git-upload-pack"), lsRefs.getPath());
+			assertEquals(0, lsRefs.getParameters().size());
+			assertNotNull("has content-length",
+					lsRefs.getRequestHeader(HDR_CONTENT_LENGTH));
+			assertNull("not chunked",
+					lsRefs.getRequestHeader(HDR_TRANSFER_ENCODING));
+			assertEquals("version=2", lsRefs.getRequestHeader("Git-Protocol"));
+			assertEquals(200, lsRefs.getStatus());
+			assertEquals("application/x-git-upload-pack-result",
+					lsRefs.getResponseHeader(HDR_CONTENT_TYPE));
+		}
+
 		// We should have needed one request to perform the fetch.
 		//
-		AccessEvent service = requests.get(1);
+		AccessEvent service = requests.get(requestNumber);
 		assertEquals("POST", service.getMethod());
 		assertEquals(join(remoteURI, "git-upload-pack"), service.getPath());
 		assertEquals(0, service.getParameters().size());
@@ -1116,9 +1435,10 @@
 
 		List<AccessEvent> requests = getRequests();
 		requests.removeAll(cloneRequests);
-		assertEquals(3, requests.size());
+		assertEquals(enableProtocolV2 ? 4 : 3, requests.size());
 
-		AccessEvent info = requests.get(0);
+		int requestNumber = 0;
+		AccessEvent info = requests.get(requestNumber++);
 		assertEquals("GET", info.getMethod());
 		assertEquals(join(remoteURI, "info/refs"), info.getPath());
 		assertEquals(1, info.getParameters().size());
@@ -1127,10 +1447,25 @@
 		assertEquals("application/x-git-upload-pack-advertisement", info
 				.getResponseHeader(HDR_CONTENT_TYPE));
 
+		if (enableProtocolV2) {
+			AccessEvent lsRefs = requests.get(requestNumber++);
+			assertEquals("POST", lsRefs.getMethod());
+			assertEquals(join(remoteURI, "git-upload-pack"), lsRefs.getPath());
+			assertEquals(0, lsRefs.getParameters().size());
+			assertNotNull("has content-length",
+					lsRefs.getRequestHeader(HDR_CONTENT_LENGTH));
+			assertNull("not chunked",
+					lsRefs.getRequestHeader(HDR_TRANSFER_ENCODING));
+			assertEquals("version=2", lsRefs.getRequestHeader("Git-Protocol"));
+			assertEquals(200, lsRefs.getStatus());
+			assertEquals("application/x-git-upload-pack-result",
+					lsRefs.getResponseHeader(HDR_CONTENT_TYPE));
+		}
+
 		// We should have needed two requests to perform the fetch
 		// due to the high number of local unknown commits.
 		//
-		AccessEvent service = requests.get(1);
+		AccessEvent service = requests.get(requestNumber++);
 		assertEquals("POST", service.getMethod());
 		assertEquals(join(remoteURI, "git-upload-pack"), service.getPath());
 		assertEquals(0, service.getParameters().size());
@@ -1143,7 +1478,7 @@
 		assertEquals("application/x-git-upload-pack-result", service
 				.getResponseHeader(HDR_CONTENT_TYPE));
 
-		service = requests.get(2);
+		service = requests.get(requestNumber);
 		assertEquals("POST", service.getMethod());
 		assertEquals(join(remoteURI, "git-upload-pack"), service.getPath());
 		assertEquals(0, service.getParameters().size());
@@ -1158,6 +1493,64 @@
 	}
 
 	@Test
+	public void testFetch_MaxHavesCutoffAfterAckOnly() throws Exception {
+		// Bootstrap by doing the clone.
+		//
+		TestRepository dst = createTestRepository();
+		try (Transport t = Transport.open(dst.getRepository(), remoteURI)) {
+			t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
+		}
+		assertEquals(B, dst.getRepository().exactRef(master).getObjectId());
+
+		// Force enough into the local client that enumeration will
+		// need more than MAX_HAVES (256) haves to be sent. The server
+		// doesn't know any of these, so it will never ACK. The client
+		// should keep going.
+		//
+		// If it does, client and server will find a common commit, and
+		// the pack file will contain exactly the one commit object Z
+		// we create on the remote, which we can test for via the progress
+		// monitor, which should have something like
+		// "Receiving objects: 100% (1/1)". If the client sends a "done"
+		// too early, the server will send more objects, and we'll have
+		// a line like "Receiving objects: 100% (8/8)".
+		TestRepository.BranchBuilder b = dst.branch(master);
+		// The client will send 32 + 64 + 128 + 256 + 512 haves. Only the
+		// last one will be a common commit. If the cutoff kicks in too
+		// early (after 480), we'll get too many objects in the fetch.
+		for (int i = 0; i < 992; i++)
+			b.commit().tick(3600 /* 1 hour */).message("c" + i).create();
+
+		// Create a new commit on the remote.
+		//
+		RevCommit Z;
+		try (TestRepository<Repository> tr = new TestRepository<>(
+				remoteRepository)) {
+			b = tr.branch(master);
+			Z = b.commit().message("Z").create();
+		}
+
+		// Now incrementally update.
+		//
+		ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+		Writer writer = new OutputStreamWriter(buffer, StandardCharsets.UTF_8);
+		TextProgressMonitor monitor = new TextProgressMonitor(writer);
+		try (Transport t = Transport.open(dst.getRepository(), remoteURI)) {
+			t.fetch(monitor, mirror(master));
+		}
+		assertEquals(Z, dst.getRepository().exactRef(master).getObjectId());
+
+		String progressMessages = new String(buffer.toByteArray(),
+				StandardCharsets.UTF_8);
+		Pattern expected = Pattern
+				.compile("Receiving objects:\\s+100% \\(1/1\\)\n");
+		if (!expected.matcher(progressMessages).find()) {
+			System.out.println(progressMessages);
+			fail("Expected only one object to be sent");
+		}
+	}
+
+	@Test
 	public void testInitialClone_BrokenServer() throws Exception {
 		try (Repository dst = createBareRepository();
 				Transport t = Transport.open(dst, brokenURI)) {
@@ -1211,7 +1604,8 @@
 					Collections.<ObjectId> emptySet());
 			fail("Server accepted want " + id.name());
 		} catch (TransportException err) {
-			assertEquals("want " + id.name() + " not valid", err.getMessage());
+			assertTrue(err.getMessage()
+					.contains("want " + id.name() + " not valid"));
 		}
 	}
 
@@ -1224,6 +1618,8 @@
 					new DfsRepositoryDescription(repoName));
 			final TestRepository<Repository> repo = new TestRepository<>(
 					badRefsRepo);
+			badRefsRepo.getConfig().setInt("protocol", null, "version",
+					enableProtocolV2 ? 2 : 0);
 
 			ServletContextHandler app = noRefServer.addContext("/git");
 			GitServlet gs = new GitServlet();
@@ -1253,7 +1649,8 @@
 						Collections.<ObjectId> emptySet());
 				fail("Successfully served ref with value " + c.getRef(master));
 			} catch (TransportException err) {
-				assertEquals("Internal server error", err.getMessage());
+				assertTrue("Unexpected exception message " + err.getMessage(),
+						err.getMessage().contains("Internal server error"));
 			}
 		} finally {
 			noRefServer.tearDown();
@@ -1429,5 +1826,4 @@
 		cfg.setBoolean("http", null, "receivepack", true);
 		cfg.save();
 	}
-
 }
diff --git a/org.eclipse.jgit.junit.ssh/src/org/eclipse/jgit/junit/ssh/SshBasicTestBase.java b/org.eclipse.jgit.junit.ssh/src/org/eclipse/jgit/junit/ssh/SshBasicTestBase.java
new file mode 100644
index 0000000..f9ca0b8
--- /dev/null
+++ b/org.eclipse.jgit.junit.ssh/src/org/eclipse/jgit/junit/ssh/SshBasicTestBase.java
@@ -0,0 +1,71 @@
+/*
+ * 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.junit.ssh;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+
+import org.eclipse.jgit.api.Git;
+import org.junit.Test;
+
+/**
+ * Some minimal cloning and fetching tests. Concrete subclasses can implement
+ * the abstract operations from {@link SshTestHarness} to run with different SSH
+ * implementations.
+ */
+public abstract class SshBasicTestBase extends SshTestHarness {
+
+	protected File defaultCloneDir;
+
+	@Override
+	public void setUp() throws Exception {
+		super.setUp();
+		defaultCloneDir = new File(getTemporaryDirectory(), "cloned");
+	}
+
+	@Test
+	public void testSshCloneWithConfig() throws Exception {
+		cloneWith("ssh://localhost/doesntmatter", defaultCloneDir, null, //
+				"Host localhost", //
+				"HostName localhost", //
+				"Port " + testPort, //
+				"User " + TEST_USER, //
+				"IdentityFile " + privateKey1.getAbsolutePath());
+	}
+
+	@Test
+	public void testSshFetchWithConfig() throws Exception {
+		File localClone = cloneWith("ssh://localhost/doesntmatter",
+				defaultCloneDir, null, //
+				"Host localhost", //
+				"HostName localhost", //
+				"Port " + testPort, //
+				"User " + TEST_USER, //
+				"IdentityFile " + privateKey1.getAbsolutePath());
+		// Do a commit in the upstream repo
+		try (Git git = new Git(db)) {
+			writeTrashFile("SomeOtherFile.txt", "Other commit");
+			git.add().addFilepattern("SomeOtherFile.txt").call();
+			git.commit().setMessage("New commit").call();
+		}
+		// Pull in the clone
+		try (Git git = Git.open(localClone)) {
+			File f = new File(git.getRepository().getWorkTree(),
+					"SomeOtherFile.txt");
+			assertFalse(f.exists());
+			git.pull().setRemote("origin").call();
+			assertTrue(f.exists());
+			assertEquals("Other commit", read(f));
+		}
+	}
+}
diff --git a/org.eclipse.jgit.junit.ssh/src/org/eclipse/jgit/junit/ssh/SshTestBase.java b/org.eclipse.jgit.junit.ssh/src/org/eclipse/jgit/junit/ssh/SshTestBase.java
index 3784741..6fa82f1 100644
--- a/org.eclipse.jgit.junit.ssh/src/org/eclipse/jgit/junit/ssh/SshTestBase.java
+++ b/org.eclipse.jgit.junit.ssh/src/org/eclipse/jgit/junit/ssh/SshTestBase.java
@@ -40,7 +40,7 @@
  * abstract operations from {@link SshTestHarness}. This gives a way to test
  * different ssh clients against a unified test suite.
  */
-public abstract class SshTestBase extends SshTestHarness {
+public abstract class SshTestBase extends SshBasicTestBase {
 
 	@DataPoints
 	public static String[] KEY_RESOURCES = { //
@@ -65,14 +65,6 @@
 			"id_ed25519_testpass", //
 			"id_ed25519_expensive_testpass" };
 
-	protected File defaultCloneDir;
-
-	@Override
-	public void setUp() throws Exception {
-		super.setUp();
-		defaultCloneDir = new File(getTemporaryDirectory(), "cloned");
-	}
-
 	@Test
 	public void testSshWithoutConfig() throws Exception {
 		assertThrows(TransportException.class,
@@ -133,16 +125,6 @@
 	}
 
 	@Test
-	public void testSshWithConfig() throws Exception {
-		cloneWith("ssh://localhost/doesntmatter", defaultCloneDir, null, //
-				"Host localhost", //
-				"HostName localhost", //
-				"Port " + testPort, //
-				"User " + TEST_USER, //
-				"IdentityFile " + privateKey1.getAbsolutePath());
-	}
-
-	@Test
 	public void testSshWithConfigEncryptedUnusedKey() throws Exception {
 		// Copy the encrypted test key from the bundle.
 		File encryptedKey = new File(sshDir, "id_dsa");
diff --git a/org.eclipse.jgit.lfs/META-INF/MANIFEST.MF b/org.eclipse.jgit.lfs/META-INF/MANIFEST.MF
index 84985e8..9a2133e 100644
--- a/org.eclipse.jgit.lfs/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.lfs/META-INF/MANIFEST.MF
@@ -11,8 +11,8 @@
  org.eclipse.jgit.lfs.internal;version="5.11.0";x-friends:="org.eclipse.jgit.lfs.test,org.eclipse.jgit.lfs.server.fs,org.eclipse.jgit.lfs.server",
  org.eclipse.jgit.lfs.lib;version="5.11.0"
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
-Import-Package: com.google.gson;version="[2.8.2,3.0.0)",
- com.google.gson.stream;version="[2.8.2,3.0.0)",
+Import-Package: com.google.gson;version="[2.8.0,3.0.0)",
+ com.google.gson.stream;version="[2.8.0,3.0.0)",
  org.apache.http.impl.client;version="[4.2.6,5.0.0)",
  org.apache.http.impl.conn;version="[4.2.6,5.0.0)",
  org.eclipse.jgit.annotations;version="[5.11.0,5.12.0)";resolution:=optional,
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.10.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.10.target
index d7e1585..1629266 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.10.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.10.target
@@ -1,30 +1,32 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <?pde?>
 <!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
-<target name="jgit-4.10" sequenceNumber="1606854603">
+<target name="jgit-4.10" sequenceNumber="1610487371">
   <locations>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
-      <unit id="org.eclipse.jetty.client" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.client.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.continuation" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.continuation.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.http" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.http.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.io" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.io.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.security" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.security.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.server" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.server.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.servlet" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.servlet.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.util" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.util.source" version="9.4.30.v20200611"/>
-      <repository id="jetty-9.4.30" location="https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.30.v20200611/"/>
+      <unit id="org.eclipse.jetty.client" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.client.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.continuation" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.continuation.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.http" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.http.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.io" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.io.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.security" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.security.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.server" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.server.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.servlet" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.servlet.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util.ajax" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util.ajax.source" version="9.4.35.v20201120"/>
+      <repository id="jetty-9.4.30" location="https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.35.v20201120/"/>
     </location>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
-      <unit id="com.google.gson" version="2.8.2.v20180104-1110"/>
-      <unit id="com.google.gson.source" version="2.8.2.v20180104-1110"/>
+      <unit id="com.google.gson" version="2.8.6.v20201231-1626"/>
+      <unit id="com.google.gson.source" version="2.8.6.v20201231-1626"/>
       <unit id="com.jcraft.jsch" version="0.1.55.v20190404-1902"/>
       <unit id="com.jcraft.jsch.source" version="0.1.55.v20190404-1902"/>
       <unit id="com.jcraft.jzlib" version="1.1.1.v201205102305"/>
@@ -84,7 +86,7 @@
       <unit id="org.slf4j.binding.log4j12.source" version="1.7.30.v20201108-2042"/>
       <unit id="org.tukaani.xz" version="1.8.0.v20180207-1613"/>
       <unit id="org.tukaani.xz.source" version="1.8.0.v20180207-1613"/>
-      <repository location="https://download.eclipse.org/tools/orbit/downloads/drops/R20201130205003/repository"/>
+      <repository location="https://download.eclipse.org/tools/orbit/downloads/drops/S20210105214148/repository"/>
     </location>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
       <unit id="org.eclipse.osgi" version="0.0.0"/>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.10.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.10.tpd
index d84f801..ac4da5c 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.10.tpd
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.10.tpd
@@ -1,7 +1,7 @@
 target "jgit-4.10" with source configurePhase
 
 include "projects/jetty-9.4.x.tpd"
-include "orbit/R20201130205003-2020-12.tpd"
+include "orbit/S20210105214148.tpd"
 
 location "https://download.eclipse.org/releases/2018-12/" {
 	org.eclipse.osgi lazy
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.11.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.11.target
index 42ef49c..afe7936 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.11.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.11.target
@@ -1,30 +1,32 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <?pde?>
 <!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
-<target name="jgit-4.11" sequenceNumber="1606854603">
+<target name="jgit-4.11" sequenceNumber="1610487371">
   <locations>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
-      <unit id="org.eclipse.jetty.client" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.client.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.continuation" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.continuation.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.http" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.http.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.io" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.io.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.security" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.security.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.server" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.server.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.servlet" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.servlet.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.util" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.util.source" version="9.4.30.v20200611"/>
-      <repository id="jetty-9.4.30" location="https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.30.v20200611/"/>
+      <unit id="org.eclipse.jetty.client" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.client.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.continuation" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.continuation.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.http" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.http.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.io" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.io.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.security" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.security.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.server" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.server.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.servlet" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.servlet.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util.ajax" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util.ajax.source" version="9.4.35.v20201120"/>
+      <repository id="jetty-9.4.30" location="https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.35.v20201120/"/>
     </location>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
-      <unit id="com.google.gson" version="2.8.2.v20180104-1110"/>
-      <unit id="com.google.gson.source" version="2.8.2.v20180104-1110"/>
+      <unit id="com.google.gson" version="2.8.6.v20201231-1626"/>
+      <unit id="com.google.gson.source" version="2.8.6.v20201231-1626"/>
       <unit id="com.jcraft.jsch" version="0.1.55.v20190404-1902"/>
       <unit id="com.jcraft.jsch.source" version="0.1.55.v20190404-1902"/>
       <unit id="com.jcraft.jzlib" version="1.1.1.v201205102305"/>
@@ -84,7 +86,7 @@
       <unit id="org.slf4j.binding.log4j12.source" version="1.7.30.v20201108-2042"/>
       <unit id="org.tukaani.xz" version="1.8.0.v20180207-1613"/>
       <unit id="org.tukaani.xz.source" version="1.8.0.v20180207-1613"/>
-      <repository location="https://download.eclipse.org/tools/orbit/downloads/drops/R20201130205003/repository"/>
+      <repository location="https://download.eclipse.org/tools/orbit/downloads/drops/S20210105214148/repository"/>
     </location>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
       <unit id="org.eclipse.osgi" version="0.0.0"/>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.11.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.11.tpd
index df221e6..c3ac590 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.11.tpd
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.11.tpd
@@ -1,7 +1,7 @@
 target "jgit-4.11" with source configurePhase
 
 include "projects/jetty-9.4.x.tpd"
-include "orbit/R20201130205003-2020-12.tpd"
+include "orbit/S20210105214148.tpd"
 
 location "https://download.eclipse.org/releases/2019-03/" {
 	org.eclipse.osgi lazy
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.12.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.12.target
index 17634cf..b7de53d 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.12.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.12.target
@@ -1,30 +1,32 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <?pde?>
 <!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
-<target name="jgit-4.12" sequenceNumber="1606854603">
+<target name="jgit-4.12" sequenceNumber="1610487371">
   <locations>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
-      <unit id="org.eclipse.jetty.client" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.client.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.continuation" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.continuation.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.http" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.http.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.io" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.io.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.security" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.security.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.server" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.server.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.servlet" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.servlet.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.util" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.util.source" version="9.4.30.v20200611"/>
-      <repository id="jetty-9.4.30" location="https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.30.v20200611/"/>
+      <unit id="org.eclipse.jetty.client" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.client.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.continuation" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.continuation.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.http" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.http.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.io" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.io.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.security" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.security.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.server" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.server.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.servlet" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.servlet.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util.ajax" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util.ajax.source" version="9.4.35.v20201120"/>
+      <repository id="jetty-9.4.30" location="https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.35.v20201120/"/>
     </location>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
-      <unit id="com.google.gson" version="2.8.2.v20180104-1110"/>
-      <unit id="com.google.gson.source" version="2.8.2.v20180104-1110"/>
+      <unit id="com.google.gson" version="2.8.6.v20201231-1626"/>
+      <unit id="com.google.gson.source" version="2.8.6.v20201231-1626"/>
       <unit id="com.jcraft.jsch" version="0.1.55.v20190404-1902"/>
       <unit id="com.jcraft.jsch.source" version="0.1.55.v20190404-1902"/>
       <unit id="com.jcraft.jzlib" version="1.1.1.v201205102305"/>
@@ -84,7 +86,7 @@
       <unit id="org.slf4j.binding.log4j12.source" version="1.7.30.v20201108-2042"/>
       <unit id="org.tukaani.xz" version="1.8.0.v20180207-1613"/>
       <unit id="org.tukaani.xz.source" version="1.8.0.v20180207-1613"/>
-      <repository location="https://download.eclipse.org/tools/orbit/downloads/drops/R20201130205003/repository"/>
+      <repository location="https://download.eclipse.org/tools/orbit/downloads/drops/S20210105214148/repository"/>
     </location>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
       <unit id="org.eclipse.osgi" version="0.0.0"/>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.12.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.12.tpd
index 56fd714..7e6ad8e 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.12.tpd
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.12.tpd
@@ -1,7 +1,7 @@
 target "jgit-4.12" with source configurePhase
 
 include "projects/jetty-9.4.x.tpd"
-include "orbit/R20201130205003-2020-12.tpd"
+include "orbit/S20210105214148.tpd"
 
 location "https://download.eclipse.org/releases/2019-06/" {
 	org.eclipse.osgi lazy
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.13.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.13.target
index 04b536e..3f9d17d 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.13.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.13.target
@@ -1,30 +1,32 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <?pde?>
 <!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
-<target name="jgit-4.13" sequenceNumber="1606854603">
+<target name="jgit-4.13" sequenceNumber="1610487371">
   <locations>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
-      <unit id="org.eclipse.jetty.client" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.client.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.continuation" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.continuation.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.http" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.http.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.io" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.io.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.security" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.security.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.server" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.server.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.servlet" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.servlet.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.util" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.util.source" version="9.4.30.v20200611"/>
-      <repository id="jetty-9.4.30" location="https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.30.v20200611/"/>
+      <unit id="org.eclipse.jetty.client" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.client.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.continuation" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.continuation.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.http" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.http.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.io" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.io.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.security" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.security.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.server" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.server.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.servlet" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.servlet.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util.ajax" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util.ajax.source" version="9.4.35.v20201120"/>
+      <repository id="jetty-9.4.30" location="https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.35.v20201120/"/>
     </location>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
-      <unit id="com.google.gson" version="2.8.2.v20180104-1110"/>
-      <unit id="com.google.gson.source" version="2.8.2.v20180104-1110"/>
+      <unit id="com.google.gson" version="2.8.6.v20201231-1626"/>
+      <unit id="com.google.gson.source" version="2.8.6.v20201231-1626"/>
       <unit id="com.jcraft.jsch" version="0.1.55.v20190404-1902"/>
       <unit id="com.jcraft.jsch.source" version="0.1.55.v20190404-1902"/>
       <unit id="com.jcraft.jzlib" version="1.1.1.v201205102305"/>
@@ -84,7 +86,7 @@
       <unit id="org.slf4j.binding.log4j12.source" version="1.7.30.v20201108-2042"/>
       <unit id="org.tukaani.xz" version="1.8.0.v20180207-1613"/>
       <unit id="org.tukaani.xz.source" version="1.8.0.v20180207-1613"/>
-      <repository location="https://download.eclipse.org/tools/orbit/downloads/drops/R20201130205003/repository"/>
+      <repository location="https://download.eclipse.org/tools/orbit/downloads/drops/S20210105214148/repository"/>
     </location>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
       <unit id="org.eclipse.osgi" version="0.0.0"/>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.13.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.13.tpd
index 46069c3..af0f845 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.13.tpd
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.13.tpd
@@ -1,7 +1,7 @@
 target "jgit-4.13" with source configurePhase
 
 include "projects/jetty-9.4.x.tpd"
-include "orbit/R20201130205003-2020-12.tpd"
+include "orbit/S20210105214148.tpd"
 
 location "https://download.eclipse.org/releases/2019-09/" {
 	org.eclipse.osgi lazy
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.14.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.14.target
index c1722ff..9b84908 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.14.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.14.target
@@ -1,30 +1,32 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <?pde?>
 <!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
-<target name="jgit-4.14" sequenceNumber="1606854603">
+<target name="jgit-4.14" sequenceNumber="1610487371">
   <locations>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
-      <unit id="org.eclipse.jetty.client" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.client.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.continuation" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.continuation.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.http" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.http.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.io" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.io.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.security" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.security.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.server" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.server.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.servlet" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.servlet.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.util" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.util.source" version="9.4.30.v20200611"/>
-      <repository id="jetty-9.4.30" location="https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.30.v20200611/"/>
+      <unit id="org.eclipse.jetty.client" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.client.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.continuation" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.continuation.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.http" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.http.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.io" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.io.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.security" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.security.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.server" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.server.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.servlet" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.servlet.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util.ajax" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util.ajax.source" version="9.4.35.v20201120"/>
+      <repository id="jetty-9.4.30" location="https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.35.v20201120/"/>
     </location>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
-      <unit id="com.google.gson" version="2.8.2.v20180104-1110"/>
-      <unit id="com.google.gson.source" version="2.8.2.v20180104-1110"/>
+      <unit id="com.google.gson" version="2.8.6.v20201231-1626"/>
+      <unit id="com.google.gson.source" version="2.8.6.v20201231-1626"/>
       <unit id="com.jcraft.jsch" version="0.1.55.v20190404-1902"/>
       <unit id="com.jcraft.jsch.source" version="0.1.55.v20190404-1902"/>
       <unit id="com.jcraft.jzlib" version="1.1.1.v201205102305"/>
@@ -84,7 +86,7 @@
       <unit id="org.slf4j.binding.log4j12.source" version="1.7.30.v20201108-2042"/>
       <unit id="org.tukaani.xz" version="1.8.0.v20180207-1613"/>
       <unit id="org.tukaani.xz.source" version="1.8.0.v20180207-1613"/>
-      <repository location="https://download.eclipse.org/tools/orbit/downloads/drops/R20201130205003/repository"/>
+      <repository location="https://download.eclipse.org/tools/orbit/downloads/drops/S20210105214148/repository"/>
     </location>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
       <unit id="org.eclipse.osgi" version="0.0.0"/>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.14.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.14.tpd
index f517ab2..0c89f0e 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.14.tpd
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.14.tpd
@@ -1,7 +1,7 @@
 target "jgit-4.14" with source configurePhase
 
 include "projects/jetty-9.4.x.tpd"
-include "orbit/R20201130205003-2020-12.tpd"
+include "orbit/S20210105214148.tpd"
 
 location "https://download.eclipse.org/releases/2019-12/201912181000/" {
 	org.eclipse.osgi lazy
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.15.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.15.target
index 7f5f5a1..b533aa1 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.15.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.15.target
@@ -1,30 +1,32 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <?pde?>
 <!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
-<target name="jgit-4.15" sequenceNumber="1606854603">
+<target name="jgit-4.15" sequenceNumber="1610487371">
   <locations>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
-      <unit id="org.eclipse.jetty.client" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.client.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.continuation" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.continuation.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.http" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.http.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.io" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.io.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.security" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.security.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.server" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.server.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.servlet" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.servlet.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.util" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.util.source" version="9.4.30.v20200611"/>
-      <repository id="jetty-9.4.30" location="https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.30.v20200611/"/>
+      <unit id="org.eclipse.jetty.client" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.client.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.continuation" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.continuation.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.http" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.http.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.io" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.io.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.security" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.security.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.server" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.server.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.servlet" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.servlet.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util.ajax" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util.ajax.source" version="9.4.35.v20201120"/>
+      <repository id="jetty-9.4.30" location="https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.35.v20201120/"/>
     </location>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
-      <unit id="com.google.gson" version="2.8.2.v20180104-1110"/>
-      <unit id="com.google.gson.source" version="2.8.2.v20180104-1110"/>
+      <unit id="com.google.gson" version="2.8.6.v20201231-1626"/>
+      <unit id="com.google.gson.source" version="2.8.6.v20201231-1626"/>
       <unit id="com.jcraft.jsch" version="0.1.55.v20190404-1902"/>
       <unit id="com.jcraft.jsch.source" version="0.1.55.v20190404-1902"/>
       <unit id="com.jcraft.jzlib" version="1.1.1.v201205102305"/>
@@ -84,7 +86,7 @@
       <unit id="org.slf4j.binding.log4j12.source" version="1.7.30.v20201108-2042"/>
       <unit id="org.tukaani.xz" version="1.8.0.v20180207-1613"/>
       <unit id="org.tukaani.xz.source" version="1.8.0.v20180207-1613"/>
-      <repository location="https://download.eclipse.org/tools/orbit/downloads/drops/R20201130205003/repository"/>
+      <repository location="https://download.eclipse.org/tools/orbit/downloads/drops/S20210105214148/repository"/>
     </location>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
       <unit id="org.eclipse.osgi" version="0.0.0"/>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.15.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.15.tpd
index 1e4a0ee..c176a4b 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.15.tpd
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.15.tpd
@@ -1,7 +1,7 @@
 target "jgit-4.15" with source configurePhase
 
 include "projects/jetty-9.4.x.tpd"
-include "orbit/R20201130205003-2020-12.tpd"
+include "orbit/S20210105214148.tpd"
 
 location "https://download.eclipse.org/releases/2020-03/202003181000/" {
 	org.eclipse.osgi lazy
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.16.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.16.target
index bba090a..45c665a 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.16.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.16.target
@@ -1,30 +1,32 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <?pde?>
 <!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
-<target name="jgit-4.16" sequenceNumber="1606854603">
+<target name="jgit-4.16" sequenceNumber="1610487371">
   <locations>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
-      <unit id="org.eclipse.jetty.client" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.client.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.continuation" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.continuation.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.http" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.http.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.io" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.io.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.security" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.security.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.server" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.server.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.servlet" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.servlet.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.util" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.util.source" version="9.4.30.v20200611"/>
-      <repository id="jetty-9.4.30" location="https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.30.v20200611/"/>
+      <unit id="org.eclipse.jetty.client" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.client.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.continuation" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.continuation.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.http" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.http.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.io" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.io.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.security" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.security.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.server" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.server.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.servlet" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.servlet.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util.ajax" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util.ajax.source" version="9.4.35.v20201120"/>
+      <repository id="jetty-9.4.30" location="https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.35.v20201120/"/>
     </location>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
-      <unit id="com.google.gson" version="2.8.2.v20180104-1110"/>
-      <unit id="com.google.gson.source" version="2.8.2.v20180104-1110"/>
+      <unit id="com.google.gson" version="2.8.6.v20201231-1626"/>
+      <unit id="com.google.gson.source" version="2.8.6.v20201231-1626"/>
       <unit id="com.jcraft.jsch" version="0.1.55.v20190404-1902"/>
       <unit id="com.jcraft.jsch.source" version="0.1.55.v20190404-1902"/>
       <unit id="com.jcraft.jzlib" version="1.1.1.v201205102305"/>
@@ -84,7 +86,7 @@
       <unit id="org.slf4j.binding.log4j12.source" version="1.7.30.v20201108-2042"/>
       <unit id="org.tukaani.xz" version="1.8.0.v20180207-1613"/>
       <unit id="org.tukaani.xz.source" version="1.8.0.v20180207-1613"/>
-      <repository location="https://download.eclipse.org/tools/orbit/downloads/drops/R20201130205003/repository"/>
+      <repository location="https://download.eclipse.org/tools/orbit/downloads/drops/S20210105214148/repository"/>
     </location>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
       <unit id="org.eclipse.osgi" version="0.0.0"/>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.16.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.16.tpd
index 2435c48..6352099 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.16.tpd
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.16.tpd
@@ -1,7 +1,7 @@
 target "jgit-4.16" with source configurePhase
 
 include "projects/jetty-9.4.x.tpd"
-include "orbit/R20201130205003-2020-12.tpd"
+include "orbit/S20210105214148.tpd"
 
 location "https://download.eclipse.org/releases/2020-06/" {
 	org.eclipse.osgi lazy
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 d7c1728..a3027bc 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,30 +1,32 @@
 <?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="1606854603">
+<target name="jgit-4.17" sequenceNumber="1610487371">
   <locations>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
-      <unit id="org.eclipse.jetty.client" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.client.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.continuation" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.continuation.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.http" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.http.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.io" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.io.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.security" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.security.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.server" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.server.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.servlet" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.servlet.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.util" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.util.source" version="9.4.30.v20200611"/>
-      <repository id="jetty-9.4.30" location="https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.30.v20200611/"/>
+      <unit id="org.eclipse.jetty.client" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.client.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.continuation" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.continuation.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.http" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.http.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.io" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.io.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.security" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.security.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.server" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.server.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.servlet" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.servlet.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util.ajax" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util.ajax.source" version="9.4.35.v20201120"/>
+      <repository id="jetty-9.4.30" location="https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.35.v20201120/"/>
     </location>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
-      <unit id="com.google.gson" version="2.8.2.v20180104-1110"/>
-      <unit id="com.google.gson.source" version="2.8.2.v20180104-1110"/>
+      <unit id="com.google.gson" version="2.8.6.v20201231-1626"/>
+      <unit id="com.google.gson.source" version="2.8.6.v20201231-1626"/>
       <unit id="com.jcraft.jsch" version="0.1.55.v20190404-1902"/>
       <unit id="com.jcraft.jsch.source" version="0.1.55.v20190404-1902"/>
       <unit id="com.jcraft.jzlib" version="1.1.1.v201205102305"/>
@@ -84,7 +86,7 @@
       <unit id="org.slf4j.binding.log4j12.source" version="1.7.30.v20201108-2042"/>
       <unit id="org.tukaani.xz" version="1.8.0.v20180207-1613"/>
       <unit id="org.tukaani.xz.source" version="1.8.0.v20180207-1613"/>
-      <repository location="https://download.eclipse.org/tools/orbit/downloads/drops/R20201130205003/repository"/>
+      <repository location="https://download.eclipse.org/tools/orbit/downloads/drops/S20210105214148/repository"/>
     </location>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
       <unit id="org.eclipse.osgi" version="0.0.0"/>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.17.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.17.tpd
index 4327415..4c75934 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.17.tpd
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.17.tpd
@@ -1,7 +1,7 @@
 target "jgit-4.17" with source configurePhase
 
 include "projects/jetty-9.4.x.tpd"
-include "orbit/R20201130205003-2020-12.tpd"
+include "orbit/S20210105214148.tpd"
 
 location "https://download.eclipse.org/releases/2020-09/" {
 	org.eclipse.osgi lazy
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 4ce2019..578fe23 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,30 +1,32 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <?pde?>
 <!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
-<target name="jgit-4.18-staging" sequenceNumber="1608217757">
+<target name="jgit-4.18" sequenceNumber="1610487371">
   <locations>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
-      <unit id="org.eclipse.jetty.client" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.client.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.continuation" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.continuation.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.http" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.http.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.io" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.io.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.security" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.security.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.server" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.server.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.servlet" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.servlet.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.util" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.util.source" version="9.4.30.v20200611"/>
-      <repository id="jetty-9.4.30" location="https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.30.v20200611/"/>
+      <unit id="org.eclipse.jetty.client" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.client.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.continuation" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.continuation.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.http" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.http.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.io" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.io.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.security" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.security.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.server" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.server.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.servlet" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.servlet.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util.ajax" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util.ajax.source" version="9.4.35.v20201120"/>
+      <repository id="jetty-9.4.30" location="https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.35.v20201120/"/>
     </location>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
-      <unit id="com.google.gson" version="2.8.2.v20180104-1110"/>
-      <unit id="com.google.gson.source" version="2.8.2.v20180104-1110"/>
+      <unit id="com.google.gson" version="2.8.6.v20201231-1626"/>
+      <unit id="com.google.gson.source" version="2.8.6.v20201231-1626"/>
       <unit id="com.jcraft.jsch" version="0.1.55.v20190404-1902"/>
       <unit id="com.jcraft.jsch.source" version="0.1.55.v20190404-1902"/>
       <unit id="com.jcraft.jzlib" version="1.1.1.v201205102305"/>
@@ -84,7 +86,7 @@
       <unit id="org.slf4j.binding.log4j12.source" version="1.7.30.v20201108-2042"/>
       <unit id="org.tukaani.xz" version="1.8.0.v20180207-1613"/>
       <unit id="org.tukaani.xz.source" version="1.8.0.v20180207-1613"/>
-      <repository location="https://download.eclipse.org/tools/orbit/downloads/drops/R20201130205003/repository"/>
+      <repository location="https://download.eclipse.org/tools/orbit/downloads/drops/S20210105214148/repository"/>
     </location>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
       <unit id="org.eclipse.osgi" version="0.0.0"/>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.18.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.18.tpd
index b457322..77384a3 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.18.tpd
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.18.tpd
@@ -1,7 +1,7 @@
-target "jgit-4.18-staging" with source configurePhase
+target "jgit-4.18" with source configurePhase
 
 include "projects/jetty-9.4.x.tpd"
-include "orbit/R20201130205003-2020-12.tpd"
+include "orbit/S20210105214148.tpd"
 
 location "https://download.eclipse.org/releases/2020-12/" {
 	org.eclipse.osgi lazy
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.19-staging.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.19-staging.target
new file mode 100644
index 0000000..567767c
--- /dev/null
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.19-staging.target
@@ -0,0 +1,96 @@
+<?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="1610487085">
+  <locations>
+    <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
+      <unit id="org.eclipse.jetty.client" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.client.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.continuation" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.continuation.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.http" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.http.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.io" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.io.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.security" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.security.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.server" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.server.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.servlet" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.servlet.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util.ajax" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util.ajax.source" version="9.4.35.v20201120"/>
+      <repository id="jetty-9.4.30" location="https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.35.v20201120/"/>
+    </location>
+    <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
+      <unit id="com.google.gson" version="2.8.6.v20201231-1626"/>
+      <unit id="com.google.gson.source" version="2.8.6.v20201231-1626"/>
+      <unit id="com.jcraft.jsch" version="0.1.55.v20190404-1902"/>
+      <unit id="com.jcraft.jsch.source" version="0.1.55.v20190404-1902"/>
+      <unit id="com.jcraft.jzlib" version="1.1.1.v201205102305"/>
+      <unit id="com.jcraft.jzlib.source" version="1.1.1.v201205102305"/>
+      <unit id="javaewah" version="1.1.7.v20200107-0831"/>
+      <unit id="javaewah.source" version="1.1.7.v20200107-0831"/>
+      <unit id="javax.servlet" version="3.1.0.v201410161800"/>
+      <unit id="javax.servlet.source" version="3.1.0.v201410161800"/>
+      <unit id="net.bytebuddy.byte-buddy" version="1.9.0.v20181107-1410"/>
+      <unit id="net.bytebuddy.byte-buddy-agent" version="1.9.0.v20181106-1534"/>
+      <unit id="net.bytebuddy.byte-buddy-agent.source" version="1.9.0.v20181106-1534"/>
+      <unit id="net.bytebuddy.byte-buddy.source" version="1.9.0.v20181107-1410"/>
+      <unit id="net.i2p.crypto.eddsa" version="0.3.0.v20181102-1323"/>
+      <unit id="net.i2p.crypto.eddsa.source" version="0.3.0.v20181102-1323"/>
+      <unit id="org.apache.ant" version="1.10.9.v20201106-1946"/>
+      <unit id="org.apache.ant.source" version="1.10.9.v20201106-1946"/>
+      <unit id="org.apache.commons.codec" version="1.14.0.v20200818-1422"/>
+      <unit id="org.apache.commons.codec.source" version="1.14.0.v20200818-1422"/>
+      <unit id="org.apache.commons.compress" version="1.19.0.v20200106-2343"/>
+      <unit id="org.apache.commons.compress.source" version="1.19.0.v20200106-2343"/>
+      <unit id="org.apache.commons.logging" version="1.2.0.v20180409-1502"/>
+      <unit id="org.apache.commons.logging.source" version="1.2.0.v20180409-1502"/>
+      <unit id="org.apache.httpcomponents.httpclient" version="4.5.10.v20200830-2311"/>
+      <unit id="org.apache.httpcomponents.httpclient.source" version="4.5.10.v20200830-2311"/>
+      <unit id="org.apache.httpcomponents.httpcore" version="4.4.12.v20200108-1212"/>
+      <unit id="org.apache.httpcomponents.httpcore.source" version="4.4.12.v20200108-1212"/>
+      <unit id="org.apache.log4j" version="1.2.15.v201012070815"/>
+      <unit id="org.apache.log4j.source" version="1.2.15.v201012070815"/>
+      <unit id="org.apache.sshd.osgi" version="2.4.0.v20200318-1614"/>
+      <unit id="org.apache.sshd.osgi.source" version="2.4.0.v20200318-1614"/>
+      <unit id="org.apache.sshd.sftp" version="2.4.0.v20200319-1547"/>
+      <unit id="org.apache.sshd.sftp.source" version="2.4.0.v20200319-1547"/>
+      <unit id="org.assertj" version="3.14.0.v20200120-1926"/>
+      <unit id="org.assertj.source" version="3.14.0.v20200120-1926"/>
+      <unit id="org.bouncycastle.bcpg" version="1.65.0.v20200527-1955"/>
+      <unit id="org.bouncycastle.bcpg.source" version="1.65.0.v20200527-1955"/>
+      <unit id="org.bouncycastle.bcpkix" version="1.65.0.v20200527-1955"/>
+      <unit id="org.bouncycastle.bcpkix.source" version="1.65.0.v20200527-1955"/>
+      <unit id="org.bouncycastle.bcprov" version="1.65.1.v20200529-1514"/>
+      <unit id="org.bouncycastle.bcprov.source" version="1.65.1.v20200529-1514"/>
+      <unit id="org.hamcrest" version="1.1.0.v20090501071000"/>
+      <unit id="org.hamcrest.core" version="1.3.0.v20180420-1519"/>
+      <unit id="org.hamcrest.core.source" version="1.3.0.v20180420-1519"/>
+      <unit id="org.hamcrest.library" version="1.3.0.v20180524-2246"/>
+      <unit id="org.hamcrest.library.source" version="1.3.0.v20180524-2246"/>
+      <unit id="org.junit" version="4.13.0.v20200204-1500"/>
+      <unit id="org.junit.source" version="4.13.0.v20200204-1500"/>
+      <unit id="org.kohsuke.args4j" version="2.33.0.v20160323-2218"/>
+      <unit id="org.kohsuke.args4j.source" version="2.33.0.v20160323-2218"/>
+      <unit id="org.mockito" version="2.23.0.v20200310-1642"/>
+      <unit id="org.mockito.source" version="2.23.0.v20200310-1642"/>
+      <unit id="org.objenesis" version="2.6.0.v20180420-1519"/>
+      <unit id="org.objenesis.source" version="2.6.0.v20180420-1519"/>
+      <unit id="org.slf4j.api" version="1.7.30.v20200204-2150"/>
+      <unit id="org.slf4j.api.source" version="1.7.30.v20200204-2150"/>
+      <unit id="org.slf4j.binding.log4j12" version="1.7.30.v20201108-2042"/>
+      <unit id="org.slf4j.binding.log4j12.source" version="1.7.30.v20201108-2042"/>
+      <unit id="org.tukaani.xz" version="1.8.0.v20180207-1613"/>
+      <unit id="org.tukaani.xz.source" version="1.8.0.v20180207-1613"/>
+      <repository location="https://download.eclipse.org/tools/orbit/downloads/drops/S20210105214148/repository"/>
+    </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/2021-03/"/>
+    </location>
+  </locations>
+</target>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.19-staging.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.19-staging.tpd
new file mode 100644
index 0000000..d016028
--- /dev/null
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.19-staging.tpd
@@ -0,0 +1,8 @@
+target "jgit-4.19-staging" with source configurePhase
+
+include "projects/jetty-9.4.x.tpd"
+include "orbit/S20210105214148.tpd"
+
+location "https://download.eclipse.org/staging/2021-03/" {
+	org.eclipse.osgi lazy
+}
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.6.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.6.target
index 061dcf2..9cc4290 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.6.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.6.target
@@ -1,30 +1,32 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <?pde?>
 <!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
-<target name="jgit-4.6" sequenceNumber="1606854620">
+<target name="jgit-4.6" sequenceNumber="1610487371">
   <locations>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
-      <unit id="org.eclipse.jetty.client" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.client.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.continuation" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.continuation.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.http" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.http.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.io" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.io.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.security" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.security.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.server" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.server.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.servlet" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.servlet.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.util" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.util.source" version="9.4.30.v20200611"/>
-      <repository id="jetty-9.4.30" location="https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.30.v20200611/"/>
+      <unit id="org.eclipse.jetty.client" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.client.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.continuation" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.continuation.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.http" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.http.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.io" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.io.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.security" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.security.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.server" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.server.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.servlet" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.servlet.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util.ajax" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util.ajax.source" version="9.4.35.v20201120"/>
+      <repository id="jetty-9.4.30" location="https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.35.v20201120/"/>
     </location>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
-      <unit id="com.google.gson" version="2.8.2.v20180104-1110"/>
-      <unit id="com.google.gson.source" version="2.8.2.v20180104-1110"/>
+      <unit id="com.google.gson" version="2.8.6.v20201231-1626"/>
+      <unit id="com.google.gson.source" version="2.8.6.v20201231-1626"/>
       <unit id="com.jcraft.jsch" version="0.1.55.v20190404-1902"/>
       <unit id="com.jcraft.jsch.source" version="0.1.55.v20190404-1902"/>
       <unit id="com.jcraft.jzlib" version="1.1.1.v201205102305"/>
@@ -84,7 +86,7 @@
       <unit id="org.slf4j.binding.log4j12.source" version="1.7.30.v20201108-2042"/>
       <unit id="org.tukaani.xz" version="1.8.0.v20180207-1613"/>
       <unit id="org.tukaani.xz.source" version="1.8.0.v20180207-1613"/>
-      <repository location="https://download.eclipse.org/tools/orbit/downloads/drops/R20201130205003/repository"/>
+      <repository location="https://download.eclipse.org/tools/orbit/downloads/drops/S20210105214148/repository"/>
     </location>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
       <unit id="org.eclipse.osgi" version="0.0.0"/>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.6.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.6.tpd
index c7fbf02..cbc1f30 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.6.tpd
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.6.tpd
@@ -1,7 +1,7 @@
 target "jgit-4.6" with source configurePhase
 
 include "projects/jetty-9.4.x.tpd"
-include "orbit/R20201130205003-2020-12.tpd"
+include "orbit/S20210105214148.tpd"
 
 location "https://download.eclipse.org/releases/neon/" {
 	org.eclipse.osgi lazy
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.7.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.7.target
index b96c54d..b7a8c40 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.7.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.7.target
@@ -1,30 +1,32 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <?pde?>
 <!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
-<target name="jgit-4.7" sequenceNumber="1606854608">
+<target name="jgit-4.7" sequenceNumber="1610487371">
   <locations>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
-      <unit id="org.eclipse.jetty.client" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.client.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.continuation" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.continuation.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.http" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.http.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.io" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.io.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.security" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.security.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.server" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.server.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.servlet" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.servlet.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.util" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.util.source" version="9.4.30.v20200611"/>
-      <repository id="jetty-9.4.30" location="https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.30.v20200611/"/>
+      <unit id="org.eclipse.jetty.client" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.client.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.continuation" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.continuation.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.http" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.http.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.io" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.io.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.security" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.security.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.server" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.server.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.servlet" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.servlet.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util.ajax" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util.ajax.source" version="9.4.35.v20201120"/>
+      <repository id="jetty-9.4.30" location="https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.35.v20201120/"/>
     </location>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
-      <unit id="com.google.gson" version="2.8.2.v20180104-1110"/>
-      <unit id="com.google.gson.source" version="2.8.2.v20180104-1110"/>
+      <unit id="com.google.gson" version="2.8.6.v20201231-1626"/>
+      <unit id="com.google.gson.source" version="2.8.6.v20201231-1626"/>
       <unit id="com.jcraft.jsch" version="0.1.55.v20190404-1902"/>
       <unit id="com.jcraft.jsch.source" version="0.1.55.v20190404-1902"/>
       <unit id="com.jcraft.jzlib" version="1.1.1.v201205102305"/>
@@ -84,7 +86,7 @@
       <unit id="org.slf4j.binding.log4j12.source" version="1.7.30.v20201108-2042"/>
       <unit id="org.tukaani.xz" version="1.8.0.v20180207-1613"/>
       <unit id="org.tukaani.xz.source" version="1.8.0.v20180207-1613"/>
-      <repository location="https://download.eclipse.org/tools/orbit/downloads/drops/R20201130205003/repository"/>
+      <repository location="https://download.eclipse.org/tools/orbit/downloads/drops/S20210105214148/repository"/>
     </location>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
       <unit id="org.eclipse.osgi" version="0.0.0"/>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.7.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.7.tpd
index 585e04b..403ec02 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.7.tpd
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.7.tpd
@@ -1,7 +1,7 @@
 target "jgit-4.7" with source configurePhase
 
 include "projects/jetty-9.4.x.tpd"
-include "orbit/R20201130205003-2020-12.tpd"
+include "orbit/S20210105214148.tpd"
 
 location "https://download.eclipse.org/releases/oxygen/" {
 	org.eclipse.osgi lazy
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.8.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.8.target
index 3ddc0bc..8084e34 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.8.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.8.target
@@ -1,30 +1,32 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <?pde?>
 <!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
-<target name="jgit-4.8" sequenceNumber="1606854603">
+<target name="jgit-4.8" sequenceNumber="1610487371">
   <locations>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
-      <unit id="org.eclipse.jetty.client" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.client.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.continuation" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.continuation.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.http" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.http.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.io" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.io.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.security" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.security.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.server" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.server.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.servlet" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.servlet.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.util" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.util.source" version="9.4.30.v20200611"/>
-      <repository id="jetty-9.4.30" location="https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.30.v20200611/"/>
+      <unit id="org.eclipse.jetty.client" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.client.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.continuation" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.continuation.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.http" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.http.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.io" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.io.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.security" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.security.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.server" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.server.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.servlet" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.servlet.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util.ajax" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util.ajax.source" version="9.4.35.v20201120"/>
+      <repository id="jetty-9.4.30" location="https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.35.v20201120/"/>
     </location>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
-      <unit id="com.google.gson" version="2.8.2.v20180104-1110"/>
-      <unit id="com.google.gson.source" version="2.8.2.v20180104-1110"/>
+      <unit id="com.google.gson" version="2.8.6.v20201231-1626"/>
+      <unit id="com.google.gson.source" version="2.8.6.v20201231-1626"/>
       <unit id="com.jcraft.jsch" version="0.1.55.v20190404-1902"/>
       <unit id="com.jcraft.jsch.source" version="0.1.55.v20190404-1902"/>
       <unit id="com.jcraft.jzlib" version="1.1.1.v201205102305"/>
@@ -84,7 +86,7 @@
       <unit id="org.slf4j.binding.log4j12.source" version="1.7.30.v20201108-2042"/>
       <unit id="org.tukaani.xz" version="1.8.0.v20180207-1613"/>
       <unit id="org.tukaani.xz.source" version="1.8.0.v20180207-1613"/>
-      <repository location="https://download.eclipse.org/tools/orbit/downloads/drops/R20201130205003/repository"/>
+      <repository location="https://download.eclipse.org/tools/orbit/downloads/drops/S20210105214148/repository"/>
     </location>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
       <unit id="org.eclipse.osgi" version="0.0.0"/>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.8.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.8.tpd
index 694fc67..c120bc9 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.8.tpd
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.8.tpd
@@ -1,7 +1,7 @@
 target "jgit-4.8" with source configurePhase
 
 include "projects/jetty-9.4.x.tpd"
-include "orbit/R20201130205003-2020-12.tpd"
+include "orbit/S20210105214148.tpd"
 
 location "https://download.eclipse.org/releases/photon/" {
 	org.eclipse.osgi lazy
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.9.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.9.target
index f119fc1..d51e023 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.9.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.9.target
@@ -1,30 +1,32 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <?pde?>
 <!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
-<target name="jgit-4.9" sequenceNumber="1606854603">
+<target name="jgit-4.9" sequenceNumber="1610487371">
   <locations>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
-      <unit id="org.eclipse.jetty.client" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.client.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.continuation" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.continuation.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.http" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.http.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.io" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.io.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.security" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.security.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.server" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.server.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.servlet" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.servlet.source" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.util" version="9.4.30.v20200611"/>
-      <unit id="org.eclipse.jetty.util.source" version="9.4.30.v20200611"/>
-      <repository id="jetty-9.4.30" location="https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.30.v20200611/"/>
+      <unit id="org.eclipse.jetty.client" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.client.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.continuation" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.continuation.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.http" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.http.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.io" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.io.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.security" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.security.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.server" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.server.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.servlet" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.servlet.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util.source" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util.ajax" version="9.4.35.v20201120"/>
+      <unit id="org.eclipse.jetty.util.ajax.source" version="9.4.35.v20201120"/>
+      <repository id="jetty-9.4.30" location="https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.35.v20201120/"/>
     </location>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
-      <unit id="com.google.gson" version="2.8.2.v20180104-1110"/>
-      <unit id="com.google.gson.source" version="2.8.2.v20180104-1110"/>
+      <unit id="com.google.gson" version="2.8.6.v20201231-1626"/>
+      <unit id="com.google.gson.source" version="2.8.6.v20201231-1626"/>
       <unit id="com.jcraft.jsch" version="0.1.55.v20190404-1902"/>
       <unit id="com.jcraft.jsch.source" version="0.1.55.v20190404-1902"/>
       <unit id="com.jcraft.jzlib" version="1.1.1.v201205102305"/>
@@ -84,7 +86,7 @@
       <unit id="org.slf4j.binding.log4j12.source" version="1.7.30.v20201108-2042"/>
       <unit id="org.tukaani.xz" version="1.8.0.v20180207-1613"/>
       <unit id="org.tukaani.xz.source" version="1.8.0.v20180207-1613"/>
-      <repository location="https://download.eclipse.org/tools/orbit/downloads/drops/R20201130205003/repository"/>
+      <repository location="https://download.eclipse.org/tools/orbit/downloads/drops/S20210105214148/repository"/>
     </location>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
       <unit id="org.eclipse.osgi" version="0.0.0"/>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.9.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.9.tpd
index ae5390c..0c896b4 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.9.tpd
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.9.tpd
@@ -1,7 +1,7 @@
 target "jgit-4.9" with source configurePhase
 
 include "projects/jetty-9.4.x.tpd"
-include "orbit/R20201130205003-2020-12.tpd"
+include "orbit/S20210105214148.tpd"
 
 location "https://download.eclipse.org/releases/2018-09/" {
 	org.eclipse.osgi lazy
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/S20210105214148.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/S20210105214148.tpd
new file mode 100644
index 0000000..58f2417
--- /dev/null
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/S20210105214148.tpd
@@ -0,0 +1,66 @@
+target "S20210105214148" with source configurePhase
+// see https://download.eclipse.org/tools/orbit/downloads/
+
+location "https://download.eclipse.org/tools/orbit/downloads/drops/S20210105214148/repository" {
+	com.google.gson [2.8.6.v20201231-1626,2.8.6.v20201231-1626]
+	com.google.gson.source [2.8.6.v20201231-1626,2.8.6.v20201231-1626]
+	com.jcraft.jsch [0.1.55.v20190404-1902,0.1.55.v20190404-1902]
+	com.jcraft.jsch.source [0.1.55.v20190404-1902,0.1.55.v20190404-1902]
+	com.jcraft.jzlib [1.1.1.v201205102305,1.1.1.v201205102305]
+	com.jcraft.jzlib.source [1.1.1.v201205102305,1.1.1.v201205102305]
+	javaewah [1.1.7.v20200107-0831,1.1.7.v20200107-0831]
+	javaewah.source [1.1.7.v20200107-0831,1.1.7.v20200107-0831]
+	javax.servlet [3.1.0.v201410161800,3.1.0.v201410161800]
+	javax.servlet.source [3.1.0.v201410161800,3.1.0.v201410161800]
+	net.bytebuddy.byte-buddy [1.9.0.v20181107-1410,1.9.0.v20181107-1410]
+	net.bytebuddy.byte-buddy-agent [1.9.0.v20181106-1534,1.9.0.v20181106-1534]
+	net.bytebuddy.byte-buddy-agent.source [1.9.0.v20181106-1534,1.9.0.v20181106-1534]
+	net.bytebuddy.byte-buddy.source [1.9.0.v20181107-1410,1.9.0.v20181107-1410]
+	net.i2p.crypto.eddsa [0.3.0.v20181102-1323,0.3.0.v20181102-1323]
+	net.i2p.crypto.eddsa.source [0.3.0.v20181102-1323,0.3.0.v20181102-1323]
+	org.apache.ant [1.10.9.v20201106-1946,1.10.9.v20201106-1946]
+	org.apache.ant.source [1.10.9.v20201106-1946,1.10.9.v20201106-1946]
+	org.apache.commons.codec [1.14.0.v20200818-1422,1.14.0.v20200818-1422]
+	org.apache.commons.codec.source [1.14.0.v20200818-1422,1.14.0.v20200818-1422]
+	org.apache.commons.compress [1.19.0.v20200106-2343,1.19.0.v20200106-2343]
+	org.apache.commons.compress.source [1.19.0.v20200106-2343,1.19.0.v20200106-2343]
+	org.apache.commons.logging [1.2.0.v20180409-1502,1.2.0.v20180409-1502]
+	org.apache.commons.logging.source [1.2.0.v20180409-1502,1.2.0.v20180409-1502]
+	org.apache.httpcomponents.httpclient [4.5.10.v20200830-2311,4.5.10.v20200830-2311]
+	org.apache.httpcomponents.httpclient.source [4.5.10.v20200830-2311,4.5.10.v20200830-2311]
+	org.apache.httpcomponents.httpcore [4.4.12.v20200108-1212,4.4.12.v20200108-1212]
+	org.apache.httpcomponents.httpcore.source [4.4.12.v20200108-1212,4.4.12.v20200108-1212]
+	org.apache.log4j [1.2.15.v201012070815,1.2.15.v201012070815]
+	org.apache.log4j.source [1.2.15.v201012070815,1.2.15.v201012070815]
+	org.apache.sshd.osgi [2.4.0.v20200318-1614,2.4.0.v20200318-1614]
+	org.apache.sshd.osgi.source [2.4.0.v20200318-1614,2.4.0.v20200318-1614]
+	org.apache.sshd.sftp [2.4.0.v20200319-1547,2.4.0.v20200319-1547]
+	org.apache.sshd.sftp.source [2.4.0.v20200319-1547,2.4.0.v20200319-1547]
+	org.assertj [3.14.0.v20200120-1926,3.14.0.v20200120-1926]
+	org.assertj.source [3.14.0.v20200120-1926,3.14.0.v20200120-1926]
+	org.bouncycastle.bcpg [1.65.0.v20200527-1955,1.65.0.v20200527-1955]
+	org.bouncycastle.bcpg.source [1.65.0.v20200527-1955,1.65.0.v20200527-1955]
+	org.bouncycastle.bcpkix [1.65.0.v20200527-1955,1.65.0.v20200527-1955]
+	org.bouncycastle.bcpkix.source [1.65.0.v20200527-1955,1.65.0.v20200527-1955]
+	org.bouncycastle.bcprov [1.65.1.v20200529-1514,1.65.1.v20200529-1514]
+	org.bouncycastle.bcprov.source [1.65.1.v20200529-1514,1.65.1.v20200529-1514]
+	org.hamcrest [1.1.0.v20090501071000,1.1.0.v20090501071000]
+	org.hamcrest.core [1.3.0.v20180420-1519,1.3.0.v20180420-1519]
+	org.hamcrest.core.source [1.3.0.v20180420-1519,1.3.0.v20180420-1519]
+	org.hamcrest.library [1.3.0.v20180524-2246,1.3.0.v20180524-2246]
+	org.hamcrest.library.source [1.3.0.v20180524-2246,1.3.0.v20180524-2246]
+	org.junit [4.13.0.v20200204-1500,4.13.0.v20200204-1500]
+	org.junit.source [4.13.0.v20200204-1500,4.13.0.v20200204-1500]
+	org.kohsuke.args4j [2.33.0.v20160323-2218,2.33.0.v20160323-2218]
+	org.kohsuke.args4j.source [2.33.0.v20160323-2218,2.33.0.v20160323-2218]
+	org.mockito [2.23.0.v20200310-1642,2.23.0.v20200310-1642]
+	org.mockito.source [2.23.0.v20200310-1642,2.23.0.v20200310-1642]
+	org.objenesis [2.6.0.v20180420-1519,2.6.0.v20180420-1519]
+	org.objenesis.source [2.6.0.v20180420-1519,2.6.0.v20180420-1519]
+	org.slf4j.api [1.7.30.v20200204-2150,1.7.30.v20200204-2150]
+	org.slf4j.api.source [1.7.30.v20200204-2150,1.7.30.v20200204-2150]
+	org.slf4j.binding.log4j12 [1.7.30.v20201108-2042,1.7.30.v20201108-2042]
+	org.slf4j.binding.log4j12.source [1.7.30.v20201108-2042,1.7.30.v20201108-2042]
+	org.tukaani.xz [1.8.0.v20180207-1613,1.8.0.v20180207-1613]
+	org.tukaani.xz.source [1.8.0.v20180207-1613,1.8.0.v20180207-1613]
+}
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/projects/jetty-9.4.x.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/projects/jetty-9.4.x.tpd
index 70c426c..72f20c4 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/projects/jetty-9.4.x.tpd
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/projects/jetty-9.4.x.tpd
@@ -1,20 +1,22 @@
 target "jetty-9.4.x" with source configurePhase
 
-location jetty-9.4.30 "https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.30.v20200611/" {
-	org.eclipse.jetty.client [9.4.30.v20200611,9.4.30.v20200611]
-	org.eclipse.jetty.client.source [9.4.30.v20200611,9.4.30.v20200611]
-	org.eclipse.jetty.continuation [9.4.30.v20200611,9.4.30.v20200611]
-	org.eclipse.jetty.continuation.source [9.4.30.v20200611,9.4.30.v20200611]
-	org.eclipse.jetty.http [9.4.30.v20200611,9.4.30.v20200611]
-	org.eclipse.jetty.http.source [9.4.30.v20200611,9.4.30.v20200611]
-	org.eclipse.jetty.io [9.4.30.v20200611,9.4.30.v20200611]
-	org.eclipse.jetty.io.source [9.4.30.v20200611,9.4.30.v20200611]
-	org.eclipse.jetty.security [9.4.30.v20200611,9.4.30.v20200611]
-	org.eclipse.jetty.security.source [9.4.30.v20200611,9.4.30.v20200611]
-	org.eclipse.jetty.server [9.4.30.v20200611,9.4.30.v20200611]
-	org.eclipse.jetty.server.source [9.4.30.v20200611,9.4.30.v20200611]
-	org.eclipse.jetty.servlet [9.4.30.v20200611,9.4.30.v20200611]
-	org.eclipse.jetty.servlet.source [9.4.30.v20200611,9.4.30.v20200611]
-	org.eclipse.jetty.util [9.4.30.v20200611,9.4.30.v20200611]
-	org.eclipse.jetty.util.source [9.4.30.v20200611,9.4.30.v20200611]
+location jetty-9.4.30 "https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.35.v20201120/" {
+	org.eclipse.jetty.client [9.4.35.v20201120,9.4.35.v20201120]
+	org.eclipse.jetty.client.source [9.4.35.v20201120,9.4.35.v20201120]
+	org.eclipse.jetty.continuation [9.4.35.v20201120,9.4.35.v20201120]
+	org.eclipse.jetty.continuation.source [9.4.35.v20201120,9.4.35.v20201120]
+	org.eclipse.jetty.http [9.4.35.v20201120,9.4.35.v20201120]
+	org.eclipse.jetty.http.source [9.4.35.v20201120,9.4.35.v20201120]
+	org.eclipse.jetty.io [9.4.35.v20201120,9.4.35.v20201120]
+	org.eclipse.jetty.io.source [9.4.35.v20201120,9.4.35.v20201120]
+	org.eclipse.jetty.security [9.4.35.v20201120,9.4.35.v20201120]
+	org.eclipse.jetty.security.source [9.4.35.v20201120,9.4.35.v20201120]
+	org.eclipse.jetty.server [9.4.35.v20201120,9.4.35.v20201120]
+	org.eclipse.jetty.server.source [9.4.35.v20201120,9.4.35.v20201120]
+	org.eclipse.jetty.servlet [9.4.35.v20201120,9.4.35.v20201120]
+	org.eclipse.jetty.servlet.source [9.4.35.v20201120,9.4.35.v20201120]
+	org.eclipse.jetty.util [9.4.35.v20201120,9.4.35.v20201120]
+	org.eclipse.jetty.util.source [9.4.35.v20201120,9.4.35.v20201120]
+	org.eclipse.jetty.util.ajax [9.4.35.v20201120,9.4.35.v20201120]
+	org.eclipse.jetty.util.ajax.source [9.4.35.v20201120,9.4.35.v20201120]
 }
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 5f9551e..1d43220 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
@@ -41,6 +41,7 @@
 import org.eclipse.jgit.revwalk.RevWalk;
 import org.eclipse.jgit.treewalk.TreeWalk;
 import org.eclipse.jgit.treewalk.filter.TreeFilter;
+import org.eclipse.jgit.util.RawParseUtils;
 import org.kohsuke.args4j.Argument;
 import org.kohsuke.args4j.Option;
 
@@ -219,13 +220,17 @@
 		}
 
 		outw.println();
-		final String[] lines = tag.getFullMessage().split("\n"); //$NON-NLS-1$
+		String[] lines = tag.getFullMessage().split("\n"); //$NON-NLS-1$
 		for (String s : lines) {
-			outw.print("    "); //$NON-NLS-1$
-			outw.print(s);
-			outw.println();
+			outw.println(s);
 		}
-
+		byte[] rawSignature = tag.getRawGpgSignature();
+		if (rawSignature != null) {
+			lines = RawParseUtils.decode(rawSignature).split("\n"); //$NON-NLS-1$
+			for (String s : lines) {
+				outw.println(s);
+			}
+		}
 		outw.println();
 	}
 
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/TextBuiltin.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/TextBuiltin.java
index 0b02dd1..f70e72d 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/TextBuiltin.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/TextBuiltin.java
@@ -63,7 +63,7 @@
 	private boolean help;
 
 	@Option(name = "--ssh", usage = "usage_sshDriver")
-	private SshDriver sshDriver = SshDriver.JSCH;
+	private SshDriver sshDriver = SshDriver.APACHE;
 
 	/**
 	 * Input stream, typically this is standard input.
@@ -220,7 +220,7 @@
 			SshdSessionFactory factory = new SshdSessionFactory(
 					new JGitKeyCache(), new DefaultProxyDataFactory());
 			Runtime.getRuntime()
-					.addShutdownHook(new Thread(() -> factory.close()));
+					.addShutdownHook(new Thread(factory::close));
 			SshSessionFactory.setInstance(factory);
 			break;
 		}
diff --git a/org.eclipse.jgit.ssh.apache.test/tst/org/eclipse/jgit/transport/sshd/ApacheSshProtocol2Test.java b/org.eclipse.jgit.ssh.apache.test/tst/org/eclipse/jgit/transport/sshd/ApacheSshProtocol2Test.java
new file mode 100644
index 0000000..0ad96b9
--- /dev/null
+++ b/org.eclipse.jgit.ssh.apache.test/tst/org/eclipse/jgit/transport/sshd/ApacheSshProtocol2Test.java
@@ -0,0 +1,56 @@
+/*
+ * 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.transport.sshd;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.nio.file.Files;
+import java.util.Arrays;
+
+import org.eclipse.jgit.junit.ssh.SshBasicTestBase;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.StoredConfig;
+import org.eclipse.jgit.transport.SshSessionFactory;
+import org.eclipse.jgit.util.FS;
+
+public class ApacheSshProtocol2Test extends SshBasicTestBase {
+
+	@Override
+	protected SshSessionFactory createSessionFactory() {
+		SshdSessionFactory result = new SshdSessionFactory(new JGitKeyCache(),
+				null);
+		// The home directory is mocked at this point!
+		result.setHomeDirectory(FS.DETECTED.userHome());
+		result.setSshDirectory(sshDir);
+		return result;
+	}
+
+	@Override
+	protected void installConfig(String... config) {
+		File configFile = new File(sshDir, Constants.CONFIG);
+		if (config != null) {
+			try {
+				Files.write(configFile.toPath(), Arrays.asList(config));
+			} catch (IOException e) {
+				throw new UncheckedIOException(e);
+			}
+		}
+	}
+
+	@Override
+	public void setUp() throws Exception {
+		super.setUp();
+		StoredConfig config = ((Repository) db).getConfig();
+		config.setInt("protocol", null, "version", 2);
+		config.save();
+	}
+}
diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/SshdSession.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/SshdSession.java
index 0fb0610..5a50cc8 100644
--- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/SshdSession.java
+++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/SshdSession.java
@@ -24,6 +24,7 @@
 import java.util.EnumSet;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicReference;
@@ -53,7 +54,7 @@
 import org.eclipse.jgit.internal.transport.sshd.JGitSshClient;
 import org.eclipse.jgit.internal.transport.sshd.SshdText;
 import org.eclipse.jgit.transport.FtpChannel;
-import org.eclipse.jgit.transport.RemoteSession;
+import org.eclipse.jgit.transport.RemoteSession2;
 import org.eclipse.jgit.transport.SshConstants;
 import org.eclipse.jgit.transport.URIish;
 import org.eclipse.jgit.util.StringUtils;
@@ -61,11 +62,12 @@
 import org.slf4j.LoggerFactory;
 
 /**
- * An implementation of {@link RemoteSession} based on Apache MINA sshd.
+ * An implementation of {@link org.eclipse.jgit.transport.RemoteSession
+ * RemoteSession} based on Apache MINA sshd.
  *
  * @since 5.2
  */
-public class SshdSession implements RemoteSession {
+public class SshdSession implements RemoteSession2 {
 
 	private static final Logger LOG = LoggerFactory
 			.getLogger(SshdSession.class);
@@ -290,8 +292,15 @@
 
 	@Override
 	public Process exec(String commandName, int timeout) throws IOException {
+		return exec(commandName, Collections.emptyMap(), timeout);
+	}
+
+	@Override
+	public Process exec(String commandName, Map<String, String> environment,
+			int timeout) throws IOException {
 		@SuppressWarnings("resource")
-		ChannelExec exec = session.createExecChannel(commandName);
+		ChannelExec exec = session.createExecChannel(commandName, null,
+				environment);
 		if (timeout <= 0) {
 			try {
 				exec.open().verify();
diff --git a/org.eclipse.jgit.ssh.jsch.test/tst/org/eclipse/jgit/transport/JSchSshProtocol2Test.java b/org.eclipse.jgit.ssh.jsch.test/tst/org/eclipse/jgit/transport/JSchSshProtocol2Test.java
new file mode 100644
index 0000000..0929c55
--- /dev/null
+++ b/org.eclipse.jgit.ssh.jsch.test/tst/org/eclipse/jgit/transport/JSchSshProtocol2Test.java
@@ -0,0 +1,92 @@
+/*
+ * 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
+ */
+
+//TODO(ms): move to org.eclipse.jgit.ssh.jsch in 6.0
+package org.eclipse.jgit.transport;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.nio.file.Files;
+import java.util.Arrays;
+
+import org.eclipse.jgit.errors.TransportException;
+import org.eclipse.jgit.junit.ssh.SshBasicTestBase;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.StoredConfig;
+import org.eclipse.jgit.transport.OpenSshConfig.Host;
+import org.eclipse.jgit.util.FS;
+
+import com.jcraft.jsch.JSch;
+import com.jcraft.jsch.JSchException;
+import com.jcraft.jsch.Session;
+
+public class JSchSshProtocol2Test extends SshBasicTestBase {
+
+	private class TestSshSessionFactory extends JschConfigSessionFactory {
+
+		@Override
+		protected void configure(Host hc, Session session) {
+			// Nothing
+		}
+
+		@Override
+		public synchronized RemoteSession getSession(URIish uri,
+				CredentialsProvider credentialsProvider, FS fs, int tms)
+				throws TransportException {
+			return super.getSession(uri, credentialsProvider, fs, tms);
+		}
+
+		@Override
+		protected JSch createDefaultJSch(FS fs) throws JSchException {
+			JSch defaultJSch = super.createDefaultJSch(fs);
+			if (knownHosts.exists()) {
+				defaultJSch.setKnownHosts(knownHosts.getAbsolutePath());
+			}
+			return defaultJSch;
+		}
+	}
+
+	@Override
+	protected SshSessionFactory createSessionFactory() {
+		return new TestSshSessionFactory();
+	}
+
+	@Override
+	protected void installConfig(String... config) {
+		SshSessionFactory factory = getSessionFactory();
+		assertTrue(factory instanceof JschConfigSessionFactory);
+		JschConfigSessionFactory j = (JschConfigSessionFactory) factory;
+		try {
+			j.setConfig(createConfig(config));
+		} catch (IOException e) {
+			throw new UncheckedIOException(e);
+		}
+	}
+
+	private OpenSshConfig createConfig(String... content) throws IOException {
+		File configFile = new File(sshDir, Constants.CONFIG);
+		if (content != null) {
+			Files.write(configFile.toPath(), Arrays.asList(content));
+		}
+		return new OpenSshConfig(getTemporaryDirectory(), configFile);
+	}
+
+	@Override
+	public void setUp() throws Exception {
+		super.setUp();
+		StoredConfig config = ((Repository) db).getConfig();
+		config.setInt("protocol", null, "version", 2);
+		config.save();
+	}
+}
diff --git a/org.eclipse.jgit.ssh.jsch/src/org/eclipse/jgit/transport/JschSession.java b/org.eclipse.jgit.ssh.jsch/src/org/eclipse/jgit/transport/JschSession.java
index 858bdf3..c7d0941 100644
--- a/org.eclipse.jgit.ssh.jsch/src/org/eclipse/jgit/transport/JschSession.java
+++ b/org.eclipse.jgit.ssh.jsch/src/org/eclipse/jgit/transport/JschSession.java
@@ -22,7 +22,9 @@
 import java.io.OutputStream;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 import java.util.concurrent.Callable;
 import java.util.concurrent.TimeUnit;
 
@@ -44,7 +46,7 @@
  * {@link org.eclipse.jgit.transport.JschConfigSessionFactory} is used to create
  * the actual session passed to the constructor.
  */
-public class JschSession implements RemoteSession {
+public class JschSession implements RemoteSession2 {
 	final Session sock;
 	final URIish uri;
 
@@ -65,7 +67,14 @@
 	/** {@inheritDoc} */
 	@Override
 	public Process exec(String command, int timeout) throws IOException {
-		return new JschProcess(command, timeout);
+		return exec(command, Collections.emptyMap(), timeout);
+	}
+
+	/** {@inheritDoc} */
+	@Override
+	public Process exec(String command, Map<String, String> environment,
+			int timeout) throws IOException {
+		return new JschProcess(command, environment, timeout);
 	}
 
 	/** {@inheritDoc} */
@@ -124,6 +133,8 @@
 		 *
 		 * @param commandName
 		 *            the command to execute
+		 * @param environment
+		 *            environment variables to pass on
 		 * @param tms
 		 *            the timeout value, in seconds, for the command.
 		 * @throws TransportException
@@ -132,11 +143,17 @@
 		 * @throws IOException
 		 *             on problems opening streams
 		 */
-		JschProcess(String commandName, int tms)
-				throws TransportException, IOException {
+		JschProcess(String commandName, Map<String, String> environment,
+				int tms) throws TransportException, IOException {
 			timeout = tms;
 			try {
 				channel = (ChannelExec) sock.openChannel("exec"); //$NON-NLS-1$
+				if (environment != null) {
+					for (Map.Entry<String, String> envVar : environment
+							.entrySet()) {
+						channel.setEnv(envVar.getKey(), envVar.getValue());
+					}
+				}
 				channel.setCommand(commandName);
 				setupStreams();
 				channel.connect(timeout > 0 ? timeout * 1000 : 0);
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevTagParseTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevTagParseTest.java
index edddc33..a3ba3d6 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevTagParseTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevTagParseTest.java
@@ -136,7 +136,7 @@
 				+ "\n" //
 				+ "iD8DBQBC0b9oF3Y\n" //
 				+ "-----END PGP SIGNATURE-----";
-		final String message = "test\n\n" + fakeSignature + '\n';
+		final String message = "test\n" + fakeSignature + '\n';
 
 		final StringBuilder body = new StringBuilder();
 
@@ -168,7 +168,7 @@
 		assertNotNull(c.getTagName());
 		assertEquals(name, c.getTagName());
 		assertEquals("test", c.getShortMessage());
-		assertEquals(message, c.getFullMessage());
+		assertEquals("test\n", c.getFullMessage());
 		assertEquals(fakeSignature + '\n',
 				new String(c.getRawGpgSignature(), US_ASCII));
 
@@ -406,7 +406,7 @@
 		b.write("tag v1.0\n".getBytes(UTF_8));
 		b.write("tagger t <t@example.com> 1218123387 +0700\n".getBytes(UTF_8));
 		b.write('\n');
-		b.write("message\n\n".getBytes(UTF_8));
+		b.write("message\n".getBytes(UTF_8));
 		b.write(signature.getBytes(US_ASCII));
 		b.write('\n');
 
@@ -417,7 +417,7 @@
 
 		assertEquals("t", t.getTaggerIdent().getName());
 		assertEquals("message", t.getShortMessage());
-		assertEquals("message\n\n" + signature + '\n', t.getFullMessage());
+		assertEquals("message\n", t.getFullMessage());
 		String gpgSig = new String(t.getRawGpgSignature(), UTF_8);
 		assertEquals(signature + '\n', gpgSig);
 	}
@@ -452,7 +452,7 @@
 
 		assertEquals("t", t.getTaggerIdent().getName());
 		assertEquals("message", t.getShortMessage());
-		assertEquals(message + signature + '\n', t.getFullMessage());
+		assertEquals(message, t.getFullMessage());
 		String gpgSig = new String(t.getRawGpgSignature(), UTF_8);
 		assertEquals(signature + '\n', gpgSig);
 	}
@@ -486,7 +486,7 @@
 
 		assertEquals("t", t.getTaggerIdent().getName());
 		assertEquals("message", t.getShortMessage());
-		assertEquals(message + signature + '\n', t.getFullMessage());
+		assertEquals(message, t.getFullMessage());
 		String gpgSig = new String(t.getRawGpgSignature(), UTF_8);
 		assertEquals(signature + '\n', gpgSig);
 	}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/BasePackConnectionTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/BasePackConnectionTest.java
index 64b16f6..7d438c1 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/BasePackConnectionTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/BasePackConnectionTest.java
@@ -16,11 +16,11 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertSame;
 
-import java.util.Arrays;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.Map;
 
+import org.eclipse.jgit.lib.Constants;
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.ObjectIdRef;
 import org.eclipse.jgit.lib.Ref;
@@ -30,18 +30,6 @@
 public class BasePackConnectionTest {
 
 	@Test
-	public void testExtractSymRefsFromCapabilities() {
-		final Map<String, String> symRefs = BasePackConnection
-				.extractSymRefsFromCapabilities(
-						Arrays.asList("symref=HEAD:refs/heads/main",
-								"symref=refs/heads/sym:refs/heads/other"));
-
-		assertEquals(2, symRefs.size());
-		assertEquals("refs/heads/main", symRefs.get("HEAD"));
-		assertEquals("refs/heads/other", symRefs.get("refs/heads/sym"));
-	}
-
-	@Test
 	public void testUpdateWithSymRefsAdds() {
 		final Ref mainRef = new ObjectIdRef.Unpeeled(Ref.Storage.LOOSE,
 				"refs/heads/main", ObjectId.fromString(
@@ -230,4 +218,30 @@
 		assertThat(refMap, not(hasKey("refs/heads/sym1")));
 		assertThat(refMap, not(hasKey("refs/heads/sym2")));
 	}
+
+	@Test
+	public void testUpdateWithSymRefsFillInHead() {
+		final String oidName = "0000000000000000000000000000000000000001";
+		final Ref advertised = new ObjectIdRef.PeeledNonTag(Ref.Storage.NETWORK,
+				Constants.HEAD, ObjectId.fromString(oidName));
+
+		final Map<String, Ref> refMap = new HashMap<>();
+		refMap.put(advertised.getName(), advertised);
+
+		final Map<String, String> symRefs = new HashMap<>();
+		symRefs.put("HEAD", "refs/heads/main");
+
+		BasePackConnection.updateWithSymRefs(refMap, symRefs);
+
+		assertThat(refMap, hasKey("HEAD"));
+		assertThat(refMap, hasKey("refs/heads/main"));
+		final Ref headRef = refMap.get("HEAD");
+		final Ref mainRef = refMap.get("refs/heads/main");
+		assertThat(headRef, instanceOf(SymbolicRef.class));
+		final SymbolicRef headSymRef = (SymbolicRef) headRef;
+		assertEquals(Constants.HEAD, headSymRef.getName());
+		assertSame(mainRef, headSymRef.getTarget());
+		assertEquals(oidName, headRef.getObjectId().name());
+		assertEquals(oidName, mainRef.getObjectId().name());
+	}
 }
\ No newline at end of file
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PacketLineInTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PacketLineInTest.java
index 7f03357..505e008 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PacketLineInTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PacketLineInTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009, Google Inc. and others
+ * Copyright (C) 2009, 2020 Google Inc. 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
@@ -13,6 +13,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertThrows;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
@@ -297,6 +298,58 @@
 		}
 	}
 
+	// parseACKv2
+
+	@Test
+	public void testParseAckV2_NAK() throws IOException {
+		final ObjectId expid = ObjectId
+				.fromString("fcfcfb1fd94829c1a1704f894fc111d14770d34e");
+		final MutableObjectId actid = new MutableObjectId();
+		actid.fromString(expid.name());
+
+		assertSame(PacketLineIn.AckNackResult.NAK,
+				PacketLineIn.parseACKv2("NAK", actid));
+		assertEquals(expid, actid);
+	}
+
+	@Test
+	public void testParseAckV2_ACK() throws IOException {
+		final ObjectId expid = ObjectId
+				.fromString("fcfcfb1fd94829c1a1704f894fc111d14770d34e");
+		final MutableObjectId actid = new MutableObjectId();
+
+		assertSame(PacketLineIn.AckNackResult.ACK_COMMON,
+				PacketLineIn.parseACKv2(
+						"ACK fcfcfb1fd94829c1a1704f894fc111d14770d34e", actid));
+		assertEquals(expid, actid);
+	}
+
+	@Test
+	public void testParseAckV2_Ready() throws IOException {
+		final ObjectId expid = ObjectId
+				.fromString("fcfcfb1fd94829c1a1704f894fc111d14770d34e");
+		final MutableObjectId actid = new MutableObjectId();
+		actid.fromString(expid.name());
+
+		assertSame(PacketLineIn.AckNackResult.ACK_READY,
+				PacketLineIn.parseACKv2("ready", actid));
+		assertEquals(expid, actid);
+	}
+
+	@Test
+	public void testParseAckV2_ERR() {
+		IOException e = assertThrows(IOException.class, () -> PacketLineIn
+				.parseACKv2("ERR want is not valid", new MutableObjectId()));
+		assertTrue(e.getMessage().contains("want is not valid"));
+	}
+
+	@Test
+	public void testParseAckV2_Invalid() {
+		IOException e = assertThrows(IOException.class,
+				() -> PacketLineIn.parseACKv2("HELO", new MutableObjectId()));
+		assertTrue(e.getMessage().contains("xpected ACK/NAK"));
+	}
+
 	// test support
 
 	private void init(String msg) {
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/TransferConfigTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/TransferConfigTest.java
new file mode 100644
index 0000000..d9b85fb
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/TransferConfigTest.java
@@ -0,0 +1,69 @@
+/*
+ * 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.transport;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import org.eclipse.jgit.lib.Config;
+import org.junit.Test;
+
+/**
+ * Tests for {@link TransferConfig} parsing.
+ */
+public class TransferConfigTest {
+
+	@Test
+	public void testParseProtocolV0() {
+		Config rc = new Config();
+		rc.setInt("protocol", null, "version", 0);
+		TransferConfig tc = new TransferConfig(rc);
+		assertEquals(TransferConfig.ProtocolVersion.V0, tc.protocolVersion);
+	}
+
+	@Test
+	public void testParseProtocolV1() {
+		Config rc = new Config();
+		rc.setInt("protocol", null, "version", 1);
+		TransferConfig tc = new TransferConfig(rc);
+		assertEquals(TransferConfig.ProtocolVersion.V0, tc.protocolVersion);
+	}
+
+	@Test
+	public void testParseProtocolV2() {
+		Config rc = new Config();
+		rc.setInt("protocol", null, "version", 2);
+		TransferConfig tc = new TransferConfig(rc);
+		assertEquals(TransferConfig.ProtocolVersion.V2, tc.protocolVersion);
+	}
+
+	@Test
+	public void testParseProtocolNotSet() {
+		Config rc = new Config();
+		TransferConfig tc = new TransferConfig(rc);
+		assertNull(tc.protocolVersion);
+	}
+
+	@Test
+	public void testParseProtocolUnknown() {
+		Config rc = new Config();
+		rc.setInt("protocol", null, "version", 3);
+		TransferConfig tc = new TransferConfig(rc);
+		assertNull(tc.protocolVersion);
+	}
+
+	@Test
+	public void testParseProtocolInvalid() {
+		Config rc = new Config();
+		rc.setString("protocol", null, "version", "foo");
+		TransferConfig tc = new TransferConfig(rc);
+		assertNull(tc.protocolVersion);
+	}
+}
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 2b5f929..a8b2e56 100644
--- a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
+++ b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
@@ -233,6 +233,7 @@
 downloadCancelledDuringIndexing=Download cancelled during indexing
 duplicateAdvertisementsOf=duplicate advertisements of {0}
 duplicateRef=Duplicate ref: {0}
+duplicateRefAttribute=Duplicate ref attribute: {0}
 duplicateRemoteRefUpdateIsIllegal=Duplicate remote ref update is illegal. Affected remote name: {0}
 duplicateStagesNotAllowed=Duplicate stages not allowed
 eitherGitDirOrWorkTreeRequired=One of setGitDir or setWorkTree must be called.
@@ -310,6 +311,10 @@
 hoursAgo={0} hours ago
 httpConfigCannotNormalizeURL=Cannot normalize URL path {0}: too many .. segments
 httpConfigInvalidURL=Cannot parse URL from subsection http.{0} in git config; ignored.
+httpFactoryInUse=Changing the HTTP connection factory after an HTTP connection has already been opened is not allowed.
+httpPreAuthTooLate=HTTP Basic preemptive authentication cannot be set once an HTTP connection has already been opened.
+httpUserInfoDecodeError=Cannot decode user info from URL {}; ignored.
+httpWrongConnectionType=Wrong connection type: expected {0}, got {1}.
 hugeIndexesAreNotSupportedByJgitYet=Huge indexes are not supported by jgit, yet
 hunkBelongsToAnotherFile=Hunk belongs to another file
 hunkDisconnectedFromFile=Hunk disconnected from file
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/LsRemoteCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/LsRemoteCommand.java
index a4ca309..0c69106 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/LsRemoteCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/LsRemoteCommand.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011, Christoph Brill <egore911@egore911.de> and others
+ * Copyright (C) 2011, 2020 Christoph Brill <egore911@egore911.de> 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
@@ -164,7 +164,7 @@
 				refSpecs.add(new RefSpec("refs/heads/*:refs/remotes/origin/*")); //$NON-NLS-1$
 			Collection<Ref> refs;
 			Map<String, Ref> refmap = new HashMap<>();
-			try (FetchConnection fc = transport.openFetch()) {
+			try (FetchConnection fc = transport.openFetch(refSpecs)) {
 				refs = fc.getRefs();
 				if (refSpecs.isEmpty())
 					for (Ref r : refs)
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 154f32c..07fb59d 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
@@ -261,6 +261,7 @@
 	/***/ public String downloadCancelledDuringIndexing;
 	/***/ public String duplicateAdvertisementsOf;
 	/***/ public String duplicateRef;
+	/***/ public String duplicateRefAttribute;
 	/***/ public String duplicateRemoteRefUpdateIsIllegal;
 	/***/ public String duplicateStagesNotAllowed;
 	/***/ public String eitherGitDirOrWorkTreeRequired;
@@ -338,6 +339,10 @@
 	/***/ public String hoursAgo;
 	/***/ public String httpConfigCannotNormalizeURL;
 	/***/ public String httpConfigInvalidURL;
+	/***/ public String httpFactoryInUse;
+	/***/ public String httpPreAuthTooLate;
+	/***/ public String httpUserInfoDecodeError;
+	/***/ public String httpWrongConnectionType;
 	/***/ public String hugeIndexesAreNotSupportedByJgitYet;
 	/***/ public String hunkBelongsToAnotherFile;
 	/***/ public String hunkDisconnectedFromFile;
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 c1beb6f..41f291b 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCache.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCache.java
@@ -202,7 +202,7 @@
 
 	private volatile long expireAfter;
 
-	private Object schedulerLock = new Lock();
+	private final Object schedulerLock = new Lock();
 
 	private RepositoryCache() {
 		cacheMap = new ConcurrentHashMap<>();
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 3bcdfaf..3499136 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevTag.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevTag.java
@@ -202,6 +202,29 @@
 		return -1;
 	}
 
+	private int getSignatureStart() {
+		byte[] raw = buffer;
+		int msgB = RawParseUtils.tagMessage(raw, 0);
+		if (msgB < 0) {
+			return msgB;
+		}
+		// Find the last signature start and return the rest
+		int start = nextStart(hSignature, raw, msgB);
+		if (start < 0) {
+			return start;
+		}
+		int next = RawParseUtils.nextLF(raw, start);
+		while (next < raw.length) {
+			int newStart = nextStart(hSignature, raw, next);
+			if (newStart < 0) {
+				break;
+			}
+			start = newStart;
+			next = RawParseUtils.nextLF(raw, start);
+		}
+		return start;
+	}
+
 	/**
 	 * Parse the GPG signature from the raw buffer.
 	 *
@@ -212,24 +235,10 @@
 	@Nullable
 	public final byte[] getRawGpgSignature() {
 		byte[] raw = buffer;
-		int msgB = RawParseUtils.tagMessage(raw, 0);
-		if (msgB < 0) {
-			return null;
-		}
-		// Find the last signature start and return the rest
-		int start = nextStart(hSignature, raw, msgB);
+		int start = getSignatureStart();
 		if (start < 0) {
 			return null;
 		}
-		int next = RawParseUtils.nextLF(raw, start);
-		while (next < raw.length) {
-			int newStart = nextStart(hSignature, raw, next);
-			if (newStart < 0) {
-				break;
-			}
-			start = newStart;
-			next = RawParseUtils.nextLF(raw, start);
-		}
 		return Arrays.copyOfRange(raw, start, raw.length);
 	}
 
@@ -249,7 +258,12 @@
 		if (msgB < 0) {
 			return ""; //$NON-NLS-1$
 		}
-		return RawParseUtils.decode(guessEncoding(), raw, msgB, raw.length);
+		int signatureStart = getSignatureStart();
+		int end = signatureStart < 0 ? raw.length : signatureStart;
+		if (end == msgB) {
+			return ""; //$NON-NLS-1$
+		}
+		return RawParseUtils.decode(guessEncoding(), raw, msgB, end);
 	}
 
 	/**
@@ -275,6 +289,16 @@
 		}
 
 		int msgE = RawParseUtils.endOfParagraph(raw, msgB);
+		int signatureStart = getSignatureStart();
+		if (signatureStart >= msgB && msgE > signatureStart) {
+			msgE = signatureStart;
+			if (msgE > msgB) {
+				msgE--;
+			}
+			if (msgB == msgE) {
+				return ""; //$NON-NLS-1$
+			}
+		}
 		String str = RawParseUtils.decode(guessEncoding(), raw, msgB, msgE);
 		if (RevCommit.hasLF(raw, msgB, msgE)) {
 			str = StringUtils.replaceLineBreaksWithSpace(str);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackConnection.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackConnection.java
index 3a36398..3826bf7 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackConnection.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackConnection.java
@@ -1,8 +1,8 @@
 /*
- * Copyright (C) 2008-2010, Google Inc.
+ * Copyright (C) 2008, 2010 Google Inc.
  * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>
  * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
- * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org> and others
+ * Copyright (C) 2008, 2020 Shawn O. Pearce <spearce@spearce.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
@@ -13,7 +13,12 @@
 
 package org.eclipse.jgit.transport;
 
+import static org.eclipse.jgit.transport.GitProtocolConstants.COMMAND_LS_REFS;
 import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_AGENT;
+import static org.eclipse.jgit.transport.GitProtocolConstants.REF_ATTR_PEELED;
+import static org.eclipse.jgit.transport.GitProtocolConstants.REF_ATTR_SYMREF_TARGET;
+import static org.eclipse.jgit.transport.GitProtocolConstants.VERSION_1;
+import static org.eclipse.jgit.transport.GitProtocolConstants.VERSION_2;
 
 import java.io.EOFException;
 import java.io.IOException;
@@ -22,23 +27,29 @@
 import java.text.MessageFormat;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
 
+import org.eclipse.jgit.annotations.NonNull;
 import org.eclipse.jgit.errors.InvalidObjectIdException;
 import org.eclipse.jgit.errors.NoRemoteRepositoryException;
 import org.eclipse.jgit.errors.PackProtocolException;
 import org.eclipse.jgit.errors.RemoteRepositoryException;
 import org.eclipse.jgit.errors.TransportException;
 import org.eclipse.jgit.internal.JGitText;
+import org.eclipse.jgit.lib.Constants;
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.ObjectIdRef;
 import org.eclipse.jgit.lib.Ref;
 import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.lib.SymbolicRef;
+import org.eclipse.jgit.util.StringUtils;
 import org.eclipse.jgit.util.io.InterruptTimer;
 import org.eclipse.jgit.util.io.TimeoutInputStream;
 import org.eclipse.jgit.util.io.TimeoutOutputStream;
@@ -92,17 +103,27 @@
 	protected boolean statelessRPC;
 
 	/** Capability tokens advertised by the remote side. */
-	private final Set<String> remoteCapablities = new HashSet<>();
+	private final Map<String, String> remoteCapabilities = new HashMap<>();
 
 	/** Extra objects the remote has, but which aren't offered as refs. */
 	protected final Set<ObjectId> additionalHaves = new HashSet<>();
 
+	private TransferConfig.ProtocolVersion protocol = TransferConfig.ProtocolVersion.V0;
+
 	BasePackConnection(PackTransport packTransport) {
 		transport = (Transport) packTransport;
 		local = transport.local;
 		uri = transport.uri;
 	}
 
+	TransferConfig.ProtocolVersion getProtocolVersion() {
+		return protocol;
+	}
+
+	void setProtocolVersion(@NonNull TransferConfig.ProtocolVersion protocol) {
+		this.protocol = protocol;
+	}
+
 	/**
 	 * Configure this connection with the directional pipes.
 	 *
@@ -147,12 +168,15 @@
 	 * {@link #close()} and the exception is wrapped (if necessary) and thrown
 	 * as a {@link org.eclipse.jgit.errors.TransportException}.
 	 *
+	 * @return {@code true} if the refs were read; {@code false} otherwise
+	 *         indicating that {@link #lsRefs} must be called
+	 *
 	 * @throws org.eclipse.jgit.errors.TransportException
 	 *             the reference list could not be scanned.
 	 */
-	protected void readAdvertisedRefs() throws TransportException {
+	protected boolean readAdvertisedRefs() throws TransportException {
 		try {
-			readAdvertisedRefsImpl();
+			return readAdvertisedRefsImpl();
 		} catch (TransportException err) {
 			close();
 			throw err;
@@ -162,35 +186,79 @@
 		}
 	}
 
-	private void readAdvertisedRefsImpl() throws IOException {
-		final LinkedHashMap<String, Ref> avail = new LinkedHashMap<>();
-		for (;;) {
+	private String readLine() throws IOException {
+		String line = pckIn.readString();
+		if (PacketLineIn.isEnd(line)) {
+			return null;
+		}
+		if (line.startsWith("ERR ")) { //$NON-NLS-1$
+			// This is a customized remote service error.
+			// Users should be informed about it.
+			throw new RemoteRepositoryException(uri, line.substring(4));
+		}
+		return line;
+	}
+
+	private boolean readAdvertisedRefsImpl() throws IOException {
+		final Map<String, Ref> avail = new LinkedHashMap<>();
+		final Map<String, String> symRefs = new LinkedHashMap<>();
+		for (boolean first = true;; first = false) {
 			String line;
 
-			try {
-				line = pckIn.readString();
-			} catch (EOFException eof) {
-				if (avail.isEmpty())
-					throw noRepository();
-				throw eof;
-			}
-			if (PacketLineIn.isEnd(line))
-				break;
-
-			if (line.startsWith("ERR ")) { //$NON-NLS-1$
-				// This is a customized remote service error.
-				// Users should be informed about it.
-				throw new RemoteRepositoryException(uri, line.substring(4));
-			}
-
-			if (avail.isEmpty()) {
+			if (first) {
+				boolean isV1 = false;
+				try {
+					line = readLine();
+				} catch (EOFException e) {
+					TransportException noRepo = noRepository();
+					noRepo.initCause(e);
+					throw noRepo;
+				}
+				if (line != null && VERSION_1.equals(line)) {
+					// Same as V0, except for this extra line. We shouldn't get
+					// it since we never request V1.
+					setProtocolVersion(TransferConfig.ProtocolVersion.V0);
+					isV1 = true;
+					line = readLine();
+				}
+				if (line == null) {
+					break;
+				}
 				final int nul = line.indexOf('\0');
 				if (nul >= 0) {
-					// The first line (if any) may contain "hidden"
-					// capability values after a NUL byte.
-					remoteCapablities.addAll(
-							Arrays.asList(line.substring(nul + 1).split(" "))); //$NON-NLS-1$
+					// Protocol V0: The first line (if any) may contain
+					// "hidden" capability values after a NUL byte.
+					for (String capability : line.substring(nul + 1)
+							.split(" ")) { //$NON-NLS-1$
+						if (capability.startsWith(CAPABILITY_SYMREF_PREFIX)) {
+							String[] parts = capability
+									.substring(
+											CAPABILITY_SYMREF_PREFIX.length())
+									.split(":", 2); //$NON-NLS-1$
+							if (parts.length == 2) {
+								symRefs.put(parts[0], parts[1]);
+							}
+						} else {
+							addCapability(capability);
+						}
+					}
 					line = line.substring(0, nul);
+					setProtocolVersion(TransferConfig.ProtocolVersion.V0);
+				} else if (!isV1 && VERSION_2.equals(line)) {
+					// Protocol V2: remaining lines are capabilities as
+					// key=value pairs
+					setProtocolVersion(TransferConfig.ProtocolVersion.V2);
+					readCapabilitiesV2();
+					// Break out here so that stateless RPC transports get a
+					// chance to set up the output stream.
+					return false;
+				} else {
+					setProtocolVersion(TransferConfig.ProtocolVersion.V0);
+				}
+			} else {
+				line = readLine();
+				if (line == null) {
+					break;
 				}
 			}
 
@@ -199,73 +267,214 @@
 				throw invalidRefAdvertisementLine(line);
 			}
 			String name = line.substring(41, line.length());
-			if (avail.isEmpty() && name.equals("capabilities^{}")) { //$NON-NLS-1$
-				// special line from git-receive-pack to show
+			if (first && name.equals("capabilities^{}")) { //$NON-NLS-1$
+				// special line from git-receive-pack (protocol V0) to show
 				// capabilities when there are no refs to advertise
 				continue;
 			}
 
-			final ObjectId id;
-			try {
-				id  = ObjectId.fromString(line.substring(0, 40));
-			} catch (InvalidObjectIdException e) {
-				PackProtocolException ppe = invalidRefAdvertisementLine(line);
-				ppe.initCause(e);
-				throw ppe;
-			}
+			final ObjectId id = toId(line, line.substring(0, 40));
 			if (name.equals(".have")) { //$NON-NLS-1$
 				additionalHaves.add(id);
-			} else if (name.endsWith("^{}")) { //$NON-NLS-1$
-				name = name.substring(0, name.length() - 3);
-				final Ref prior = avail.get(name);
-				if (prior == null)
-					throw new PackProtocolException(uri, MessageFormat.format(
-							JGitText.get().advertisementCameBefore, name, name));
-
-				if (prior.getPeeledObjectId() != null)
-					throw duplicateAdvertisement(name + "^{}"); //$NON-NLS-1$
-
-				avail.put(name, new ObjectIdRef.PeeledTag(
-						Ref.Storage.NETWORK, name, prior.getObjectId(), id));
 			} else {
-				final Ref prior = avail.put(name, new ObjectIdRef.PeeledNonTag(
-						Ref.Storage.NETWORK, name, id));
-				if (prior != null)
-					throw duplicateAdvertisement(name);
+				processLineV1(name, id, avail);
 			}
 		}
-		updateWithSymRefs(avail, extractSymRefsFromCapabilities(remoteCapablities));
+		updateWithSymRefs(avail, symRefs);
 		available(avail);
+		return true;
 	}
 
 	/**
-	 * Finds values in the given capabilities of the form:
+	 * Issue a protocol V2 ls-refs command and read its response.
 	 *
-	 * <pre>
-	 * symref=<em>source</em>:<em>target</em>
-	 * </pre>
-	 *
-	 * And returns a Map of source->target entries.
-	 *
-	 * @param capabilities
-	 *            the capabilities lines
-	 * @return a Map of the symref entries from capabilities
-	 * @throws NullPointerException
-	 *             if capabilities, or any entry in it, is null
+	 * @param refSpecs
+	 *            to produce ref prefixes from if the server supports git
+	 *            protocol V2
+	 * @param additionalPatterns
+	 *            to use for ref prefixes if the server supports git protocol V2
+	 * @throws TransportException
+	 *             if the command could not be run or its output not be read
 	 */
-	static Map<String, String> extractSymRefsFromCapabilities(Collection<String> capabilities) {
+	protected void lsRefs(Collection<RefSpec> refSpecs,
+			String... additionalPatterns) throws TransportException {
+		try {
+			lsRefsImpl(refSpecs, additionalPatterns);
+		} catch (TransportException err) {
+			close();
+			throw err;
+		} catch (IOException | RuntimeException err) {
+			close();
+			throw new TransportException(err.getMessage(), err);
+		}
+	}
+
+	private void lsRefsImpl(Collection<RefSpec> refSpecs,
+			String... additionalPatterns) throws IOException {
+		pckOut.writeString("command=" + COMMAND_LS_REFS); //$NON-NLS-1$
+		// Add the user-agent
+		String agent = UserAgent.get();
+		if (agent != null && isCapableOf(OPTION_AGENT)) {
+			pckOut.writeString(OPTION_AGENT + '=' + agent);
+		}
+		pckOut.writeDelim();
+		pckOut.writeString("peel"); //$NON-NLS-1$
+		pckOut.writeString("symrefs"); //$NON-NLS-1$
+		for (String refPrefix : getRefPrefixes(refSpecs, additionalPatterns)) {
+			pckOut.writeString("ref-prefix " + refPrefix); //$NON-NLS-1$
+		}
+		pckOut.end();
+		final Map<String, Ref> avail = new LinkedHashMap<>();
 		final Map<String, String> symRefs = new LinkedHashMap<>();
-		for (String option : capabilities) {
-			if (option.startsWith(CAPABILITY_SYMREF_PREFIX)) {
-				String[] symRef = option
-						.substring(CAPABILITY_SYMREF_PREFIX.length())
-						.split(":", 2); //$NON-NLS-1$
-				if (symRef.length == 2) {
-					symRefs.put(symRef[0], symRef[1]);
-				}
+		for (;;) {
+			String line = readLine();
+			if (line == null) {
+				break;
+			}
+			// Expecting to get a line in the form "sha1 refname"
+			if (line.length() < 41 || line.charAt(40) != ' ') {
+				throw invalidRefAdvertisementLine(line);
+			}
+			String name = line.substring(41, line.length());
+			final ObjectId id = toId(line, line.substring(0, 40));
+			if (name.equals(".have")) { //$NON-NLS-1$
+				additionalHaves.add(id);
+			} else {
+				processLineV2(line, id, name, avail, symRefs);
 			}
 		}
-		return symRefs;
+		updateWithSymRefs(avail, symRefs);
+		available(avail);
+	}
+
+	private Collection<String> getRefPrefixes(Collection<RefSpec> refSpecs,
+			String... additionalPatterns) {
+		if (refSpecs.isEmpty() && (additionalPatterns == null
+				|| additionalPatterns.length == 0)) {
+			return Collections.emptyList();
+		}
+		Set<String> patterns = new HashSet<>();
+		if (additionalPatterns != null) {
+			Arrays.stream(additionalPatterns).filter(Objects::nonNull)
+					.forEach(patterns::add);
+		}
+		for (RefSpec spec : refSpecs) {
+			// TODO: for now we only do protocol V2 for fetch. For push
+			// RefSpecs, the logic would need to be different. (At the
+			// minimum, take spec.getDestination().)
+			String src = spec.getSource();
+			if (ObjectId.isId(src)) {
+				continue;
+			}
+			if (spec.isWildcard()) {
+				patterns.add(src.substring(0, src.indexOf('*')));
+			} else {
+				patterns.add(src);
+				patterns.add(Constants.R_REFS + src);
+				patterns.add(Constants.R_HEADS + src);
+				patterns.add(Constants.R_TAGS + src);
+			}
+		}
+		return patterns;
+	}
+
+	private void readCapabilitiesV2() throws IOException {
+		// In git protocol V2, capabilities are different. If it's a key-value
+		// pair, the key may be a command name, and the value a space-separated
+		// list of capabilities for that command. We still store it in the same
+		// map as for protocol v0/v1. Protocol v2 code has to account for this.
+		for (;;) {
+			String line = readLine();
+			if (line == null) {
+				break;
+			}
+			addCapability(line);
+		}
+	}
+
+	private void addCapability(String capability) {
+		String parts[] = capability.split("=", 2); //$NON-NLS-1$
+		if (parts.length == 2) {
+			remoteCapabilities.put(parts[0], parts[1]);
+		}
+		remoteCapabilities.put(capability, null);
+	}
+
+	private ObjectId toId(String line, String value)
+			throws PackProtocolException {
+		try {
+			return ObjectId.fromString(value);
+		} catch (InvalidObjectIdException e) {
+			PackProtocolException ppe = invalidRefAdvertisementLine(line);
+			ppe.initCause(e);
+			throw ppe;
+		}
+	}
+
+	private void processLineV1(String name, ObjectId id, Map<String, Ref> avail)
+			throws IOException {
+		if (name.endsWith("^{}")) { //$NON-NLS-1$
+			name = name.substring(0, name.length() - 3);
+			final Ref prior = avail.get(name);
+			if (prior == null) {
+				throw new PackProtocolException(uri, MessageFormat.format(
+						JGitText.get().advertisementCameBefore, name, name));
+			}
+			if (prior.getPeeledObjectId() != null) {
+				throw duplicateAdvertisement(name + "^{}"); //$NON-NLS-1$
+			}
+			avail.put(name, new ObjectIdRef.PeeledTag(Ref.Storage.NETWORK, name,
+					prior.getObjectId(), id));
+		} else {
+			final Ref prior = avail.put(name, new ObjectIdRef.PeeledNonTag(
+					Ref.Storage.NETWORK, name, id));
+			if (prior != null) {
+				throw duplicateAdvertisement(name);
+			}
+		}
+	}
+
+	private void processLineV2(String line, ObjectId id, String rest,
+			Map<String, Ref> avail, Map<String, String> symRefs)
+			throws IOException {
+		String[] parts = rest.split(" "); //$NON-NLS-1$
+		String name = parts[0];
+		// Two attributes possible, symref-target or peeled
+		String symRefTarget = null;
+		String peeled = null;
+		for (int i = 1; i < parts.length; i++) {
+			if (parts[i].startsWith(REF_ATTR_SYMREF_TARGET)) {
+				if (symRefTarget != null) {
+					throw new PackProtocolException(uri, MessageFormat.format(
+							JGitText.get().duplicateRefAttribute, line));
+				}
+				symRefTarget = parts[i]
+						.substring(REF_ATTR_SYMREF_TARGET.length());
+			} else if (parts[i].startsWith(REF_ATTR_PEELED)) {
+				if (peeled != null) {
+					throw new PackProtocolException(uri, MessageFormat.format(
+							JGitText.get().duplicateRefAttribute, line));
+				}
+				peeled = parts[i].substring(REF_ATTR_PEELED.length());
+			}
+			if (peeled != null && symRefTarget != null) {
+				break;
+			}
+		}
+		Ref idRef;
+		if (peeled != null) {
+			idRef = new ObjectIdRef.PeeledTag(Ref.Storage.NETWORK, name, id,
+					toId(line, peeled));
+		} else {
+			idRef = new ObjectIdRef.PeeledNonTag(Ref.Storage.NETWORK, name, id);
+		}
+		Ref prior = avail.put(name, idRef);
+		if (prior != null) {
+			throw duplicateAdvertisement(name);
+		}
+		if (!StringUtils.isEmptyOrNull(symRefTarget)) {
+			symRefs.put(name, symRefTarget);
+		}
 	}
 
 	/**
@@ -334,6 +543,22 @@
 				}
 			}
 		}
+		// If HEAD is still in the symRefs map here, the real ref was not
+		// reported, but we know it must point to the object reported for HEAD.
+		// So fill it in in the refMap.
+		String headRefName = symRefs.get(Constants.HEAD);
+		if (headRefName != null && !refMap.containsKey(headRefName)) {
+			Ref headRef = refMap.get(Constants.HEAD);
+			if (headRef != null) {
+				ObjectId headObj = headRef.getObjectId();
+				headRef = new ObjectIdRef.PeeledNonTag(Ref.Storage.NETWORK,
+						headRefName, headObj);
+				refMap.put(headRefName, headRef);
+				headRef = new SymbolicRef(Constants.HEAD, headRef);
+				refMap.put(Constants.HEAD, headRef);
+				symRefs.remove(Constants.HEAD);
+			}
+		}
 	}
 
 	/**
@@ -357,7 +582,7 @@
 	 * @return whether this option is supported
 	 */
 	protected boolean isCapableOf(String option) {
-		return remoteCapablities.contains(option);
+		return remoteCapabilities.containsKey(option);
 	}
 
 	/**
@@ -378,6 +603,17 @@
 	}
 
 	/**
+	 * Return a capability value.
+	 *
+	 * @param option
+	 *            to get
+	 * @return the value stored, if any.
+	 */
+	protected String getCapability(String option) {
+		return remoteCapabilities.get(option);
+	}
+
+	/**
 	 * Add user agent capability
 	 *
 	 * @param b
@@ -385,7 +621,7 @@
 	 */
 	protected void addUserAgentCapability(StringBuilder b) {
 		String a = UserAgent.get();
-		if (a != null && UserAgent.hasAgent(remoteCapablities)) {
+		if (a != null && remoteCapabilities.get(OPTION_AGENT) != null) {
 			b.append(' ').append(OPTION_AGENT).append('=').append(a);
 		}
 	}
@@ -393,7 +629,8 @@
 	/** {@inheritDoc} */
 	@Override
 	public String getPeerUserAgent() {
-		return UserAgent.getAgent(remoteCapablities, super.getPeerUserAgent());
+		String agent = remoteCapabilities.get(OPTION_AGENT);
+		return agent != null ? agent : super.getPeerUserAgent();
 	}
 
 	private PackProtocolException duplicateAdvertisement(String name) {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackFetchConnection.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackFetchConnection.java
index a2fb51f..d344dea 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackFetchConnection.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackFetchConnection.java
@@ -1,7 +1,7 @@
 /*
- * Copyright (C) 2008-2010, Google Inc.
+ * Copyright (C) 2008, 2010 Google Inc.
  * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
- * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org> and others
+ * Copyright (C) 2008, 2020 Shawn O. Pearce <spearce@spearce.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
@@ -16,18 +16,21 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.text.MessageFormat;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Date;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
 import java.util.Set;
 
 import org.eclipse.jgit.errors.PackProtocolException;
+import org.eclipse.jgit.errors.RemoteRepositoryException;
 import org.eclipse.jgit.errors.TransportException;
 import org.eclipse.jgit.internal.JGitText;
 import org.eclipse.jgit.internal.storage.file.PackLock;
 import org.eclipse.jgit.lib.AnyObjectId;
 import org.eclipse.jgit.lib.Config;
-import org.eclipse.jgit.lib.Constants;
 import org.eclipse.jgit.lib.MutableObjectId;
 import org.eclipse.jgit.lib.NullProgressMonitor;
 import org.eclipse.jgit.lib.ObjectId;
@@ -44,6 +47,7 @@
 import org.eclipse.jgit.revwalk.filter.RevFilter;
 import org.eclipse.jgit.transport.GitProtocolConstants.MultiAck;
 import org.eclipse.jgit.transport.PacketLineIn.AckNackResult;
+import org.eclipse.jgit.util.StringUtils;
 import org.eclipse.jgit.util.TemporaryBuffer;
 
 /**
@@ -207,7 +211,10 @@
 
 	private int maxHaves;
 
-	/** RPC state, if {@link BasePackConnection#statelessRPC} is true. */
+	/**
+	 * RPC state, if {@link BasePackConnection#statelessRPC} is true or protocol
+	 * V2 is used.
+	 */
 	private TemporaryBuffer.Heap state;
 
 	private PacketLineOut pckState;
@@ -321,6 +328,13 @@
 		return Collections.<PackLock> emptyList();
 	}
 
+	private void clearState() {
+		walk.dispose();
+		reachableCommits = null;
+		state = null;
+		pckState = null;
+	}
+
 	/**
 	 * Execute common ancestor negotiation and fetch the objects.
 	 *
@@ -349,18 +363,34 @@
 			markRefsAdvertised();
 			markReachable(have, maxTimeWanted(want));
 
+			if (TransferConfig.ProtocolVersion.V2
+					.equals(getProtocolVersion())) {
+				// Protocol V2 always is a "stateless" protocol, even over a
+				// bidirectional pipe: the server serves one "fetch" request and
+				// then forgets anything it has learned, so the next fetch
+				// request has to re-send all wants and previously determined
+				// common objects as "have"s again.
+				state = new TemporaryBuffer.Heap(Integer.MAX_VALUE);
+				pckState = new PacketLineOut(state);
+				try {
+					doFetchV2(monitor, want, outputStream);
+				} finally {
+					clearState();
+				}
+				return;
+			}
+			// Protocol V0/1
 			if (statelessRPC) {
 				state = new TemporaryBuffer.Heap(Integer.MAX_VALUE);
 				pckState = new PacketLineOut(state);
 			}
-
-			if (sendWants(want)) {
+			PacketLineOut output = statelessRPC ? pckState : pckOut;
+			if (sendWants(want, output)) {
+				output.end();
+				outNeedsEnd = false;
 				negotiate(monitor);
 
-				walk.dispose();
-				reachableCommits = null;
-				state = null;
-				pckState = null;
+				clearState();
 
 				receivePack(monitor, outputStream);
 			}
@@ -373,6 +403,185 @@
 		}
 	}
 
+	private void doFetchV2(ProgressMonitor monitor, Collection<Ref> want,
+			OutputStream outputStream) throws IOException, CancelledException {
+		sideband = true;
+		negotiateBegin();
+
+		pckState.writeString("command=" + GitProtocolConstants.COMMAND_FETCH); //$NON-NLS-1$
+		// Capabilities are sent as command arguments in protocol V2
+		String agent = UserAgent.get();
+		if (agent != null && isCapableOf(GitProtocolConstants.OPTION_AGENT)) {
+			pckState.writeString(
+					GitProtocolConstants.OPTION_AGENT + '=' + agent);
+		}
+		Set<String> capabilities = new HashSet<>();
+		String advertised = getCapability(GitProtocolConstants.COMMAND_FETCH);
+		if (!StringUtils.isEmptyOrNull(advertised)) {
+			capabilities.addAll(Arrays.asList(advertised.split("\\s+"))); //$NON-NLS-1$
+		}
+		// Arguments
+		pckState.writeDelim();
+		for (String capability : getCapabilitiesV2(capabilities)) {
+			pckState.writeString(capability);
+		}
+		if (!sendWants(want, pckState)) {
+			// We already have everything we wanted.
+			return;
+		}
+		// If we send something, we always close it properly ourselves.
+		outNeedsEnd = false;
+
+		FetchStateV2 fetchState = new FetchStateV2();
+		boolean sentDone = false;
+		for (;;) {
+			// The "state" buffer contains the full fetch request with all
+			// common objects found so far.
+			state.writeTo(out, monitor);
+			sentDone = sendNextHaveBatch(fetchState, pckOut, monitor);
+			if (sentDone) {
+				break;
+			}
+			if (readAcknowledgments(fetchState, pckIn, monitor)) {
+				// We got a "ready": next should be a patch file.
+				break;
+			}
+			// Note: C git reads and requires here (and after a packfile) a
+			// "0002" packet in stateless RPC transports (https). This "response
+			// end" packet is even mentioned in the protocol V2 technical
+			// documentation. However, it is not actually part of the public
+			// protocol; it occurs only in an internal protocol wrapper in the C
+			// git implementation.
+		}
+		clearState();
+		String line = pckIn.readString();
+		// If we sent a done, we may have an error reply here.
+		if (sentDone && line.startsWith("ERR ")) { //$NON-NLS-1$
+			throw new RemoteRepositoryException(uri, line.substring(4));
+		}
+		// "shallow-info", "wanted-refs", and "packfile-uris" would have to be
+		// handled here in that order.
+		if (!GitProtocolConstants.SECTION_PACKFILE.equals(line)) {
+			throw new PackProtocolException(
+					MessageFormat.format(JGitText.get().expectedGot,
+							GitProtocolConstants.SECTION_PACKFILE, line));
+		}
+		receivePack(monitor, outputStream);
+	}
+
+	/**
+	 * Sends the next batch of "have"s and terminates the {@code output}.
+	 *
+	 * @param fetchState
+	 *            is updated with information about the number of items written,
+	 *            and whether to expect a packfile next
+	 * @param output
+	 *            to write to
+	 * @param monitor
+	 *            for progress reporting and cancellation
+	 * @return {@code true} if a "done" was written and we should thus expect a
+	 *         packfile next
+	 * @throws IOException
+	 *             on errors
+	 * @throws CancelledException
+	 *             on cancellation
+	 */
+	private boolean sendNextHaveBatch(FetchStateV2 fetchState,
+			PacketLineOut output, ProgressMonitor monitor)
+			throws IOException, CancelledException {
+		long n = 0;
+		while (n < fetchState.havesToSend) {
+			final RevCommit c = walk.next();
+			if (c == null) {
+				break;
+			}
+			output.writeString("have " + c.getId().name() + '\n'); //$NON-NLS-1$
+			n++;
+			if (n % 10 == 0 && monitor.isCancelled()) {
+				throw new CancelledException();
+			}
+		}
+		fetchState.havesTotal += n;
+		if (n == 0
+				|| (fetchState.hadAcks
+						&& fetchState.havesWithoutAck > MAX_HAVES)
+				|| fetchState.havesTotal > maxHaves) {
+			output.writeString("done\n"); //$NON-NLS-1$
+			output.end();
+			return true;
+		}
+		// Increment only after the test above. Of course we have no ACKs yet
+		// for the newly added "have"s, so it makes no sense to count them
+		// against the MAX_HAVES limit.
+		fetchState.havesWithoutAck += n;
+		output.end();
+		fetchState.incHavesToSend(statelessRPC);
+		return false;
+	}
+
+	/**
+	 * Reads and processes acknowledgments, adding ACKed objects as "have"s to
+	 * the global state {@link TemporaryBuffer}.
+	 *
+	 * @param fetchState
+	 *            to update
+	 * @param input
+	 *            to read from
+	 * @param monitor
+	 *            for progress reporting and cancellation
+	 * @return {@code true} if a "ready" was received and a packfile is expected
+	 *         next
+	 * @throws IOException
+	 *             on errors
+	 * @throws CancelledException
+	 *             on cancellation
+	 */
+	private boolean readAcknowledgments(FetchStateV2 fetchState,
+			PacketLineIn input, ProgressMonitor monitor)
+			throws IOException, CancelledException {
+		String line = input.readString();
+		if (!GitProtocolConstants.SECTION_ACKNOWLEDGMENTS.equals(line)) {
+			throw new PackProtocolException(MessageFormat.format(
+					JGitText.get().expectedGot,
+					GitProtocolConstants.SECTION_ACKNOWLEDGMENTS, line));
+		}
+		MutableObjectId returnedId = new MutableObjectId();
+		line = input.readString();
+		boolean gotReady = false;
+		long n = 0;
+		while (!PacketLineIn.isEnd(line) && !PacketLineIn.isDelimiter(line)) {
+			AckNackResult ack = PacketLineIn.parseACKv2(line, returnedId);
+			// If we got a "ready", we just skip the remaining lines after
+			// having checked them for being valid. (Normally, the "ready"
+			// should be the last line anyway.)
+			if (!gotReady) {
+				if (ack == AckNackResult.ACK_COMMON) {
+					// markCommon appends the object to the "state"
+					markCommon(walk.parseAny(returnedId), ack, true);
+					fetchState.havesWithoutAck = 0;
+					fetchState.hadAcks = true;
+				} else if (ack == AckNackResult.ACK_READY) {
+					gotReady = true;
+				}
+			}
+			n++;
+			if (n % 10 == 0 && monitor.isCancelled()) {
+				throw new CancelledException();
+			}
+			line = input.readString();
+		}
+		if (gotReady) {
+			if (!PacketLineIn.isDelimiter(line)) {
+				throw new PackProtocolException(MessageFormat
+						.format(JGitText.get().expectedGot, "0001", line)); //$NON-NLS-1$
+			}
+		} else if (!PacketLineIn.isEnd(line)) {
+			throw new PackProtocolException(MessageFormat
+					.format(JGitText.get().expectedGot, "0000", line)); //$NON-NLS-1$
+		}
+		return gotReady;
+	}
+
 	/** {@inheritDoc} */
 	@Override
 	public void close() {
@@ -456,8 +665,8 @@
 		}
 	}
 
-	private boolean sendWants(Collection<Ref> want) throws IOException {
-		final PacketLineOut p = statelessRPC ? pckState : pckOut;
+	private boolean sendWants(Collection<Ref> want, PacketLineOut p)
+			throws IOException {
 		boolean first = true;
 		for (Ref r : want) {
 			ObjectId objectId = r.getObjectId();
@@ -479,10 +688,11 @@
 			final StringBuilder line = new StringBuilder(46);
 			line.append("want "); //$NON-NLS-1$
 			line.append(objectId.name());
-			if (first) {
+			if (first && TransferConfig.ProtocolVersion.V0
+					.equals(getProtocolVersion())) {
 				line.append(enableCapabilities());
-				first = false;
 			}
+			first = false;
 			line.append('\n');
 			p.writeString(line.toString());
 		}
@@ -492,11 +702,34 @@
 		if (!filterSpec.isNoOp()) {
 			p.writeString(filterSpec.filterLine());
 		}
-		p.end();
-		outNeedsEnd = false;
 		return true;
 	}
 
+	private Set<String> getCapabilitiesV2(Set<String> advertisedCapabilities)
+			throws TransportException {
+		Set<String> capabilities = new LinkedHashSet<>();
+		// Protocol V2 is implicitly capable of all these.
+		if (noProgress) {
+			capabilities.add(OPTION_NO_PROGRESS);
+		}
+		if (includeTags) {
+			capabilities.add(OPTION_INCLUDE_TAG);
+		}
+		if (allowOfsDelta) {
+			capabilities.add(OPTION_OFS_DELTA);
+		}
+		if (thinPack) {
+			capabilities.add(OPTION_THIN_PACK);
+		}
+		if (!filterSpec.isNoOp()
+				&& !advertisedCapabilities.contains(OPTION_FILTER)) {
+			throw new PackProtocolException(uri,
+					JGitText.get().filterRequiresCapability);
+		}
+		// The FilterSpec will be added later in sendWants().
+		return capabilities;
+	}
+
 	private String enableCapabilities() throws TransportException {
 		final StringBuilder line = new StringBuilder();
 		if (noProgress)
@@ -622,7 +855,7 @@
 					// we need to continue to talk about other parts of
 					// our local history.
 					//
-					markCommon(walk.parseAny(ackId), anr);
+					markCommon(walk.parseAny(ackId), anr, statelessRPC);
 					receivedAck = true;
 					receivedContinue = true;
 					havesSinceLastContinue = 0;
@@ -757,16 +990,10 @@
 		}
 	}
 
-	private void markCommon(RevObject obj, AckNackResult anr)
+	private void markCommon(RevObject obj, AckNackResult anr, boolean useState)
 			throws IOException {
-		if (statelessRPC && anr == AckNackResult.ACK_COMMON && !obj.has(STATE)) {
-			StringBuilder s;
-
-			s = new StringBuilder(6 + Constants.OBJECT_ID_STRING_LENGTH);
-			s.append("have "); //$NON-NLS-1$
-			s.append(obj.name());
-			s.append('\n');
-			pckState.writeString(s.toString());
+		if (useState && anr == AckNackResult.ACK_COMMON && !obj.has(STATE)) {
+			pckState.writeString("have " + obj.name() + '\n'); //$NON-NLS-1$
 			obj.add(STATE);
 		}
 		obj.add(COMMON);
@@ -806,4 +1033,31 @@
 	private static class CancelledException extends Exception {
 		private static final long serialVersionUID = 1L;
 	}
+
+	private static class FetchStateV2 {
+
+		long havesToSend = 32;
+
+		long havesTotal;
+
+		// Set to true if we got at least one ACK in protocol V2.
+		boolean hadAcks;
+
+		// Counts haves without ACK. Use as cutoff for negotiation only once
+		// hadAcks == true.
+		long havesWithoutAck;
+
+		void incHavesToSend(boolean statelessRPC) {
+			if (statelessRPC) {
+				// Increase this quicker since connection setup costs accumulate
+				if (havesToSend < 16384) {
+					havesToSend *= 2;
+				} else {
+					havesToSend = havesToSend * 11 / 10;
+				}
+			} else {
+				havesToSend += 32;
+			}
+		}
+	}
 }
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchProcess.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchProcess.java
index 00b726e..bdebfa6 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchProcess.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchProcess.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
- * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org> and others
+ * Copyright (C) 2008, 2020 Shawn O. Pearce <spearce@spearce.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
@@ -110,7 +110,21 @@
 	private void executeImp(final ProgressMonitor monitor,
 			final FetchResult result) throws NotSupportedException,
 			TransportException {
-		conn = transport.openFetch();
+		final TagOpt tagopt = transport.getTagOpt();
+		String getTags = (tagopt == TagOpt.NO_TAGS) ? null : Constants.R_TAGS;
+		String getHead = null;
+		try {
+			// If we don't have a HEAD yet, we're cloning and need to get the
+			// upstream HEAD, too.
+			Ref head = transport.local.exactRef(Constants.HEAD);
+			ObjectId id = head != null ? head.getObjectId() : null;
+			if (id == null || id.equals(ObjectId.zeroId())) {
+				getHead = Constants.HEAD;
+			}
+		} catch (IOException e) {
+			// Ignore
+		}
+		conn = transport.openFetch(toFetch, getTags, getHead);
 		try {
 			result.setAdvertisedRefs(transport.getURI(), conn.getRefsMap());
 			result.peerUserAgent = conn.getPeerUserAgent();
@@ -127,7 +141,6 @@
 			}
 
 			Collection<Ref> additionalTags = Collections.<Ref> emptyList();
-			final TagOpt tagopt = transport.getTagOpt();
 			if (tagopt == TagOpt.AUTO_FOLLOW)
 				additionalTags = expandAutoFollowTags();
 			else if (tagopt == TagOpt.FETCH_TAGS)
@@ -261,7 +274,17 @@
 		if (conn != null)
 			return;
 
-		conn = transport.openFetch();
+		// Build prefixes
+		Set<String> prefixes = new HashSet<>();
+		for (Ref toGet : askFor.values()) {
+			String src = toGet.getName();
+			prefixes.add(src);
+			prefixes.add(Constants.R_REFS + src);
+			prefixes.add(Constants.R_HEADS + src);
+			prefixes.add(Constants.R_TAGS + src);
+		}
+		conn = transport.openFetch(Collections.emptyList(),
+				prefixes.toArray(new String[0]));
 
 		// Since we opened a new connection we cannot be certain
 		// that the system we connected to has the same exact set
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/GitProtocolConstants.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/GitProtocolConstants.java
index 35e2978..36fce7a 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/GitProtocolConstants.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/GitProtocolConstants.java
@@ -1,7 +1,7 @@
 /*
- * Copyright (C) 2008-2013, Google Inc.
+ * Copyright (C) 2008, 2013 Google Inc.
  * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
- * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org> and others
+ * Copyright (C) 2008, 2020 Shawn O. Pearce <spearce@spearce.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
@@ -247,6 +247,74 @@
 	 */
 	public static final String COMMAND_FETCH = "fetch"; //$NON-NLS-1$
 
+	/**
+	 * HTTP header to set by clients to request a specific git protocol version
+	 * in the HTTP transport.
+	 *
+	 * @since 5.11
+	 */
+	public static final String PROTOCOL_HEADER = "Git-Protocol"; //$NON-NLS-1$
+
+	/**
+	 * Environment variable to set by clients to request a specific git protocol
+	 * in the file:// and ssh:// transports.
+	 *
+	 * @since 5.11
+	 */
+	public static final String PROTOCOL_ENVIRONMENT_VARIABLE = "GIT_PROTOCOL"; //$NON-NLS-1$
+
+	/**
+	 * Protocol V2 ref advertisement attribute containing the peeled object id
+	 * for annotated tags.
+	 *
+	 * @since 5.11
+	 */
+	public static final String REF_ATTR_PEELED = "peeled:"; //$NON-NLS-1$
+
+	/**
+	 * Protocol V2 ref advertisement attribute containing the name of the ref
+	 * for symbolic refs.
+	 *
+	 * @since 5.11
+	 */
+	public static final String REF_ATTR_SYMREF_TARGET = "symref-target:"; //$NON-NLS-1$
+
+	/**
+	 * Protocol V2 acknowledgments section header.
+	 *
+	 * @since 5.11
+	 */
+	public static final String SECTION_ACKNOWLEDGMENTS = "acknowledgments"; //$NON-NLS-1$
+
+	/**
+	 * Protocol V2 packfile section header.
+	 *
+	 * @since 5.11
+	 */
+	public static final String SECTION_PACKFILE = "packfile"; //$NON-NLS-1$
+
+	/**
+	 * Protocol announcement for protocol version 1. This is the same as V0,
+	 * except for this initial line.
+	 *
+	 * @since 5.11
+	 */
+	public static final String VERSION_1 = "version 1"; //$NON-NLS-1$
+
+	/**
+	 * Protocol announcement for protocol version 2.
+	 *
+	 * @since 5.11
+	 */
+	public static final String VERSION_2 = "version 2"; //$NON-NLS-1$
+
+	/**
+	 * Protocol request for protocol version 2.
+	 *
+	 * @since 5.11
+	 */
+	public static final String VERSION_2_REQUEST = "version=2"; //$NON-NLS-1$
+
 	enum MultiAck {
 		OFF, CONTINUE, DETAILED;
 	}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/HttpTransport.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/HttpTransport.java
index 49c8b58..febeb3c 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/HttpTransport.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/HttpTransport.java
@@ -26,7 +26,7 @@
 	 *
 	 * @since 3.3
 	 */
-	protected static HttpConnectionFactory connectionFactory = new JDKHttpConnectionFactory();
+	protected static volatile HttpConnectionFactory connectionFactory = new JDKHttpConnectionFactory();
 
 	/**
 	 * Get the {@link org.eclipse.jgit.transport.http.HttpConnectionFactory}
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 350311e..68c5b34 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PacketLineIn.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PacketLineIn.java
@@ -103,6 +103,38 @@
 		this.limit = limit;
 	}
 
+	/**
+	 * Parses a ACK/NAK line in protocol V2.
+	 *
+	 * @param line
+	 *            to parse
+	 * @param returnedId
+	 *            in case of {@link AckNackResult#ACK_COMMON ACK_COMMON}
+	 * @return one of {@link AckNackResult#NAK NAK},
+	 *         {@link AckNackResult#ACK_COMMON ACK_COMMON}, or
+	 *         {@link AckNackResult#ACK_READY ACK_READY}
+	 * @throws IOException
+	 *             on protocol or transport errors
+	 */
+	static AckNackResult parseACKv2(String line, MutableObjectId returnedId)
+			throws IOException {
+		if ("NAK".equals(line)) { //$NON-NLS-1$
+			return AckNackResult.NAK;
+		}
+		if (line.startsWith("ACK ") && line.length() == 44) { //$NON-NLS-1$
+			returnedId.fromString(line.substring(4, 44));
+			return AckNackResult.ACK_COMMON;
+		}
+		if ("ready".equals(line)) { //$NON-NLS-1$
+			return AckNackResult.ACK_READY;
+		}
+		if (line.startsWith("ERR ")) { //$NON-NLS-1$
+			throw new PackProtocolException(line.substring(4));
+		}
+		throw new PackProtocolException(
+				MessageFormat.format(JGitText.get().expectedACKNAKGot, line));
+	}
+
 	AckNackResult readACK(MutableObjectId returnedId) throws IOException {
 		final String line = readString();
 		if (line.length() == 0)
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PacketLineOut.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PacketLineOut.java
index 6fc2042..77f0a7a 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PacketLineOut.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PacketLineOut.java
@@ -1,7 +1,7 @@
 /*
- * Copyright (C) 2008-2010, Google Inc.
- * Copyright (C) 2008-2009, Robin Rosenberg <robin.rosenberg@dewire.com>
- * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org> and others
+ * Copyright (C) 2008, 2010 Google Inc.
+ * Copyright (C) 2008, 2009 Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2008, 2020 Shawn O. Pearce <spearce@spearce.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
@@ -33,12 +33,15 @@
  * against the underlying OutputStream.
  */
 public class PacketLineOut {
+
 	private static final Logger log = LoggerFactory.getLogger(PacketLineOut.class);
 
 	private final OutputStream out;
 
 	private final byte[] lenbuffer;
 
+	private final boolean logEnabled;
+
 	private boolean flushOnEnd;
 
 	private boolean usingSideband;
@@ -50,9 +53,24 @@
 	 *            stream.
 	 */
 	public PacketLineOut(OutputStream outputStream) {
+		this(outputStream, true);
+	}
+
+	/**
+	 * Create a new packet line writer that potentially doesn't log.
+	 *
+	 * @param outputStream
+	 *            stream.
+	 * @param enableLogging
+	 *            {@code false} to suppress all logging; {@code true} to log
+	 *            normally
+	 * @since 5.11
+	 */
+	public PacketLineOut(OutputStream outputStream, boolean enableLogging) {
 		out = outputStream;
 		lenbuffer = new byte[5];
 		flushOnEnd = true;
+		logEnabled = enableLogging;
 	}
 
 	/**
@@ -139,9 +157,15 @@
 			out.write(lenbuffer, 0, 4);
 		}
 		out.write(buf, pos, len);
-		if (log.isDebugEnabled()) {
-			String s = RawParseUtils.decode(UTF_8, buf, pos, len);
-			log.debug("git> " + s); //$NON-NLS-1$
+		if (logEnabled && log.isDebugEnabled()) {
+			// Escape a trailing \n to avoid empty lines in the log.
+			if (len > 0 && buf[pos + len - 1] == '\n') {
+				log.debug(
+						"git> " + RawParseUtils.decode(UTF_8, buf, pos, len - 1) //$NON-NLS-1$
+								+ "\\n"); //$NON-NLS-1$
+			} else {
+				log.debug("git> " + RawParseUtils.decode(UTF_8, buf, pos, len)); //$NON-NLS-1$
+			}
 		}
 	}
 
@@ -156,7 +180,9 @@
 	public void writeDelim() throws IOException {
 		formatLength(1);
 		out.write(lenbuffer, 0, 4);
-		log.debug("git> 0001"); //$NON-NLS-1$
+		if (logEnabled && log.isDebugEnabled()) {
+			log.debug("git> 0001"); //$NON-NLS-1$
+		}
 	}
 
 	/**
@@ -175,9 +201,12 @@
 	public void end() throws IOException {
 		formatLength(0);
 		out.write(lenbuffer, 0, 4);
-		log.debug("git> 0000"); //$NON-NLS-1$
-		if (flushOnEnd)
+		if (logEnabled && log.isDebugEnabled()) {
+			log.debug("git> 0000"); //$NON-NLS-1$
+		}
+		if (flushOnEnd) {
 			flush();
+		}
 	}
 
 	/**
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 3adebba..c525e66 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/RefAdvertiser.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/RefAdvertiser.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008-2010, Google Inc. and others
+ * Copyright (C) 2008, 2020 Google Inc. 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
@@ -13,6 +13,8 @@
 import static java.nio.charset.StandardCharsets.UTF_8;
 import static org.eclipse.jgit.lib.Constants.OBJECT_ID_STRING_LENGTH;
 import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_SYMREF;
+import static org.eclipse.jgit.transport.GitProtocolConstants.REF_ATTR_PEELED;
+import static org.eclipse.jgit.transport.GitProtocolConstants.REF_ATTR_SYMREF_TARGET;
 
 import java.io.IOException;
 import java.nio.ByteBuffer;
@@ -287,7 +289,8 @@
 
 			if (useProtocolV2) {
 				String symrefPart = symrefs.containsKey(ref.getName())
-						? (" symref-target:" + symrefs.get(ref.getName())) //$NON-NLS-1$
+						? (' ' + REF_ATTR_SYMREF_TARGET
+								+ symrefs.get(ref.getName()))
 						: ""; //$NON-NLS-1$
 				String peelPart = ""; //$NON-NLS-1$
 				if (derefTags) {
@@ -296,7 +299,8 @@
 					}
 					ObjectId peeledObjectId = ref.getPeeledObjectId();
 					if (peeledObjectId != null) {
-						peelPart = " peeled:" + peeledObjectId.getName(); //$NON-NLS-1$
+						peelPart = ' ' + REF_ATTR_PEELED
+								+ peeledObjectId.getName();
 					}
 				}
 				writeOne(objectId.getName() + " " + ref.getName() + symrefPart //$NON-NLS-1$
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/RemoteSession2.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/RemoteSession2.java
new file mode 100644
index 0000000..23f670a
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/RemoteSession2.java
@@ -0,0 +1,45 @@
+/*
+ * 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.transport;
+
+import java.io.IOException;
+import java.util.Map;
+
+/**
+ * A {@link RemoteSession} that supports passing environment variables to
+ * commands.
+ *
+ * @since 5.11
+ */
+public interface RemoteSession2 extends RemoteSession {
+
+	/**
+	 * Creates a new remote {@link Process} to execute the given command. The
+	 * returned process's streams exist and are connected, and execution of the
+	 * process is already started.
+	 *
+	 * @param commandName
+	 *            command to execute
+	 * @param environment
+	 *            environment variables to pass on
+	 * @param timeout
+	 *            timeout value, in seconds, for creating the remote process
+	 * @return a new remote process, already started
+	 * @throws java.io.IOException
+	 *             may be thrown in several cases. For example, on problems
+	 *             opening input or output streams or on problems connecting or
+	 *             communicating with the remote host. For the latter two cases,
+	 *             a TransportException may be thrown (a subclass of
+	 *             java.io.IOException).
+	 */
+	Process exec(String commandName, Map<String, String> environment,
+			int timeout) throws IOException;
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransferConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransferConfig.java
index 0b38159..83ffd41 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransferConfig.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransferConfig.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008-2009, Google Inc. and others
+ * Copyright (C) 2008, 2020 Google Inc. 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
@@ -101,6 +101,9 @@
 					return v;
 				}
 			}
+			if ("1".equals(name)) { //$NON-NLS-1$
+				return V0;
+			}
 			return null;
 		}
 	}
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 2ddd0a6..1c998f4 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/Transport.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/Transport.java
@@ -1,8 +1,8 @@
 /*
- * Copyright (C) 2008-2009, Google Inc.
+ * Copyright (C) 2008, 2009 Google Inc.
  * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>
  * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
- * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org> and others
+ * Copyright (C) 2008, 2020 Shawn O. Pearce <spearce@spearce.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
@@ -39,6 +39,7 @@
 import java.util.concurrent.CopyOnWriteArrayList;
 
 import org.eclipse.jgit.annotations.NonNull;
+import org.eclipse.jgit.annotations.Nullable;
 import org.eclipse.jgit.api.errors.AbortedByHookException;
 import org.eclipse.jgit.errors.NotSupportedException;
 import org.eclipse.jgit.errors.TransportException;
@@ -774,6 +775,10 @@
 	private PrintStream hookOutRedirect;
 
 	private PrePushHook prePush;
+
+	@Nullable
+	TransferConfig.ProtocolVersion protocol;
+
 	/**
 	 * Create a new transport instance.
 	 *
@@ -789,6 +794,7 @@
 		final TransferConfig tc = local.getConfig().get(TransferConfig.KEY);
 		this.local = local;
 		this.uri = uri;
+		this.protocol = tc.protocolVersion;
 		this.objectChecker = tc.newObjectChecker();
 		this.credentialsProvider = CredentialsProvider.getDefault();
 		prePush = Hooks.prePush(local, hookOutRedirect);
@@ -1453,6 +1459,43 @@
 			TransportException;
 
 	/**
+	 * Begins a new connection for fetching from the remote repository.
+	 * <p>
+	 * If the transport has no local repository, the fetch connection can only
+	 * be used for reading remote refs.
+	 * </p>
+	 * <p>
+	 * If the server supports git protocol V2, the {@link RefSpec}s and the
+	 * additional patterns, if any, are used to restrict the server's ref
+	 * advertisement to matching refs only.
+	 * </p>
+	 * <p>
+	 * Transports that want to support git protocol V2 <em>must</em> override
+	 * this; the default implementation ignores its arguments and calls
+	 * {@link #openFetch()}.
+	 * </p>
+	 *
+	 * @param refSpecs
+	 *            that will be fetched via
+	 *            {@link FetchConnection#fetch(ProgressMonitor, Collection, java.util.Set, OutputStream)} later
+	 * @param additionalPatterns
+	 *            that will be set as ref prefixes if the server supports git
+	 *            protocol V2; {@code null} values are ignored
+	 *
+	 * @return a fresh connection to fetch from the remote repository.
+	 * @throws org.eclipse.jgit.errors.NotSupportedException
+	 *             the implementation does not support fetching.
+	 * @throws org.eclipse.jgit.errors.TransportException
+	 *             the remote connection could not be established.
+	 * @since 5.11
+	 */
+	public FetchConnection openFetch(Collection<RefSpec> refSpecs,
+			String... additionalPatterns)
+			throws NotSupportedException, TransportException {
+		return openFetch();
+	}
+
+	/**
 	 * Begins a new connection for pushing into the remote repository.
 	 *
 	 * @return a fresh connection to push into the remote repository.
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportGitAnon.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportGitAnon.java
index 820ec1a..fa4392d 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportGitAnon.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportGitAnon.java
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>
  * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
- * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org> and others
+ * Copyright (C) 2008, 2020 Shawn O. Pearce <spearce@spearce.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
@@ -22,6 +22,7 @@
 import java.net.InetSocketAddress;
 import java.net.Socket;
 import java.net.UnknownHostException;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.EnumSet;
 import java.util.Set;
@@ -94,6 +95,13 @@
 		return new TcpFetchConnection();
 	}
 
+	@Override
+	public FetchConnection openFetch(Collection<RefSpec> refSpecs,
+			String... additionalPatterns)
+			throws NotSupportedException, TransportException {
+		return new TcpFetchConnection(refSpecs, additionalPatterns);
+	}
+
 	/** {@inheritDoc} */
 	@Override
 	public PushConnection openPush() throws TransportException {
@@ -130,7 +138,8 @@
 		return s;
 	}
 
-	void service(String name, PacketLineOut pckOut)
+	void service(String name, PacketLineOut pckOut,
+			TransferConfig.ProtocolVersion gitProtocol)
 			throws IOException {
 		final StringBuilder cmd = new StringBuilder();
 		cmd.append(name);
@@ -144,6 +153,11 @@
 			cmd.append(uri.getPort());
 		}
 		cmd.append('\0');
+		if (TransferConfig.ProtocolVersion.V2.equals(gitProtocol)) {
+			cmd.append('\0');
+			cmd.append(GitProtocolConstants.VERSION_2_REQUEST);
+			cmd.append('\0');
+		}
 		pckOut.writeString(cmd.toString());
 		pckOut.flush();
 	}
@@ -152,6 +166,11 @@
 		private Socket sock;
 
 		TcpFetchConnection() throws TransportException {
+			this(Collections.emptyList());
+		}
+
+		TcpFetchConnection(Collection<RefSpec> refSpecs,
+				String... additionalPatterns) throws TransportException {
 			super(TransportGitAnon.this);
 			sock = openConnection();
 			try {
@@ -162,13 +181,19 @@
 				sOut = new BufferedOutputStream(sOut);
 
 				init(sIn, sOut);
-				service("git-upload-pack", pckOut); //$NON-NLS-1$
+				TransferConfig.ProtocolVersion gitProtocol = protocol;
+				if (gitProtocol == null) {
+					gitProtocol = TransferConfig.ProtocolVersion.V2;
+				}
+				service("git-upload-pack", pckOut, gitProtocol); //$NON-NLS-1$
 			} catch (IOException err) {
 				close();
 				throw new TransportException(uri,
 						JGitText.get().remoteHungUpUnexpectedly, err);
 			}
-			readAdvertisedRefs();
+			if (!readAdvertisedRefs()) {
+				lsRefs(refSpecs, additionalPatterns);
+			}
 		}
 
 		@Override
@@ -201,7 +226,7 @@
 				sOut = new BufferedOutputStream(sOut);
 
 				init(sIn, sOut);
-				service("git-receive-pack", pckOut); //$NON-NLS-1$
+				service("git-receive-pack", pckOut, null); //$NON-NLS-1$
 			} catch (IOException err) {
 				close();
 				throw new TransportException(uri,
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 b9cb248..19ed4fb 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportGitSsh.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportGitSsh.java
@@ -1,8 +1,8 @@
 /*
- * Copyright (C) 2008-2010, Google Inc.
+ * Copyright (C) 2008, 2010 Google Inc.
  * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>
  * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
- * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org> and others
+ * Copyright (C) 2008, 2020 Shawn O. Pearce <spearce@spearce.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
@@ -19,11 +19,13 @@
 import java.text.MessageFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.EnumSet;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Locale;
+import java.util.Map;
 import java.util.Set;
 
 import org.eclipse.jgit.errors.NoRemoteRepositoryException;
@@ -144,6 +146,13 @@
 		return new SshFetchConnection();
 	}
 
+	@Override
+	public FetchConnection openFetch(Collection<RefSpec> refSpecs,
+			String... additionalPatterns)
+			throws NotSupportedException, TransportException {
+		return new SshFetchConnection(refSpecs, additionalPatterns);
+	}
+
 	/** {@inheritDoc} */
 	@Override
 	public PushConnection openPush() throws TransportException {
@@ -196,29 +205,38 @@
 		return SystemReader.getInstance().getenv("GIT_SSH") != null; //$NON-NLS-1$
 	}
 
-	private class ExtSession implements RemoteSession {
+	private class ExtSession implements RemoteSession2 {
+
 		@Override
 		public Process exec(String command, int timeout)
 				throws TransportException {
+			return exec(command, null, timeout);
+		}
+
+		@Override
+		public Process exec(String command, Map<String, String> environment,
+				int timeout) throws TransportException {
 			String ssh = SystemReader.getInstance().getenv("GIT_SSH"); //$NON-NLS-1$
 			boolean putty = ssh.toLowerCase(Locale.ROOT).contains("plink"); //$NON-NLS-1$
 
 			List<String> args = new ArrayList<>();
 			args.add(ssh);
-			if (putty
-					&& !ssh.toLowerCase(Locale.ROOT).contains("tortoiseplink")) //$NON-NLS-1$
+			if (putty && !ssh.toLowerCase(Locale.ROOT)
+					.contains("tortoiseplink")) {//$NON-NLS-1$
 				args.add("-batch"); //$NON-NLS-1$
+			}
 			if (0 < getURI().getPort()) {
 				args.add(putty ? "-P" : "-p"); //$NON-NLS-1$ //$NON-NLS-2$
 				args.add(String.valueOf(getURI().getPort()));
 			}
-			if (getURI().getUser() != null)
+			if (getURI().getUser() != null) {
 				args.add(getURI().getUser() + "@" + getURI().getHost()); //$NON-NLS-1$
-			else
+			} else {
 				args.add(getURI().getHost());
+			}
 			args.add(command);
 
-			ProcessBuilder pb = createProcess(args);
+			ProcessBuilder pb = createProcess(args, environment);
 			try {
 				return pb.start();
 			} catch (IOException err) {
@@ -226,9 +244,13 @@
 			}
 		}
 
-		private ProcessBuilder createProcess(List<String> args) {
+		private ProcessBuilder createProcess(List<String> args,
+				Map<String, String> environment) {
 			ProcessBuilder pb = new ProcessBuilder();
 			pb.command(args);
+			if (environment != null) {
+				pb.environment().putAll(environment);
+			}
 			File directory = local != null ? local.getDirectory() : null;
 			if (directory != null) {
 				pb.environment().put(Constants.GIT_DIR_KEY,
@@ -249,10 +271,31 @@
 		private StreamCopyThread errorThread;
 
 		SshFetchConnection() throws TransportException {
+			this(Collections.emptyList());
+		}
+
+		SshFetchConnection(Collection<RefSpec> refSpecs,
+				String... additionalPatterns) throws TransportException {
 			super(TransportGitSsh.this);
 			try {
-				process = getSession().exec(commandFor(getOptionUploadPack()),
-						getTimeout());
+				RemoteSession session = getSession();
+				TransferConfig.ProtocolVersion gitProtocol = protocol;
+				if (gitProtocol == null) {
+					gitProtocol = TransferConfig.ProtocolVersion.V2;
+				}
+				if (session instanceof RemoteSession2
+						&& TransferConfig.ProtocolVersion.V2
+								.equals(gitProtocol)) {
+					process = ((RemoteSession2) session).exec(
+							commandFor(getOptionUploadPack()), Collections
+									.singletonMap(
+											GitProtocolConstants.PROTOCOL_ENVIRONMENT_VARIABLE,
+											GitProtocolConstants.VERSION_2_REQUEST),
+							getTimeout());
+				} else {
+					process = session.exec(commandFor(getOptionUploadPack()),
+							getTimeout());
+				}
 				final MessageWriter msg = new MessageWriter();
 				setMessageWriter(msg);
 
@@ -272,7 +315,9 @@
 			}
 
 			try {
-				readAdvertisedRefs();
+				if (!readAdvertisedRefs()) {
+					lsRefs(refSpecs, additionalPatterns);
+				}
 			} catch (NoRemoteRepositoryException notFound) {
 				final String msgs = getMessages();
 				checkExecFailure(process.exitValue(), getOptionUploadPack(),
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java
index 6768387..2e5d18d 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java
@@ -1,8 +1,8 @@
 /*
- * Copyright (C) 2008-2010, Google Inc.
+ * Copyright (C) 2008, 2010 Google Inc.
  * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
  * Copyright (C) 2013, Matthias Sohn <matthias.sohn@sap.com>
- * Copyright (C) 2017, Thomas Wolf <thomas.wolf@paranor.ch> and others
+ * Copyright (C) 2017, 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
@@ -33,14 +33,15 @@
 import static org.eclipse.jgit.util.HttpSupport.METHOD_GET;
 import static org.eclipse.jgit.util.HttpSupport.METHOD_POST;
 
+import java.io.BufferedInputStream;
 import java.io.BufferedReader;
-import java.io.ByteArrayInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.InterruptedIOException;
 import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
 import java.net.HttpCookie;
 import java.net.MalformedURLException;
 import java.net.Proxy;
@@ -49,10 +50,12 @@
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.net.URL;
+import java.net.URLDecoder;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.InvalidPathException;
 import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.security.GeneralSecurityException;
 import java.security.cert.CertPathBuilderException;
 import java.security.cert.CertPathValidatorException;
 import java.security.cert.CertificateException;
@@ -75,6 +78,7 @@
 
 import javax.net.ssl.SSLHandshakeException;
 
+import org.eclipse.jgit.annotations.NonNull;
 import org.eclipse.jgit.errors.ConfigInvalidException;
 import org.eclipse.jgit.errors.NoRemoteRepositoryException;
 import org.eclipse.jgit.errors.NotSupportedException;
@@ -95,6 +99,8 @@
 import org.eclipse.jgit.transport.HttpAuthMethod.Type;
 import org.eclipse.jgit.transport.HttpConfig.HttpRedirectMode;
 import org.eclipse.jgit.transport.http.HttpConnection;
+import org.eclipse.jgit.transport.http.HttpConnectionFactory;
+import org.eclipse.jgit.transport.http.HttpConnectionFactory2;
 import org.eclipse.jgit.util.HttpSupport;
 import org.eclipse.jgit.util.IO;
 import org.eclipse.jgit.util.RawParseUtils;
@@ -132,6 +138,9 @@
 
 	private static final String SVC_RECEIVE_PACK = "git-receive-pack"; //$NON-NLS-1$
 
+	private static final byte[] VERSION = "version" //$NON-NLS-1$
+			.getBytes(StandardCharsets.US_ASCII);
+
 	/**
 	 * Accept-Encoding header in the HTTP request
 	 * (https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html).
@@ -257,6 +266,12 @@
 
 	private boolean sslFailure = false;
 
+	private HttpConnectionFactory factory;
+
+	private HttpConnectionFactory2.GitSession gitSession;
+
+	private boolean factoryUsed;
+
 	/**
 	 * All stored cookies bound to this repo (independent of the baseUrl)
 	 */
@@ -279,6 +294,7 @@
 		sslVerify = http.isSslVerify();
 		cookieFile = getCookieFileFromConfig(http);
 		relevantCookies = filterCookies(cookieFile, baseUrl);
+		factory = HttpTransport.getConnectionFactory();
 	}
 
 	private URL toURL(URIish urish) throws MalformedURLException {
@@ -321,6 +337,7 @@
 		sslVerify = http.isSslVerify();
 		cookieFile = getCookieFileFromConfig(http);
 		relevantCookies = filterCookies(cookieFile, baseUrl);
+		factory = HttpTransport.getConnectionFactory();
 	}
 
 	/**
@@ -339,11 +356,15 @@
 
 	@SuppressWarnings("resource") // Closed by caller
 	private FetchConnection getConnection(HttpConnection c, InputStream in,
-			String service) throws IOException {
+			String service, Collection<RefSpec> refSpecs,
+			String... additionalPatterns) throws IOException {
 		BaseConnection f;
 		if (isSmartHttp(c, service)) {
-			readSmartHeaders(in, service);
-			f = new SmartHttpFetchConnection(in);
+			InputStream withMark = in.markSupported() ? in
+					: new BufferedInputStream(in);
+			readSmartHeaders(withMark, service);
+			f = new SmartHttpFetchConnection(withMark, refSpecs,
+					additionalPatterns);
 		} else {
 			// Assume this server doesn't support smart HTTP fetch
 			// and fall back on dumb object walking.
@@ -353,15 +374,98 @@
 		return (FetchConnection) f;
 	}
 
+	/**
+	 * Sets the {@link HttpConnectionFactory} to be used by this
+	 * {@link TransportHttp} instance.
+	 * <p>
+	 * If no factory is set explicitly, the {@link TransportHttp} instance uses
+	 * the {@link HttpTransport#getConnectionFactory() globally defined
+	 * factory}.
+	 * </p>
+	 *
+	 * @param customFactory
+	 *            the {@link HttpConnectionFactory} to use
+	 * @throws IllegalStateException
+	 *             if an HTTP/HTTPS connection has already been opened on this
+	 *             {@link TransportHttp} instance
+	 * @since 5.11
+	 */
+	public void setHttpConnectionFactory(
+			@NonNull HttpConnectionFactory customFactory) {
+		if (factoryUsed) {
+			throw new IllegalStateException(JGitText.get().httpFactoryInUse);
+		}
+		factory = customFactory;
+	}
+
+	/**
+	 * Retrieves the {@link HttpConnectionFactory} used by this
+	 * {@link TransportHttp} instance.
+	 *
+	 * @return the {@link HttpConnectionFactory}
+	 * @since 5.11
+	 */
+	@NonNull
+	public HttpConnectionFactory getHttpConnectionFactory() {
+		return factory;
+	}
+
+	/**
+	 * Sets preemptive Basic HTTP authentication. If the given {@code username}
+	 * or {@code password} is empty or {@code null}, no preemptive
+	 * authentication will be done. If {@code username} and {@code password} are
+	 * set, they will override authority information from the URI
+	 * ("user:password@").
+	 * <p>
+	 * If the connection encounters redirects, the pre-authentication will be
+	 * cleared if the redirect goes to a different host.
+	 * </p>
+	 *
+	 * @param username
+	 *            to use
+	 * @param password
+	 *            to use
+	 * @throws IllegalStateException
+	 *             if an HTTP/HTTPS connection has already been opened on this
+	 *             {@link TransportHttp} instance
+	 * @since 5.11
+	 */
+	public void setPreemptiveBasicAuthentication(String username,
+			String password) {
+		if (factoryUsed) {
+			throw new IllegalStateException(JGitText.get().httpPreAuthTooLate);
+		}
+		if (StringUtils.isEmptyOrNull(username)
+				|| StringUtils.isEmptyOrNull(password)) {
+			authMethod = authFromUri(currentUri);
+		} else {
+			HttpAuthMethod basic = HttpAuthMethod.Type.BASIC.method(null);
+			basic.authorize(username, password);
+			authMethod = basic;
+		}
+	}
+
 	/** {@inheritDoc} */
 	@Override
 	public FetchConnection openFetch() throws TransportException,
 			NotSupportedException {
+		return openFetch(Collections.emptyList());
+	}
+
+	@Override
+	public FetchConnection openFetch(Collection<RefSpec> refSpecs,
+			String... additionalPatterns)
+			throws NotSupportedException, TransportException {
 		final String service = SVC_UPLOAD_PACK;
 		try {
-			final HttpConnection c = connect(service);
+			TransferConfig.ProtocolVersion gitProtocol = protocol;
+			if (gitProtocol == null) {
+				gitProtocol = TransferConfig.ProtocolVersion.V2;
+			}
+			HttpConnection c = connect(service, gitProtocol);
 			try (InputStream in = openInputStream(c)) {
-				return getConnection(c, in, service);
+				return getConnection(c, in, service, refSpecs,
+						additionalPatterns);
 			}
 		} catch (NotSupportedException | TransportException err) {
 			throw err;
@@ -456,8 +560,9 @@
 
 	private PushConnection smartPush(String service, HttpConnection c,
 			InputStream in) throws IOException, TransportException {
-		readSmartHeaders(in, service);
-		SmartHttpPushConnection p = new SmartHttpPushConnection(in);
+		BufferedInputStream inBuf = new BufferedInputStream(in);
+		readSmartHeaders(inBuf, service);
+		SmartHttpPushConnection p = new SmartHttpPushConnection(inBuf);
 		p.setPeerUserAgent(c.getHeaderField(HttpSupport.HDR_SERVER));
 		return p;
 	}
@@ -465,7 +570,10 @@
 	/** {@inheritDoc} */
 	@Override
 	public void close() {
-		// No explicit connections are maintained.
+		if (gitSession != null) {
+			gitSession.close();
+			gitSession = null;
+		}
 	}
 
 	/**
@@ -492,9 +600,40 @@
 		return new NoRemoteRepositoryException(u, text);
 	}
 
+	private HttpAuthMethod authFromUri(URIish u) {
+		String user = u.getUser();
+		String pass = u.getPass();
+		if (user != null && pass != null) {
+			try {
+				// User/password are _not_ application/x-www-form-urlencoded. In
+				// particular the "+" sign would be replaced by a space.
+				user = URLDecoder.decode(user.replace("+", "%2B"), //$NON-NLS-1$ //$NON-NLS-2$
+						StandardCharsets.UTF_8.name());
+				pass = URLDecoder.decode(pass.replace("+", "%2B"), //$NON-NLS-1$ //$NON-NLS-2$
+						StandardCharsets.UTF_8.name());
+				HttpAuthMethod basic = HttpAuthMethod.Type.BASIC.method(null);
+				basic.authorize(user, pass);
+				return basic;
+			} catch (IllegalArgumentException
+					| UnsupportedEncodingException e) {
+				LOG.warn(JGitText.get().httpUserInfoDecodeError, u);
+			}
+		}
+		return HttpAuthMethod.Type.NONE.method(null);
+	}
+
 	private HttpConnection connect(String service)
 			throws TransportException, NotSupportedException {
+		return connect(service, null);
+	}
+
+	private HttpConnection connect(String service,
+			TransferConfig.ProtocolVersion protocolVersion)
+			throws TransportException, NotSupportedException {
 		URL u = getServiceURL(service);
+		if (HttpAuthMethod.Type.NONE.equals(authMethod.getType())) {
+			authMethod = authFromUri(currentUri);
+		}
 		int authAttempts = 1;
 		int redirects = 0;
 		Collection<Type> ignoreTypes = null;
@@ -507,6 +646,11 @@
 				} else {
 					conn.setRequestProperty(HDR_ACCEPT, "*/*"); //$NON-NLS-1$
 				}
+				if (TransferConfig.ProtocolVersion.V2.equals(protocolVersion)) {
+					conn.setRequestProperty(
+							GitProtocolConstants.PROTOCOL_HEADER,
+							GitProtocolConstants.VERSION_2_REQUEST);
+				}
 				final int status = HttpSupport.response(conn);
 				processResponseCookies(conn);
 				switch (status) {
@@ -796,7 +940,13 @@
 		}
 		try {
 			URI redirectTo = new URI(location);
+			// Reset authentication if the redirect has user/password info or
+			// if the host is different.
+			boolean resetAuth = !StringUtils
+					.isEmptyOrNull(redirectTo.getUserInfo());
+			String currentHost = currentUrl.getHost();
 			redirectTo = currentUrl.toURI().resolve(redirectTo);
+			resetAuth = resetAuth || !currentHost.equals(redirectTo.getHost());
 			String redirected = redirectTo.toASCIIString();
 			if (!isValidRedirect(baseUrl, redirected, checkFor)) {
 				throw new TransportException(uri,
@@ -805,6 +955,9 @@
 			}
 			redirected = redirected.substring(0, redirected.indexOf(checkFor));
 			URIish result = new URIish(redirected);
+			if (resetAuth) {
+				authMethod = HttpAuthMethod.Type.NONE.method(null);
+			}
 			if (LOG.isInfoEnabled()) {
 				LOG.info(MessageFormat.format(JGitText.get().redirectHttp,
 						uri.setPass(null),
@@ -885,9 +1038,20 @@
 		}
 
 		final Proxy proxy = HttpSupport.proxyFor(proxySelector, u);
-		HttpConnection conn = connectionFactory.create(u, proxy);
+		factoryUsed = true;
+		HttpConnection conn = factory.create(u, proxy);
 
-		if (!sslVerify && "https".equals(u.getProtocol())) { //$NON-NLS-1$
+		if (gitSession == null && (factory instanceof HttpConnectionFactory2)) {
+			gitSession = ((HttpConnectionFactory2) factory).newSession();
+		}
+		if (gitSession != null) {
+			try {
+				gitSession.configure(conn, sslVerify);
+			} catch (GeneralSecurityException e) {
+				throw new IOException(e.getMessage(), e);
+			}
+		} else if (!sslVerify && "https".equals(u.getProtocol())) { //$NON-NLS-1$
+			// Backwards compatibility
 			HttpSupport.disableSslVerify(conn);
 		}
 
@@ -1148,20 +1312,37 @@
 
 	private void readSmartHeaders(InputStream in, String service)
 			throws IOException {
-		// A smart reply will have a '#' after the first 4 bytes, but
-		// a dumb reply cannot contain a '#' until after byte 41. Do a
+		// A smart protocol V0 reply will have a '#' after the first 4 bytes,
+		// but a dumb reply cannot contain a '#' until after byte 41. Do a
 		// quick check to make sure its a smart reply before we parse
 		// as a pkt-line stream.
 		//
-		final byte[] magic = new byte[5];
+		// There appears to be a confusion about this in protocol V2. Github
+		// sends the # service line as a git (not http) header also when
+		// protocol V2 is used. Gitlab also does so. JGit's UploadPack doesn't,
+		// and thus Gerrit also does not.
+		final byte[] magic = new byte[14];
+		if (!in.markSupported()) {
+			throw new TransportException(uri,
+					JGitText.get().inputStreamMustSupportMark);
+		}
+		in.mark(14);
 		IO.readFully(in, magic, 0, magic.length);
+		// Did we get 000dversion 2 or similar? (Canonical is 000eversion 2\n,
+		// but JGit and thus Gerrit omits the \n.)
+		if (Arrays.equals(Arrays.copyOfRange(magic, 4, 11), VERSION)
+				&& magic[12] >= '1' && magic[12] <= '9') {
+			// It's a smart server doing version 1 or greater, but not sending
+			// the # service line header. Don't consume the version line.
+			in.reset();
+			return;
+		}
 		if (magic[4] != '#') {
 			throw new TransportException(uri, MessageFormat.format(
 					JGitText.get().expectedPktLineWithService, RawParseUtils.decode(magic)));
 		}
-
-		final PacketLineIn pckIn = new PacketLineIn(new UnionInputStream(
-				new ByteArrayInputStream(magic), in));
+		in.reset();
+		final PacketLineIn pckIn = new PacketLineIn(in);
 		final String exp = "# service=" + service; //$NON-NLS-1$
 		final String act = pckIn.readString();
 		if (!exp.equals(act)) {
@@ -1327,12 +1508,24 @@
 
 		SmartHttpFetchConnection(InputStream advertisement)
 				throws TransportException {
+			this(advertisement, Collections.emptyList());
+		}
+
+		SmartHttpFetchConnection(InputStream advertisement,
+				Collection<RefSpec> refSpecs, String... additionalPatterns)
+				throws TransportException {
 			super(TransportHttp.this);
 			statelessRPC = true;
 
 			init(advertisement, DisabledOutputStream.INSTANCE);
 			outNeedsEnd = false;
-			readAdvertisedRefs();
+			if (!readAdvertisedRefs()) {
+				// Must be protocol V2
+				LongPollService service = new LongPollService(SVC_UPLOAD_PACK,
+						getProtocolVersion());
+				init(service.getInputStream(), service.getOutputStream());
+				lsRefs(refSpecs, additionalPatterns);
+			}
 		}
 
 		@Override
@@ -1340,7 +1533,8 @@
 				final Collection<Ref> want, final Set<ObjectId> have,
 				final OutputStream outputStream) throws TransportException {
 			try {
-				svc = new MultiRequestService(SVC_UPLOAD_PACK);
+				svc = new MultiRequestService(SVC_UPLOAD_PACK,
+						getProtocolVersion());
 				init(svc.getInputStream(), svc.getOutputStream());
 				super.doFetch(monitor, want, have, outputStream);
 			} finally {
@@ -1369,7 +1563,8 @@
 		protected void doPush(final ProgressMonitor monitor,
 				final Map<String, RemoteRefUpdate> refUpdates,
 				OutputStream outputStream) throws TransportException {
-			final Service svc = new MultiRequestService(SVC_RECEIVE_PACK);
+			final Service svc = new MultiRequestService(SVC_RECEIVE_PACK,
+					getProtocolVersion());
 			init(svc.getInputStream(), svc.getOutputStream());
 			super.doPush(monitor, refUpdates, outputStream);
 		}
@@ -1389,10 +1584,14 @@
 
 		protected final HttpExecuteStream execute;
 
+		protected final TransferConfig.ProtocolVersion protocolVersion;
+
 		final UnionInputStream in;
 
-		Service(String serviceName) {
+		Service(String serviceName,
+				TransferConfig.ProtocolVersion protocolVersion) {
 			this.serviceName = serviceName;
+			this.protocolVersion = protocolVersion;
 			this.requestType = "application/x-" + serviceName + "-request"; //$NON-NLS-1$ //$NON-NLS-2$
 			this.responseType = "application/x-" + serviceName + "-result"; //$NON-NLS-1$ //$NON-NLS-2$
 
@@ -1408,6 +1607,10 @@
 			conn.setDoOutput(true);
 			conn.setRequestProperty(HDR_CONTENT_TYPE, requestType);
 			conn.setRequestProperty(HDR_ACCEPT, responseType);
+			if (TransferConfig.ProtocolVersion.V2.equals(protocolVersion)) {
+				conn.setRequestProperty(GitProtocolConstants.PROTOCOL_HEADER,
+						GitProtocolConstants.VERSION_2_REQUEST);
+			}
 		}
 
 		void sendRequest() throws IOException {
@@ -1663,8 +1866,9 @@
 	class MultiRequestService extends Service {
 		boolean finalRequest;
 
-		MultiRequestService(String serviceName) {
-			super(serviceName);
+		MultiRequestService(String serviceName,
+				TransferConfig.ProtocolVersion protocolVersion) {
+			super(serviceName, protocolVersion);
 		}
 
 		/** Keep opening send-receive pairs to the given URI. */
@@ -1701,11 +1905,10 @@
 
 	/** Service for maintaining a single long-poll connection. */
 	class LongPollService extends Service {
-		/**
-		 * @param serviceName
-		 */
-		LongPollService(String serviceName) {
-			super(serviceName);
+
+		LongPollService(String serviceName,
+				TransferConfig.ProtocolVersion protocolVersion) {
+			super(serviceName, protocolVersion);
 		}
 
 		/** Only open one send-receive request. */
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 403f98d..77d1419 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportLocal.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportLocal.java
@@ -1,9 +1,9 @@
 /*
  * Copyright (C) 2007, Dave Watson <dwatson@mimvista.com>
- * Copyright (C) 2008-2010, Google Inc.
+ * Copyright (C) 2008, 2010 Google Inc.
  * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>
  * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
- * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org> and others
+ * Copyright (C) 2008, 2020 Shawn O. Pearce <spearce@spearce.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
@@ -20,6 +20,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.Map;
 import java.util.Set;
@@ -153,11 +154,17 @@
 	/** {@inheritDoc} */
 	@Override
 	public FetchConnection openFetch() throws TransportException {
+		return openFetch(Collections.emptyList());
+	}
+
+	@Override
+	public FetchConnection openFetch(Collection<RefSpec> refSpecs,
+			String... additionalPatterns) throws TransportException {
 		final String up = getOptionUploadPack();
 		if (!"git-upload-pack".equals(up) //$NON-NLS-1$
-				&& !"git upload-pack".equals(up)) //$NON-NLS-1$
-			return new ForkLocalFetchConnection();
-
+				&& !"git upload-pack".equals(up)) {//$NON-NLS-1$
+			return new ForkLocalFetchConnection(refSpecs, additionalPatterns);
+		}
 		UploadPackFactory<Void> upf = (Void req,
 				Repository db) -> createUploadPack(db);
 		return new InternalFetchConnection<>(this, upf, null, openRepo());
@@ -193,6 +200,23 @@
 	 */
 	protected Process spawn(String cmd)
 			throws TransportException {
+		return spawn(cmd, null);
+	}
+
+	/**
+	 * Spawn process
+	 *
+	 * @param cmd
+	 *            command
+	 * @param protocolVersion
+	 *            to use
+	 * @return a {@link java.lang.Process} object.
+	 * @throws org.eclipse.jgit.errors.TransportException
+	 *             if any.
+	 */
+	private Process spawn(String cmd,
+			TransferConfig.ProtocolVersion protocolVersion)
+			throws TransportException {
 		try {
 			String[] args = { "." }; //$NON-NLS-1$
 			ProcessBuilder proc = local.getFS().runInShell(cmd, args);
@@ -208,7 +232,10 @@
 			env.remove("GIT_GRAFT_FILE"); //$NON-NLS-1$
 			env.remove("GIT_INDEX_FILE"); //$NON-NLS-1$
 			env.remove("GIT_NO_REPLACE_OBJECTS"); //$NON-NLS-1$
-
+			if (TransferConfig.ProtocolVersion.V2.equals(protocolVersion)) {
+				env.put(GitProtocolConstants.PROTOCOL_ENVIRONMENT_VARIABLE,
+						GitProtocolConstants.VERSION_2_REQUEST);
+			}
 			return proc.start();
 		} catch (IOException err) {
 			throw new TransportException(uri, err.getMessage(), err);
@@ -221,12 +248,21 @@
 		private Thread errorReaderThread;
 
 		ForkLocalFetchConnection() throws TransportException {
+			this(Collections.emptyList());
+		}
+
+		ForkLocalFetchConnection(Collection<RefSpec> refSpecs,
+				String... additionalPatterns) throws TransportException {
 			super(TransportLocal.this);
 
 			final MessageWriter msg = new MessageWriter();
 			setMessageWriter(msg);
 
-			uploadPack = spawn(getOptionUploadPack());
+			TransferConfig.ProtocolVersion gitProtocol = protocol;
+			if (gitProtocol == null) {
+				gitProtocol = TransferConfig.ProtocolVersion.V2;
+			}
+			uploadPack = spawn(getOptionUploadPack(), gitProtocol);
 
 			final InputStream upErr = uploadPack.getErrorStream();
 			errorReaderThread = new StreamCopyThread(upErr, msg.getRawStream());
@@ -239,7 +275,9 @@
 			upOut = new BufferedOutputStream(upOut);
 
 			init(upIn, upOut);
-			readAdvertisedRefs();
+			if (!readAdvertisedRefs()) {
+				lsRefs(refSpecs, additionalPatterns);
+			}
 		}
 
 		@Override
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 1242ef1..e0b86f5 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008-2010, Google Inc. and others
+ * Copyright (C) 2008, 2020 Google Inc. 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
@@ -33,6 +33,7 @@
 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_THIN_PACK;
+import static org.eclipse.jgit.transport.GitProtocolConstants.VERSION_2_REQUEST;
 import static org.eclipse.jgit.util.RefMap.toRefMap;
 
 import java.io.ByteArrayOutputStream;
@@ -709,7 +710,7 @@
 	 * @since 5.0
 	 */
 	public void setExtraParameters(Collection<String> params) {
-		this.clientRequestedV2 = params.contains("version=2"); //$NON-NLS-1$
+		this.clientRequestedV2 = params.contains(VERSION_2_REQUEST);
 	}
 
 	/**
@@ -722,7 +723,8 @@
 	}
 
 	private boolean useProtocolV2() {
-		return ProtocolVersion.V2.equals(transferConfig.protocolVersion)
+		return (transferConfig.protocolVersion == null
+			|| ProtocolVersion.V2.equals(transferConfig.protocolVersion))
 				&& clientRequestedV2;
 	}
 
@@ -1191,17 +1193,18 @@
 
 		if (req.wasDoneReceived()) {
 			processHaveLines(req.getPeerHas(), ObjectId.zeroId(),
-					new PacketLineOut(NullOutputStream.INSTANCE),
+					new PacketLineOut(NullOutputStream.INSTANCE, false),
 					accumulator);
 		} else {
-			pckOut.writeString("acknowledgments\n"); //$NON-NLS-1$
+			pckOut.writeString(
+					GitProtocolConstants.SECTION_ACKNOWLEDGMENTS + '\n');
 			for (ObjectId id : req.getPeerHas()) {
 				if (walk.getObjectReader().has(id)) {
 					pckOut.writeString("ACK " + id.getName() + "\n"); //$NON-NLS-1$ //$NON-NLS-2$
 				}
 			}
 			processHaveLines(req.getPeerHas(), ObjectId.zeroId(),
-					new PacketLineOut(NullOutputStream.INSTANCE),
+					new PacketLineOut(NullOutputStream.INSTANCE, false),
 					accumulator);
 			if (okToGiveUp()) {
 				pckOut.writeString("ready\n"); //$NON-NLS-1$
@@ -1243,7 +1246,8 @@
 			if (!pckOut.isUsingSideband()) {
 				// sendPack will write "packfile\n" for us if sideband-all is used.
 				// But sideband-all is not used, so we have to write it ourselves.
-				pckOut.writeString("packfile\n"); //$NON-NLS-1$
+				pckOut.writeString(
+						GitProtocolConstants.SECTION_PACKFILE + '\n');
 			}
 
 			accumulator.timeNegotiating = Duration
@@ -2327,7 +2331,8 @@
 					// for us if provided a PackfileUriConfig. In this case, we
 					// are not providing a PackfileUriConfig, so we have to
 					// write this line ourselves.
-					pckOut.writeString("packfile\n"); //$NON-NLS-1$
+					pckOut.writeString(
+							GitProtocolConstants.SECTION_PACKFILE + '\n');
 				}
 			}
 			pw.writePack(pm, NullProgressMonitor.INSTANCE, packOut);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/http/HttpConnectionFactory2.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/http/HttpConnectionFactory2.java
new file mode 100644
index 0000000..88abc60
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/http/HttpConnectionFactory2.java
@@ -0,0 +1,66 @@
+/*
+ * 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.transport.http;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+
+import org.eclipse.jgit.annotations.NonNull;
+
+/**
+ * A {@link HttpConnectionFactory} that supports client-side sessions that can
+ * maintain state and configure connections.
+ *
+ * @since 5.11
+ */
+public interface HttpConnectionFactory2 extends HttpConnectionFactory {
+
+	/**
+	 * Creates a new {@link GitSession} instance that can be used with
+	 * connections created by this {@link HttpConnectionFactory} instance.
+	 *
+	 * @return a new {@link GitSession}
+	 */
+	@NonNull
+	GitSession newSession();
+
+	/**
+	 * A {@code GitSession} groups the multiple HTTP connections
+	 * {@link org.eclipse.jgit.transport.TransportHttp TransportHttp} uses for
+	 * the requests it makes during a git fetch or push. A {@code GitSession}
+	 * can maintain client-side HTTPS state and can configure individual
+	 * connections.
+	 */
+	interface GitSession {
+
+		/**
+		 * Configure a just created {@link HttpConnection}.
+		 *
+		 * @param connection
+		 *            to configure; created by the same
+		 *            {@link HttpConnectionFactory} instance
+		 * @param sslVerify
+		 *            whether SSL is to be verified
+		 * @return the configured {@connection}
+		 * @throws IOException
+		 *             if the connection cannot be configured
+		 * @throws GeneralSecurityException
+		 *             if the connection cannot be configured
+		 */
+		@NonNull
+		HttpConnection configure(@NonNull HttpConnection connection,
+				boolean sslVerify) throws IOException, GeneralSecurityException;
+
+		/**
+		 * Closes the {@link GitSession}, releasing any internal state.
+		 */
+		void close();
+	}
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/http/JDKHttpConnectionFactory.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/http/JDKHttpConnectionFactory.java
index b39f157..1b5d1b3 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/http/JDKHttpConnectionFactory.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/http/JDKHttpConnectionFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Christian Halstrick <christian.halstrick@sap.com> and others
+ * Copyright (C) 2013, 2020 Christian Halstrick <christian.halstrick@sap.com> 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
@@ -12,6 +12,18 @@
 import java.io.IOException;
 import java.net.Proxy;
 import java.net.URL;
+import java.security.GeneralSecurityException;
+import java.text.MessageFormat;
+
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+
+import org.eclipse.jgit.internal.JGitText;
+import org.eclipse.jgit.internal.transport.http.DelegatingSSLSocketFactory;
+import org.eclipse.jgit.util.HttpSupport;
 
 /**
  * A factory returning instances of
@@ -19,17 +31,70 @@
  *
  * @since 3.3
  */
-public class JDKHttpConnectionFactory implements HttpConnectionFactory {
-	/** {@inheritDoc} */
+public class JDKHttpConnectionFactory implements HttpConnectionFactory2 {
+
 	@Override
 	public HttpConnection create(URL url) throws IOException {
 		return new JDKHttpConnection(url);
 	}
 
-	/** {@inheritDoc} */
 	@Override
 	public HttpConnection create(URL url, Proxy proxy)
 			throws IOException {
 		return new JDKHttpConnection(url, proxy);
 	}
+
+	@Override
+	public GitSession newSession() {
+		return new JdkConnectionSession();
+	}
+
+	private static class JdkConnectionSession implements GitSession {
+
+		private SSLContext securityContext;
+
+		private SSLSocketFactory socketFactory;
+
+		@Override
+		public JDKHttpConnection configure(HttpConnection connection,
+				boolean sslVerify) throws GeneralSecurityException {
+			if (!(connection instanceof JDKHttpConnection)) {
+				throw new IllegalArgumentException(MessageFormat.format(
+						JGitText.get().httpWrongConnectionType,
+						JDKHttpConnection.class.getName(),
+						connection.getClass().getName()));
+			}
+			JDKHttpConnection conn = (JDKHttpConnection) connection;
+			String scheme = conn.getURL().getProtocol();
+			if (!"https".equals(scheme) || sslVerify) { //$NON-NLS-1$
+				// sslVerify == true: use the JDK defaults
+				return conn;
+			}
+			if (securityContext == null) {
+				securityContext = SSLContext.getInstance("TLS"); //$NON-NLS-1$
+				TrustManager[] trustAllCerts = {
+						new NoCheckX509TrustManager() };
+				securityContext.init(null, trustAllCerts, null);
+				socketFactory = new DelegatingSSLSocketFactory(
+						securityContext.getSocketFactory()) {
+
+					@Override
+					protected void configure(SSLSocket socket) {
+						HttpSupport.configureTLS(socket);
+					}
+				};
+			}
+			conn.setHostnameVerifier((name, session) -> true);
+			((HttpsURLConnection) conn.wrappedUrlConnection)
+					.setSSLSocketFactory(socketFactory);
+			return conn;
+		}
+
+		@Override
+		public void close() {
+			securityContext = null;
+			socketFactory = null;
+		}
+	}
+
 }
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/http/NoCheckX509TrustManager.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/http/NoCheckX509TrustManager.java
new file mode 100644
index 0000000..5cd4fb4
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/http/NoCheckX509TrustManager.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2016, 2020 JGit contributors
+ *
+ * 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
+ *
+ * Contributors:
+ *    Saša Živkov 2016 - initial API
+ *    Thomas Wolf 2020 - extracted from HttpSupport
+ */
+package org.eclipse.jgit.transport.http;
+
+import java.security.cert.X509Certificate;
+
+import javax.net.ssl.X509TrustManager;
+
+/**
+ * A {@link X509TrustManager} that doesn't verify anything. Can be used for
+ * skipping SSL checks.
+ *
+ * @since 5.11
+ */
+public class NoCheckX509TrustManager implements X509TrustManager {
+
+	@Override
+	public X509Certificate[] getAcceptedIssuers() {
+		return null;
+	}
+
+	@Override
+	public void checkClientTrusted(X509Certificate[] certs,
+			String authType) {
+		// no check
+	}
+
+	@Override
+	public void checkServerTrusted(X509Certificate[] certs,
+			String authType) {
+		// no check
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/HttpSupport.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/HttpSupport.java
index 04b3eab..23a73fa 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/HttpSupport.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/HttpSupport.java
@@ -24,21 +24,18 @@
 import java.net.URLEncoder;
 import java.security.KeyManagementException;
 import java.security.NoSuchAlgorithmException;
-import java.security.cert.X509Certificate;
 import java.text.MessageFormat;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.LinkedHashSet;
 import java.util.Set;
 
-import javax.net.ssl.HostnameVerifier;
-import javax.net.ssl.SSLSession;
 import javax.net.ssl.SSLSocket;
 import javax.net.ssl.TrustManager;
-import javax.net.ssl.X509TrustManager;
 
 import org.eclipse.jgit.internal.JGitText;
 import org.eclipse.jgit.transport.http.HttpConnection;
+import org.eclipse.jgit.transport.http.NoCheckX509TrustManager;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -301,40 +298,13 @@
 	 */
 	public static void disableSslVerify(HttpConnection conn)
 			throws IOException {
-		final TrustManager[] trustAllCerts = new TrustManager[] {
-				new DummyX509TrustManager() };
+		TrustManager[] trustAllCerts = {
+				new NoCheckX509TrustManager() };
 		try {
 			conn.configure(null, trustAllCerts, null);
-			conn.setHostnameVerifier(new DummyHostnameVerifier());
+			conn.setHostnameVerifier((name, session) -> true);
 		} catch (KeyManagementException | NoSuchAlgorithmException e) {
-			throw new IOException(e.getMessage());
-		}
-	}
-
-	private static class DummyX509TrustManager implements X509TrustManager {
-		@Override
-		public X509Certificate[] getAcceptedIssuers() {
-			return null;
-		}
-
-		@Override
-		public void checkClientTrusted(X509Certificate[] certs,
-				String authType) {
-			// no check
-		}
-
-		@Override
-		public void checkServerTrusted(X509Certificate[] certs,
-				String authType) {
-			// no check
-		}
-	}
-
-	private static class DummyHostnameVerifier implements HostnameVerifier {
-		@Override
-		public boolean verify(String hostname, SSLSession session) {
-			// always accept
-			return true;
+			throw new IOException(e.getMessage(), e);
 		}
 	}
 
diff --git a/pom.xml b/pom.xml
index 1f1e72e..e2aa7ca 100644
--- a/pom.xml
+++ b/pom.xml
@@ -162,7 +162,7 @@
     <commons-compress-version>1.19</commons-compress-version>
     <osgi-core-version>4.3.1</osgi-core-version>
     <servlet-api-version>3.1.0</servlet-api-version>
-    <jetty-version>9.4.30.v20200611</jetty-version>
+    <jetty-version>9.4.35.v20201120</jetty-version>
     <japicmp-version>0.14.4</japicmp-version>
     <httpclient-version>4.5.10</httpclient-version>
     <httpcore-version>4.4.12</httpcore-version>
@@ -170,9 +170,9 @@
     <log4j-version>1.2.15</log4j-version>
     <maven-javadoc-plugin-version>3.2.0</maven-javadoc-plugin-version>
     <tycho-extras-version>1.7.0</tycho-extras-version>
-    <gson-version>2.8.2</gson-version>
+    <gson-version>2.8.6</gson-version>
     <bouncycastle-version>1.65</bouncycastle-version>
-    <spotbugs-maven-plugin-version>4.1.4</spotbugs-maven-plugin-version>
+    <spotbugs-maven-plugin-version>4.2.0</spotbugs-maven-plugin-version>
     <maven-project-info-reports-plugin-version>3.1.1</maven-project-info-reports-plugin-version>
     <maven-jxr-plugin-version>3.0.0</maven-jxr-plugin-version>
     <maven-surefire-plugin-version>3.0.0-M5</maven-surefire-plugin-version>