Merge branch 'stable-5.0'

* stable-5.0:
  Fix GC run in foreground to not use executor

Change-Id: I484391e5589d70de136126d153f886f5afa12e88
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
diff --git a/.mailmap b/.mailmap
index 96a4f257..7c9dc3d 100644
--- a/.mailmap
+++ b/.mailmap
@@ -7,3 +7,4 @@
 Shawn Pearce <spearce@spearce.org>           Shawn O. Pearce <sop@google.com>
 Shawn Pearce <spearce@spearce.org>           Shawn Pearce <sop@google.com>
 Shawn Pearce <spearce@spearce.org>           Shawn O. Pearce <spearce@spearce.org>
+Terry Parker <tparker@google.com>            tparker <tparker@google.com>
diff --git a/lib/BUILD b/lib/BUILD
index 10496a7..53eb191 100644
--- a/lib/BUILD
+++ b/lib/BUILD
@@ -51,6 +51,7 @@
     name = "httpcore",
     visibility = [
         "//org.eclipse.jgit.http.apache:__pkg__",
+        "//org.eclipse.jgit.http.test:__pkg__",
         "//org.eclipse.jgit.lfs.server:__pkg__",
         "//org.eclipse.jgit.lfs.server.test:__pkg__",
         "//org.eclipse.jgit.pgm:__pkg__",
diff --git a/org.eclipse.jgit.ant.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.ant.test/META-INF/MANIFEST.MF
index a9c216a..bd3c963 100644
--- a/org.eclipse.jgit.ant.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.ant.test/META-INF/MANIFEST.MF
@@ -4,13 +4,13 @@
 Bundle-Name: %plugin_name
 Automatic-Module-Name: org.eclipse.jgit.ant.test
 Bundle-SymbolicName: org.eclipse.jgit.ant.test
-Bundle-Version: 5.0.3.qualifier
+Bundle-Version: 5.1.0.qualifier
 Bundle-ActivationPolicy: lazy
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
 Import-Package: org.apache.tools.ant,
- org.eclipse.jgit.ant.tasks;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.junit;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.lib;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.util;version="[5.0.3,5.1.0)",
+ org.eclipse.jgit.ant.tasks;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.junit;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.lib;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.util;version="[5.1.0,5.2.0)",
  org.hamcrest.core;version="[1.1.0,2.0.0)",
  org.junit;version="[4.12,5.0.0)"
diff --git a/org.eclipse.jgit.ant.test/pom.xml b/org.eclipse.jgit.ant.test/pom.xml
index fca2cca..3765582 100644
--- a/org.eclipse.jgit.ant.test/pom.xml
+++ b/org.eclipse.jgit.ant.test/pom.xml
@@ -50,7 +50,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>org.eclipse.jgit-parent</artifactId>
-    <version>5.0.3-SNAPSHOT</version>
+    <version>5.1.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.ant.test</artifactId>
diff --git a/org.eclipse.jgit.ant/META-INF/MANIFEST.MF b/org.eclipse.jgit.ant/META-INF/MANIFEST.MF
index f4d04d0..d4dc839 100644
--- a/org.eclipse.jgit.ant/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.ant/META-INF/MANIFEST.MF
@@ -3,11 +3,11 @@
 Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.ant
 Bundle-SymbolicName: org.eclipse.jgit.ant
-Bundle-Version: 5.0.3.qualifier
+Bundle-Version: 5.1.0.qualifier
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
 Import-Package: org.apache.tools.ant,
-  org.eclipse.jgit.storage.file;version="[5.0.3,5.1.0)"
+  org.eclipse.jgit.storage.file;version="[5.1.0,5.2.0)"
 Bundle-Localization: plugin
 Bundle-Vendor: %Provider-Name
-Export-Package: org.eclipse.jgit.ant.tasks;version="5.0.3";
+Export-Package: org.eclipse.jgit.ant.tasks;version="5.1.0";
  uses:="org.apache.tools.ant.types,org.apache.tools.ant"
diff --git a/org.eclipse.jgit.ant/pom.xml b/org.eclipse.jgit.ant/pom.xml
index 1300065..4fe0f3f 100644
--- a/org.eclipse.jgit.ant/pom.xml
+++ b/org.eclipse.jgit.ant/pom.xml
@@ -48,7 +48,7 @@
 	<parent>
 		<groupId>org.eclipse.jgit</groupId>
 		<artifactId>org.eclipse.jgit-parent</artifactId>
-		<version>5.0.3-SNAPSHOT</version>
+		<version>5.1.0-SNAPSHOT</version>
 	</parent>
 
 	<artifactId>org.eclipse.jgit.ant</artifactId>
diff --git a/org.eclipse.jgit.archive/META-INF/MANIFEST.MF b/org.eclipse.jgit.archive/META-INF/MANIFEST.MF
index 6422ae2..3fd49f7 100644
--- a/org.eclipse.jgit.archive/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.archive/META-INF/MANIFEST.MF
@@ -3,7 +3,7 @@
 Bundle-Name: %plugin_name
 Automatic-Module-Name: org.eclipse.jgit.archive
 Bundle-SymbolicName: org.eclipse.jgit.archive
-Bundle-Version: 5.0.3.qualifier
+Bundle-Version: 5.1.0.qualifier
 Bundle-Vendor: %provider_name
 Bundle-Localization: plugin
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
@@ -13,15 +13,15 @@
  org.apache.commons.compress.compressors.bzip2;version="[1.4,2.0)",
  org.apache.commons.compress.compressors.gzip;version="[1.4,2.0)",
  org.apache.commons.compress.compressors.xz;version="[1.4,2.0)",
- org.eclipse.jgit.api;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.lib;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.nls;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.revwalk;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.util;version="[5.0.3,5.1.0)",
+ org.eclipse.jgit.api;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.lib;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.nls;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.revwalk;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.util;version="[5.1.0,5.2.0)",
  org.osgi.framework;version="[1.3.0,2.0.0)"
 Bundle-ActivationPolicy: lazy
 Bundle-Activator: org.eclipse.jgit.archive.FormatActivator
-Export-Package: org.eclipse.jgit.archive;version="5.0.3";
+Export-Package: org.eclipse.jgit.archive;version="5.1.0";
   uses:="org.eclipse.jgit.lib,
    org.eclipse.jgit.api,
    org.apache.commons.compress.archivers,
diff --git a/org.eclipse.jgit.archive/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.archive/META-INF/SOURCE-MANIFEST.MF
index 9e245d4..ae65f94 100644
--- a/org.eclipse.jgit.archive/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.archive/META-INF/SOURCE-MANIFEST.MF
@@ -3,5 +3,5 @@
 Bundle-Name: org.eclipse.jgit.archive - Sources
 Bundle-SymbolicName: org.eclipse.jgit.archive.source
 Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 5.0.3.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit.archive;version="5.0.3.qualifier";roots="."
+Bundle-Version: 5.1.0.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit.archive;version="5.1.0.qualifier";roots="."
diff --git a/org.eclipse.jgit.archive/pom.xml b/org.eclipse.jgit.archive/pom.xml
index 8418051..1b4a994 100644
--- a/org.eclipse.jgit.archive/pom.xml
+++ b/org.eclipse.jgit.archive/pom.xml
@@ -50,7 +50,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>org.eclipse.jgit-parent</artifactId>
-    <version>5.0.3-SNAPSHOT</version>
+    <version>5.1.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.archive</artifactId>
diff --git a/org.eclipse.jgit.http.apache/META-INF/MANIFEST.MF b/org.eclipse.jgit.http.apache/META-INF/MANIFEST.MF
index 86cfe78..fb9ec51 100644
--- a/org.eclipse.jgit.http.apache/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.http.apache/META-INF/MANIFEST.MF
@@ -3,7 +3,7 @@
 Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.http.apache
 Bundle-SymbolicName: org.eclipse.jgit.http.apache
-Bundle-Version: 5.0.3.qualifier
+Bundle-Version: 5.1.0.qualifier
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
 Bundle-Localization: plugin
 Bundle-Vendor: %Provider-Name
@@ -23,10 +23,10 @@
  org.apache.http.impl.client;version="[4.3.0,5.0.0)",
  org.apache.http.impl.conn;version="[4.3.0,5.0.0)",
  org.apache.http.params;version="[4.3.0,5.0.0)",
- org.eclipse.jgit.nls;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.transport.http;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.util;version="[5.0.3,5.1.0)"
-Export-Package: org.eclipse.jgit.transport.http.apache;version="5.0.3";
+ org.eclipse.jgit.nls;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.transport.http;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.util;version="[5.1.0,5.2.0)"
+Export-Package: org.eclipse.jgit.transport.http.apache;version="5.1.0";
   uses:="org.apache.http.client,
    org.eclipse.jgit.transport.http,
    org.apache.http.entity,
diff --git a/org.eclipse.jgit.http.apache/pom.xml b/org.eclipse.jgit.http.apache/pom.xml
index 1941979..844cb00 100644
--- a/org.eclipse.jgit.http.apache/pom.xml
+++ b/org.eclipse.jgit.http.apache/pom.xml
@@ -48,7 +48,7 @@
 	<parent>
 		<groupId>org.eclipse.jgit</groupId>
 		<artifactId>org.eclipse.jgit-parent</artifactId>
-		<version>5.0.3-SNAPSHOT</version>
+		<version>5.1.0-SNAPSHOT</version>
 	</parent>
 
 	<artifactId>org.eclipse.jgit.http.apache</artifactId>
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 7f1fecb..77c5dc0 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
@@ -272,10 +272,14 @@ private void execute() throws IOException, ClientProtocolException {
 	public Map<String, List<String>> getHeaderFields() {
 		Map<String, List<String>> ret = new HashMap<>();
 		for (Header hdr : resp.getAllHeaders()) {
-			List<String> list = new LinkedList<>();
-			for (HeaderElement hdrElem : hdr.getElements())
+			List<String> list = ret.get(hdr.getName());
+			if (list == null) {
+				list = new LinkedList<>();
+				ret.put(hdr.getName(), list);
+			}
+			for (HeaderElement hdrElem : hdr.getElements()) {
 				list.add(hdrElem.toString());
-			ret.put(hdr.getName(), list);
+			}
 		}
 		return ret;
 	}
diff --git a/org.eclipse.jgit.http.server/META-INF/MANIFEST.MF b/org.eclipse.jgit.http.server/META-INF/MANIFEST.MF
index ad1a716..33057c3 100644
--- a/org.eclipse.jgit.http.server/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.http.server/META-INF/MANIFEST.MF
@@ -3,13 +3,13 @@
 Bundle-Name: %plugin_name
 Automatic-Module-Name: org.eclipse.jgit.http.server
 Bundle-SymbolicName: org.eclipse.jgit.http.server
-Bundle-Version: 5.0.3.qualifier
+Bundle-Version: 5.1.0.qualifier
 Bundle-Localization: plugin
 Bundle-Vendor: %provider_name
-Export-Package: org.eclipse.jgit.http.server;version="5.0.3",
- org.eclipse.jgit.http.server.glue;version="5.0.3";
+Export-Package: org.eclipse.jgit.http.server;version="5.1.0",
+ org.eclipse.jgit.http.server.glue;version="5.1.0";
   uses:="javax.servlet,javax.servlet.http",
- org.eclipse.jgit.http.server.resolver;version="5.0.3";
+ org.eclipse.jgit.http.server.resolver;version="5.1.0";
   uses:="org.eclipse.jgit.transport.resolver,
    org.eclipse.jgit.lib,
    org.eclipse.jgit.transport,
@@ -18,12 +18,12 @@
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
 Import-Package: javax.servlet;version="[2.5.0,3.2.0)",
  javax.servlet.http;version="[2.5.0,3.2.0)",
- org.eclipse.jgit.errors;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.internal.storage.dfs;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.internal.storage.file;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.lib;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.nls;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.revwalk;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.transport;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.transport.resolver;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.util;version="[5.0.3,5.1.0)"
+ org.eclipse.jgit.errors;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.internal.storage.dfs;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.internal.storage.file;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.lib;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.nls;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.revwalk;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.transport;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.transport.resolver;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.util;version="[5.1.0,5.2.0)"
diff --git a/org.eclipse.jgit.http.server/pom.xml b/org.eclipse.jgit.http.server/pom.xml
index b7deb38..815afae 100644
--- a/org.eclipse.jgit.http.server/pom.xml
+++ b/org.eclipse.jgit.http.server/pom.xml
@@ -52,7 +52,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>org.eclipse.jgit-parent</artifactId>
-    <version>5.0.3-SNAPSHOT</version>
+    <version>5.1.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.http.server</artifactId>
diff --git a/org.eclipse.jgit.http.test/BUILD b/org.eclipse.jgit.http.test/BUILD
index 85a2242..dcffa06 100644
--- a/org.eclipse.jgit.http.test/BUILD
+++ b/org.eclipse.jgit.http.test/BUILD
@@ -10,6 +10,7 @@
     deps = [
         ":helpers",
         "//lib:commons-logging",
+        "//lib:httpcore",
         "//lib:jetty-http",
         "//lib:jetty-io",
         "//lib:jetty-security",
diff --git a/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF
index 6aeb708..678f77f 100644
--- a/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF
@@ -3,7 +3,7 @@
 Bundle-Name: %plugin_name
 Automatic-Module-Name: org.eclipse.jgit.http.test
 Bundle-SymbolicName: org.eclipse.jgit.http.test
-Bundle-Version: 5.0.3.qualifier
+Bundle-Version: 5.1.0.qualifier
 Bundle-Vendor: %provider_name
 Bundle-Localization: plugin
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
@@ -11,6 +11,9 @@
  javax.servlet.http;version="[2.5.0,3.2.0)",
  org.apache.commons.codec;version="[1.6.0,2.0.0)",
  org.apache.commons.codec.binary;version="[1.6.0,2.0.0)",
+ org.apache.http;version="[4.3.0,5.0.0)",
+ org.apache.http.client;version="[4.3.0,5.0.0)",
+ org.apache.http.message;version="[4.3.0,5.0.0)",
  org.eclipse.jetty.continuation;version="[9.4.5,10.0.0)",
  org.eclipse.jetty.http;version="[9.4.5,10.0.0)",
  org.eclipse.jetty.io;version="[9.4.5,10.0.0)",
@@ -25,25 +28,25 @@
  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.errors;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.http.server;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.http.server.glue;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.http.server.resolver;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.internal;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.internal.storage.dfs;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.internal.storage.file;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.internal.storage.reftable;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.junit;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.junit.http;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.lib;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.nls;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.revwalk;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.storage.file;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.transport;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.transport.http;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.transport.http.apache;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.transport.resolver;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.util;version="[5.0.3,5.1.0)",
+ org.eclipse.jgit.errors;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.http.server;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.http.server.glue;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.http.server.resolver;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.internal;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.internal.storage.dfs;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.internal.storage.file;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.internal.storage.reftable;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.junit;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.junit.http;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.lib;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.nls;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.revwalk;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.storage.file;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.transport;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.transport.http;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.transport.http.apache;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.transport.resolver;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.util;version="[5.1.0,5.2.0)",
  org.hamcrest;version="[1.1.0,2.0.0)",
  org.hamcrest.core;version="[1.1.0,2.0.0)",
  org.junit;version="[4.12,5.0.0)",
diff --git a/org.eclipse.jgit.http.test/pom.xml b/org.eclipse.jgit.http.test/pom.xml
index 305b29f..c4a8580 100644
--- a/org.eclipse.jgit.http.test/pom.xml
+++ b/org.eclipse.jgit.http.test/pom.xml
@@ -51,7 +51,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>org.eclipse.jgit-parent</artifactId>
-    <version>5.0.3-SNAPSHOT</version>
+    <version>5.1.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.http.test</artifactId>
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 ef059bf..61f272c 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
@@ -175,7 +175,9 @@ public void testRepositoryNotFound_Dumb() throws Exception {
 			} catch (NoRemoteRepositoryException err) {
 				String exp = uri + ": " + uri
 						+ "/info/refs?service=git-upload-pack not found";
-				assertEquals(exp, err.getMessage());
+				assertNotNull(err.getMessage());
+				assertTrue("Unexpected error message",
+						err.getMessage().startsWith(exp));
 			}
 		}
 	}
@@ -191,7 +193,9 @@ public void testRepositoryNotFound_Smart() throws Exception {
 			} catch (NoRemoteRepositoryException err) {
 				String exp = uri + ": " + uri
 						+ "/info/refs?service=git-upload-pack not found";
-				assertEquals(exp, err.getMessage());
+				assertNotNull(err.getMessage());
+				assertTrue("Unexpected error message",
+						err.getMessage().startsWith(exp));
 			}
 		}
 	}
diff --git a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/transport/http/apache/HttpClientConnectionTest.java b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/transport/http/apache/HttpClientConnectionTest.java
new file mode 100644
index 0000000..678ed64
--- /dev/null
+++ b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/transport/http/apache/HttpClientConnectionTest.java
@@ -0,0 +1,90 @@
+package org.eclipse.jgit.transport.http.apache;

+

+import org.apache.http.HttpEntity;

+import org.apache.http.HttpResponse;

+import org.apache.http.ProtocolVersion;

+import org.apache.http.StatusLine;

+import org.apache.http.message.AbstractHttpMessage;

+import org.junit.Test;

+

+import java.net.MalformedURLException;

+import java.util.List;

+import java.util.Locale;

+

+import static org.junit.Assert.assertEquals;

+import static org.junit.Assert.assertTrue;

+

+public class HttpClientConnectionTest {

+    @Test

+    public void testGetHeaderFieldsAllowMultipleValues() throws MalformedURLException {

+        HttpResponse responseMock = new HttpResponseMock();

+        String headerField = "WWW-Authenticate";

+        responseMock.addHeader(headerField, "Basic");

+        responseMock.addHeader(headerField, "Digest");

+        responseMock.addHeader(headerField, "NTLM");

+        HttpClientConnection connection = new HttpClientConnection("http://0.0.0.0/");

+        connection.resp = responseMock;

+        List<String> headerValues = connection.getHeaderFields().get(headerField);

+        assertEquals(3, headerValues.size());

+        assertTrue(headerValues.contains("Basic"));

+        assertTrue(headerValues.contains("Digest"));

+        assertTrue(headerValues.contains("NTLM"));

+    }

+

+    private class HttpResponseMock extends AbstractHttpMessage implements HttpResponse {

+        @Override

+        public StatusLine getStatusLine() {

+            return null;

+        }

+

+        @Override

+        public void setStatusLine(StatusLine statusLine) {

+

+        }

+

+        @Override

+        public void setStatusLine(ProtocolVersion protocolVersion, int i) {

+

+        }

+

+        @Override

+        public void setStatusLine(ProtocolVersion protocolVersion, int i, String s) {

+

+        }

+

+        @Override

+        public void setStatusCode(int i) throws IllegalStateException {

+

+        }

+

+        @Override

+        public void setReasonPhrase(String s) throws IllegalStateException {

+

+        }

+

+        @Override

+        public HttpEntity getEntity() {

+            return null;

+        }

+

+        @Override

+        public void setEntity(HttpEntity httpEntity) {

+

+        }

+

+        @Override

+        public Locale getLocale() {

+            return null;

+        }

+

+        @Override

+        public void setLocale(Locale locale) {

+

+        }

+

+        @Override

+        public ProtocolVersion getProtocolVersion() {

+            return null;

+        }

+    }

+}

diff --git a/org.eclipse.jgit.junit.http/META-INF/MANIFEST.MF b/org.eclipse.jgit.junit.http/META-INF/MANIFEST.MF
index 953d7d8..31f9e2c 100644
--- a/org.eclipse.jgit.junit.http/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.junit.http/META-INF/MANIFEST.MF
@@ -3,7 +3,7 @@
 Bundle-Name: %plugin_name
 Automatic-Module-Name: org.eclipse.jgit.junit.http
 Bundle-SymbolicName: org.eclipse.jgit.junit.http
-Bundle-Version: 5.0.3.qualifier
+Bundle-Version: 5.1.0.qualifier
 Bundle-Localization: plugin
 Bundle-Vendor: %provider_name
 Bundle-ActivationPolicy: lazy
@@ -22,16 +22,16 @@
  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.ssl;version="[9.4.5,10.0.0)",
- org.eclipse.jgit.errors;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.http.server;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.internal.storage.file;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.junit;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.lib;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.revwalk;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.transport;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.transport.resolver;version="[5.0.3,5.1.0)",
+ org.eclipse.jgit.errors;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.http.server;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.internal.storage.file;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.junit;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.lib;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.revwalk;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.transport;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.transport.resolver;version="[5.1.0,5.2.0)",
  org.junit;version="[4.12,5.0.0)"
-Export-Package: org.eclipse.jgit.junit.http;version="5.0.3";
+Export-Package: org.eclipse.jgit.junit.http;version="5.1.0";
   uses:="org.eclipse.jgit.transport,
    org.eclipse.jgit.junit,
    javax.servlet.http,
diff --git a/org.eclipse.jgit.junit.http/pom.xml b/org.eclipse.jgit.junit.http/pom.xml
index b179c9a..77d9372 100644
--- a/org.eclipse.jgit.junit.http/pom.xml
+++ b/org.eclipse.jgit.junit.http/pom.xml
@@ -50,7 +50,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>org.eclipse.jgit-parent</artifactId>
-    <version>5.0.3-SNAPSHOT</version>
+    <version>5.1.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.junit.http</artifactId>
diff --git a/org.eclipse.jgit.junit/META-INF/MANIFEST.MF b/org.eclipse.jgit.junit/META-INF/MANIFEST.MF
index 6f32c14..1ed1a55 100644
--- a/org.eclipse.jgit.junit/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.junit/META-INF/MANIFEST.MF
@@ -3,31 +3,31 @@
 Bundle-Name: %plugin_name
 Automatic-Module-Name: org.eclipse.jgit.junit
 Bundle-SymbolicName: org.eclipse.jgit.junit
-Bundle-Version: 5.0.3.qualifier
+Bundle-Version: 5.1.0.qualifier
 Bundle-Localization: plugin
 Bundle-Vendor: %provider_name
 Bundle-ActivationPolicy: lazy
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
-Import-Package: org.eclipse.jgit.api;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.api.errors;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.dircache;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.errors;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.internal.storage.file;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.internal.storage.pack;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.lib;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.merge;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.revwalk;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.storage.file;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.treewalk;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.treewalk.filter;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.util;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.util.io;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.util.time;version="[5.0.3,5.1.0)",
+Import-Package: org.eclipse.jgit.api;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.api.errors;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.dircache;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.errors;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.internal.storage.file;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.internal.storage.pack;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.lib;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.merge;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.revwalk;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.storage.file;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.treewalk;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.treewalk.filter;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.util;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.util.io;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.util.time;version="[5.1.0,5.2.0)",
  org.junit;version="[4.12,5.0.0)",
  org.junit.rules;version="[4.12,5.0.0)",
  org.junit.runner;version="[4.12,5.0.0)",
  org.junit.runners.model;version="[4.12,5.0.0)"
-Export-Package: org.eclipse.jgit.junit;version="5.0.3";
+Export-Package: org.eclipse.jgit.junit;version="5.1.0";
   uses:="org.eclipse.jgit.dircache,
    org.eclipse.jgit.lib,
    org.eclipse.jgit.revwalk,
@@ -36,4 +36,4 @@
    org.eclipse.jgit.util,
    org.eclipse.jgit.storage.file,
    org.eclipse.jgit.api",
- org.eclipse.jgit.junit.time;version="5.0.3"
+ org.eclipse.jgit.junit.time;version="5.1.0"
diff --git a/org.eclipse.jgit.junit/pom.xml b/org.eclipse.jgit.junit/pom.xml
index da6612f..589e641 100644
--- a/org.eclipse.jgit.junit/pom.xml
+++ b/org.eclipse.jgit.junit/pom.xml
@@ -52,7 +52,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>org.eclipse.jgit-parent</artifactId>
-    <version>5.0.3-SNAPSHOT</version>
+    <version>5.1.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.junit</artifactId>
diff --git a/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/TestRepository.java b/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/TestRepository.java
index d23c0d3..49715e5 100644
--- a/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/TestRepository.java
+++ b/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/TestRepository.java
@@ -276,7 +276,7 @@ public RevBlob blob(String content) throws Exception {
 	 *
 	 * @param content
 	 *            binary file content.
-	 * @return reference to the blob.
+	 * @return the new, fully parsed blob.
 	 * @throws Exception
 	 */
 	public RevBlob blob(byte[] content) throws Exception {
@@ -285,7 +285,7 @@ public RevBlob blob(byte[] content) throws Exception {
 			id = ins.insert(Constants.OBJ_BLOB, content);
 			ins.flush();
 		}
-		return pool.lookupBlob(id);
+		return (RevBlob) pool.parseAny(id);
 	}
 
 	/**
@@ -312,21 +312,22 @@ public DirCacheEntry file(String path, RevBlob blob)
 	 * @param entries
 	 *            the files to include in the tree. The collection does not need
 	 *            to be sorted properly and may be empty.
-	 * @return reference to the tree specified by the entry list.
+	 * @return the new, fully parsed tree specified by the entry list.
 	 * @throws Exception
 	 */
 	public RevTree tree(DirCacheEntry... entries) throws Exception {
 		final DirCache dc = DirCache.newInCore();
 		final DirCacheBuilder b = dc.builder();
-		for (DirCacheEntry e : entries)
+		for (DirCacheEntry e : entries) {
 			b.add(e);
+		}
 		b.finish();
 		ObjectId root;
 		try (ObjectInserter ins = inserter) {
 			root = dc.writeTree(ins);
 			ins.flush();
 		}
-		return pool.lookupTree(root);
+		return pool.parseTree(root);
 	}
 
 	/**
@@ -422,7 +423,7 @@ public RevCommit commit(int secDelta, RevCommit... parents)
 	 *            the root tree for the commit.
 	 * @param parents
 	 *            zero or more parents of the commit.
-	 * @return the new commit.
+	 * @return the new, fully parsed commit.
 	 * @throws Exception
 	 */
 	public RevCommit commit(final int secDelta, final RevTree tree,
@@ -442,7 +443,7 @@ public RevCommit commit(final int secDelta, final RevTree tree,
 			id = ins.insert(c);
 			ins.flush();
 		}
-		return pool.lookupCommit(id);
+		return pool.parseCommit(id);
 	}
 
 	/**
@@ -467,7 +468,7 @@ public CommitBuilder commit() {
 	 *            with {@code refs/tags/}.
 	 * @param dst
 	 *            object the tag should be pointed at.
-	 * @return the annotated tag object.
+	 * @return the new, fully parsed annotated tag object.
 	 * @throws Exception
 	 */
 	public RevTag tag(String name, RevObject dst) throws Exception {
@@ -481,7 +482,7 @@ public RevTag tag(String name, RevObject dst) throws Exception {
 			id = ins.insert(t);
 			ins.flush();
 		}
-		return (RevTag) pool.lookupAny(id, Constants.OBJ_TAG);
+		return pool.parseTag(id);
 	}
 
 	/**
@@ -705,8 +706,8 @@ public void reset(String name) throws Exception {
 	 *
 	 * @param id
 	 *            commit-ish to cherry-pick.
-	 * @return newly created commit, or null if no work was done due to the
-	 *         resulting tree being identical.
+	 * @return the new, fully parsed commit, or null if no work was done due to
+	 *         the resulting tree being identical.
 	 * @throws Exception
 	 */
 	public RevCommit cherryPick(AnyObjectId id) throws Exception {
@@ -757,7 +758,7 @@ public RevCommit cherryPick(AnyObjectId id) throws Exception {
 	public void updateServerInfo() throws Exception {
 		if (db instanceof FileRepository) {
 			final FileRepository fr = (FileRepository) db;
-			RefWriter rw = new RefWriter(fr.getAllRefs().values()) {
+			RefWriter rw = new RefWriter(fr.getRefDatabase().getRefs()) {
 				@Override
 				protected void writeFile(String name, byte[] bin)
 						throws IOException {
@@ -852,7 +853,7 @@ public void fsck(RevObject... tips) throws MissingObjectException,
 				for (RevObject o : tips)
 					ow.markStart(ow.parseAny(o));
 			} else {
-				for (Ref r : db.getAllRefs().values())
+				for (Ref r : db.getRefDatabase().getRefs())
 					ow.markStart(ow.parseAny(r.getObjectId()));
 			}
 
@@ -905,7 +906,7 @@ public void packAndPrune() throws Exception {
 			final File pack, idx;
 			try (PackWriter pw = new PackWriter(db)) {
 				Set<ObjectId> all = new HashSet<>();
-				for (Ref r : db.getAllRefs().values())
+				for (Ref r : db.getRefDatabase().getRefs())
 					all.add(r.getObjectId());
 				pw.preparePack(m, all, PackWriter.NONE);
 
@@ -1197,7 +1198,7 @@ public RevCommit create() throws Exception {
 					commitId = ins.insert(c);
 					ins.flush();
 				}
-				self = pool.lookupCommit(commitId);
+				self = pool.parseCommit(commitId);
 
 				if (branch != null)
 					branch.update(self);
diff --git a/org.eclipse.jgit.lfs.server.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.lfs.server.test/META-INF/MANIFEST.MF
index 71bafbc..6962942 100644
--- a/org.eclipse.jgit.lfs.server.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.lfs.server.test/META-INF/MANIFEST.MF
@@ -3,7 +3,7 @@
 Bundle-Name: %plugin_name
 Automatic-Module-Name: org.eclipse.jgit.lfs.server.test
 Bundle-SymbolicName: org.eclipse.jgit.lfs.server.test
-Bundle-Version: 5.0.3.qualifier
+Bundle-Version: 5.1.0.qualifier
 Bundle-Vendor: %provider_name
 Bundle-Localization: plugin
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
@@ -28,24 +28,24 @@
  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.0.3,5.1.0)",
- org.eclipse.jgit.api.errors;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.internal.storage.file;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.junit;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.junit.http;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.lfs;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.lfs.errors;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.lfs.lib;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.lfs.server;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.lfs.server.fs;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.lfs.test;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.lib;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.revwalk;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.storage.file;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.transport;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.treewalk;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.treewalk.filter;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.util;version="[5.0.3,5.1.0)",
+ org.eclipse.jgit.api;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.api.errors;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.internal.storage.file;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.junit;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.junit.http;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.lfs;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.lfs.errors;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.lfs.lib;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.lfs.server;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.lfs.server.fs;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.lfs.test;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.lib;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.revwalk;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.storage.file;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.transport;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.treewalk;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.treewalk.filter;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.util;version="[5.1.0,5.2.0)",
  org.hamcrest.core;version="[1.1.0,2.0.0)",
  org.junit;version="[4.12,5.0.0)",
  org.junit.rules;version="[4.12,5.0.0)",
diff --git a/org.eclipse.jgit.lfs.server.test/pom.xml b/org.eclipse.jgit.lfs.server.test/pom.xml
index 157a5ba..6848a01 100644
--- a/org.eclipse.jgit.lfs.server.test/pom.xml
+++ b/org.eclipse.jgit.lfs.server.test/pom.xml
@@ -50,7 +50,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>org.eclipse.jgit-parent</artifactId>
-    <version>5.0.3-SNAPSHOT</version>
+    <version>5.1.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.lfs.server.test</artifactId>
diff --git a/org.eclipse.jgit.lfs.server/META-INF/MANIFEST.MF b/org.eclipse.jgit.lfs.server/META-INF/MANIFEST.MF
index cf78e89..eceb02b 100644
--- a/org.eclipse.jgit.lfs.server/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.lfs.server/META-INF/MANIFEST.MF
@@ -3,19 +3,19 @@
 Bundle-Name: %plugin_name
 Automatic-Module-Name: org.eclipse.jgit.lfs.server
 Bundle-SymbolicName: org.eclipse.jgit.lfs.server
-Bundle-Version: 5.0.3.qualifier
+Bundle-Version: 5.1.0.qualifier
 Bundle-Localization: plugin
 Bundle-Vendor: %provider_name
-Export-Package: org.eclipse.jgit.lfs.server;version="5.0.3";
+Export-Package: org.eclipse.jgit.lfs.server;version="5.1.0";
   uses:="javax.servlet.http,
    org.eclipse.jgit.lfs.lib",
- org.eclipse.jgit.lfs.server.fs;version="5.0.3";
+ org.eclipse.jgit.lfs.server.fs;version="5.1.0";
   uses:="javax.servlet,
    javax.servlet.http,
    org.eclipse.jgit.lfs.server,
    org.eclipse.jgit.lfs.lib",
- org.eclipse.jgit.lfs.server.internal;version="5.0.3";x-internal:=true,
- org.eclipse.jgit.lfs.server.s3;version="5.0.3";
+ org.eclipse.jgit.lfs.server.internal;version="5.1.0";x-internal:=true,
+ org.eclipse.jgit.lfs.server.s3;version="5.1.0";
   uses:="org.eclipse.jgit.lfs.server,
    org.eclipse.jgit.lfs.lib"
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
@@ -25,15 +25,15 @@
  javax.servlet.http;version="[3.1.0,4.0.0)",
  org.apache.http;version="[4.3.0,5.0.0)",
  org.apache.http.client;version="[4.3.0,5.0.0)",
- org.eclipse.jgit.annotations;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.internal;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.internal.storage.file;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.lfs.errors;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.lfs.internal;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.lfs.lib;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.lib;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.nls;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.transport.http;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.transport.http.apache;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.util;version="[5.0.3,5.1.0)",
+ org.eclipse.jgit.annotations;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.internal;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.internal.storage.file;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.lfs.errors;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.lfs.internal;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.lfs.lib;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.lib;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.nls;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.transport.http;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.transport.http.apache;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.util;version="[5.1.0,5.2.0)",
  org.slf4j;version="[1.7.0,2.0.0)"
diff --git a/org.eclipse.jgit.lfs.server/pom.xml b/org.eclipse.jgit.lfs.server/pom.xml
index 349a3bb..5c64b93 100644
--- a/org.eclipse.jgit.lfs.server/pom.xml
+++ b/org.eclipse.jgit.lfs.server/pom.xml
@@ -50,7 +50,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>org.eclipse.jgit-parent</artifactId>
-    <version>5.0.3-SNAPSHOT</version>
+    <version>5.1.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.lfs.server</artifactId>
diff --git a/org.eclipse.jgit.lfs.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.lfs.test/META-INF/MANIFEST.MF
index 9a25539..91f0d22 100644
--- a/org.eclipse.jgit.lfs.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.lfs.test/META-INF/MANIFEST.MF
@@ -3,23 +3,23 @@
 Bundle-Name: %plugin_name
 Automatic-Module-Name: org.eclipse.jgit.lfs.test
 Bundle-SymbolicName: org.eclipse.jgit.lfs.test
-Bundle-Version: 5.0.3.qualifier
+Bundle-Version: 5.1.0.qualifier
 Bundle-Vendor: %provider_name
 Bundle-Localization: plugin
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
-Import-Package: org.eclipse.jgit.internal.storage.dfs;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.junit;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.lfs;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.lfs.errors;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.lfs.lib;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.lib;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.revwalk;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.treewalk;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.treewalk.filter;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.util;version="[5.0.3,5.1.0)",
+Import-Package: org.eclipse.jgit.internal.storage.dfs;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.junit;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.lfs;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.lfs.errors;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.lfs.lib;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.lib;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.revwalk;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.treewalk;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.treewalk.filter;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.util;version="[5.1.0,5.2.0)",
  org.hamcrest.core;version="[1.1.0,2.0.0)",
  org.junit;version="[4.12,5.0.0)",
  org.junit.runner;version="[4.12,5.0.0)",
  org.junit.runners;version="[4.12,5.0.0)"
-Export-Package: org.eclipse.jgit.lfs.test;version="5.0.3";x-friends:="org.eclipse.jgit.lfs.server.test"
+Export-Package: org.eclipse.jgit.lfs.test;version="5.1.0";x-friends:="org.eclipse.jgit.lfs.server.test"
 
diff --git a/org.eclipse.jgit.lfs.test/pom.xml b/org.eclipse.jgit.lfs.test/pom.xml
index 0a565eb..a0bd8fd 100644
--- a/org.eclipse.jgit.lfs.test/pom.xml
+++ b/org.eclipse.jgit.lfs.test/pom.xml
@@ -50,7 +50,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>org.eclipse.jgit-parent</artifactId>
-    <version>5.0.3-SNAPSHOT</version>
+    <version>5.1.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.lfs.test</artifactId>
diff --git a/org.eclipse.jgit.lfs/META-INF/MANIFEST.MF b/org.eclipse.jgit.lfs/META-INF/MANIFEST.MF
index 1dfc7ac..dcfe841 100644
--- a/org.eclipse.jgit.lfs/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.lfs/META-INF/MANIFEST.MF
@@ -3,34 +3,33 @@
 Bundle-Name: %plugin_name
 Automatic-Module-Name: org.eclipse.jgit.lfs
 Bundle-SymbolicName: org.eclipse.jgit.lfs
-Bundle-Version: 5.0.3.qualifier
+Bundle-Version: 5.1.0.qualifier
 Bundle-Localization: plugin
 Bundle-Vendor: %provider_name
-Export-Package: org.eclipse.jgit.lfs;version="5.0.3",
- org.eclipse.jgit.lfs.errors;version="5.0.3",
- org.eclipse.jgit.lfs.internal;version="5.0.3";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.0.3"
+Export-Package: org.eclipse.jgit.lfs;version="5.1.0",
+ org.eclipse.jgit.lfs.errors;version="5.1.0",
+ org.eclipse.jgit.lfs.internal;version="5.1.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.1.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)",
  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.0.3,5.1.0)";resolution:=optional,
- org.eclipse.jgit.api.errors;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.attributes;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.diff;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.errors;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.hooks;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.internal.storage.file;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.lib;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.nls;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.revwalk;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.storage.file;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.storage.pack;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.transport;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.transport.http;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.treewalk;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.treewalk.filter;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.util;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.util.io;version="[5.0.3,5.1.0)",
- org.slf4j;version="[1.7.0,2.0.0)"
+ org.eclipse.jgit.annotations;version="[5.1.0,5.2.0)";resolution:=optional,
+ org.eclipse.jgit.api.errors;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.attributes;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.diff;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.errors;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.hooks;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.internal.storage.file;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.lib;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.nls;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.revwalk;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.storage.file;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.storage.pack;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.transport;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.transport.http;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.treewalk;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.treewalk.filter;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.util;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.util.io;version="[5.1.0,5.2.0)"
diff --git a/org.eclipse.jgit.lfs/pom.xml b/org.eclipse.jgit.lfs/pom.xml
index e541f93..7628eb2 100644
--- a/org.eclipse.jgit.lfs/pom.xml
+++ b/org.eclipse.jgit.lfs/pom.xml
@@ -50,7 +50,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>org.eclipse.jgit-parent</artifactId>
-    <version>5.0.3-SNAPSHOT</version>
+    <version>5.1.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.lfs</artifactId>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.feature/feature.xml
index b618ac8..1e28693 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.feature/feature.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.feature/feature.xml
@@ -2,7 +2,7 @@
 <feature
       id="org.eclipse.jgit"
       label="%featureName"
-      version="5.0.3.qualifier"
+      version="5.1.0.qualifier"
       provider-name="%providerName">
 
    <description url="http://www.eclipse.org/jgit/">
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.feature/pom.xml
index 92dc994..bcb943f 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.feature/pom.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.feature/pom.xml
@@ -50,7 +50,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>jgit.tycho.parent</artifactId>
-    <version>5.0.3-SNAPSHOT</version>
+    <version>5.1.0-SNAPSHOT</version>
   </parent>
 
   <groupId>org.eclipse.jgit.feature</groupId>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.http.apache.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.http.apache.feature/feature.xml
index 11e7d2e..6372eed 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.http.apache.feature/feature.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.http.apache.feature/feature.xml
@@ -2,7 +2,7 @@
 <feature
       id="org.eclipse.jgit.http.apache"
       label="%featureName"
-      version="5.0.3.qualifier"
+      version="5.1.0.qualifier"
       provider-name="%providerName">
 
    <description url="http://www.eclipse.org/jgit/">
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.http.apache.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.http.apache.feature/pom.xml
index d8360e4..ca2f59a 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.http.apache.feature/pom.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.http.apache.feature/pom.xml
@@ -50,7 +50,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>jgit.tycho.parent</artifactId>
-    <version>5.0.3-SNAPSHOT</version>
+    <version>5.1.0-SNAPSHOT</version>
   </parent>
 
   <groupId>org.eclipse.jgit.feature</groupId>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/feature.xml
index 2ca32a0..271eb61 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/feature.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/feature.xml
@@ -2,7 +2,7 @@
 <feature
       id="org.eclipse.jgit.junit"
       label="%featureName"
-      version="5.0.3.qualifier"
+      version="5.1.0.qualifier"
       provider-name="%providerName">
 
    <description url="http://www.eclipse.org/jgit/">
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/pom.xml
index 46149f5..8add83c 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/pom.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/pom.xml
@@ -50,7 +50,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>jgit.tycho.parent</artifactId>
-    <version>5.0.3-SNAPSHOT</version>
+    <version>5.1.0-SNAPSHOT</version>
   </parent>
 
   <groupId>org.eclipse.jgit.feature</groupId>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.lfs.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.lfs.feature/feature.xml
index 1a17783..99d68ee 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.lfs.feature/feature.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.lfs.feature/feature.xml
@@ -2,7 +2,7 @@
 <feature
       id="org.eclipse.jgit.lfs"
       label="%featureName"
-      version="5.0.3.qualifier"
+      version="5.1.0.qualifier"
       provider-name="%providerName">
 
    <description url="http://www.eclipse.org/jgit/">
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.lfs.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.lfs.feature/pom.xml
index a228921..36d8b87 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.lfs.feature/pom.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.lfs.feature/pom.xml
@@ -50,7 +50,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>jgit.tycho.parent</artifactId>
-    <version>5.0.3-SNAPSHOT</version>
+    <version>5.1.0-SNAPSHOT</version>
   </parent>
 
   <groupId>org.eclipse.jgit.feature</groupId>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/feature.xml
index 67a2659..6864b8b 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/feature.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/feature.xml
@@ -2,7 +2,7 @@
 <feature
       id="org.eclipse.jgit.pgm"
       label="%featureName"
-      version="5.0.3.qualifier"
+      version="5.1.0.qualifier"
       provider-name="%providerName">
 
    <description url="http://www.eclipse.org/jgit/">
@@ -31,8 +31,8 @@
          version="0.0.0"/>
 
    <requires>
-      <import feature="org.eclipse.jgit" version="5.0.3" match="equivalent"/>
-      <import feature="org.eclipse.jgit.lfs" version="5.0.3" match="equivalent"/>
+      <import feature="org.eclipse.jgit" version="5.1.0" match="equivalent"/>
+      <import feature="org.eclipse.jgit.lfs" version="5.1.0" match="equivalent"/>
    </requires>
 
    <plugin
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/pom.xml
index aad49e1..37fe1af 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/pom.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/pom.xml
@@ -50,7 +50,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>jgit.tycho.parent</artifactId>
-    <version>5.0.3-SNAPSHOT</version>
+    <version>5.1.0-SNAPSHOT</version>
   </parent>
 
   <groupId>org.eclipse.jgit.feature</groupId>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.source.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.source.feature/feature.xml
index 581fb1b..cd25071 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.source.feature/feature.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.source.feature/feature.xml
@@ -2,7 +2,7 @@
 <feature
       id="org.eclipse.jgit.pgm.source"
       label="%featureName"
-      version="5.0.3.qualifier"
+      version="5.1.0.qualifier"
       provider-name="%providerName">
 
    <description url="http://www.eclipse.org/jgit/">
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.source.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.source.feature/pom.xml
index 5350268..74f9e6a 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.source.feature/pom.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.source.feature/pom.xml
@@ -50,7 +50,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>jgit.tycho.parent</artifactId>
-    <version>5.0.3-SNAPSHOT</version>
+    <version>5.1.0-SNAPSHOT</version>
   </parent>
 
   <groupId>org.eclipse.jgit.feature</groupId>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.repository/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.repository/pom.xml
index 8b5df75..7904064 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.repository/pom.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.repository/pom.xml
@@ -50,7 +50,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>jgit.tycho.parent</artifactId>
-    <version>5.0.3-SNAPSHOT</version>
+    <version>5.1.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.repository</artifactId>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/feature.xml
index 211e868..9086623 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/feature.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/feature.xml
@@ -2,7 +2,7 @@
 <feature
       id="org.eclipse.jgit.source"
       label="%featureName"
-      version="5.0.3.qualifier"
+      version="5.1.0.qualifier"
       provider-name="%providerName">
 
    <description url="http://www.eclipse.org/jgit/">
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/pom.xml
index 6a77ad7..1f589a7 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/pom.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/pom.xml
@@ -50,7 +50,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>jgit.tycho.parent</artifactId>
-    <version>5.0.3-SNAPSHOT</version>
+    <version>5.1.0-SNAPSHOT</version>
   </parent>
 
   <groupId>org.eclipse.jgit.feature</groupId>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/META-INF/MANIFEST.MF b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/META-INF/MANIFEST.MF
index 0c32cf3..d728459 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/META-INF/MANIFEST.MF
@@ -2,4 +2,4 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: JGit Target Platform Bundle
 Bundle-SymbolicName: org.eclipse.jgit.target
-Bundle-Version: 5.0.3.qualifier
+Bundle-Version: 5.1.0.qualifier
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.5.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.5.target
index 9fab245..ad7c27c 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.5.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.5.target
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <?pde?>
 <!-- generated with https://github.com/mbarbero/fr.obeo.releng.targetplatform -->
-<target name="jgit-4.5" sequenceNumber="1528375371">
+<target name="jgit-4.5" sequenceNumber="1534584553">
   <locations>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
       <unit id="org.eclipse.jetty.client" version="9.4.8.v20171121"/>
@@ -25,16 +25,16 @@
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
       <unit id="org.apache.ant" version="1.9.6.v201510161327"/>
       <unit id="org.apache.ant.source" version="1.9.6.v201510161327"/>
-      <unit id="org.apache.commons.codec" version="1.9.0.v20170208-1614"/>
-      <unit id="org.apache.commons.codec.source" version="1.9.0.v20170208-1614"/>
+      <unit id="org.apache.commons.codec" version="1.10.0.v20180409-1845"/>
+      <unit id="org.apache.commons.codec.source" version="1.10.0.v20180409-1845"/>
       <unit id="org.apache.commons.compress" version="1.15.0.v20180119-1613"/>
       <unit id="org.apache.commons.compress.source" version="1.15.0.v20180119-1613"/>
-      <unit id="org.apache.commons.logging" version="1.1.1.v201101211721"/>
-      <unit id="org.apache.commons.logging.source" version="1.1.1.v201101211721"/>
-      <unit id="org.apache.httpcomponents.httpcore" version="4.4.6.v20170210-0925"/>
-      <unit id="org.apache.httpcomponents.httpcore.source" version="4.4.6.v20170210-0925"/>
-      <unit id="org.apache.httpcomponents.httpclient" version="4.5.2.v20180410-1551"/>
-      <unit id="org.apache.httpcomponents.httpclient.source" version="4.5.2.v20180410-1551"/>
+      <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.5.v20180409-1525"/>
+      <unit id="org.apache.httpcomponents.httpclient.source" version="4.5.5.v20180409-1525"/>
+      <unit id="org.apache.httpcomponents.httpcore" version="4.4.9.v20180409-1525"/>
+      <unit id="org.apache.httpcomponents.httpcore.source" version="4.4.9.v20180409-1525"/>
       <unit id="org.apache.log4j" version="1.2.15.v201012070815"/>
       <unit id="org.apache.log4j.source" version="1.2.15.v201012070815"/>
       <unit id="org.kohsuke.args4j" version="2.33.0.v20160323-2218"/>
@@ -66,7 +66,7 @@
       <unit id="org.slf4j.impl.log4j12.source" version="1.7.2.v20131105-2200"/>
       <unit id="com.jcraft.jzlib" version="1.1.1.v201205102305"/>
       <unit id="com.jcraft.jzlib.source" version="1.1.1.v201205102305"/>
-      <repository location="http://download.eclipse.org/tools/orbit/downloads/drops/R20180606145124/repository"/>
+      <repository location="http://download.eclipse.org/tools/orbit/downloads/drops/S20180730183850/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.5.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.5.tpd
index c85343c..3ad176d 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.5.tpd
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.5.tpd
@@ -1,7 +1,7 @@
 target "jgit-4.5" with source configurePhase
 
 include "projects/jetty-9.4.8.tpd"
-include "orbit/R20180606145124-Photon.tpd"
+include "orbit/S20180730183850-2018-09.tpd"
 
 location "http://download.eclipse.org/releases/mars/" {
 	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 909b330..9fec46b 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,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <?pde?>
 <!-- generated with https://github.com/mbarbero/fr.obeo.releng.targetplatform -->
-<target name="jgit-4.6" sequenceNumber="1528375359">
+<target name="jgit-4.6" sequenceNumber="1534584542">
   <locations>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
       <unit id="org.eclipse.jetty.client" version="9.4.8.v20171121"/>
@@ -25,16 +25,16 @@
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
       <unit id="org.apache.ant" version="1.9.6.v201510161327"/>
       <unit id="org.apache.ant.source" version="1.9.6.v201510161327"/>
-      <unit id="org.apache.commons.codec" version="1.9.0.v20170208-1614"/>
-      <unit id="org.apache.commons.codec.source" version="1.9.0.v20170208-1614"/>
+      <unit id="org.apache.commons.codec" version="1.10.0.v20180409-1845"/>
+      <unit id="org.apache.commons.codec.source" version="1.10.0.v20180409-1845"/>
       <unit id="org.apache.commons.compress" version="1.15.0.v20180119-1613"/>
       <unit id="org.apache.commons.compress.source" version="1.15.0.v20180119-1613"/>
-      <unit id="org.apache.commons.logging" version="1.1.1.v201101211721"/>
-      <unit id="org.apache.commons.logging.source" version="1.1.1.v201101211721"/>
-      <unit id="org.apache.httpcomponents.httpcore" version="4.4.6.v20170210-0925"/>
-      <unit id="org.apache.httpcomponents.httpcore.source" version="4.4.6.v20170210-0925"/>
-      <unit id="org.apache.httpcomponents.httpclient" version="4.5.2.v20180410-1551"/>
-      <unit id="org.apache.httpcomponents.httpclient.source" version="4.5.2.v20180410-1551"/>
+      <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.5.v20180409-1525"/>
+      <unit id="org.apache.httpcomponents.httpclient.source" version="4.5.5.v20180409-1525"/>
+      <unit id="org.apache.httpcomponents.httpcore" version="4.4.9.v20180409-1525"/>
+      <unit id="org.apache.httpcomponents.httpcore.source" version="4.4.9.v20180409-1525"/>
       <unit id="org.apache.log4j" version="1.2.15.v201012070815"/>
       <unit id="org.apache.log4j.source" version="1.2.15.v201012070815"/>
       <unit id="org.kohsuke.args4j" version="2.33.0.v20160323-2218"/>
@@ -66,7 +66,7 @@
       <unit id="org.slf4j.impl.log4j12.source" version="1.7.2.v20131105-2200"/>
       <unit id="com.jcraft.jzlib" version="1.1.1.v201205102305"/>
       <unit id="com.jcraft.jzlib.source" version="1.1.1.v201205102305"/>
-      <repository location="http://download.eclipse.org/tools/orbit/downloads/drops/R20180606145124/repository"/>
+      <repository location="http://download.eclipse.org/tools/orbit/downloads/drops/S20180730183850/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 3c2a910..fcc8ba2 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.8.tpd"
-include "orbit/R20180606145124-Photon.tpd"
+include "orbit/S20180730183850-2018-09.tpd"
 
 location "http://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 8b064bc..b6691af 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,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <?pde?>
 <!-- generated with https://github.com/mbarbero/fr.obeo.releng.targetplatform -->
-<target name="jgit-4.7" sequenceNumber="1528375339">
+<target name="jgit-4.7" sequenceNumber="1534584523">
   <locations>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
       <unit id="org.eclipse.jetty.client" version="9.4.8.v20171121"/>
@@ -25,16 +25,16 @@
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
       <unit id="org.apache.ant" version="1.9.6.v201510161327"/>
       <unit id="org.apache.ant.source" version="1.9.6.v201510161327"/>
-      <unit id="org.apache.commons.codec" version="1.9.0.v20170208-1614"/>
-      <unit id="org.apache.commons.codec.source" version="1.9.0.v20170208-1614"/>
+      <unit id="org.apache.commons.codec" version="1.10.0.v20180409-1845"/>
+      <unit id="org.apache.commons.codec.source" version="1.10.0.v20180409-1845"/>
       <unit id="org.apache.commons.compress" version="1.15.0.v20180119-1613"/>
       <unit id="org.apache.commons.compress.source" version="1.15.0.v20180119-1613"/>
-      <unit id="org.apache.commons.logging" version="1.1.1.v201101211721"/>
-      <unit id="org.apache.commons.logging.source" version="1.1.1.v201101211721"/>
-      <unit id="org.apache.httpcomponents.httpcore" version="4.4.6.v20170210-0925"/>
-      <unit id="org.apache.httpcomponents.httpcore.source" version="4.4.6.v20170210-0925"/>
-      <unit id="org.apache.httpcomponents.httpclient" version="4.5.2.v20180410-1551"/>
-      <unit id="org.apache.httpcomponents.httpclient.source" version="4.5.2.v20180410-1551"/>
+      <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.5.v20180409-1525"/>
+      <unit id="org.apache.httpcomponents.httpclient.source" version="4.5.5.v20180409-1525"/>
+      <unit id="org.apache.httpcomponents.httpcore" version="4.4.9.v20180409-1525"/>
+      <unit id="org.apache.httpcomponents.httpcore.source" version="4.4.9.v20180409-1525"/>
       <unit id="org.apache.log4j" version="1.2.15.v201012070815"/>
       <unit id="org.apache.log4j.source" version="1.2.15.v201012070815"/>
       <unit id="org.kohsuke.args4j" version="2.33.0.v20160323-2218"/>
@@ -66,7 +66,7 @@
       <unit id="org.slf4j.impl.log4j12.source" version="1.7.2.v20131105-2200"/>
       <unit id="com.jcraft.jzlib" version="1.1.1.v201205102305"/>
       <unit id="com.jcraft.jzlib.source" version="1.1.1.v201205102305"/>
-      <repository location="http://download.eclipse.org/tools/orbit/downloads/drops/R20180606145124/repository"/>
+      <repository location="http://download.eclipse.org/tools/orbit/downloads/drops/S20180730183850/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 4e543ff..2b04cbc 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.8.tpd"
-include "orbit/R20180606145124-Photon.tpd"
+include "orbit/S20180730183850-2018-09.tpd"
 
 location "http://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 6f57c9d..7d6097a 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,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <?pde?>
 <!-- generated with https://github.com/mbarbero/fr.obeo.releng.targetplatform -->
-<target name="jgit-4.8" sequenceNumber="1528872727">
+<target name="jgit-4.8" sequenceNumber="1534584518">
   <locations>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
       <unit id="org.eclipse.jetty.client" version="9.4.8.v20171121"/>
@@ -25,14 +25,16 @@
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
       <unit id="org.apache.ant" version="1.9.6.v201510161327"/>
       <unit id="org.apache.ant.source" version="1.9.6.v201510161327"/>
-      <unit id="org.apache.commons.codec" version="1.9.0.v20170208-1614"/>
-      <unit id="org.apache.commons.codec.source" version="1.9.0.v20170208-1614"/>
+      <unit id="org.apache.commons.codec" version="1.10.0.v20180409-1845"/>
+      <unit id="org.apache.commons.codec.source" version="1.10.0.v20180409-1845"/>
       <unit id="org.apache.commons.compress" version="1.15.0.v20180119-1613"/>
       <unit id="org.apache.commons.compress.source" version="1.15.0.v20180119-1613"/>
-      <unit id="org.apache.commons.logging" version="1.1.1.v201101211721"/>
-      <unit id="org.apache.commons.logging.source" version="1.1.1.v201101211721"/>
-      <unit id="org.apache.httpcomponents.httpcore" version="4.4.6.v20170210-0925"/>
-      <unit id="org.apache.httpcomponents.httpcore.source" version="4.4.6.v20170210-0925"/>
+      <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.5.v20180409-1525"/>
+      <unit id="org.apache.httpcomponents.httpclient.source" version="4.5.5.v20180409-1525"/>
+      <unit id="org.apache.httpcomponents.httpcore" version="4.4.9.v20180409-1525"/>
+      <unit id="org.apache.httpcomponents.httpcore.source" version="4.4.9.v20180409-1525"/>
       <unit id="org.apache.log4j" version="1.2.15.v201012070815"/>
       <unit id="org.apache.log4j.source" version="1.2.15.v201012070815"/>
       <unit id="org.kohsuke.args4j" version="2.33.0.v20160323-2218"/>
@@ -64,12 +66,7 @@
       <unit id="org.slf4j.impl.log4j12.source" version="1.7.2.v20131105-2200"/>
       <unit id="com.jcraft.jzlib" version="1.1.1.v201205102305"/>
       <unit id="com.jcraft.jzlib.source" version="1.1.1.v201205102305"/>
-      <repository location="http://download.eclipse.org/tools/orbit/downloads/drops/R20180606145124/repository"/>
-    </location>
-    <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
-      <unit id="org.apache.httpcomponents.httpclient" version="4.5.2.v20170210-0925"/>
-      <unit id="org.apache.httpcomponents.httpclient.source" version="4.5.2.v20170210-0925"/>
-      <repository location="http://download.eclipse.org/tools/orbit/downloads/drops/R20170919201930/repository/"/>
+      <repository location="http://download.eclipse.org/tools/orbit/downloads/drops/S20180730183850/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 efcba7c..7c3392b 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.8.tpd"
-include "orbit/R20180606145124-Photon.tpd"
+include "orbit/S20180730183850-2018-09.tpd"
 
 location "http://download.eclipse.org/releases/oxygen/" {
 	org.eclipse.osgi lazy
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20180606145124-Photon.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/S20180730183850-2018-09.tpd
similarity index 72%
rename from org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20180606145124-Photon.tpd
rename to org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/S20180730183850-2018-09.tpd
index 808b9d6..0f9cc61 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20180606145124-Photon.tpd
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/S20180730183850-2018-09.tpd
@@ -1,17 +1,19 @@
-target "R20180606145124-Photon" with source configurePhase
+target "S20180730183850-2018-09" with source configurePhase
 // see http://download.eclipse.org/tools/orbit/downloads/
 
-location "http://download.eclipse.org/tools/orbit/downloads/drops/R20180606145124/repository" {
+location "http://download.eclipse.org/tools/orbit/downloads/drops/S20180730183850/repository" {
 	org.apache.ant [1.9.6.v201510161327,1.9.6.v201510161327]
 	org.apache.ant.source [1.9.6.v201510161327,1.9.6.v201510161327]
-	org.apache.commons.codec [1.9.0.v20170208-1614,1.9.0.v20170208-1614]
-	org.apache.commons.codec.source [1.9.0.v20170208-1614,1.9.0.v20170208-1614]
+	org.apache.commons.codec [1.10.0.v20180409-1845,1.10.0.v20180409-1845]
+	org.apache.commons.codec.source [1.10.0.v20180409-1845,1.10.0.v20180409-1845]
 	org.apache.commons.compress [1.15.0.v20180119-1613,1.15.0.v20180119-1613]
 	org.apache.commons.compress.source [1.15.0.v20180119-1613,1.15.0.v20180119-1613s]
-	org.apache.commons.logging [1.1.1.v201101211721,1.1.1.v201101211721]
-	org.apache.commons.logging.source [1.1.1.v201101211721,1.1.1.v201101211721]
-	org.apache.httpcomponents.httpcore [4.4.6.v20170210-0925,4.4.6.v20170210-0925]
-	org.apache.httpcomponents.httpcore.source [4.4.6.v20170210-0925,4.4.6.v20170210-0925]
+	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.5.v20180409-1525,4.5.5.v20180409-1525]
+	org.apache.httpcomponents.httpclient.source [4.5.5.v20180409-1525,4.5.5.v20180409-1525]
+	org.apache.httpcomponents.httpcore [4.4.9.v20180409-1525,4.4.9.v20180409-1525]
+	org.apache.httpcomponents.httpcore.source [4.4.9.v20180409-1525,4.4.9.v20180409-1525]
 	org.apache.log4j [1.2.15.v201012070815,1.2.15.v201012070815]
 	org.apache.log4j.source [1.2.15.v201012070815,1.2.15.v201012070815]
 	org.kohsuke.args4j [2.33.0.v20160323-2218,2.33.0.v20160323-2218]
@@ -44,9 +46,3 @@
 	com.jcraft.jzlib [1.1.1.v201205102305,1.1.1.v201205102305]
 	com.jcraft.jzlib.source [1.1.1.v201205102305,1.1.1.v201205102305]
 }
-
-location "http://download.eclipse.org/tools/orbit/downloads/drops/R20170919201930/repository/" {
-	// platform uses this outdated version of httpclient in Photon
-	org.apache.httpcomponents.httpclient [4.5.2.v20170210-0925,4.5.2.v20170210-0925]
-	org.apache.httpcomponents.httpclient.source [4.5.2.v20170210-0925,4.5.2.v20170210-0925]
-}
\ No newline at end of file
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/pom.xml
index 1be9ccc..6ac5e24 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/pom.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/pom.xml
@@ -49,7 +49,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>jgit.tycho.parent</artifactId>
-    <version>5.0.3-SNAPSHOT</version>
+    <version>5.1.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.target</artifactId>
diff --git a/org.eclipse.jgit.packaging/pom.xml b/org.eclipse.jgit.packaging/pom.xml
index 4da657d..3e05a06 100644
--- a/org.eclipse.jgit.packaging/pom.xml
+++ b/org.eclipse.jgit.packaging/pom.xml
@@ -53,13 +53,13 @@
 
   <groupId>org.eclipse.jgit</groupId>
   <artifactId>jgit.tycho.parent</artifactId>
-  <version>5.0.3-SNAPSHOT</version>
+  <version>5.1.0-SNAPSHOT</version>
   <packaging>pom</packaging>
 
   <name>JGit Tycho Parent</name>
 
   <properties>
-    <tycho-version>1.1.0</tycho-version>
+    <tycho-version>1.2.0</tycho-version>
     <tycho-extras-version>${tycho-version}</tycho-extras-version>
     <target-platform>jgit-4.6</target-platform>
   </properties>
@@ -169,7 +169,7 @@
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-resources-plugin</artifactId>
-          <version>3.0.2</version>
+          <version>3.1.0</version>
           <configuration>
             <encoding>ISO-8859-1</encoding>
           </configuration>
@@ -236,12 +236,12 @@
         <plugin>
           <groupId>org.eclipse.cbi.maven.plugins</groupId>
           <artifactId>eclipse-jarsigner-plugin</artifactId>
-          <version>1.1.4</version>
+          <version>1.1.5</version>
         </plugin>
         <plugin>
           <groupId>org.codehaus.mojo</groupId>
           <artifactId>build-helper-maven-plugin</artifactId>
-          <version>1.12</version>
+          <version>3.0.0</version>
         </plugin>
       </plugins>
     </pluginManagement>
diff --git a/org.eclipse.jgit.pgm.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.pgm.test/META-INF/MANIFEST.MF
index a906687..d5e8fc4 100644
--- a/org.eclipse.jgit.pgm.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.pgm.test/META-INF/MANIFEST.MF
@@ -3,28 +3,28 @@
 Bundle-Name: %plugin_name
 Automatic-Module-Name: org.eclipse.jgit.pgm.test
 Bundle-SymbolicName: org.eclipse.jgit.pgm.test
-Bundle-Version: 5.0.3.qualifier
+Bundle-Version: 5.1.0.qualifier
 Bundle-Vendor: %provider_name
 Bundle-Localization: plugin
 Bundle-ActivationPolicy: lazy
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
-Import-Package: org.eclipse.jgit.api;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.api.errors;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.diff;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.dircache;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.internal.storage.file;version="5.0.3",
- org.eclipse.jgit.junit;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.lib;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.merge;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.pgm;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.pgm.internal;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.pgm.opt;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.revwalk;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.storage.file;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.transport;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.treewalk;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.util;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.util.io;version="[5.0.3,5.1.0)",
+Import-Package: org.eclipse.jgit.api;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.api.errors;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.diff;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.dircache;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.internal.storage.file;version="5.1.0",
+ org.eclipse.jgit.junit;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.lib;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.merge;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.pgm;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.pgm.internal;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.pgm.opt;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.revwalk;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.storage.file;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.transport;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.treewalk;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.util;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.util.io;version="[5.1.0,5.2.0)",
  org.hamcrest.core;bundle-version="[1.1.0,2.0.0)",
  org.junit;version="[4.12,5.0.0)",
  org.junit.rules;version="[4.12,5.0.0)",
diff --git a/org.eclipse.jgit.pgm.test/pom.xml b/org.eclipse.jgit.pgm.test/pom.xml
index e82efa3..ac30368 100644
--- a/org.eclipse.jgit.pgm.test/pom.xml
+++ b/org.eclipse.jgit.pgm.test/pom.xml
@@ -50,7 +50,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>org.eclipse.jgit-parent</artifactId>
-    <version>5.0.3-SNAPSHOT</version>
+    <version>5.1.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.pgm.test</artifactId>
diff --git a/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF b/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF
index bf5ef80..56c1141 100644
--- a/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF
@@ -3,7 +3,7 @@
 Bundle-Name: %plugin_name
 Automatic-Module-Name: org.eclipse.jgit.pgm
 Bundle-SymbolicName: org.eclipse.jgit.pgm
-Bundle-Version: 5.0.3.qualifier
+Bundle-Version: 5.1.0.qualifier
 Bundle-Vendor: %provider_name
 Bundle-ActivationPolicy: lazy
 Bundle-Localization: plugin
@@ -28,49 +28,49 @@
  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.0.3,5.1.0)",
- org.eclipse.jgit.api.errors;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.archive;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.awtui;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.blame;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.diff;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.dircache;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.errors;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.gitrepo;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.internal.ketch;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.internal.storage.dfs;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.internal.storage.file;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.internal.storage.io;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.internal.storage.pack;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.internal.storage.reftable;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.internal.storage.reftree;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.lfs;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.lfs.lib;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.lfs.server;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.lfs.server.fs;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.lfs.server.s3;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.lib;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.merge;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.nls;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.notes;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.revplot;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.revwalk;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.revwalk.filter;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.storage.file;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.storage.pack;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.transport;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.transport.http.apache;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.transport.resolver;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.treewalk;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.treewalk.filter;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.util;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.util.io;version="[5.0.3,5.1.0)",
+ org.eclipse.jgit.api;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.api.errors;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.archive;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.awtui;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.blame;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.diff;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.dircache;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.errors;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.gitrepo;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.internal.ketch;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.internal.storage.dfs;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.internal.storage.file;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.internal.storage.io;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.internal.storage.pack;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.internal.storage.reftable;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.internal.storage.reftree;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.lfs;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.lfs.lib;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.lfs.server;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.lfs.server.fs;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.lfs.server.s3;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.lib;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.merge;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.nls;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.notes;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.revplot;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.revwalk;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.revwalk.filter;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.storage.file;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.storage.pack;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.transport;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.transport.http.apache;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.transport.resolver;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.treewalk;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.treewalk.filter;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.util;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.util.io;version="[5.1.0,5.2.0)",
  org.kohsuke.args4j;version="[2.33.0,3.0.0)",
  org.kohsuke.args4j.spi;version="[2.33.0,3.0.0)"
-Export-Package: org.eclipse.jgit.console;version="5.0.3";
+Export-Package: org.eclipse.jgit.console;version="5.1.0";
   uses:="org.eclipse.jgit.transport,
    org.eclipse.jgit.util",
- org.eclipse.jgit.pgm;version="5.0.3";
+ org.eclipse.jgit.pgm;version="5.1.0";
   uses:="org.eclipse.jgit.revwalk,
    org.eclipse.jgit.treewalk.filter,
    org.eclipse.jgit.pgm.opt,
@@ -81,11 +81,11 @@
    org.eclipse.jgit.treewalk,
    javax.swing,
    org.eclipse.jgit.transport",
- org.eclipse.jgit.pgm.debug;version="5.0.3";
+ org.eclipse.jgit.pgm.debug;version="5.1.0";
   uses:="org.eclipse.jgit.util.io,
    org.eclipse.jgit.pgm",
- org.eclipse.jgit.pgm.internal;version="5.0.3";x-friends:="org.eclipse.jgit.pgm.test,org.eclipse.jgit.test",
- org.eclipse.jgit.pgm.opt;version="5.0.3";
+ org.eclipse.jgit.pgm.internal;version="5.1.0";x-friends:="org.eclipse.jgit.pgm.test,org.eclipse.jgit.test",
+ org.eclipse.jgit.pgm.opt;version="5.1.0";
   uses:="org.eclipse.jgit.lib,
    org.eclipse.jgit.revwalk,
    org.kohsuke.args4j.spi,
diff --git a/org.eclipse.jgit.pgm/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.pgm/META-INF/SOURCE-MANIFEST.MF
index 60a0688..affd3c9 100644
--- a/org.eclipse.jgit.pgm/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.pgm/META-INF/SOURCE-MANIFEST.MF
@@ -3,5 +3,5 @@
 Bundle-Name: org.eclipse.jgit.pgm - Sources
 Bundle-SymbolicName: org.eclipse.jgit.pgm.source
 Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 5.0.3.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit.pgm;version="5.0.3.qualifier";roots="."
+Bundle-Version: 5.1.0.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit.pgm;version="5.1.0.qualifier";roots="."
diff --git a/org.eclipse.jgit.pgm/pom.xml b/org.eclipse.jgit.pgm/pom.xml
index 0135776..d050e79 100644
--- a/org.eclipse.jgit.pgm/pom.xml
+++ b/org.eclipse.jgit.pgm/pom.xml
@@ -50,7 +50,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>org.eclipse.jgit-parent</artifactId>
-    <version>5.0.3-SNAPSHOT</version>
+    <version>5.1.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.pgm</artifactId>
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ReadReftable.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ReadReftable.java
index fda1901..0b36e9c 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ReadReftable.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ReadReftable.java
@@ -70,7 +70,7 @@ protected void run() throws Exception {
 				BlockSource src = BlockSource.from(in);
 				ReftableReader reader = new ReftableReader(src)) {
 			try (RefCursor rc = ref != null
-					? reader.seekRef(ref)
+					? reader.seekRefsWithPrefix(ref)
 					: reader.allRefs()) {
 				while (rc.next()) {
 					write(rc.getRef());
diff --git a/org.eclipse.jgit.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.test/META-INF/MANIFEST.MF
index ca557df..e0ad0b4 100644
--- a/org.eclipse.jgit.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.test/META-INF/MANIFEST.MF
@@ -3,58 +3,58 @@
 Bundle-Name: %plugin_name
 Automatic-Module-Name: org.eclipse.jgit.test
 Bundle-SymbolicName: org.eclipse.jgit.test
-Bundle-Version: 5.0.3.qualifier
+Bundle-Version: 5.1.0.qualifier
 Bundle-Localization: plugin
 Bundle-Vendor: %provider_name
 Bundle-ActivationPolicy: lazy
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
 Import-Package: com.googlecode.javaewah;version="[1.1.6,2.0.0)",
  com.jcraft.jsch;version="[0.1.54,0.2.0)",
- org.eclipse.jgit.api;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.api.errors;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.attributes;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.awtui;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.blame;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.diff;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.dircache;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.errors;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.events;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.fnmatch;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.gitrepo;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.hooks;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.ignore;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.ignore.internal;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.internal;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.internal.fsck;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.internal.storage.dfs;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.internal.storage.file;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.internal.storage.io;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.internal.storage.pack;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.internal.storage.reftable;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.internal.storage.reftree;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.junit;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.lfs;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.lib;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.merge;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.nls;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.notes;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.patch;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.pgm;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.pgm.internal;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.revplot;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.revwalk;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.revwalk.filter;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.storage.file;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.storage.pack;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.submodule;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.transport;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.transport.http;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.transport.resolver;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.treewalk;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.treewalk.filter;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.util;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.util.io;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.util.sha1;version="[5.0.3,5.1.0)",
+ org.eclipse.jgit.api;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.api.errors;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.attributes;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.awtui;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.blame;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.diff;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.dircache;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.errors;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.events;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.fnmatch;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.gitrepo;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.hooks;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.ignore;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.ignore.internal;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.internal;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.internal.fsck;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.internal.storage.dfs;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.internal.storage.file;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.internal.storage.io;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.internal.storage.pack;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.internal.storage.reftable;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.internal.storage.reftree;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.junit;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.lfs;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.lib;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.merge;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.nls;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.notes;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.patch;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.pgm;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.pgm.internal;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.revplot;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.revwalk;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.revwalk.filter;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.storage.file;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.storage.pack;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.submodule;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.transport;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.transport.http;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.transport.resolver;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.treewalk;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.treewalk.filter;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.util;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.util.io;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.util.sha1;version="[5.1.0,5.2.0)",
  org.junit;version="[4.12,5.0.0)",
  org.junit.experimental.theories;version="[4.12,5.0.0)",
  org.junit.rules;version="[4.12,5.0.0)",
diff --git a/org.eclipse.jgit.test/pom.xml b/org.eclipse.jgit.test/pom.xml
index f6ad0ce..017db3d 100644
--- a/org.eclipse.jgit.test/pom.xml
+++ b/org.eclipse.jgit.test/pom.xml
@@ -52,7 +52,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>org.eclipse.jgit-parent</artifactId>
-    <version>5.0.3-SNAPSHOT</version>
+    <version>5.1.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.test</artifactId>
@@ -157,7 +157,7 @@
       <plugin>
         <artifactId>maven-surefire-plugin</artifactId>
         <configuration>
-          <argLine>-Xmx256m -Dfile.encoding=UTF-8 -Djava.io.tmpdir=${project.build.directory}</argLine>
+          <argLine>-Xmx1024m -Dfile.encoding=UTF-8 -Djava.io.tmpdir=${project.build.directory}</argLine>
           <includes>
             <include>**/*Test.java</include>
             <include>**/*Tests.java</include>
diff --git a/org.eclipse.jgit.test/tests.bzl b/org.eclipse.jgit.test/tests.bzl
index b1b7b7a..64dfe07 100644
--- a/org.eclipse.jgit.test/tests.bzl
+++ b/org.eclipse.jgit.test/tests.bzl
@@ -42,6 +42,10 @@
         '//lib:jsch',
       ]
 
+    heap_size = "-Xmx256m"
+    if src.endswith("HugeCommitMessageTest.java"):
+      heap_size = "-Xmx512m"
+
     junit_tests(
       name = name,
       tags = labels,
@@ -57,5 +61,5 @@
         '//org.eclipse.jgit.lfs:jgit-lfs',
       ],
       flaky = flaky,
-      jvm_flags = ["-Xmx256m", "-Dfile.encoding=UTF-8"],
+      jvm_flags = [heap_size, "-Dfile.encoding=UTF-8"],
     )
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PushCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PushCommandTest.java
index 1af37e2..ca86d81 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PushCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PushCommandTest.java
@@ -245,7 +245,7 @@ public void testPushRefUpdate() throws Exception {
 				git.add().addFilepattern("f" + i).call();
 				commit = git.commit().setMessage("adding f" + i).call();
 				git.push().setRemote("test").call();
-				git2.getRepository().getAllRefs();
+				git2.getRepository().getRefDatabase().getRefs();
 				assertEquals("failed to update on attempt " + i, commit.getId(),
 						git2.getRepository().resolve("refs/heads/test"));
 			}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RebaseCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RebaseCommandTest.java
index 96e7091..621e061 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RebaseCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RebaseCommandTest.java
@@ -57,9 +57,12 @@
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStreamReader;
+import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Set;
 
 import org.eclipse.jgit.api.MergeResult.MergeStatus;
 import org.eclipse.jgit.api.RebaseCommand.InteractiveHandler;
@@ -75,6 +78,7 @@
 import org.eclipse.jgit.errors.IllegalTodoFileModification;
 import org.eclipse.jgit.errors.IncorrectObjectTypeException;
 import org.eclipse.jgit.errors.MissingObjectException;
+import org.eclipse.jgit.events.ListenerHandle;
 import org.eclipse.jgit.junit.RepositoryTestCase;
 import org.eclipse.jgit.lib.AbbreviatedObjectId;
 import org.eclipse.jgit.lib.ConfigConstants;
@@ -1981,6 +1985,62 @@ public void testRebaseWithAutoStash()
 	}
 
 	@Test
+	public void testRebaseWithAutoStashAndSubdirs() throws Exception {
+		// create file0, add and commit
+		db.getConfig().setBoolean(ConfigConstants.CONFIG_REBASE_SECTION, null,
+				ConfigConstants.CONFIG_KEY_AUTOSTASH, true);
+		writeTrashFile("sub/file0", "file0");
+		git.add().addFilepattern("sub/file0").call();
+		git.commit().setMessage("commit0").call();
+		// create file1, add and commit
+		writeTrashFile(FILE1, "file1");
+		git.add().addFilepattern(FILE1).call();
+		RevCommit commit = git.commit().setMessage("commit1").call();
+
+		// create topic branch and checkout / create file2, add and commit
+		createBranch(commit, "refs/heads/topic");
+		checkoutBranch("refs/heads/topic");
+		writeTrashFile("file2", "file2");
+		git.add().addFilepattern("file2").call();
+		git.commit().setMessage("commit2").call();
+
+		// checkout master branch / modify file1, add and commit
+		checkoutBranch("refs/heads/master");
+		writeTrashFile(FILE1, "modified file1");
+		git.add().addFilepattern(FILE1).call();
+		git.commit().setMessage("commit3").call();
+
+		// checkout topic branch / modify file0
+		checkoutBranch("refs/heads/topic");
+		writeTrashFile("sub/file0", "unstaged modified file0");
+
+		Set<String> modifiedFiles = new HashSet<>();
+		ListenerHandle handle = db.getListenerList()
+				.addWorkingTreeModifiedListener(
+						event -> modifiedFiles.addAll(event.getModified()));
+		try {
+			// rebase
+			assertEquals(Status.OK, git.rebase()
+					.setUpstream("refs/heads/master").call().getStatus());
+		} finally {
+			handle.remove();
+		}
+		checkFile(new File(new File(db.getWorkTree(), "sub"), "file0"),
+				"unstaged modified file0");
+		checkFile(new File(db.getWorkTree(), FILE1), "modified file1");
+		checkFile(new File(db.getWorkTree(), "file2"), "file2");
+		assertEquals(
+				"[file1, mode:100644, content:modified file1]"
+						+ "[file2, mode:100644, content:file2]"
+						+ "[sub/file0, mode:100644, content:file0]",
+				indexState(CONTENT));
+		assertEquals(RepositoryState.SAFE, db.getRepositoryState());
+		List<String> modified = new ArrayList<>(modifiedFiles);
+		Collections.sort(modified);
+		assertEquals("[file1, sub/file0]", modified.toString());
+	}
+
+	@Test
 	public void testRebaseWithAutoStashConflictOnApply() throws Exception {
 		// create file0, add and commit
 		db.getConfig().setBoolean(ConfigConstants.CONFIG_REBASE_SECTION, null,
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/StashApplyCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/StashApplyCommandTest.java
index ad3ab7f..fa6c960 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/StashApplyCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/StashApplyCommandTest.java
@@ -234,7 +234,7 @@ public void workingDirectoryModifyInSubfolder() throws Exception {
 		ObjectId unstashed = git.stashApply().call();
 		assertEquals(stashed, unstashed);
 		assertEquals("content2", read(subfolderFile));
-		recorder.assertEvent(new String[] { "d1/d2/f.txt", "d1/d2", "d1" },
+		recorder.assertEvent(new String[] { "d1/d2/f.txt" },
 				ChangeRecorder.EMPTY);
 
 		Status status = git.status().call();
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/gitrepo/RepoCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/gitrepo/RepoCommandTest.java
index df31ab0..1eca587 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/gitrepo/RepoCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/gitrepo/RepoCommandTest.java
@@ -268,7 +268,8 @@ public void androidSetup() throws Exception {
 						.getCachedBytes(Integer.MAX_VALUE);
 				Config base = new Config();
 				BlobBasedConfig cfg = new BlobBasedConfig(base, bytes);
-				String subUrl = cfg.getString("submodule", "base", "url");
+				String subUrl = cfg.getString("submodule", "platform/base",
+						"url");
 				assertEquals(subUrl, "../base");
 			}
 		}
@@ -301,7 +302,8 @@ public void recordUnreachableRemotes() throws Exception {
 						.getCachedBytes(Integer.MAX_VALUE);
 				Config base = new Config();
 				BlobBasedConfig cfg = new BlobBasedConfig(base, bytes);
-				String subUrl = cfg.getString("submodule", "base", "url");
+				String subUrl = cfg.getString("submodule", "platform/base",
+						"url");
 				assertEquals(subUrl, "https://host.com/platform/base");
 			}
 		}
@@ -387,8 +389,8 @@ public void absoluteRemoteURL() throws Exception {
 								.getCachedBytes(Integer.MAX_VALUE);
 						Config base = new Config();
 						BlobBasedConfig cfg = new BlobBasedConfig(base, bytes);
-						String subUrl = cfg.getString("submodule", "src",
-								"url");
+						String subUrl = cfg.getString("submodule",
+								"chromium/src", "url");
 						assertEquals(
 								"https://chromium.googlesource.com/chromium/src",
 								subUrl);
@@ -443,8 +445,8 @@ public void absoluteRemoteURLAbsoluteTargetURL() throws Exception {
 								.getCachedBytes(Integer.MAX_VALUE);
 						Config base = new Config();
 						BlobBasedConfig cfg = new BlobBasedConfig(base, bytes);
-						String subUrl = cfg.getString("submodule", "src",
-								"url");
+						String subUrl = cfg.getString("submodule",
+								"chromium/src", "url");
 						assertEquals("../chromium/src", subUrl);
 					}
 					fetchSlash = !fetchSlash;
@@ -613,7 +615,7 @@ public void testBareRepo() throws Exception {
 				String content = reader.readLine();
 				assertEquals(
 						"The first line of .gitmodules file should be as expected",
-						"[submodule \"foo\"]", content);
+						"[submodule \"" + defaultUri + "\"]", content);
 			}
 			// The gitlink should be the same as remote head sha1
 			String gitlink = localDb.resolve(Constants.HEAD + ":foo").name();
@@ -801,9 +803,9 @@ public void testReplaceManifestBare() throws Exception {
 				.append("<manifest>")
 				.append("<remote name=\"remote1\" fetch=\".\" />")
 				.append("<default revision=\"master\" remote=\"remote1\" />")
-				.append("<project path=\"bar\" name=\"").append(defaultUri)
-				.append("\" revision=\"").append(BRANCH).append("\" >")
-				.append("<copyfile src=\"hello.txt\" dest=\"Hello.txt\" />")
+				.append("<project path=\"bar\" name=\"").append(notDefaultUri)
+				.append("\" >")
+				.append("<copyfile src=\"world.txt\" dest=\"World.txt\" />")
 				.append("</project>").append("</manifest>");
 		JGitTestUtil.writeTrashFile(tempDb, "new.xml", xmlContent.toString());
 		command = new RepoCommand(remoteDb);
@@ -819,8 +821,8 @@ public void testReplaceManifestBare() throws Exception {
 			File hello = new File(localDb.getWorkTree(), "Hello");
 			assertFalse("The Hello file shouldn't exist", hello.exists());
 			// The Hello.txt file should exist
-			File hellotxt = new File(localDb.getWorkTree(), "Hello.txt");
-			assertTrue("The Hello.txt file should exist", hellotxt.exists());
+			File hellotxt = new File(localDb.getWorkTree(), "World.txt");
+			assertTrue("The World.txt file should exist", hellotxt.exists());
 			dotmodules = new File(localDb.getWorkTree(),
 					Constants.DOT_GIT_MODULES);
 		}
@@ -835,9 +837,9 @@ public void testReplaceManifestBare() throws Exception {
 				String line = reader.readLine();
 				if (line == null)
 					break;
-				if (line.contains("submodule \"foo\""))
+				if (line.contains("submodule \"" + defaultUri + "\""))
 					foo = true;
-				if (line.contains("submodule \"bar\""))
+				if (line.contains("submodule \"" + notDefaultUri + "\""))
 					bar = true;
 			}
 			assertTrue("The bar submodule should exist", bar);
@@ -876,9 +878,7 @@ public void testRemoveOverlappingBare() throws Exception {
 				Constants.DOT_GIT_MODULES);
 		}
 
-		// The .gitmodules file should have 'submodule "foo"' and shouldn't
-		// have
-		// 'submodule "foo/bar"' lines.
+		// Check .gitmodules file
 		try (BufferedReader reader = new BufferedReader(
 				new FileReader(dotmodules))) {
 			boolean foo = false;
@@ -888,16 +888,17 @@ public void testRemoveOverlappingBare() throws Exception {
 				String line = reader.readLine();
 				if (line == null)
 					break;
-				if (line.contains("submodule \"foo\""))
+				if (line.contains("submodule \"" + defaultUri + "\""))
 					foo = true;
-				if (line.contains("submodule \"foo/bar\""))
+				if (line.contains("submodule \"" + groupBUri + "\""))
 					foobar = true;
-				if (line.contains("submodule \"a\""))
+				if (line.contains("submodule \"" + groupAUri + "\""))
 					a = true;
 			}
-			assertTrue("The foo submodule should exist", foo);
-			assertFalse("The foo/bar submodule shouldn't exist", foobar);
-			assertTrue("The a submodule should exist", a);
+			assertTrue("The " + defaultUri + " submodule should exist", foo);
+			assertFalse("The " + groupBUri + " submodule shouldn't exist",
+					foobar);
+			assertTrue("The " + groupAUri + " submodule should exist", a);
 		}
 	}
 
@@ -1033,11 +1034,11 @@ public void testRecordRemoteBranch() throws Exception {
 			assertEquals(
 					"Recording remote branches should work for short branch descriptions",
 					"master",
-					c.getString("submodule", "with-branch", "branch"));
+					c.getString("submodule", notDefaultUri, "branch"));
 			assertEquals(
 					"Recording remote branches should work for full ref specs",
 					"refs/heads/master",
-					c.getString("submodule", "with-long-branch", "branch"));
+					c.getString("submodule", defaultUri, "branch"));
 		}
 	}
 
@@ -1095,7 +1096,7 @@ public void testRecordShallowRecommendation() throws Exception {
 				.append("<project path=\"shallow-please\" ").append("name=\"")
 				.append(defaultUri).append("\" ").append("clone-depth=\"1\" />")
 				.append("<project path=\"non-shallow\" ").append("name=\"")
-				.append(defaultUri).append("\" />").append("</manifest>");
+				.append(notDefaultUri).append("\" />").append("</manifest>");
 		JGitTestUtil.writeTrashFile(tempDb, "manifest.xml",
 				xmlContent.toString());
 
@@ -1115,9 +1116,9 @@ public void testRecordShallowRecommendation() throws Exception {
 			FileBasedConfig c = new FileBasedConfig(gitmodules, FS.DETECTED);
 			c.load();
 			assertEquals("Recording shallow configuration should work", "true",
-					c.getString("submodule", "shallow-please", "shallow"));
+					c.getString("submodule", defaultUri, "shallow"));
 			assertNull("Recording non shallow configuration should work",
-					c.getString("submodule", "non-shallow", "shallow"));
+					c.getString("submodule", notDefaultUri, "shallow"));
 		}
 	}
 
@@ -1176,6 +1177,43 @@ public void testDefaultRemoteRevision() throws Exception {
 		}
 	}
 
+	@Test
+	public void testTwoPathUseTheSameName() throws Exception {
+		Repository remoteDb = createBareRepository();
+		Repository tempDb = createWorkRepository();
+
+		StringBuilder xmlContent = new StringBuilder();
+		xmlContent.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
+				.append("<manifest>")
+				.append("<remote name=\"remote1\" fetch=\".\" />")
+				.append("<default revision=\"master\" remote=\"remote1\" />")
+				.append("<project path=\"path1\" ").append("name=\"")
+				.append(defaultUri).append("\" />")
+				.append("<project path=\"path2\" ").append("name=\"")
+				.append(defaultUri).append("\" />").append("</manifest>");
+		JGitTestUtil.writeTrashFile(tempDb, "manifest.xml",
+				xmlContent.toString());
+
+		RepoCommand command = new RepoCommand(remoteDb);
+		command.setPath(
+				tempDb.getWorkTree().getAbsolutePath() + "/manifest.xml")
+				.setURI(rootUri).setRecommendShallow(true).call();
+		File directory = createTempDirectory("testBareRepo");
+		try (Repository localDb = Git.cloneRepository().setDirectory(directory)
+				.setURI(remoteDb.getDirectory().toURI().toString()).call()
+				.getRepository();) {
+			File gitmodules = new File(localDb.getWorkTree(), ".gitmodules");
+			assertTrue("The .gitmodules file should exist",
+					gitmodules.exists());
+			FileBasedConfig c = new FileBasedConfig(gitmodules, FS.DETECTED);
+			c.load();
+			assertEquals("A module should exist for path1", "path1",
+					c.getString("submodule", defaultUri + "/path1", "path"));
+			assertEquals("A module should exist for path2", "path2",
+					c.getString("submodule", defaultUri + "/path2", "path"));
+		}
+	}
+
 	private void resolveRelativeUris() {
 		// Find the longest common prefix ends with "/" as rootUri.
 		defaultUri = defaultDb.getDirectory().toURI().toString();
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsGarbageCollectorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsGarbageCollectorTest.java
index 5b567d0..bfa30d5 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsGarbageCollectorTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsGarbageCollectorTest.java
@@ -972,7 +972,7 @@ private void run(DfsGarbageCollector gc) throws IOException {
 	private static boolean isReachable(Repository repo, AnyObjectId id)
 			throws IOException {
 		try (RevWalk rw = new RevWalk(repo)) {
-			for (Ref ref : repo.getAllRefs().values()) {
+			for (Ref ref : repo.getRefDatabase().getRefs()) {
 				rw.markStart(rw.parseCommit(ref.getObjectId()));
 			}
 			for (RevCommit next; (next = rw.next()) != null;) {
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackDescriptionTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackDescriptionTest.java
new file mode 100644
index 0000000..55e1a9c
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackDescriptionTest.java
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 2018, Google LLC.
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ *   copyright notice, this list of conditions and the following
+ *   disclaimer in the documentation and/or other materials provided
+ *   with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ *   names of its contributors may be used to endorse or promote
+ *   products derived from this software without specific prior
+ *   written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.eclipse.jgit.internal.storage.dfs;
+
+import static org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource.COMPACT;
+import static org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource.GC;
+import static org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource.GC_REST;
+import static org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource.GC_TXN;
+import static org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource.INSERT;
+import static org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource.RECEIVE;
+import static org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource.UNREACHABLE_GARBAGE;
+import static org.eclipse.jgit.internal.storage.pack.PackExt.INDEX;
+import static org.eclipse.jgit.internal.storage.pack.PackExt.PACK;
+import static org.junit.Assert.assertEquals;
+
+import java.util.Comparator;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource;
+import org.junit.Before;
+import org.junit.Test;
+
+public final class DfsPackDescriptionTest {
+	private AtomicInteger counter;
+
+	@Before
+	public void setUp() {
+		counter = new AtomicInteger();
+	}
+
+	@Test
+	public void objectLookupComparatorEqual() throws Exception {
+		DfsPackDescription a = create(RECEIVE);
+		a.setFileSize(PACK, 1);
+		a.setFileSize(INDEX, 1);
+		a.setLastModified(1);
+		a.setObjectCount(1);
+		a.setMaxUpdateIndex(1);
+
+		DfsPackDescription b = create(INSERT);
+		b.setFileSize(PACK, 1);
+		b.setFileSize(INDEX, 2);
+		b.setLastModified(1);
+		b.setObjectCount(1);
+		b.setMaxUpdateIndex(2);
+
+		assertComparesEqual(DfsPackDescription.objectLookupComparator(), a, b);
+	}
+
+	@Test
+	public void objectLookupComparatorPackSource() throws Exception {
+		DfsPackDescription a = create(COMPACT);
+		a.setFileSize(PACK, 2);
+		a.setLastModified(1);
+		a.setObjectCount(2);
+
+		DfsPackDescription b = create(GC);
+		b.setFileSize(PACK, 1);
+		b.setLastModified(2);
+		b.setObjectCount(1);
+
+		assertComparesLessThan(DfsPackDescription.objectLookupComparator(), a, b);
+	}
+
+	@Test
+	public void objectLookupComparatorCustomPackSourceComparator()
+			throws Exception {
+		DfsPackDescription a = create(GC);
+
+		DfsPackDescription b = create(COMPACT);
+
+		assertComparesLessThan(DfsPackDescription.objectLookupComparator(), b, a);
+		assertComparesLessThan(
+				DfsPackDescription.objectLookupComparator(
+					new PackSource.ComparatorBuilder()
+						.add(GC)
+						.add(INSERT, RECEIVE, GC_REST, GC_TXN, UNREACHABLE_GARBAGE)
+						.add(COMPACT)
+						.build()),
+				a, b);
+	}
+
+	@Test
+	public void objectLookupComparatorGcFileSize() throws Exception {
+		// a is older and smaller.
+		DfsPackDescription a = create(GC_REST);
+		a.setFileSize(PACK, 100);
+		a.setLastModified(1);
+		a.setObjectCount(2);
+
+		// b is newer and larger.
+		DfsPackDescription b = create(GC_REST);
+		b.setFileSize(PACK, 200);
+		b.setLastModified(2);
+		b.setObjectCount(1);
+
+		// Since they have the same GC type, tiebreaker is size, and a comes first.
+		assertComparesLessThan(DfsPackDescription.objectLookupComparator(), a, b);
+	}
+
+	@Test
+	public void objectLookupComparatorNonGcLastModified()
+			throws Exception {
+		// a is older and smaller.
+		DfsPackDescription a = create(INSERT);
+		a.setFileSize(PACK, 100);
+		a.setLastModified(1);
+		a.setObjectCount(2);
+
+		// b is newer and larger.
+		DfsPackDescription b = create(INSERT);
+		b.setFileSize(PACK, 200);
+		b.setLastModified(2);
+		b.setObjectCount(1);
+
+		// Since they have the same type but not GC, tiebreaker is last modified,
+		// and b comes first.
+		assertComparesLessThan(DfsPackDescription.objectLookupComparator(), b, a);
+	}
+
+	@Test
+	public void objectLookupComparatorObjectCount() throws Exception {
+		DfsPackDescription a = create(INSERT);
+		a.setObjectCount(1);
+
+		DfsPackDescription b = create(INSERT);
+		b.setObjectCount(2);
+
+		assertComparesLessThan(DfsPackDescription.objectLookupComparator(), a, b);
+	}
+
+	@Test
+	public void reftableComparatorEqual() throws Exception {
+		DfsPackDescription a = create(INSERT);
+		a.setFileSize(PACK, 100);
+		a.setObjectCount(1);
+
+		DfsPackDescription b = create(INSERT);
+		b.setFileSize(PACK, 200);
+		a.setObjectCount(2);
+
+		assertComparesEqual(DfsPackDescription.reftableComparator(), a, b);
+	}
+
+	@Test
+	public void reftableComparatorPackSource() throws Exception {
+		DfsPackDescription a = create(INSERT);
+		a.setMaxUpdateIndex(1);
+		a.setLastModified(1);
+
+		DfsPackDescription b = create(GC);
+		b.setMaxUpdateIndex(2);
+		b.setLastModified(2);
+
+		assertComparesLessThan(DfsPackDescription.reftableComparator(), b, a);
+	}
+
+	@Test
+	public void reftableComparatorMaxUpdateIndex() throws Exception {
+		DfsPackDescription a = create(INSERT);
+		a.setMaxUpdateIndex(1);
+		a.setLastModified(2);
+
+		DfsPackDescription b = create(INSERT);
+		b.setMaxUpdateIndex(2);
+		b.setLastModified(1);
+
+		assertComparesLessThan(DfsPackDescription.reftableComparator(), a, b);
+	}
+
+	@Test
+	public void reftableComparatorLastModified() throws Exception {
+		DfsPackDescription a = create(INSERT);
+		a.setLastModified(1);
+
+		DfsPackDescription b = create(INSERT);
+		b.setLastModified(2);
+
+		assertComparesLessThan(DfsPackDescription.reftableComparator(), a, b);
+	}
+
+	@Test
+	public void reuseComparatorEqual() throws Exception {
+		DfsPackDescription a = create(RECEIVE);
+		a.setFileSize(PACK, 1);
+		a.setFileSize(INDEX, 1);
+		a.setLastModified(1);
+		a.setObjectCount(1);
+		a.setMaxUpdateIndex(1);
+
+		DfsPackDescription b = create(INSERT);
+		b.setFileSize(PACK, 2);
+		b.setFileSize(INDEX, 2);
+		b.setLastModified(2);
+		b.setObjectCount(2);
+		b.setMaxUpdateIndex(2);
+
+		assertComparesEqual(DfsPackDescription.reuseComparator(), a, b);
+	}
+
+	@Test
+	public void reuseComparatorGcPackSize() throws Exception {
+		DfsPackDescription a = create(GC_REST);
+		a.setFileSize(PACK, 1);
+		a.setFileSize(INDEX, 1);
+		a.setLastModified(2);
+		a.setObjectCount(1);
+		a.setMaxUpdateIndex(1);
+
+		DfsPackDescription b = create(GC_REST);
+		b.setFileSize(PACK, 2);
+		b.setFileSize(INDEX, 2);
+		b.setLastModified(1);
+		b.setObjectCount(2);
+		b.setMaxUpdateIndex(2);
+
+		assertComparesLessThan(DfsPackDescription.reuseComparator(), b, a);
+	}
+
+	private DfsPackDescription create(PackSource source) {
+		return new DfsPackDescription(
+				new DfsRepositoryDescription("repo"),
+				"pack_" + counter.incrementAndGet(),
+				source);
+	}
+
+	private static <T> void assertComparesEqual(
+			Comparator<T> comparator, T o1, T o2) {
+		assertEquals(
+				"first object must compare equal to itself",
+				0, comparator.compare(o1, o1));
+		assertEquals(
+				"second object must compare equal to itself",
+				0, comparator.compare(o2, o2));
+		assertEquals(
+				"first object must compare equal to second object",
+				0, comparator.compare(o1, o2));
+	}
+
+	private static <T> void assertComparesLessThan(
+			Comparator<T> comparator, T o1, T o2) {
+		assertEquals(
+				"first object must compare equal to itself",
+				0, comparator.compare(o1, o1));
+		assertEquals(
+				"second object must compare equal to itself",
+				0, comparator.compare(o2, o2));
+		assertEquals(
+				"first object must compare less than second object",
+				-1, comparator.compare(o1, o2));
+	}
+}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/PackSourceTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/PackSourceTest.java
new file mode 100644
index 0000000..7bf1f58
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/PackSourceTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2018, Google LLC.
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ *   copyright notice, this list of conditions and the following
+ *   disclaimer in the documentation and/or other materials provided
+ *   with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ *   names of its contributors may be used to endorse or promote
+ *   products derived from this software without specific prior
+ *   written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.eclipse.jgit.internal.storage.dfs;
+
+import static org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource.COMPACT;
+import static org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource.DEFAULT_COMPARATOR;
+import static org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource.GC;
+import static org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource.GC_REST;
+import static org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource.GC_TXN;
+import static org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource.INSERT;
+import static org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource.RECEIVE;
+import static org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource.UNREACHABLE_GARBAGE;
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+public class PackSourceTest {
+	@Test
+	public void defaultComaprator() throws Exception {
+		assertEquals(0, DEFAULT_COMPARATOR.compare(INSERT, INSERT));
+		assertEquals(0, DEFAULT_COMPARATOR.compare(RECEIVE, RECEIVE));
+		assertEquals(0, DEFAULT_COMPARATOR.compare(COMPACT, COMPACT));
+		assertEquals(0, DEFAULT_COMPARATOR.compare(GC, GC));
+		assertEquals(0, DEFAULT_COMPARATOR.compare(GC_REST, GC_REST));
+		assertEquals(0, DEFAULT_COMPARATOR.compare(GC_TXN, GC_TXN));
+		assertEquals(0, DEFAULT_COMPARATOR.compare(UNREACHABLE_GARBAGE, UNREACHABLE_GARBAGE));
+
+		assertEquals(0, DEFAULT_COMPARATOR.compare(INSERT, RECEIVE));
+		assertEquals(0, DEFAULT_COMPARATOR.compare(RECEIVE, INSERT));
+
+		assertEquals(-1, DEFAULT_COMPARATOR.compare(INSERT, COMPACT));
+		assertEquals(1, DEFAULT_COMPARATOR.compare(COMPACT, INSERT));
+
+		assertEquals(-1, DEFAULT_COMPARATOR.compare(RECEIVE, COMPACT));
+		assertEquals(1, DEFAULT_COMPARATOR.compare(COMPACT, RECEIVE));
+
+		assertEquals(-1, DEFAULT_COMPARATOR.compare(COMPACT, GC));
+		assertEquals(1, DEFAULT_COMPARATOR.compare(GC, COMPACT));
+
+		assertEquals(-1, DEFAULT_COMPARATOR.compare(GC, GC_REST));
+		assertEquals(1, DEFAULT_COMPARATOR.compare(GC_REST, GC));
+
+		assertEquals(-1, DEFAULT_COMPARATOR.compare(GC_REST, GC_TXN));
+		assertEquals(1, DEFAULT_COMPARATOR.compare(GC_TXN, GC_REST));
+
+		assertEquals(-1, DEFAULT_COMPARATOR.compare(GC_TXN, UNREACHABLE_GARBAGE));
+		assertEquals(1, DEFAULT_COMPARATOR.compare(UNREACHABLE_GARBAGE, GC_TXN));
+	}
+}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/pack/GcCommitSelectionTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/pack/GcCommitSelectionTest.java
index d9b58e2..ffb6f4e 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/pack/GcCommitSelectionTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/pack/GcCommitSelectionTest.java
@@ -50,6 +50,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
@@ -243,7 +244,8 @@ public void testSelectionOrderingWithChains() throws Exception {
 
 		List<RevCommit> commits = Arrays.asList(m0, m1, m2, b3, m4, b5, m6, b7,
 				m8, m9);
-		PackWriterBitmapPreparer preparer = newPeparer(m9, commits);
+		PackWriterBitmapPreparer preparer = newPreparer(
+				Collections.singleton(m9), commits, new PackConfig());
 		List<BitmapCommit> selection = new ArrayList<>(
 				preparer.selectCommits(commits.size(), PackWriter.NONE));
 
@@ -267,15 +269,107 @@ private RevCommit addCommit(BranchBuilder bb, String msg,
 		return commit.create();
 	}
 
-	private PackWriterBitmapPreparer newPeparer(RevCommit want,
-			List<RevCommit> commits)
-			throws IOException {
+	@Test
+	public void testDistributionOnMultipleBranches() throws Exception {
+		BranchBuilder[] branches = { tr.branch("refs/heads/main"),
+				tr.branch("refs/heads/a"), tr.branch("refs/heads/b"),
+				tr.branch("refs/heads/c") };
+		RevCommit[] tips = new RevCommit[branches.length];
+		List<RevCommit> commits = createHistory(branches, tips);
+		PackConfig config = new PackConfig();
+		config.setBitmapContiguousCommitCount(1);
+		config.setBitmapRecentCommitSpan(5);
+		config.setBitmapDistantCommitSpan(20);
+		config.setBitmapRecentCommitCount(100);
+		Set<RevCommit> wants = new HashSet<>(Arrays.asList(tips));
+		PackWriterBitmapPreparer preparer = newPreparer(wants, commits, config);
+		List<BitmapCommit> selection = new ArrayList<>(
+				preparer.selectCommits(commits.size(), PackWriter.NONE));
+		Set<ObjectId> selected = new HashSet<>();
+		for (BitmapCommit c : selection) {
+			selected.add(c.toObjectId());
+		}
+
+		// Verify that each branch has uniform bitmap selection coverage
+		for (RevCommit c : wants) {
+			assertTrue(selected.contains(c.toObjectId()));
+			int count = 1;
+			int selectedCount = 1;
+			RevCommit parent = c;
+			while (parent.getParentCount() != 0) {
+				parent = parent.getParent(0);
+				count++;
+				if (selected.contains(parent.toObjectId())) {
+					selectedCount++;
+				}
+			}
+			// The selection algorithm prefers merges and will look in the
+			// current range plus the recent commit span before selecting a
+			// commit. Since this history has no merges, we expect the recent
+			// span should have 100/10=10 and distant commit spans should have
+			// 100/25=4 per 100 commit range.
+			int expectedCount = 10 + (count - 100 - 24) / 25;
+			assertTrue(expectedCount <= selectedCount);
+		}
+	}
+
+	private List<RevCommit> createHistory(BranchBuilder[] branches,
+			RevCommit[] tips) throws Exception {
+		/*-
+		 * Create a history like this, where branches a, b and c branch off of the main branch
+		 * at commits 100, 200 and 300, and where commit times move forward alternating between
+		 * branches.
+		 *
+		 * o...o...o...o...o      commits root,m0,m1,...,m399
+		 *      \   \   \
+		 *       \   \   o...     commits branch_c,c300,c301,...,c399
+		 *        \   \
+		 *         \   o...o...   commits branch_b,b200,b201,...,b399
+		 *          \
+		 *           o...o...o... commits branch_a,b100,b101,...,a399
+		 */
+		List<RevCommit> commits = new ArrayList<>();
+		String[] prefixes = { "m", "a", "b", "c" };
+		int branchCount = branches.length;
+		tips[0] = addCommit(commits, branches[0], "root");
+		int counter = 0;
+
+		for (int b = 0; b < branchCount; b++) {
+			for (int i = 0; i < 100; i++, counter++) {
+				for (int j = 0; j <= b; j++) {
+					tips[j] = addCommit(commits, branches[j],
+							prefixes[j] + counter);
+				}
+			}
+			// Create a new branch from current value of the master branch
+			if (b < branchCount - 1) {
+				tips[b + 1] = addCommit(branches[b + 1],
+						"branch_" + prefixes[b + 1], tips[0]);
+			}
+		}
+		return commits;
+	}
+
+	private RevCommit addCommit(List<RevCommit> commits, BranchBuilder bb,
+			String msg, RevCommit... parents) throws Exception {
+		CommitBuilder commit = bb.commit().message(msg).add(msg, msg).tick(1);
+		if (parents.length > 0) {
+			commit.noParents();
+			for (RevCommit parent : parents) {
+				commit.parent(parent);
+			}
+		}
+		RevCommit c = commit.create();
+		commits.add(c);
+		return c;
+	}
+
+	private PackWriterBitmapPreparer newPreparer(Set<RevCommit> wants,
+			List<RevCommit> commits, PackConfig config) throws IOException {
 		List<ObjectToPack> objects = new ArrayList<>(commits.size());
 		for (RevCommit commit : commits) {
 			objects.add(new ObjectToPack(commit, Constants.OBJ_COMMIT));
 		}
-		Set<ObjectId> wants = Collections.singleton((ObjectId) want);
-		PackConfig config = new PackConfig();
 		PackBitmapIndexBuilder builder = new PackBitmapIndexBuilder(objects);
 		return new PackWriterBitmapPreparer(
 				tr.getRepository().newObjectReader(), builder,
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/MergedReftableTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/MergedReftableTest.java
index ec60bd9..1d11573 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/MergedReftableTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/MergedReftableTest.java
@@ -80,7 +80,7 @@ public void noTables() throws IOException {
 		try (RefCursor rc = mr.seekRef(HEAD)) {
 			assertFalse(rc.next());
 		}
-		try (RefCursor rc = mr.seekRef(R_HEADS)) {
+		try (RefCursor rc = mr.seekRefsWithPrefix(R_HEADS)) {
 			assertFalse(rc.next());
 		}
 	}
@@ -94,7 +94,7 @@ public void oneEmptyTable() throws IOException {
 		try (RefCursor rc = mr.seekRef(HEAD)) {
 			assertFalse(rc.next());
 		}
-		try (RefCursor rc = mr.seekRef(R_HEADS)) {
+		try (RefCursor rc = mr.seekRefsWithPrefix(R_HEADS)) {
 			assertFalse(rc.next());
 		}
 	}
@@ -108,7 +108,7 @@ public void twoEmptyTables() throws IOException {
 		try (RefCursor rc = mr.seekRef(HEAD)) {
 			assertFalse(rc.next());
 		}
-		try (RefCursor rc = mr.seekRef(R_HEADS)) {
+		try (RefCursor rc = mr.seekRefsWithPrefix(R_HEADS)) {
 			assertFalse(rc.next());
 		}
 	}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/ReftableTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/ReftableTest.java
index 3ea3061..0ee785c 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/ReftableTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/ReftableTest.java
@@ -101,7 +101,7 @@ public void emptyTable() throws IOException {
 		try (RefCursor rc = t.seekRef(HEAD)) {
 			assertFalse(rc.next());
 		}
-		try (RefCursor rc = t.seekRef(R_HEADS)) {
+		try (RefCursor rc = t.seekRefsWithPrefix(R_HEADS)) {
 			assertFalse(rc.next());
 		}
 		try (LogCursor rc = t.allLogs()) {
@@ -317,10 +317,10 @@ public void seekNotFound() throws IOException {
 	public void namespaceNotFound() throws IOException {
 		Ref exp = ref(MASTER, 1);
 		ReftableReader t = read(write(exp));
-		try (RefCursor rc = t.seekRef("refs/changes/")) {
+		try (RefCursor rc = t.seekRefsWithPrefix("refs/changes/")) {
 			assertFalse(rc.next());
 		}
-		try (RefCursor rc = t.seekRef("refs/tags/")) {
+		try (RefCursor rc = t.seekRefsWithPrefix("refs/tags/")) {
 			assertFalse(rc.next());
 		}
 	}
@@ -332,12 +332,12 @@ public void namespaceHeads() throws IOException {
 		Ref v1 = tag(V1_0, 3, 4);
 
 		ReftableReader t = read(write(master, next, v1));
-		try (RefCursor rc = t.seekRef("refs/tags/")) {
+		try (RefCursor rc = t.seekRefsWithPrefix("refs/tags/")) {
 			assertTrue(rc.next());
 			assertEquals(V1_0, rc.getRef().getName());
 			assertFalse(rc.next());
 		}
-		try (RefCursor rc = t.seekRef("refs/heads/")) {
+		try (RefCursor rc = t.seekRefsWithPrefix("refs/heads/")) {
 			assertTrue(rc.next());
 			assertEquals(MASTER, rc.getRef().getName());
 
@@ -484,7 +484,7 @@ public void onlyReflog() throws IOException {
 		try (RefCursor rc = t.allRefs()) {
 			assertFalse(rc.next());
 		}
-		try (RefCursor rc = t.seekRef("refs/heads/")) {
+		try (RefCursor rc = t.seekRefsWithPrefix("refs/heads/")) {
 			assertFalse(rc.next());
 		}
 		try (LogCursor lc = t.allLogs()) {
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/HugeCommitMessageTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/HugeCommitMessageTest.java
new file mode 100644
index 0000000..4193c4b
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/HugeCommitMessageTest.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2018, Thomas Wolf <thomas.wolf@paranor.ch>
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ *   copyright notice, this list of conditions and the following
+ *   disclaimer in the documentation and/or other materials provided
+ *   with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ *   names of its contributors may be used to endorse or promote
+ *   products derived from this software without specific prior
+ *   written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.eclipse.jgit.lib;
+
+import static org.junit.Assert.assertTrue;
+
+import java.util.List;
+
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.junit.RepositoryTestCase;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.storage.file.WindowCacheConfig;
+import org.eclipse.jgit.storage.pack.PackConfig;
+import org.junit.Test;
+
+public class HugeCommitMessageTest extends RepositoryTestCase {
+
+	private static final int HUGE_SIZE = Math.max(15 * WindowCacheConfig.MB,
+			PackConfig.DEFAULT_BIG_FILE_THRESHOLD + WindowCacheConfig.MB);
+	// Larger than the 5MB fallback limit in RevWalk.getCachedBytes(RevObject
+	// obj, ObjectLoader ldr), and also larger than the default
+	// streamFileThreshold.
+
+	@Test
+	public void testHugeCommitMessage() throws Exception {
+		try (Git git = new Git(db)) {
+			writeTrashFile("foo", "foo");
+			git.add().addFilepattern("foo").call();
+			WindowCacheConfig wc = new WindowCacheConfig();
+			wc.setStreamFileThreshold(HUGE_SIZE + WindowCacheConfig.MB);
+			wc.install();
+			RevCommit commit = git.commit()
+					.setMessage(insanelyHugeCommitMessage()).call();
+			Ref master = db.findRef("master");
+			List<Ref> actual = git.branchList().setContains(commit.getName())
+					.call();
+			assertTrue("Should be contained in branch master",
+					actual.contains(master));
+		}
+	}
+
+	private String insanelyHugeCommitMessage() {
+		final String oneLine = "012345678901234567890123456789012345678901234567890123456789\n";
+		StringBuilder b = new StringBuilder(HUGE_SIZE + oneLine.length());
+		// Give the message a real header; otherwise even writing the reflog
+		// message may run into troubles because RevCommit.getShortMessage()
+		// will return the whole message.
+		b.append("An insanely huge commit message\n\n");
+		while (b.length() < HUGE_SIZE) {
+			b.append(oneLine);
+		}
+		return b.toString();
+	}
+
+}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RacyGitTests.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RacyGitTests.java
index 8d9ccab..3542dfa 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RacyGitTests.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RacyGitTests.java
@@ -45,6 +45,7 @@
 import static java.lang.Long.valueOf;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
 
 import java.io.File;
 import java.io.FileOutputStream;
@@ -157,10 +158,13 @@ public void testRacyGitDetection() throws Exception {
 		// Remember the last modTime of index file. All modifications times of
 		// further modification are translated to this value so it looks that
 		// files have been modified in the same time slot as the index file
-		modTimes.add(Long.valueOf(db.getIndexFile().lastModified()));
+		long indexMod = db.getIndexFile().lastModified();
+		modTimes.add(Long.valueOf(indexMod));
 
 		// modify one file
-		addToWorkDir("a", "a2");
+		long aMod = addToWorkDir("a", "a2").lastModified();
+		assumeTrue(aMod == indexMod);
+
 		// now update the index the index. 'a' has to be racily clean -- because
 		// it's modification time is exactly the same as the previous index file
 		// mod time.
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RefTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RefTest.java
index 2481e64..a42027b 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RefTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RefTest.java
@@ -58,7 +58,7 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.util.List;
-import java.util.Map;
+import java.util.Optional;
 import java.util.TreeSet;
 
 import org.eclipse.jgit.lib.Ref.Storage;
@@ -148,17 +148,22 @@ public void testReadAllIncludingSymrefs() throws Exception {
 		ObjectId r = db.resolve("refs/remotes/origin/HEAD");
 		assertEquals(masterId, r);
 
-		Map<String, Ref> allRefs = db.getAllRefs();
-		Ref refHEAD = allRefs.get("refs/remotes/origin/HEAD");
-		assertNotNull(refHEAD);
-		assertEquals(masterId, refHEAD.getObjectId());
-		assertFalse(refHEAD.isPeeled());
-		assertNull(refHEAD.getPeeledObjectId());
+		List<Ref> allRefs = db.getRefDatabase().getRefs();
+		Optional<Ref> refHEAD = allRefs.stream()
+				.filter(ref -> ref.getName().equals("refs/remotes/origin/HEAD"))
+				.findAny();
+		assertTrue(refHEAD.isPresent());
+		assertEquals(masterId, refHEAD.get().getObjectId());
+		assertFalse(refHEAD.get().isPeeled());
+		assertNull(refHEAD.get().getPeeledObjectId());
 
-		Ref refmaster = allRefs.get("refs/remotes/origin/master");
-		assertEquals(masterId, refmaster.getObjectId());
-		assertFalse(refmaster.isPeeled());
-		assertNull(refmaster.getPeeledObjectId());
+		Optional<Ref> refmaster = allRefs.stream().filter(
+				ref -> ref.getName().equals("refs/remotes/origin/master"))
+				.findAny();
+		assertTrue(refmaster.isPresent());
+		assertEquals(masterId, refmaster.get().getObjectId());
+		assertFalse(refmaster.get().isPeeled());
+		assertNull(refmaster.get().getPeeledObjectId());
 	}
 
 	@Test
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/MergerTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/MergerTest.java
index 58093a3..da4513d 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/MergerTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/MergerTest.java
@@ -60,6 +60,7 @@
 import org.eclipse.jgit.api.Git;
 import org.eclipse.jgit.api.MergeResult;
 import org.eclipse.jgit.api.MergeResult.MergeStatus;
+import org.eclipse.jgit.api.RebaseResult;
 import org.eclipse.jgit.api.errors.CheckoutConflictException;
 import org.eclipse.jgit.api.errors.GitAPIException;
 import org.eclipse.jgit.api.errors.JGitInternalException;
@@ -428,6 +429,44 @@ public void mergeWithCrlfAutoCrlfTrue(MergeStrategy strategy)
 				indexState(CONTENT));
 	}
 
+	@Theory
+	public void rebaseWithCrlfAutoCrlfTrue(MergeStrategy strategy)
+			throws IOException, GitAPIException {
+		Git git = Git.wrap(db);
+		db.getConfig().setString("core", null, "autocrlf", "true");
+		db.getConfig().save();
+		writeTrashFile("crlf.txt", "line 1\r\nline 2\r\nline 3\r\n");
+		git.add().addFilepattern("crlf.txt").call();
+		RevCommit first = git.commit().setMessage("base").call();
+
+		git.checkout().setCreateBranch(true).setStartPoint(first)
+				.setName("brancha").call();
+
+		File testFile = writeTrashFile("crlf.txt",
+				"line 1\r\nmodified line\r\nline 3\r\n");
+		git.add().addFilepattern("crlf.txt").call();
+		git.commit().setMessage("on brancha").call();
+
+		git.checkout().setName("master").call();
+		File otherFile = writeTrashFile("otherfile.txt", "a line\r\n");
+		git.add().addFilepattern("otherfile.txt").call();
+		git.commit().setMessage("on master").call();
+
+		git.checkout().setName("brancha").call();
+		checkFile(testFile, "line 1\r\nmodified line\r\nline 3\r\n");
+		assertFalse(otherFile.exists());
+
+		RebaseResult rebaseResult = git.rebase().setStrategy(strategy)
+				.setUpstream(db.resolve("master")).call();
+		assertEquals(RebaseResult.Status.OK, rebaseResult.getStatus());
+		checkFile(testFile, "line 1\r\nmodified line\r\nline 3\r\n");
+		checkFile(otherFile, "a line\r\n");
+		assertEquals(
+				"[crlf.txt, mode:100644, content:line 1\nmodified line\nline 3\n]"
+						+ "[otherfile.txt, mode:100644, content:a line\n]",
+				indexState(CONTENT));
+	}
+
 	/**
 	 * Merging two equal subtrees when the index does not contain any file in
 	 * that subtree should lead to a merged state.
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevObjectTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevObjectTest.java
index 8e389ae..4969305 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevObjectTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevObjectTest.java
@@ -144,13 +144,13 @@ public void testAddRevFlag() throws Exception {
 		final RevCommit a = commit();
 		final RevFlag flag1 = rw.newFlag("flag1");
 		final RevFlag flag2 = rw.newFlag("flag2");
-		assertEquals(0, a.flags);
+		assertEquals(RevWalk.PARSED, a.flags);
 
 		a.add(flag1);
-		assertEquals(flag1.mask, a.flags);
+		assertEquals(RevWalk.PARSED | flag1.mask, a.flags);
 
 		a.add(flag2);
-		assertEquals(flag1.mask | flag2.mask, a.flags);
+		assertEquals(RevWalk.PARSED | flag1.mask | flag2.mask, a.flags);
 	}
 
 	@Test
@@ -162,10 +162,10 @@ public void testAddRevFlagSet() throws Exception {
 		s.add(flag1);
 		s.add(flag2);
 
-		assertEquals(0, a.flags);
+		assertEquals(RevWalk.PARSED, a.flags);
 
 		a.add(s);
-		assertEquals(flag1.mask | flag2.mask, a.flags);
+		assertEquals(RevWalk.PARSED | flag1.mask | flag2.mask, a.flags);
 	}
 
 	@Test
@@ -175,9 +175,9 @@ public void testRemoveRevFlag() throws Exception {
 		final RevFlag flag2 = rw.newFlag("flag2");
 		a.add(flag1);
 		a.add(flag2);
-		assertEquals(flag1.mask | flag2.mask, a.flags);
+		assertEquals(RevWalk.PARSED | flag1.mask | flag2.mask, a.flags);
 		a.remove(flag2);
-		assertEquals(flag1.mask, a.flags);
+		assertEquals(RevWalk.PARSED | flag1.mask, a.flags);
 	}
 
 	@Test
@@ -191,8 +191,8 @@ public void testRemoveRevFlagSet() throws Exception {
 		s.add(flag2);
 		a.add(flag3);
 		a.add(s);
-		assertEquals(flag1.mask | flag2.mask | flag3.mask, a.flags);
+		assertEquals(RevWalk.PARSED | flag1.mask | flag2.mask | flag3.mask, a.flags);
 		a.remove(s);
-		assertEquals(flag3.mask, a.flags);
+		assertEquals(RevWalk.PARSED | flag3.mask, a.flags);
 	}
 }
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkCullTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkCullTest.java
index fb52828..7984a37 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkCullTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkCullTest.java
@@ -85,7 +85,7 @@ public void testProperlyCullAllAncestors2() throws Exception {
 
 	@Test
 	public void testProperlyCullAllAncestors_LongHistory() throws Exception {
-		final RevCommit a = commit();
+		RevCommit a = commit();
 		RevCommit b = commit(a);
 		for (int i = 0; i < 24; i++) {
 			b = commit(b);
@@ -94,6 +94,12 @@ public void testProperlyCullAllAncestors_LongHistory() throws Exception {
 		}
 		final RevCommit c = commit(b);
 
+		// TestRepository eagerly parses newly created objects. The current rw
+		// is caching that parsed state. To verify that RevWalk itself is lazy,
+		// set up a new one.
+		rw.close();
+		rw = createRevWalk();
+		RevCommit a2 = rw.lookupCommit(a);
 		markStart(c);
 		markUninteresting(b);
 		assertCommit(c, rw.next());
@@ -102,6 +108,6 @@ public void testProperlyCullAllAncestors_LongHistory() throws Exception {
 		// We should have aborted before we got back so far that "a"
 		// would be parsed. Thus, its parents shouldn't be allocated.
 		//
-		assertNull(a.parents);
+		assertNull(a2.parents);
 	}
 }
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkShallowTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkShallowTest.java
index 6df36e7..7554d7a 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkShallowTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkShallowTest.java
@@ -58,138 +58,155 @@ public class RevWalkShallowTest extends RevWalkTestCase {
 
 	@Test
 	public void testDepth1() throws Exception {
-		final RevCommit a = commit();
-		final RevCommit b = commit(a);
-		final RevCommit c = commit(b);
-		final RevCommit d = commit(c);
+		RevCommit[] commits = setupLinearChain();
 
-		createShallowFile(d);
+		createShallowFile(commits[3]);
+		updateCommits(commits);
 
-		rw.reset();
-		markStart(d);
-		assertCommit(d, rw.next());
+		rw.markStart(commits[3]);
+		assertCommit(commits[3], rw.next());
 		assertNull(rw.next());
 	}
 
 	@Test
 	public void testDepth2() throws Exception {
-		final RevCommit a = commit();
-		final RevCommit b = commit(a);
-		final RevCommit c = commit(b);
-		final RevCommit d = commit(c);
+		RevCommit[] commits = setupLinearChain();
 
-		createShallowFile(c);
+		createShallowFile(commits[2]);
+		updateCommits(commits);
 
-		rw.reset();
-		markStart(d);
-		assertCommit(d, rw.next());
-		assertCommit(c, rw.next());
+		rw.markStart(commits[3]);
+		assertCommit(commits[3], rw.next());
+		assertCommit(commits[2], rw.next());
 		assertNull(rw.next());
 	}
 
 	@Test
 	public void testDepth3() throws Exception {
-		final RevCommit a = commit();
-		final RevCommit b = commit(a);
-		final RevCommit c = commit(b);
-		final RevCommit d = commit(c);
+		RevCommit[] commits = setupLinearChain();
 
-		createShallowFile(b);
+		createShallowFile(commits[1]);
+		updateCommits(commits);
 
-		rw.reset();
-		markStart(d);
-		assertCommit(d, rw.next());
-		assertCommit(c, rw.next());
-		assertCommit(b, rw.next());
-		assertNull(rw.next());
-	}
-
-	@Test
-	public void testMergeCommitOneParentShallow() throws Exception {
-		final RevCommit a = commit();
-		final RevCommit b = commit(a);
-		final RevCommit c = commit(b);
-		final RevCommit d = commit(b);
-		final RevCommit e = commit(d);
-		final RevCommit merge = commit(c, e);
-
-		createShallowFile(e);
-
-		rw.reset();
-		markStart(merge);
-		assertCommit(merge, rw.next());
-		assertCommit(e, rw.next());
-		assertCommit(c, rw.next());
-		assertCommit(b, rw.next());
-		assertCommit(a, rw.next());
-		assertNull(rw.next());
-	}
-
-	@Test
-	public void testMergeCommitEntirelyShallow() throws Exception {
-		final RevCommit a = commit();
-		final RevCommit b = commit(a);
-		final RevCommit c = commit(b);
-		final RevCommit d = commit(b);
-		final RevCommit e = commit(d);
-		final RevCommit merge = commit(c, e);
-
-		createShallowFile(c, e);
-
-		rw.reset();
-		markStart(merge);
-		assertCommit(merge, rw.next());
-		assertCommit(e, rw.next());
-		assertCommit(c, rw.next());
+		rw.markStart(commits[3]);
+		assertCommit(commits[3], rw.next());
+		assertCommit(commits[2], rw.next());
+		assertCommit(commits[1], rw.next());
 		assertNull(rw.next());
 	}
 
 	@Test
 	public void testObjectDirectorySnapshot() throws Exception {
-		RevCommit a = commit();
-		RevCommit b = commit(a);
-		RevCommit c = commit(b);
-		RevCommit d = commit(c);
+		RevCommit[] commits = setupLinearChain();
 
-		createShallowFile(d);
+		createShallowFile(commits[3]);
+		updateCommits(commits);
 
-		rw.reset();
-		markStart(d);
-		assertCommit(d, rw.next());
+		markStart(commits[3]);
+		assertCommit(commits[3], rw.next());
 		assertNull(rw.next());
 
-		rw = createRevWalk();
-		a = rw.lookupCommit(a);
-		b = rw.lookupCommit(b);
-		c = rw.lookupCommit(c);
-		d = rw.lookupCommit(d);
+		createShallowFile(commits[2]);
+		updateCommits(commits);
 
-		rw.reset();
-		markStart(d);
-		assertCommit(d, rw.next());
+		markStart(commits[3]);
+		assertCommit(commits[3], rw.next());
+		assertCommit(commits[2], rw.next());
 		assertNull(rw.next());
+	}
 
-		createShallowFile(c);
+	private RevCommit[] setupLinearChain() throws Exception {
+		RevCommit[] commits = new RevCommit[4];
+		RevCommit parent = null;
+		for (int i = 0; i < commits.length; i++) {
+			commits[i] = parent != null ? commit(parent) : commit();
+			parent = commits[i];
+		}
+		return commits;
+	}
 
-		rw = createRevWalk();
-		a = rw.lookupCommit(a);
-		b = rw.lookupCommit(b);
-		c = rw.lookupCommit(c);
-		d = rw.lookupCommit(d);
+	@Test
+	public void testMergeCommitOneParentShallow() throws Exception {
+		RevCommit[] commits = setupMergeChain();
 
-		rw.reset();
-		markStart(d);
-		assertCommit(d, rw.next());
-		assertCommit(c, rw.next());
+		createShallowFile(commits[4]);
+		updateCommits(commits);
+
+		markStart(commits[5]);
+		assertCommit(commits[5], rw.next());
+		assertCommit(commits[4], rw.next());
+		assertCommit(commits[2], rw.next());
+		assertCommit(commits[1], rw.next());
+		assertCommit(commits[0], rw.next());
 		assertNull(rw.next());
 	}
 
+	@Test
+	public void testMergeCommitEntirelyShallow() throws Exception {
+		RevCommit[] commits = setupMergeChain();
+
+		createShallowFile(commits[2], commits[4]);
+		updateCommits(commits);
+
+		markStart(commits[5]);
+		assertCommit(commits[5], rw.next());
+		assertCommit(commits[4], rw.next());
+		assertCommit(commits[2], rw.next());
+		assertNull(rw.next());
+	}
+
+	private RevCommit[] setupMergeChain() throws Exception {
+		/*-
+		 * Create a history like this, diverging at 1 and merging at 5:
+		 *
+		 *      ---o--o       commits 3,4
+		 *     /       \
+		 * o--o--o------o   commits 0,1,2,5
+		 */
+		RevCommit[] commits = new RevCommit[6];
+		commits[0] = commit();
+		commits[1] = commit(commits[0]);
+		commits[2] = commit(commits[1]);
+		commits[3] = commit(commits[1]);
+		commits[4] = commit(commits[3]);
+		commits[5] = commit(commits[2], commits[4]);
+		return commits;
+	}
+
+	private void updateCommits(RevCommit[] commits) {
+		// Relookup commits using the new RevWalk
+		for (int i = 0; i < commits.length; i++) {
+			commits[i] = rw.lookupCommit(commits[i].getId());
+		}
+	}
+
 	private void createShallowFile(ObjectId... shallowCommits)
 			throws IOException {
-		final StringBuilder builder = new StringBuilder();
-		for (ObjectId commit : shallowCommits)
+		// Reset the RevWalk since the new shallow file invalidates the existing
+		// RevWalk's shallow state.
+		rw.close();
+		rw = createRevWalk();
+		StringBuilder builder = new StringBuilder();
+		for (ObjectId commit : shallowCommits) {
 			builder.append(commit.getName() + "\n");
+		}
 		JGitTestUtil.write(new File(db.getDirectory(), "shallow"),
 				builder.toString());
 	}
+
+	@Test
+	public void testShallowCommitParse() throws Exception {
+		RevCommit a = commit();
+		RevCommit b = commit(a);
+
+		createShallowFile(b);
+
+		rw.close();
+		rw = createRevWalk();
+		b = rw.parseCommit(b);
+
+		markStart(b);
+		assertCommit(b, rw.next());
+		assertNull(rw.next());
+	}
 }
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkUtilsReachableTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkUtilsReachableTest.java
index a26ae10..cb92a95 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkUtilsReachableTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkUtilsReachableTest.java
@@ -115,7 +115,7 @@ private Ref branch(String name, RevCommit dst) throws Exception {
 	}
 
 	private void assertContains(RevCommit commit, Collection<Ref> refsThatShouldContainCommit) throws Exception {
-		Collection<Ref> allRefs = db.getAllRefs().values();
+		Collection<Ref> allRefs = db.getRefDatabase().getRefs();
 		Collection<Ref> sortedRefs = RefComparator.sort(allRefs);
 		List<Ref> actual = RevWalkUtils.findBranchesReachableFrom(commit,
 				rw, sortedRefs);
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/submodule/SubmoduleAddTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/submodule/SubmoduleAddTest.java
index 1a67e41..0676eab 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/submodule/SubmoduleAddTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/submodule/SubmoduleAddTest.java
@@ -136,7 +136,49 @@ public void addSubmodule() throws Exception {
 			}
 
 			SubmoduleWalk generator = SubmoduleWalk.forIndex(db);
+			generator.loadModulesConfig();
 			assertTrue(generator.next());
+			assertEquals(path, generator.getModuleName());
+			assertEquals(path, generator.getPath());
+			assertEquals(commit, generator.getObjectId());
+			assertEquals(uri, generator.getModulesUrl());
+			assertEquals(path, generator.getModulesPath());
+			assertEquals(uri, generator.getConfigUrl());
+			try (Repository subModRepo = generator.getRepository()) {
+				assertNotNull(subModRepo);
+				assertEquals(subCommit, commit);
+			}
+
+			Status status = Git.wrap(db).status().call();
+			assertTrue(status.getAdded().contains(Constants.DOT_GIT_MODULES));
+			assertTrue(status.getAdded().contains(path));
+		}
+	}
+
+	@Test
+	public void addSubmoduleWithName() throws Exception {
+		try (Git git = new Git(db)) {
+			writeTrashFile("file.txt", "content");
+			git.add().addFilepattern("file.txt").call();
+			RevCommit commit = git.commit().setMessage("create file").call();
+
+			SubmoduleAddCommand command = new SubmoduleAddCommand(db);
+			String name = "testsub";
+			command.setName(name);
+			String path = "sub";
+			command.setPath(path);
+			String uri = db.getDirectory().toURI().toString();
+			command.setURI(uri);
+			ObjectId subCommit;
+			try (Repository repo = command.call()) {
+				assertNotNull(repo);
+				subCommit = repo.resolve(Constants.HEAD);
+			}
+
+			SubmoduleWalk generator = SubmoduleWalk.forIndex(db);
+			generator.loadModulesConfig();
+			assertTrue(generator.next());
+			assertEquals(name, generator.getModuleName());
 			assertEquals(path, generator.getPath());
 			assertEquals(commit, generator.getObjectId());
 			assertEquals(uri, generator.getModulesUrl());
@@ -268,4 +310,18 @@ public void addSubmoduleWithExistingSubmoduleDefined() throws Exception {
 					ConfigConstants.CONFIG_KEY_URL));
 		}
 	}
+
+	@Test
+	public void denySubmoduleWithDotDot() throws Exception {
+		SubmoduleAddCommand command = new SubmoduleAddCommand(db);
+		command.setName("dir/../");
+		command.setPath("sub");
+		command.setURI(db.getDirectory().toURI().toString());
+		try {
+			command.call();
+			fail();
+		} catch (IllegalArgumentException e) {
+			// Expected
+		}
+	}
 }
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/UploadPackTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/UploadPackTest.java
index ef083da..79d3d87 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/UploadPackTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/UploadPackTest.java
@@ -1,20 +1,24 @@
 package org.eclipse.jgit.transport;
 
+import static org.hamcrest.Matchers.containsString;
 import static org.hamcrest.Matchers.hasItems;
 import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
 import static org.hamcrest.Matchers.theInstance;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.StringWriter;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
 import org.eclipse.jgit.errors.PackProtocolException;
 import org.eclipse.jgit.errors.TransportException;
 import org.eclipse.jgit.internal.storage.dfs.DfsGarbageCollector;
@@ -29,8 +33,8 @@
 import org.eclipse.jgit.lib.TextProgressMonitor;
 import org.eclipse.jgit.revwalk.RevBlob;
 import org.eclipse.jgit.revwalk.RevCommit;
-import org.eclipse.jgit.revwalk.RevTree;
 import org.eclipse.jgit.revwalk.RevTag;
+import org.eclipse.jgit.revwalk.RevTree;
 import org.eclipse.jgit.transport.UploadPack.RequestPolicy;
 import org.eclipse.jgit.transport.resolver.ServiceNotAuthorizedException;
 import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException;
@@ -227,6 +231,44 @@ public UploadPack create(Object req, Repository db)
 	}
 
 	@Test
+	public void testFetchExplicitBlobWithFilter() throws Exception {
+		InMemoryRepository server2 = newRepo("server2");
+		TestRepository<InMemoryRepository> remote2 =
+				new TestRepository<>(server2);
+		RevBlob blob1 = remote2.blob("foobar");
+		RevBlob blob2 = remote2.blob("fooba");
+		RevTree tree = remote2.tree(remote2.file("1", blob1),
+				remote2.file("2", blob2));
+		RevCommit commit = remote2.commit(tree);
+		remote2.update("master", commit);
+		remote2.update("a_blob", blob1);
+
+		server2.getConfig().setBoolean("uploadpack", null, "allowfilter", true);
+
+		testProtocol = new TestProtocol<>(
+				new UploadPackFactory<Object>() {
+					@Override
+					public UploadPack create(Object req, Repository db)
+							throws ServiceNotEnabledException,
+							ServiceNotAuthorizedException {
+						UploadPack up = new UploadPack(db);
+						return up;
+					}
+				}, null);
+		uri = testProtocol.register(ctx, server2);
+
+		try (Transport tn = testProtocol.open(uri, client, "server2")) {
+			tn.setFilterBlobLimit(0);
+			tn.fetch(NullProgressMonitor.INSTANCE, Arrays.asList(
+						new RefSpec(commit.name()),
+						new RefSpec(blob1.name())));
+			assertTrue(client.hasObject(tree.toObjectId()));
+			assertTrue(client.hasObject(blob1.toObjectId()));
+			assertFalse(client.hasObject(blob2.toObjectId()));
+		}
+	}
+
+	@Test
 	public void testFetchWithBlobLimitFilter() throws Exception {
 		InMemoryRepository server2 = newRepo("server2");
 		TestRepository<InMemoryRepository> remote2 =
@@ -262,6 +304,47 @@ public UploadPack create(Object req, Repository db)
 	}
 
 	@Test
+	public void testFetchExplicitBlobWithFilterAndBitmaps() throws Exception {
+		InMemoryRepository server2 = newRepo("server2");
+		TestRepository<InMemoryRepository> remote2 =
+				new TestRepository<>(server2);
+		RevBlob blob1 = remote2.blob("foobar");
+		RevBlob blob2 = remote2.blob("fooba");
+		RevTree tree = remote2.tree(remote2.file("1", blob1),
+				remote2.file("2", blob2));
+		RevCommit commit = remote2.commit(tree);
+		remote2.update("master", commit);
+		remote2.update("a_blob", blob1);
+
+		server2.getConfig().setBoolean("uploadpack", null, "allowfilter", true);
+
+		// generate bitmaps
+		new DfsGarbageCollector(server2).pack(null);
+		server2.scanForRepoChanges();
+
+		testProtocol = new TestProtocol<>(
+				new UploadPackFactory<Object>() {
+					@Override
+					public UploadPack create(Object req, Repository db)
+							throws ServiceNotEnabledException,
+							ServiceNotAuthorizedException {
+						UploadPack up = new UploadPack(db);
+						return up;
+					}
+				}, null);
+		uri = testProtocol.register(ctx, server2);
+
+		try (Transport tn = testProtocol.open(uri, client, "server2")) {
+			tn.setFilterBlobLimit(0);
+			tn.fetch(NullProgressMonitor.INSTANCE, Arrays.asList(
+						new RefSpec(commit.name()),
+						new RefSpec(blob1.name())));
+			assertTrue(client.hasObject(blob1.toObjectId()));
+			assertFalse(client.hasObject(blob2.toObjectId()));
+		}
+	}
+
+	@Test
 	public void testFetchWithBlobLimitFilterAndBitmaps() throws Exception {
 		InMemoryRepository server2 = newRepo("server2");
 		TestRepository<InMemoryRepository> remote2 =
@@ -340,7 +423,8 @@ public UploadPack create(Object req, Repository db)
 	 * and returns UploadPack's output stream.
 	 */
 	private ByteArrayInputStream uploadPackV2Setup(RequestPolicy requestPolicy,
-			RefFilter refFilter, String... inputLines) throws Exception {
+			RefFilter refFilter, ProtocolV2Hook hook, String... inputLines)
+			throws Exception {
 
 		ByteArrayOutputStream send = new ByteArrayOutputStream();
 		PacketLineOut pckOut = new PacketLineOut(send);
@@ -361,6 +445,9 @@ private ByteArrayInputStream uploadPackV2Setup(RequestPolicy requestPolicy,
 		if (refFilter != null)
 			up.setRefFilter(refFilter);
 		up.setExtraParameters(Sets.of("version=2"));
+		if (hook != null) {
+			up.setProtocolV2Hook(hook);
+		}
 
 		ByteArrayOutputStream recv = new ByteArrayOutputStream();
 		up.upload(new ByteArrayInputStream(send.toByteArray()), recv, null);
@@ -374,9 +461,10 @@ private ByteArrayInputStream uploadPackV2Setup(RequestPolicy requestPolicy,
 	 * advertisement by the server.
 	 */
 	private ByteArrayInputStream uploadPackV2(RequestPolicy requestPolicy,
-			RefFilter refFilter, String... inputLines) throws Exception {
+			RefFilter refFilter, ProtocolV2Hook hook, String... inputLines)
+			throws Exception {
 		ByteArrayInputStream recvStream =
-			uploadPackV2Setup(requestPolicy, refFilter, inputLines);
+				uploadPackV2Setup(requestPolicy, refFilter, hook, inputLines);
 		PacketLineIn pckIn = new PacketLineIn(recvStream);
 
 		// drain capabilities
@@ -387,15 +475,33 @@ private ByteArrayInputStream uploadPackV2(RequestPolicy requestPolicy,
 	}
 
 	private ByteArrayInputStream uploadPackV2(String... inputLines) throws Exception {
-		return uploadPackV2(null, null, inputLines);
+		return uploadPackV2(null, null, null, inputLines);
+	}
+
+	private static class TestV2Hook implements ProtocolV2Hook {
+		private CapabilitiesV2Request capabilitiesRequest;
+
+		private LsRefsV2Request lsRefsRequest;
+
+		@Override
+		public void onCapabilities(CapabilitiesV2Request req) {
+			capabilitiesRequest = req;
+		}
+
+		@Override
+		public void onLsRefs(LsRefsV2Request req) {
+			lsRefsRequest = req;
+		}
 	}
 
 	@Test
 	public void testV2Capabilities() throws Exception {
+		TestV2Hook hook = new TestV2Hook();
 		ByteArrayInputStream recvStream =
-			uploadPackV2Setup(null, null, PacketLineIn.END);
+				uploadPackV2Setup(null, null, hook, PacketLineIn.END);
 		PacketLineIn pckIn = new PacketLineIn(recvStream);
 
+		assertThat(hook.capabilitiesRequest, notNullValue());
 		assertThat(pckIn.readString(), is("version 2"));
 		assertThat(
 			Arrays.asList(pckIn.readString(), pckIn.readString()),
@@ -413,7 +519,7 @@ public void testV2Capabilities() throws Exception {
 	public void testV2CapabilitiesAllowFilter() throws Exception {
 		server.getConfig().setBoolean("uploadpack", null, "allowfilter", true);
 		ByteArrayInputStream recvStream =
-			uploadPackV2Setup(null, null, PacketLineIn.END);
+				uploadPackV2Setup(null, null, null, PacketLineIn.END);
 		PacketLineIn pckIn = new PacketLineIn(recvStream);
 
 		assertThat(pckIn.readString(), is("version 2"));
@@ -426,6 +532,51 @@ public void testV2CapabilitiesAllowFilter() throws Exception {
 	}
 
 	@Test
+	public void testV2CapabilitiesRefInWant() throws Exception {
+		server.getConfig().setBoolean("uploadpack", null, "allowrefinwant", true);
+		ByteArrayInputStream recvStream =
+				uploadPackV2Setup(null, null, null, PacketLineIn.END);
+		PacketLineIn pckIn = new PacketLineIn(recvStream);
+
+		assertThat(pckIn.readString(), is("version 2"));
+		assertThat(
+			Arrays.asList(pckIn.readString(), pckIn.readString()),
+			// TODO(jonathantanmy) This check overspecifies the
+			// order of the capabilities of "fetch".
+			hasItems("ls-refs", "fetch=ref-in-want shallow"));
+		assertTrue(pckIn.readString() == PacketLineIn.END);
+	}
+
+	@Test
+	public void testV2CapabilitiesRefInWantNotAdvertisedIfUnallowed() throws Exception {
+		server.getConfig().setBoolean("uploadpack", null, "allowrefinwant", false);
+		ByteArrayInputStream recvStream =
+				uploadPackV2Setup(null, null, null, PacketLineIn.END);
+		PacketLineIn pckIn = new PacketLineIn(recvStream);
+
+		assertThat(pckIn.readString(), is("version 2"));
+		assertThat(
+			Arrays.asList(pckIn.readString(), pckIn.readString()),
+			hasItems("ls-refs", "fetch=shallow"));
+		assertTrue(pckIn.readString() == PacketLineIn.END);
+	}
+
+	@Test
+	public void testV2CapabilitiesRefInWantNotAdvertisedIfAdvertisingForbidden() throws Exception {
+		server.getConfig().setBoolean("uploadpack", null, "allowrefinwant", true);
+		server.getConfig().setBoolean("uploadpack", null, "advertiserefinwant", false);
+		ByteArrayInputStream recvStream =
+				uploadPackV2Setup(null, null, null, PacketLineIn.END);
+		PacketLineIn pckIn = new PacketLineIn(recvStream);
+
+		assertThat(pckIn.readString(), is("version 2"));
+		assertThat(
+			Arrays.asList(pckIn.readString(), pckIn.readString()),
+			hasItems("ls-refs", "fetch=shallow"));
+		assertTrue(pckIn.readString() == PacketLineIn.END);
+	}
+
+	@Test
 	@SuppressWarnings("boxing")
 	public void testV2EmptyRequest() throws Exception {
 		ByteArrayInputStream recvStream = uploadPackV2(PacketLineIn.END);
@@ -442,9 +593,12 @@ public void testV2LsRefs() throws Exception {
 		RevTag tag = remote.tag("tag", tip);
 		remote.update("refs/tags/tag", tag);
 
-		ByteArrayInputStream recvStream = uploadPackV2("command=ls-refs\n", PacketLineIn.END);
+		TestV2Hook hook = new TestV2Hook();
+		ByteArrayInputStream recvStream = uploadPackV2(null, null, hook,
+				"command=ls-refs\n", PacketLineIn.END);
 		PacketLineIn pckIn = new PacketLineIn(recvStream);
 
+		assertThat(hook.lsRefsRequest, notNullValue());
 		assertThat(pckIn.readString(), is(tip.toObjectId().getName() + " HEAD"));
 		assertThat(pckIn.readString(), is(tip.toObjectId().getName() + " refs/heads/master"));
 		assertThat(pckIn.readString(), is(tag.toObjectId().getName() + " refs/tags/tag"));
@@ -579,6 +733,10 @@ private ReceivedPackStatistics parsePack(ByteArrayInputStream recvStream, Progre
 				new StringWriter(), NullOutputStream.INSTANCE);
 		PackParser pp = client.newObjectInserter().newPackParser(sb);
 		pp.parse(NullProgressMonitor.INSTANCE);
+
+		// Ensure that there is nothing left in the stream.
+		assertThat(recvStream.read(), is(-1));
+
 		return pp.getReceivedPackStatistics();
 	}
 
@@ -592,6 +750,7 @@ public void testV2FetchRequestPolicyAdvertised() throws Exception {
 		uploadPackV2(
 			RequestPolicy.ADVERTISED,
 			null,
+			null,
 			"command=fetch\n",
 			PacketLineIn.DELIM,
 			"want " + advertized.name() + "\n",
@@ -604,6 +763,7 @@ public void testV2FetchRequestPolicyAdvertised() throws Exception {
 		uploadPackV2(
 			RequestPolicy.ADVERTISED,
 			null,
+			null,
 			"command=fetch\n",
 			PacketLineIn.DELIM,
 			"want " + unadvertized.name() + "\n",
@@ -621,6 +781,7 @@ public void testV2FetchRequestPolicyReachableCommit() throws Exception {
 		uploadPackV2(
 			RequestPolicy.REACHABLE_COMMIT,
 			null,
+			null,
 			"command=fetch\n",
 			PacketLineIn.DELIM,
 			"want " + reachable.name() + "\n",
@@ -633,6 +794,7 @@ public void testV2FetchRequestPolicyReachableCommit() throws Exception {
 		uploadPackV2(
 			RequestPolicy.REACHABLE_COMMIT,
 			null,
+			null,
 			"command=fetch\n",
 			PacketLineIn.DELIM,
 			"want " + unreachable.name() + "\n",
@@ -649,6 +811,7 @@ public void testV2FetchRequestPolicyTip() throws Exception {
 		uploadPackV2(
 			RequestPolicy.TIP,
 			new RejectAllRefFilter(),
+			null,
 			"command=fetch\n",
 			PacketLineIn.DELIM,
 			"want " + tip.name() + "\n",
@@ -661,6 +824,7 @@ public void testV2FetchRequestPolicyTip() throws Exception {
 		uploadPackV2(
 			RequestPolicy.TIP,
 			new RejectAllRefFilter(),
+			null,
 			"command=fetch\n",
 			PacketLineIn.DELIM,
 			"want " + parentOfTip.name() + "\n",
@@ -678,6 +842,7 @@ public void testV2FetchRequestPolicyReachableCommitTip() throws Exception {
 		uploadPackV2(
 			RequestPolicy.REACHABLE_COMMIT_TIP,
 			new RejectAllRefFilter(),
+			null,
 			"command=fetch\n",
 			PacketLineIn.DELIM,
 			"want " + parentOfTip.name() + "\n",
@@ -690,6 +855,7 @@ public void testV2FetchRequestPolicyReachableCommitTip() throws Exception {
 		uploadPackV2(
 			RequestPolicy.REACHABLE_COMMIT_TIP,
 			new RejectAllRefFilter(),
+			null,
 			"command=fetch\n",
 			PacketLineIn.DELIM,
 			"want " + unreachable.name() + "\n",
@@ -704,6 +870,7 @@ public void testV2FetchRequestPolicyAny() throws Exception {
 		uploadPackV2(
 			RequestPolicy.ANY,
 			null,
+			null,
 			"command=fetch\n",
 			PacketLineIn.DELIM,
 			"want " + unreachable.name() + "\n",
@@ -1078,6 +1245,178 @@ public void testV2FetchFilterWhenNotAllowed() throws Exception {
 			PacketLineIn.END);
 	}
 
+	@Test
+	public void testV2FetchWantRefIfNotAllowed() throws Exception {
+		RevCommit one = remote.commit().message("1").create();
+		remote.update("one", one);
+
+		try {
+			uploadPackV2(
+				"command=fetch\n",
+				PacketLineIn.DELIM,
+				"want-ref refs/heads/one\n",
+				"done\n",
+				PacketLineIn.END);
+		} catch (PackProtocolException e) {
+			assertThat(
+				e.getMessage(),
+				containsString("unexpected want-ref refs/heads/one"));
+			return;
+		}
+		fail("expected PackProtocolException");
+	}
+
+	@Test
+	public void testV2FetchWantRef() throws Exception {
+		RevCommit one = remote.commit().message("1").create();
+		RevCommit two = remote.commit().message("2").create();
+		RevCommit three = remote.commit().message("3").create();
+		remote.update("one", one);
+		remote.update("two", two);
+		remote.update("three", three);
+
+		server.getConfig().setBoolean("uploadpack", null, "allowrefinwant", true);
+
+		ByteArrayInputStream recvStream = uploadPackV2(
+			"command=fetch\n",
+			PacketLineIn.DELIM,
+			"want-ref refs/heads/one\n",
+			"want-ref refs/heads/two\n",
+			"done\n",
+			PacketLineIn.END);
+		PacketLineIn pckIn = new PacketLineIn(recvStream);
+		assertThat(pckIn.readString(), is("wanted-refs"));
+		assertThat(
+				Arrays.asList(pckIn.readString(), pckIn.readString()),
+				hasItems(
+					one.toObjectId().getName() + " refs/heads/one",
+					two.toObjectId().getName() + " refs/heads/two"));
+		assertThat(pckIn.readString(), theInstance(PacketLineIn.DELIM));
+		assertThat(pckIn.readString(), is("packfile"));
+		parsePack(recvStream);
+
+		assertTrue(client.hasObject(one.toObjectId()));
+		assertTrue(client.hasObject(two.toObjectId()));
+		assertFalse(client.hasObject(three.toObjectId()));
+	}
+
+	@Test
+	public void testV2FetchBadWantRef() throws Exception {
+		RevCommit one = remote.commit().message("1").create();
+		remote.update("one", one);
+
+		server.getConfig().setBoolean("uploadpack", null, "allowrefinwant", true);
+
+		try {
+			uploadPackV2(
+				"command=fetch\n",
+				PacketLineIn.DELIM,
+				"want-ref refs/heads/one\n",
+				"want-ref refs/heads/nonExistentRef\n",
+				"done\n",
+				PacketLineIn.END);
+		} catch (PackProtocolException e) {
+			assertThat(
+				e.getMessage(),
+				containsString("Invalid ref name: refs/heads/nonExistentRef"));
+			return;
+		}
+		fail("expected PackProtocolException");
+	}
+
+	@Test
+	public void testV2FetchMixedWantRef() throws Exception {
+		RevCommit one = remote.commit().message("1").create();
+		RevCommit two = remote.commit().message("2").create();
+		RevCommit three = remote.commit().message("3").create();
+		remote.update("one", one);
+		remote.update("two", two);
+		remote.update("three", three);
+
+		server.getConfig().setBoolean("uploadpack", null, "allowrefinwant", true);
+
+		ByteArrayInputStream recvStream = uploadPackV2(
+			"command=fetch\n",
+			PacketLineIn.DELIM,
+			"want-ref refs/heads/one\n",
+			"want " + two.toObjectId().getName() + "\n",
+			"done\n",
+			PacketLineIn.END);
+		PacketLineIn pckIn = new PacketLineIn(recvStream);
+		assertThat(pckIn.readString(), is("wanted-refs"));
+		assertThat(
+				pckIn.readString(),
+				is(one.toObjectId().getName() + " refs/heads/one"));
+		assertThat(pckIn.readString(), theInstance(PacketLineIn.DELIM));
+		assertThat(pckIn.readString(), is("packfile"));
+		parsePack(recvStream);
+
+		assertTrue(client.hasObject(one.toObjectId()));
+		assertTrue(client.hasObject(two.toObjectId()));
+		assertFalse(client.hasObject(three.toObjectId()));
+	}
+
+	@Test
+	public void testV2FetchWantRefWeAlreadyHave() throws Exception {
+		RevCommit one = remote.commit().message("1").create();
+		remote.update("one", one);
+
+		server.getConfig().setBoolean("uploadpack", null, "allowrefinwant", true);
+
+		ByteArrayInputStream recvStream = uploadPackV2(
+			"command=fetch\n",
+			PacketLineIn.DELIM,
+			"want-ref refs/heads/one\n",
+			"have " + one.toObjectId().getName(),
+			"done\n",
+			PacketLineIn.END);
+		PacketLineIn pckIn = new PacketLineIn(recvStream);
+
+		// The client still needs to know the hash of the object that
+		// refs/heads/one points to, even though it already has the
+		// object ...
+		assertThat(pckIn.readString(), is("wanted-refs"));
+		assertThat(
+				pckIn.readString(),
+				is(one.toObjectId().getName() + " refs/heads/one"));
+		assertThat(pckIn.readString(), theInstance(PacketLineIn.DELIM));
+
+		// ... but the client does not need the object itself.
+		assertThat(pckIn.readString(), is("packfile"));
+		parsePack(recvStream);
+		assertFalse(client.hasObject(one.toObjectId()));
+	}
+
+	@Test
+	public void testV2FetchWantRefAndDeepen() throws Exception {
+		RevCommit parent = remote.commit().message("parent").create();
+		RevCommit child = remote.commit().message("x").parent(parent).create();
+		remote.update("branch1", child);
+
+		server.getConfig().setBoolean("uploadpack", null, "allowrefinwant", true);
+
+		ByteArrayInputStream recvStream = uploadPackV2(
+			"command=fetch\n",
+			PacketLineIn.DELIM,
+			"want-ref refs/heads/branch1\n",
+			"deepen 1\n",
+			"done\n",
+			PacketLineIn.END);
+		PacketLineIn pckIn = new PacketLineIn(recvStream);
+
+		// shallow-info appears first, then wanted-refs.
+		assertThat(pckIn.readString(), is("shallow-info"));
+		assertThat(pckIn.readString(), is("shallow " + child.toObjectId().getName()));
+		assertThat(pckIn.readString(), theInstance(PacketLineIn.DELIM));
+		assertThat(pckIn.readString(), is("wanted-refs"));
+		assertThat(pckIn.readString(), is(child.toObjectId().getName() + " refs/heads/branch1"));
+		assertThat(pckIn.readString(), theInstance(PacketLineIn.DELIM));
+		assertThat(pckIn.readString(), is("packfile"));
+		parsePack(recvStream);
+		assertTrue(client.hasObject(child.toObjectId()));
+		assertFalse(client.hasObject(parent.toObjectId()));
+	}
+
 	private static class RejectAllRefFilter implements RefFilter {
 		@Override
 		public Map<String, Ref> filter(Map<String, Ref> refs) {
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/FileTreeIteratorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/FileTreeIteratorTest.java
index 0e009b9..e031678 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/FileTreeIteratorTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/FileTreeIteratorTest.java
@@ -331,7 +331,7 @@ public void testIsModifiedSymlinkAsFile() throws Exception {
 		DirCacheEntry dce = db.readDirCache().getEntry("symlink");
 		dce.setFileMode(FileMode.SYMLINK);
 		try (ObjectReader objectReader = db.newObjectReader()) {
-			DirCacheCheckout.checkoutEntry(db, dce, objectReader);
+			DirCacheCheckout.checkoutEntry(db, dce, objectReader, false, null);
 
 			FileTreeIterator fti = new FileTreeIterator(trash, db.getFS(),
 					db.getConfig().get(WorkingTreeOptions.KEY));
diff --git a/org.eclipse.jgit.ui/META-INF/MANIFEST.MF b/org.eclipse.jgit.ui/META-INF/MANIFEST.MF
index 407c3e7..c8d6d4d 100644
--- a/org.eclipse.jgit.ui/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.ui/META-INF/MANIFEST.MF
@@ -4,14 +4,14 @@
 Bundle-Name: %plugin_name
 Automatic-Module-Name: org.eclipse.jgit.ui
 Bundle-SymbolicName: org.eclipse.jgit.ui
-Bundle-Version: 5.0.3.qualifier
+Bundle-Version: 5.1.0.qualifier
 Bundle-Vendor: %provider_name
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
-Export-Package: org.eclipse.jgit.awtui;version="5.0.3"
-Import-Package: org.eclipse.jgit.errors;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.lib;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.nls;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.revplot;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.revwalk;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.transport;version="[5.0.3,5.1.0)",
- org.eclipse.jgit.util;version="[5.0.3,5.1.0)"
+Export-Package: org.eclipse.jgit.awtui;version="5.1.0"
+Import-Package: org.eclipse.jgit.errors;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.lib;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.nls;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.revplot;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.revwalk;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.transport;version="[5.1.0,5.2.0)",
+ org.eclipse.jgit.util;version="[5.1.0,5.2.0)"
diff --git a/org.eclipse.jgit.ui/pom.xml b/org.eclipse.jgit.ui/pom.xml
index 232ec6c..b52840d 100644
--- a/org.eclipse.jgit.ui/pom.xml
+++ b/org.eclipse.jgit.ui/pom.xml
@@ -52,7 +52,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>org.eclipse.jgit-parent</artifactId>
-    <version>5.0.3-SNAPSHOT</version>
+    <version>5.1.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.ui</artifactId>
diff --git a/org.eclipse.jgit/.settings/.api_filters b/org.eclipse.jgit/.settings/.api_filters
index e51bf20..b7b49bc 100644
--- a/org.eclipse.jgit/.settings/.api_filters
+++ b/org.eclipse.jgit/.settings/.api_filters
@@ -1,5 +1,12 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <component id="org.eclipse.jgit" version="2">
+    <resource path="src/org/eclipse/jgit/lib/ConfigConstants.java" type="org.eclipse.jgit.lib.ConfigConstants">
+        <filter id="337768515">
+            <message_arguments>
+                <message_argument value="org.eclipse.jgit.lib.ConfigConstants"/>
+            </message_arguments>
+        </filter>
+    </resource>
     <resource path="src/org/eclipse/jgit/lib/ObjectIdSerializer.java" type="org.eclipse.jgit.lib.ObjectIdSerializer">
         <filter id="1141899266">
             <message_arguments>
@@ -16,4 +23,11 @@
             </message_arguments>
         </filter>
     </resource>
+    <resource path="src/org/eclipse/jgit/transport/GitProtocolConstants.java" type="org.eclipse.jgit.transport.GitProtocolConstants">
+        <filter id="337768515">
+            <message_arguments>
+                <message_argument value="org.eclipse.jgit.transport.GitProtocolConstants"/>
+            </message_arguments>
+        </filter>
+    </resource>
 </component>
diff --git a/org.eclipse.jgit/META-INF/MANIFEST.MF b/org.eclipse.jgit/META-INF/MANIFEST.MF
index 90906d5..82e088c 100644
--- a/org.eclipse.jgit/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit/META-INF/MANIFEST.MF
@@ -3,12 +3,12 @@
 Bundle-Name: %plugin_name
 Automatic-Module-Name: org.eclipse.jgit
 Bundle-SymbolicName: org.eclipse.jgit
-Bundle-Version: 5.0.3.qualifier
+Bundle-Version: 5.1.0.qualifier
 Bundle-Localization: plugin
 Bundle-Vendor: %provider_name
 Bundle-ActivationPolicy: lazy
-Export-Package: org.eclipse.jgit.annotations;version="5.0.3",
- org.eclipse.jgit.api;version="5.0.3";
+Export-Package: org.eclipse.jgit.annotations;version="5.1.0",
+ org.eclipse.jgit.api;version="5.1.0";
   uses:="org.eclipse.jgit.revwalk,
    org.eclipse.jgit.treewalk.filter,
    org.eclipse.jgit.diff,
@@ -22,52 +22,52 @@
    org.eclipse.jgit.submodule,
    org.eclipse.jgit.transport,
    org.eclipse.jgit.merge",
- org.eclipse.jgit.api.errors;version="5.0.3";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.errors",
- org.eclipse.jgit.attributes;version="5.0.3",
- org.eclipse.jgit.blame;version="5.0.3";
+ org.eclipse.jgit.api.errors;version="5.1.0";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.errors",
+ org.eclipse.jgit.attributes;version="5.1.0",
+ org.eclipse.jgit.blame;version="5.1.0";
   uses:="org.eclipse.jgit.lib,
    org.eclipse.jgit.revwalk,
    org.eclipse.jgit.treewalk.filter,
    org.eclipse.jgit.diff",
- org.eclipse.jgit.diff;version="5.0.3";
+ org.eclipse.jgit.diff;version="5.1.0";
   uses:="org.eclipse.jgit.patch,
    org.eclipse.jgit.lib,
    org.eclipse.jgit.treewalk,
    org.eclipse.jgit.revwalk,
    org.eclipse.jgit.treewalk.filter,
    org.eclipse.jgit.util",
- org.eclipse.jgit.dircache;version="5.0.3";
+ org.eclipse.jgit.dircache;version="5.1.0";
   uses:="org.eclipse.jgit.lib,
    org.eclipse.jgit.treewalk,
    org.eclipse.jgit.util,
    org.eclipse.jgit.events,
    org.eclipse.jgit.attributes",
- org.eclipse.jgit.errors;version="5.0.3";
+ org.eclipse.jgit.errors;version="5.1.0";
   uses:="org.eclipse.jgit.lib,
    org.eclipse.jgit.internal.storage.pack,
    org.eclipse.jgit.transport,
    org.eclipse.jgit.dircache",
- org.eclipse.jgit.events;version="5.0.3";uses:="org.eclipse.jgit.lib",
- org.eclipse.jgit.fnmatch;version="5.0.3",
- org.eclipse.jgit.gitrepo;version="5.0.3";
+ org.eclipse.jgit.events;version="5.1.0";uses:="org.eclipse.jgit.lib",
+ org.eclipse.jgit.fnmatch;version="5.1.0",
+ org.eclipse.jgit.gitrepo;version="5.1.0";
   uses:="org.eclipse.jgit.api,
    org.eclipse.jgit.lib,
    org.eclipse.jgit.revwalk,
    org.xml.sax.helpers,
    org.xml.sax",
- org.eclipse.jgit.gitrepo.internal;version="5.0.3";x-internal:=true,
- org.eclipse.jgit.hooks;version="5.0.3";uses:="org.eclipse.jgit.lib",
- org.eclipse.jgit.ignore;version="5.0.3",
- org.eclipse.jgit.ignore.internal;version="5.0.3";x-friends:="org.eclipse.jgit.test",
- org.eclipse.jgit.internal;version="5.0.3";x-friends:="org.eclipse.jgit.test,org.eclipse.jgit.http.test",
- org.eclipse.jgit.internal.fsck;version="5.0.3";x-friends:="org.eclipse.jgit.test",
- org.eclipse.jgit.internal.ketch;version="5.0.3";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm",
- org.eclipse.jgit.internal.storage.dfs;version="5.0.3";
+ org.eclipse.jgit.gitrepo.internal;version="5.1.0";x-internal:=true,
+ org.eclipse.jgit.hooks;version="5.1.0";uses:="org.eclipse.jgit.lib",
+ org.eclipse.jgit.ignore;version="5.1.0",
+ org.eclipse.jgit.ignore.internal;version="5.1.0";x-friends:="org.eclipse.jgit.test",
+ org.eclipse.jgit.internal;version="5.1.0";x-friends:="org.eclipse.jgit.test,org.eclipse.jgit.http.test",
+ org.eclipse.jgit.internal.fsck;version="5.1.0";x-friends:="org.eclipse.jgit.test",
+ org.eclipse.jgit.internal.ketch;version="5.1.0";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm",
+ org.eclipse.jgit.internal.storage.dfs;version="5.1.0";
   x-friends:="org.eclipse.jgit.test,
    org.eclipse.jgit.http.server,
    org.eclipse.jgit.http.test,
    org.eclipse.jgit.lfs.test",
- org.eclipse.jgit.internal.storage.file;version="5.0.3";
+ org.eclipse.jgit.internal.storage.file;version="5.1.0";
   x-friends:="org.eclipse.jgit.test,
    org.eclipse.jgit.junit,
    org.eclipse.jgit.junit.http,
@@ -75,12 +75,12 @@
    org.eclipse.jgit.lfs,
    org.eclipse.jgit.pgm,
    org.eclipse.jgit.pgm.test",
- org.eclipse.jgit.internal.storage.io;version="5.0.3";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm",
- org.eclipse.jgit.internal.storage.pack;version="5.0.3";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm",
- org.eclipse.jgit.internal.storage.reftable;version="5.0.3";
+ org.eclipse.jgit.internal.storage.io;version="5.1.0";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm",
+ org.eclipse.jgit.internal.storage.pack;version="5.1.0";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm",
+ org.eclipse.jgit.internal.storage.reftable;version="5.1.0";
   x-friends:="org.eclipse.jgit.http.test,org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm",
- org.eclipse.jgit.internal.storage.reftree;version="5.0.3";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm",
- org.eclipse.jgit.lib;version="5.0.3";
+ org.eclipse.jgit.internal.storage.reftree;version="5.1.0";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm",
+ org.eclipse.jgit.lib;version="5.1.0";
   uses:="org.eclipse.jgit.revwalk,
    org.eclipse.jgit.treewalk.filter,
    org.eclipse.jgit.util,
@@ -90,33 +90,33 @@
    org.eclipse.jgit.treewalk,
    org.eclipse.jgit.transport,
    org.eclipse.jgit.submodule",
- org.eclipse.jgit.lib.internal;version="5.0.3";x-internal:=true,
- org.eclipse.jgit.merge;version="5.0.3";
+ org.eclipse.jgit.lib.internal;version="5.1.0";x-internal:=true,
+ org.eclipse.jgit.merge;version="5.1.0";
   uses:="org.eclipse.jgit.lib,
    org.eclipse.jgit.treewalk,
    org.eclipse.jgit.revwalk,
    org.eclipse.jgit.diff,
    org.eclipse.jgit.dircache,
    org.eclipse.jgit.api",
- org.eclipse.jgit.nls;version="5.0.3",
- org.eclipse.jgit.notes;version="5.0.3";
+ org.eclipse.jgit.nls;version="5.1.0",
+ org.eclipse.jgit.notes;version="5.1.0";
   uses:="org.eclipse.jgit.lib,
    org.eclipse.jgit.treewalk,
    org.eclipse.jgit.revwalk,
    org.eclipse.jgit.merge",
- org.eclipse.jgit.patch;version="5.0.3";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.diff",
- org.eclipse.jgit.revplot;version="5.0.3";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.revwalk",
- org.eclipse.jgit.revwalk;version="5.0.3";
+ org.eclipse.jgit.patch;version="5.1.0";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.diff",
+ org.eclipse.jgit.revplot;version="5.1.0";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.revwalk",
+ org.eclipse.jgit.revwalk;version="5.1.0";
   uses:="org.eclipse.jgit.lib,
    org.eclipse.jgit.treewalk,
    org.eclipse.jgit.treewalk.filter,
    org.eclipse.jgit.diff,
    org.eclipse.jgit.revwalk.filter",
- org.eclipse.jgit.revwalk.filter;version="5.0.3";uses:="org.eclipse.jgit.revwalk,org.eclipse.jgit.lib,org.eclipse.jgit.util",
- org.eclipse.jgit.storage.file;version="5.0.3";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.util",
- org.eclipse.jgit.storage.pack;version="5.0.3";uses:="org.eclipse.jgit.lib",
- org.eclipse.jgit.submodule;version="5.0.3";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.treewalk.filter,org.eclipse.jgit.treewalk",
- org.eclipse.jgit.transport;version="5.0.3";
+ org.eclipse.jgit.revwalk.filter;version="5.1.0";uses:="org.eclipse.jgit.revwalk,org.eclipse.jgit.lib,org.eclipse.jgit.util",
+ org.eclipse.jgit.storage.file;version="5.1.0";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.util",
+ org.eclipse.jgit.storage.pack;version="5.1.0";uses:="org.eclipse.jgit.lib",
+ org.eclipse.jgit.submodule;version="5.1.0";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.treewalk.filter,org.eclipse.jgit.treewalk",
+ org.eclipse.jgit.transport;version="5.1.0";
   uses:="org.eclipse.jgit.transport.resolver,
    org.eclipse.jgit.revwalk,
    org.eclipse.jgit.internal.storage.pack,
@@ -128,24 +128,24 @@
    org.eclipse.jgit.transport.http,
    org.eclipse.jgit.errors,
    org.eclipse.jgit.storage.pack",
- org.eclipse.jgit.transport.http;version="5.0.3";uses:="javax.net.ssl",
- org.eclipse.jgit.transport.resolver;version="5.0.3";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.transport",
- org.eclipse.jgit.treewalk;version="5.0.3";
+ org.eclipse.jgit.transport.http;version="5.1.0";uses:="javax.net.ssl",
+ org.eclipse.jgit.transport.resolver;version="5.1.0";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.transport",
+ org.eclipse.jgit.treewalk;version="5.1.0";
   uses:="org.eclipse.jgit.lib,
    org.eclipse.jgit.revwalk,
    org.eclipse.jgit.attributes,
    org.eclipse.jgit.treewalk.filter,
    org.eclipse.jgit.util,
    org.eclipse.jgit.dircache",
- org.eclipse.jgit.treewalk.filter;version="5.0.3";uses:="org.eclipse.jgit.treewalk",
- org.eclipse.jgit.util;version="5.0.3";
+ org.eclipse.jgit.treewalk.filter;version="5.1.0";uses:="org.eclipse.jgit.treewalk",
+ org.eclipse.jgit.util;version="5.1.0";
   uses:="org.eclipse.jgit.lib,
    org.eclipse.jgit.transport.http,
    org.eclipse.jgit.storage.file,
    org.ietf.jgss",
- org.eclipse.jgit.util.io;version="5.0.3",
- org.eclipse.jgit.util.sha1;version="5.0.3",
- org.eclipse.jgit.util.time;version="5.0.3"
+ org.eclipse.jgit.util.io;version="5.1.0",
+ org.eclipse.jgit.util.sha1;version="5.1.0",
+ org.eclipse.jgit.util.time;version="5.1.0"
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
 Import-Package: com.googlecode.javaewah;version="[1.1.6,2.0.0)",
  com.jcraft.jsch;version="[0.1.37,0.2.0)",
diff --git a/org.eclipse.jgit/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit/META-INF/SOURCE-MANIFEST.MF
index 185ee82..99e4c0c 100644
--- a/org.eclipse.jgit/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit/META-INF/SOURCE-MANIFEST.MF
@@ -3,5 +3,5 @@
 Bundle-Name: org.eclipse.jgit - Sources
 Bundle-SymbolicName: org.eclipse.jgit.source
 Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 5.0.3.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit;version="5.0.3.qualifier";roots="."
+Bundle-Version: 5.1.0.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit;version="5.1.0.qualifier";roots="."
diff --git a/org.eclipse.jgit/pom.xml b/org.eclipse.jgit/pom.xml
index ae9ea6d..9dc588d 100644
--- a/org.eclipse.jgit/pom.xml
+++ b/org.eclipse.jgit/pom.xml
@@ -53,7 +53,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>org.eclipse.jgit-parent</artifactId>
-    <version>5.0.3-SNAPSHOT</version>
+    <version>5.1.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit</artifactId>
diff --git a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
index 576d0c7..2150d5c 100644
--- a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
+++ b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
@@ -377,6 +377,7 @@
 invalidLineInConfigFileWithParam=Invalid line in config file: {0}
 invalidModeFor=Invalid mode {0} for {1} {2} in {3}.
 invalidModeForPath=Invalid mode {0} for path {1}
+invalidNameContainsDotDot=Invalid name (contains ".."): {1}
 invalidObject=Invalid {0} {1}: {2}
 invalidOldIdSent=invalid old id sent
 invalidPacketLineHeader=Invalid packet line header: {0}
@@ -578,6 +579,7 @@
 renameBranchFailedBecauseTag=Can not rename as Ref {0} is a tag
 renameBranchFailedUnknownReason=Rename failed with unknown reason
 renameBranchUnexpectedResult=Unexpected rename result {0}
+renameCancelled=Rename detection was cancelled
 renameFileFailed=Could not rename file {0} to {1}
 renamesAlreadyFound=Renames have already been found.
 renamesBreakingModifies=Breaking apart modified file pairs
@@ -756,8 +758,8 @@
 upstreamBranchName=branch ''{0}'' of {1}
 uriNotConfigured=Submodule URI not configured
 uriNotFound={0} not found
+uriNotFoundWithMessage={0} not found: {1}
 URINotSupported=URI not supported: {0}
-URLNotFound={0} not found
 userConfigFileInvalid=User config file {0} invalid {1}
 walkFailure=Walk failure.
 wantNotValid=want {0} not valid
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/CleanCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/CleanCommand.java
index 0d9fe41..43085dc 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/CleanCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/CleanCommand.java
@@ -136,7 +136,7 @@ public Set<String> call() throws NoWorkTreeException, GitAPIException {
 		} catch (IOException e) {
 			throw new JGitInternalException(e.getMessage(), e);
 		} finally {
-			if (!files.isEmpty()) {
+			if (!dryRun && !files.isEmpty()) {
 				repo.fireEvent(new WorkingTreeModifiedEvent(null, files));
 			}
 		}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java
index 98c16b8..1783c41 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java
@@ -275,9 +275,7 @@ public RebaseResult call() throws GitAPIException, NoHeadException,
 					throw new JGitInternalException(ioe.getMessage(), ioe);
 				}
 			case PROCESS_STEPS:
-				// fall through
 			case SKIP:
-				// fall through
 			case CONTINUE:
 				String upstreamCommitId = rebaseState.readFile(ONTO);
 				try {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleAddCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleAddCommand.java
index 9538d2b..b8d4468 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleAddCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleAddCommand.java
@@ -76,6 +76,8 @@
 public class SubmoduleAddCommand extends
 		TransportCommand<SubmoduleAddCommand, Repository> {
 
+	private String name;
+
 	private String path;
 
 	private String uri;
@@ -93,6 +95,18 @@ public SubmoduleAddCommand(Repository repo) {
 	}
 
 	/**
+	 * Set the submodule name
+	 *
+	 * @param name
+	 * @return this command
+	 * @since 5.1
+	 */
+	public SubmoduleAddCommand setName(String name) {
+		this.name = name;
+		return this;
+	}
+
+	/**
 	 * Set repository-relative path of submodule
 	 *
 	 * @param path
@@ -160,6 +174,25 @@ public Repository call() throws GitAPIException {
 			throw new IllegalArgumentException(JGitText.get().pathNotConfigured);
 		if (uri == null || uri.length() == 0)
 			throw new IllegalArgumentException(JGitText.get().uriNotConfigured);
+		if (name == null || name.length() == 0) {
+			// Use the path as the default.
+			name = path;
+		}
+		if (name.contains("/../") || name.contains("\\..\\") //$NON-NLS-1$ //$NON-NLS-2$
+				|| name.startsWith("../") || name.startsWith("..\\") //$NON-NLS-1$ //$NON-NLS-2$
+				|| name.endsWith("/..") || name.endsWith("\\..")) { //$NON-NLS-1$ //$NON-NLS-2$
+			// Submodule names are used to store the submodule repositories
+			// under $GIT_DIR/modules. Having ".." in submodule names makes a
+			// vulnerability (CVE-2018-11235
+			// https://bugs.eclipse.org/bugs/show_bug.cgi?id=535027#c0)
+			// Reject the names with them. The callers need to make sure the
+			// names free from these. We don't automatically replace these
+			// characters or canonicalize by regarding the name as a file path.
+			// Since Path class is platform dependent, we manually check '/' and
+			// '\\' patterns here.
+			throw new IllegalArgumentException(MessageFormat
+					.format(JGitText.get().invalidNameContainsDotDot, name));
+		}
 
 		try {
 			if (submoduleExists())
@@ -193,7 +226,7 @@ public Repository call() throws GitAPIException {
 
 		// Save submodule URL to parent repository's config
 		StoredConfig config = repo.getConfig();
-		config.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
+		config.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, name,
 				ConfigConstants.CONFIG_KEY_URL, resolvedUri);
 		try {
 			config.save();
@@ -207,9 +240,9 @@ public Repository call() throws GitAPIException {
 		try {
 			modulesConfig.load();
 			modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION,
-					path, ConfigConstants.CONFIG_KEY_PATH, path);
+					name, ConfigConstants.CONFIG_KEY_PATH, path);
 			modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION,
-					path, ConfigConstants.CONFIG_KEY_URL, uri);
+					name, ConfigConstants.CONFIG_KEY_URL, uri);
 			modulesConfig.save();
 		} catch (IOException e) {
 			throw new JGitInternalException(e.getMessage(), e);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/blame/BlameGenerator.java b/org.eclipse.jgit/src/org/eclipse/jgit/blame/BlameGenerator.java
index 1ad7a30..9cec645 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/blame/BlameGenerator.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/blame/BlameGenerator.java
@@ -539,7 +539,7 @@ private boolean result(Candidate n) throws IOException {
 		n.beginResult(revPool);
 		outCandidate = n;
 		outRegion = n.regionList;
-		return true;
+		return outRegion != null;
 	}
 
 	private boolean reverseResult(Candidate parent, Candidate source)
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffFormatter.java b/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffFormatter.java
index 7aaa500..e7ad0bc 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffFormatter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffFormatter.java
@@ -67,6 +67,7 @@
 import org.eclipse.jgit.dircache.DirCacheIterator;
 import org.eclipse.jgit.errors.AmbiguousObjectException;
 import org.eclipse.jgit.errors.BinaryBlobException;
+import org.eclipse.jgit.errors.CancelledException;
 import org.eclipse.jgit.errors.CorruptObjectException;
 import org.eclipse.jgit.errors.IncorrectObjectTypeException;
 import org.eclipse.jgit.errors.MissingObjectException;
@@ -577,7 +578,14 @@ private List<DiffEntry> detectRenames(List<DiffEntry> files)
 			throws IOException {
 		renameDetector.reset();
 		renameDetector.addAll(files);
-		return renameDetector.compute(reader, progressMonitor);
+		try {
+			return renameDetector.compute(reader, progressMonitor);
+		} catch (CancelledException e) {
+			// TODO: consider propagating once bug 536323 is tackled
+			// (making DiffEntry.scan() and DiffFormatter.scan() and
+			// format() cancellable).
+			return Collections.emptyList();
+		}
 	}
 
 	private boolean isAdd(List<DiffEntry> files) {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/diff/RenameDetector.java b/org.eclipse.jgit/src/org/eclipse/jgit/diff/RenameDetector.java
index 7bb217d..772fbb5 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/diff/RenameDetector.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/diff/RenameDetector.java
@@ -57,6 +57,7 @@
 
 import org.eclipse.jgit.diff.DiffEntry.ChangeType;
 import org.eclipse.jgit.diff.SimilarityIndex.TableFullException;
+import org.eclipse.jgit.errors.CancelledException;
 import org.eclipse.jgit.internal.JGitText;
 import org.eclipse.jgit.lib.AbbreviatedObjectId;
 import org.eclipse.jgit.lib.FileMode;
@@ -332,8 +333,13 @@ public List<DiffEntry> compute() throws IOException {
 	 *         representing all files that have been changed.
 	 * @throws java.io.IOException
 	 *             file contents cannot be read from the repository.
+	 * @throws CancelledException
+	 *             if rename detection was cancelled
 	 */
-	public List<DiffEntry> compute(ProgressMonitor pm) throws IOException {
+	// TODO(ms): use org.eclipse.jgit.api.errors.CanceledException in next major
+	// version
+	public List<DiffEntry> compute(ProgressMonitor pm)
+			throws IOException, CancelledException {
 		if (!done) {
 			try {
 				return compute(objectReader, pm);
@@ -355,9 +361,13 @@ public List<DiffEntry> compute(ProgressMonitor pm) throws IOException {
 	 *         representing all files that have been changed.
 	 * @throws java.io.IOException
 	 *             file contents cannot be read from the repository.
+	 * @throws CancelledException
+	 *             if rename detection was cancelled
 	 */
+	// TODO(ms): use org.eclipse.jgit.api.errors.CanceledException in next major
+	// version
 	public List<DiffEntry> compute(ObjectReader reader, ProgressMonitor pm)
-			throws IOException {
+			throws IOException, CancelledException {
 		final ContentSource cs = ContentSource.create(reader);
 		return compute(new ContentSource.Pair(cs, cs), pm);
 	}
@@ -373,9 +383,13 @@ public List<DiffEntry> compute(ObjectReader reader, ProgressMonitor pm)
 	 *         representing all files that have been changed.
 	 * @throws java.io.IOException
 	 *             file contents cannot be read from the repository.
+	 * @throws CancelledException
+	 *             if rename detection was cancelled
 	 */
+	// TODO(ms): use org.eclipse.jgit.api.errors.CanceledException in next major
+	// version
 	public List<DiffEntry> compute(ContentSource.Pair reader, ProgressMonitor pm)
-			throws IOException {
+			throws IOException, CancelledException {
 		if (!done) {
 			done = true;
 
@@ -415,8 +429,15 @@ public void reset() {
 		done = false;
 	}
 
+	private void advanceOrCancel(ProgressMonitor pm) throws CancelledException {
+		if (pm.isCancelled()) {
+			throw new CancelledException(JGitText.get().renameCancelled);
+		}
+		pm.update(1);
+	}
+
 	private void breakModifies(ContentSource.Pair reader, ProgressMonitor pm)
-			throws IOException {
+			throws IOException, CancelledException {
 		ArrayList<DiffEntry> newEntries = new ArrayList<>(entries.size());
 
 		pm.beginTask(JGitText.get().renamesBreakingModifies, entries.size());
@@ -437,13 +458,13 @@ private void breakModifies(ContentSource.Pair reader, ProgressMonitor pm)
 			} else {
 				newEntries.add(e);
 			}
-			pm.update(1);
+			advanceOrCancel(pm);
 		}
 
 		entries = newEntries;
 	}
 
-	private void rejoinModifies(ProgressMonitor pm) {
+	private void rejoinModifies(ProgressMonitor pm) throws CancelledException {
 		HashMap<String, DiffEntry> nameMap = new HashMap<>();
 		ArrayList<DiffEntry> newAdded = new ArrayList<>(added.size());
 
@@ -452,7 +473,7 @@ private void rejoinModifies(ProgressMonitor pm) {
 
 		for (DiffEntry src : deleted) {
 			nameMap.put(src.oldPath, src);
-			pm.update(1);
+			advanceOrCancel(pm);
 		}
 
 		for (DiffEntry dst : added) {
@@ -468,7 +489,7 @@ private void rejoinModifies(ProgressMonitor pm) {
 			} else {
 				newAdded.add(dst);
 			}
-			pm.update(1);
+			advanceOrCancel(pm);
 		}
 
 		added = newAdded;
@@ -498,7 +519,7 @@ private int calculateModifyScore(ContentSource.Pair reader, DiffEntry d)
 
 	private void findContentRenames(ContentSource.Pair reader,
 			ProgressMonitor pm)
-			throws IOException {
+			throws IOException, CancelledException {
 		int cnt = Math.max(added.size(), deleted.size());
 		if (getRenameLimit() == 0 || cnt <= getRenameLimit()) {
 			SimilarityRenameDetector d;
@@ -516,7 +537,8 @@ private void findContentRenames(ContentSource.Pair reader,
 	}
 
 	@SuppressWarnings("unchecked")
-	private void findExactRenames(ProgressMonitor pm) {
+	private void findExactRenames(ProgressMonitor pm)
+			throws CancelledException {
 		pm.beginTask(JGitText.get().renamesFindingExact, //
 				added.size() + added.size() + deleted.size()
 						+ added.size() * deleted.size());
@@ -562,7 +584,7 @@ private void findExactRenames(ProgressMonitor pm) {
 			} else {
 				left.add(a);
 			}
-			pm.update(1);
+			advanceOrCancel(pm);
 		}
 
 		for (List<DiffEntry> adds : nonUniqueAdds) {
@@ -604,6 +626,10 @@ private void findExactRenames(ProgressMonitor pm) {
 						int score = SimilarityRenameDetector.nameScore(addedName, deletedName);
 						matrix[mNext] = SimilarityRenameDetector.encode(score, delIdx, addIdx);
 						mNext++;
+						if (pm.isCancelled()) {
+							throw new CancelledException(
+									JGitText.get().renameCancelled);
+						}
 					}
 				}
 
@@ -617,7 +643,7 @@ private void findExactRenames(ProgressMonitor pm) {
 					DiffEntry a = adds.get(addIdx);
 
 					if (a == null) {
-						pm.update(1);
+						advanceOrCancel(pm);
 						continue; // was already matched earlier
 					}
 
@@ -635,11 +661,12 @@ private void findExactRenames(ProgressMonitor pm) {
 
 					entries.add(DiffEntry.pair(type, d, a, 100));
 					adds.set(addIdx, null); // Claim the destination was matched.
-					pm.update(1);
+					advanceOrCancel(pm);
 				}
 			} else {
 				left.addAll(adds);
 			}
+			advanceOrCancel(pm);
 		}
 		added = left;
 
@@ -692,7 +719,8 @@ private static DiffEntry bestPathMatch(DiffEntry src, List<DiffEntry> list) {
 
 	@SuppressWarnings("unchecked")
 	private HashMap<AbbreviatedObjectId, Object> populateMap(
-			List<DiffEntry> diffEntries, ProgressMonitor pm) {
+			List<DiffEntry> diffEntries, ProgressMonitor pm)
+			throws CancelledException {
 		HashMap<AbbreviatedObjectId, Object> map = new HashMap<>();
 		for (DiffEntry de : diffEntries) {
 			Object old = map.put(id(de), de);
@@ -706,7 +734,7 @@ private HashMap<AbbreviatedObjectId, Object> populateMap(
 				((List<DiffEntry>) old).add(de);
 				map.put(id(de), old);
 			}
-			pm.update(1);
+			advanceOrCancel(pm);
 		}
 		return map;
 	}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/diff/SimilarityRenameDetector.java b/org.eclipse.jgit/src/org/eclipse/jgit/diff/SimilarityRenameDetector.java
index 653658b..d8a05c3 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/diff/SimilarityRenameDetector.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/diff/SimilarityRenameDetector.java
@@ -54,6 +54,7 @@
 
 import org.eclipse.jgit.diff.DiffEntry.ChangeType;
 import org.eclipse.jgit.diff.SimilarityIndex.TableFullException;
+import org.eclipse.jgit.errors.CancelledException;
 import org.eclipse.jgit.internal.JGitText;
 import org.eclipse.jgit.lib.FileMode;
 import org.eclipse.jgit.lib.NullProgressMonitor;
@@ -128,7 +129,7 @@ void setRenameScore(int score) {
 		renameScore = score;
 	}
 
-	void compute(ProgressMonitor pm) throws IOException {
+	void compute(ProgressMonitor pm) throws IOException, CancelledException {
 		if (pm == null)
 			pm = NullProgressMonitor.INSTANCE;
 
@@ -142,6 +143,11 @@ void compute(ProgressMonitor pm) throws IOException {
 		// we have looked at everything that is above our minimum score.
 		//
 		for (--mNext; mNext >= 0; mNext--) {
+			if (pm.isCancelled()) {
+				// TODO(ms): use org.eclipse.jgit.api.errors.CanceledException
+				// in next major version
+				throw new CancelledException(JGitText.get().renameCancelled);
+			}
 			long ent = matrix[mNext];
 			int sIdx = srcFile(ent);
 			int dIdx = dstFile(ent);
@@ -209,7 +215,8 @@ private static List<DiffEntry> compactDstList(List<DiffEntry> in) {
 		return r;
 	}
 
-	private int buildMatrix(ProgressMonitor pm) throws IOException {
+	private int buildMatrix(ProgressMonitor pm)
+			throws IOException, CancelledException {
 		// Allocate for the worst-case scenario where every pair has a
 		// score that we need to consider. We might not need that many.
 		//
@@ -234,6 +241,14 @@ private int buildMatrix(ProgressMonitor pm) throws IOException {
 			SimilarityIndex s = null;
 
 			for (int dstIdx = 0; dstIdx < dsts.size(); dstIdx++) {
+				if (pm.isCancelled()) {
+					// TODO(ms): use
+					// org.eclipse.jgit.api.errors.CanceledException in next
+					// major version
+					throw new CancelledException(
+							JGitText.get().renameCancelled);
+				}
+
 				DiffEntry dstEnt = dsts.get(dstIdx);
 
 				if (!isFile(dstEnt.newMode)) {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java
index 0b03eb1..bad71de 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java
@@ -1366,7 +1366,11 @@ private boolean isModifiedSubtree_IndexTree(String path, ObjectId tree)
 	 *            object reader to use for checkout
 	 * @throws java.io.IOException
 	 * @since 3.6
+	 * @deprecated since 5.1, use
+	 *             {@link #checkoutEntry(Repository, DirCacheEntry, ObjectReader, boolean, CheckoutMetadata)}
+	 *             instead
 	 */
+	@Deprecated
 	public static void checkoutEntry(Repository repo, DirCacheEntry entry,
 			ObjectReader or) throws IOException {
 		checkoutEntry(repo, entry, or, false, null);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoCommand.java
index 80fd3cf..45a239d 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoCommand.java
@@ -55,8 +55,8 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
-import java.util.Set;
 import java.util.StringJoiner;
+import java.util.TreeMap;
 
 import org.eclipse.jgit.annotations.Nullable;
 import org.eclipse.jgit.api.Git;
@@ -115,16 +115,15 @@ public class RepoCommand extends GitCommand<RevCommit> {
 	private String groupsParam;
 	private String branch;
 	private String targetBranch = Constants.HEAD;
-	private boolean recordRemoteBranch = false;
-	private boolean recordSubmoduleLabels = false;
-	private boolean recordShallowSubmodules = false;
+	private boolean recordRemoteBranch = true;
+	private boolean recordSubmoduleLabels = true;
+	private boolean recordShallowSubmodules = true;
 	private PersonIdent author;
 	private RemoteReader callback;
 	private InputStream inputStream;
 	private IncludedFileReader includedReader;
 	private boolean ignoreRemoteFailures = false;
 
-	private List<RepoProject> bareProjects;
 	private ProgressMonitor monitor;
 
 	/**
@@ -519,37 +518,33 @@ public RevCommit call() throws GitAPIException {
 		}
 
 		if (repo.isBare()) {
-			bareProjects = new ArrayList<>();
 			if (author == null)
 				author = new PersonIdent(repo);
 			if (callback == null)
 				callback = new DefaultRemoteReader();
-			for (RepoProject proj : filteredProjects) {
-				addSubmoduleBare(proj.getUrl(), proj.getPath(),
-						proj.getRevision(), proj.getCopyFiles(),
-						proj.getLinkFiles(), proj.getGroups(),
-						proj.getRecommendShallow());
-			}
+			List<RepoProject> renamedProjects = renameProjects(filteredProjects);
+
 			DirCache index = DirCache.newInCore();
 			DirCacheBuilder builder = index.builder();
 			ObjectInserter inserter = repo.newObjectInserter();
 			try (RevWalk rw = new RevWalk(repo)) {
 				Config cfg = new Config();
 				StringBuilder attributes = new StringBuilder();
-				for (RepoProject proj : bareProjects) {
+				for (RepoProject proj : renamedProjects) {
+					String name = proj.getName();
 					String path = proj.getPath();
-					String nameUri = proj.getName();
+					String url = proj.getUrl();
 					ObjectId objectId;
 					if (ObjectId.isId(proj.getRevision())) {
 						objectId = ObjectId.fromString(proj.getRevision());
 					} else {
-						objectId = callback.sha1(nameUri, proj.getRevision());
+						objectId = callback.sha1(url, proj.getRevision());
 						if (objectId == null && !ignoreRemoteFailures) {
-							throw new RemoteUnavailableException(nameUri);
+							throw new RemoteUnavailableException(url);
 						}
 						if (recordRemoteBranch) {
 							// can be branch or tag
-							cfg.setString("submodule", path, "branch", //$NON-NLS-1$ //$NON-NLS-2$
+							cfg.setString("submodule", name, "branch", //$NON-NLS-1$ //$NON-NLS-2$
 									proj.getRevision());
 						}
 
@@ -559,7 +554,7 @@ public RevCommit call() throws GitAPIException {
 							// depth in the 'clone-depth' field, while
 							// git core only uses a binary 'shallow = true/false'
 							// hint, we'll map any depth to 'shallow = true'
-							cfg.setBoolean("submodule", path, "shallow", //$NON-NLS-1$ //$NON-NLS-2$
+							cfg.setBoolean("submodule", name, "shallow", //$NON-NLS-1$ //$NON-NLS-2$
 									true);
 						}
 					}
@@ -575,12 +570,13 @@ public RevCommit call() throws GitAPIException {
 						attributes.append(rec.toString());
 					}
 
-					URI submodUrl = URI.create(nameUri);
+					URI submodUrl = URI.create(url);
 					if (targetUri != null) {
 						submodUrl = relativize(targetUri, submodUrl);
 					}
-					cfg.setString("submodule", path, "path", path); //$NON-NLS-1$ //$NON-NLS-2$
-					cfg.setString("submodule", path, "url", submodUrl.toString()); //$NON-NLS-1$ //$NON-NLS-2$
+					cfg.setString("submodule", name, "path", path); //$NON-NLS-1$ //$NON-NLS-2$
+					cfg.setString("submodule", name, "url", //$NON-NLS-1$ //$NON-NLS-2$
+							submodUrl.toString());
 
 					// create gitlink
 					if (objectId != null) {
@@ -591,7 +587,7 @@ public RevCommit call() throws GitAPIException {
 
 						for (CopyFile copyfile : proj.getCopyFiles()) {
 							byte[] src = callback.readFile(
-								nameUri, proj.getRevision(), copyfile.src);
+								url, proj.getRevision(), copyfile.src);
 							objectId = inserter.insert(Constants.OBJ_BLOB, src);
 							dcEntry = new DirCacheEntry(copyfile.dest);
 							dcEntry.setObjectId(objectId);
@@ -691,7 +687,7 @@ public RevCommit call() throws GitAPIException {
 		} else {
 			try (Git git = new Git(repo)) {
 				for (RepoProject proj : filteredProjects) {
-					addSubmodule(proj.getUrl(), proj.getPath(),
+					addSubmodule(proj.getName(), proj.getUrl(), proj.getPath(),
 							proj.getRevision(), proj.getCopyFiles(),
 							proj.getLinkFiles(), git);
 				}
@@ -703,9 +699,9 @@ public RevCommit call() throws GitAPIException {
 		}
 	}
 
-	private void addSubmodule(String url, String path, String revision,
-			List<CopyFile> copyfiles, List<LinkFile> linkfiles, Git git)
-			throws GitAPIException, IOException {
+	private void addSubmodule(String name, String url, String path,
+			String revision, List<CopyFile> copyfiles, List<LinkFile> linkfiles,
+			Git git) throws GitAPIException, IOException {
 		assert (!repo.isBare());
 		assert (git != null);
 		if (!linkfiles.isEmpty()) {
@@ -713,7 +709,8 @@ private void addSubmodule(String url, String path, String revision,
 					JGitText.get().nonBareLinkFilesNotSupported);
 		}
 
-		SubmoduleAddCommand add = git.submoduleAdd().setPath(path).setURI(url);
+		SubmoduleAddCommand add = git.submoduleAdd().setName(name).setPath(path)
+				.setURI(url);
 		if (monitor != null)
 			add.setProgressMonitor(monitor);
 
@@ -731,16 +728,42 @@ private void addSubmodule(String url, String path, String revision,
 		}
 	}
 
-	private void addSubmoduleBare(String url, String path, String revision,
-			List<CopyFile> copyfiles, List<LinkFile> linkfiles,
-			Set<String> groups, String recommendShallow) {
-		assert (repo.isBare());
-		assert (bareProjects != null);
-		RepoProject proj = new RepoProject(url, path, revision, null, groups,
-				recommendShallow);
-		proj.addCopyFiles(copyfiles);
-		proj.addLinkFiles(linkfiles);
-		bareProjects.add(proj);
+	/**
+	 * Rename the projects if there's a conflict when converted to submodules.
+	 *
+	 * @param projects
+	 *            parsed projects
+	 * @return projects that are renamed if necessary
+	 */
+	private List<RepoProject> renameProjects(List<RepoProject> projects) {
+		Map<String, List<RepoProject>> m = new TreeMap<>();
+		for (RepoProject proj : projects) {
+			List<RepoProject> l = m.get(proj.getName());
+			if (l == null) {
+				l = new ArrayList<>();
+				m.put(proj.getName(), l);
+			}
+			l.add(proj);
+		}
+
+		List<RepoProject> ret = new ArrayList<>();
+		for (List<RepoProject> ps : m.values()) {
+			boolean nameConflict = ps.size() != 1;
+			for (RepoProject proj : ps) {
+				String name = proj.getName();
+				if (nameConflict) {
+					name += SLASH + proj.getPath();
+				}
+				RepoProject p = new RepoProject(name,
+						proj.getPath(), proj.getRevision(), null,
+						proj.getGroups(), proj.getRecommendShallow());
+				p.setUrl(proj.getUrl());
+				p.addCopyFiles(proj.getCopyFiles());
+				p.addLinkFiles(proj.getLinkFiles());
+				ret.add(p);
+			}
+		}
+		return ret;
 	}
 
 	/*
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 a52fab9..2373b97 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
@@ -438,6 +438,7 @@ public static JGitText get() {
 	/***/ public String invalidLineInConfigFileWithParam;
 	/***/ public String invalidModeFor;
 	/***/ public String invalidModeForPath;
+	/***/ public String invalidNameContainsDotDot;
 	/***/ public String invalidObject;
 	/***/ public String invalidOldIdSent;
 	/***/ public String invalidPacketLineHeader;
@@ -639,6 +640,7 @@ public static JGitText get() {
 	/***/ public String renameBranchFailedBecauseTag;
 	/***/ public String renameBranchFailedUnknownReason;
 	/***/ public String renameBranchUnexpectedResult;
+	/***/ public String renameCancelled;
 	/***/ public String renameFileFailed;
 	/***/ public String renamesAlreadyFound;
 	/***/ public String renamesBreakingModifies;
@@ -817,8 +819,8 @@ public static JGitText get() {
 	/***/ public String upstreamBranchName;
 	/***/ public String uriNotConfigured;
 	/***/ public String uriNotFound;
+	/***/ public String uriNotFoundWithMessage;
 	/***/ public String URINotSupported;
-	/***/ public String URLNotFound;
 	/***/ public String userConfigFileInvalid;
 	/***/ public String walkFailure;
 	/***/ public String wantNotValid;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsConfig.java
index 3e2963a..2f796a9 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsConfig.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsConfig.java
@@ -48,7 +48,13 @@
 import org.eclipse.jgit.errors.ConfigInvalidException;
 import org.eclipse.jgit.lib.StoredConfig;
 
-final class DfsConfig extends StoredConfig {
+/**
+ * Config implementation used by DFS repositories.
+ * <p>
+ * The current implementation acts as if there is no persistent storage: loading
+ * simply clears the config, and saving does nothing.
+ */
+public final class DfsConfig extends StoredConfig {
 	/** {@inheritDoc} */
 	@Override
 	public void load() throws IOException, ConfigInvalidException {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsFsck.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsFsck.java
index 985393c..3f96d09 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsFsck.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsFsck.java
@@ -146,7 +146,7 @@ private void checkConnectivity(ProgressMonitor pm, FsckError errors)
 			throws IOException {
 		pm.beginTask(JGitText.get().countingObjects, ProgressMonitor.UNKNOWN);
 		try (ObjectWalk ow = new ObjectWalk(repo)) {
-			for (Ref r : repo.getAllRefs().values()) {
+			for (Ref r : repo.getRefDatabase().getRefs()) {
 				ObjectId objectId = r.getObjectId();
 				if (objectId == null) {
 					// skip unborn branch
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsObjDatabase.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsObjDatabase.java
index ca54ee2..09d5937 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsObjDatabase.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsObjDatabase.java
@@ -43,13 +43,17 @@
 
 package org.eclipse.jgit.internal.storage.dfs;
 
+import static java.util.stream.Collectors.joining;
+
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -86,10 +90,16 @@ public void markDirty() {
 		}
 	};
 
-	/** Sources for a pack file. */
+	/**
+	 * Sources for a pack file.
+	 * <p>
+	 * <strong>Note:</strong> When sorting packs by source, do not use the default
+	 * comparator based on {@link Enum#compareTo}. Prefer {@link
+	 * #DEFAULT_COMPARATOR} or your own {@link ComparatorBuilder}.
+	 */
 	public static enum PackSource {
 		/** The pack is created by ObjectInserter due to local activity. */
-		INSERT(0),
+		INSERT,
 
 		/**
 		 * The pack is created by PackParser due to a network event.
@@ -100,7 +110,7 @@ public static enum PackSource {
 		 * storage layout preferred by this version. Received packs are likely
 		 * to be either compacted or garbage collected in the future.
 		 */
-		RECEIVE(0),
+		RECEIVE,
 
 		/**
 		 * The pack was created by compacting multiple packs together.
@@ -111,7 +121,7 @@ public static enum PackSource {
 		 *
 		 * @see DfsPackCompactor
 		 */
-		COMPACT(1),
+		COMPACT,
 
 		/**
 		 * Pack was created by Git garbage collection by this implementation.
@@ -122,17 +132,17 @@ public static enum PackSource {
 		 *
 		 * @see DfsGarbageCollector
 		 */
-		GC(2),
+		GC,
 
 		/** Created from non-heads by {@link DfsGarbageCollector}. */
-		GC_REST(3),
+		GC_REST,
 
 		/**
 		 * RefTreeGraph pack was created by Git garbage collection.
 		 *
 		 * @see DfsGarbageCollector
 		 */
-		GC_TXN(4),
+		GC_TXN,
 
 		/**
 		 * Pack was created by Git garbage collection.
@@ -141,12 +151,86 @@ public static enum PackSource {
 		 * last GC pass. It is retained in a new pack until it is safe to prune
 		 * these objects from the repository.
 		 */
-		UNREACHABLE_GARBAGE(5);
+		UNREACHABLE_GARBAGE;
 
-		final int category;
+		/**
+		 * Default comparator for sources.
+		 * <p>
+		 * Sorts generally newer, smaller types such as {@code INSERT} and {@code
+		 * RECEIVE} earlier; older, larger types such as {@code GC} later; and
+		 * {@code UNREACHABLE_GARBAGE} at the end.
+		 */
+		public static final Comparator<PackSource> DEFAULT_COMPARATOR =
+				new ComparatorBuilder()
+						.add(INSERT, RECEIVE)
+						.add(COMPACT)
+						.add(GC)
+						.add(GC_REST)
+						.add(GC_TXN)
+						.add(UNREACHABLE_GARBAGE)
+						.build();
 
-		PackSource(int category) {
-			this.category = category;
+		/**
+		 * Builder for describing {@link PackSource} ordering where some values are
+		 * explicitly considered equal to others.
+		 */
+		public static class ComparatorBuilder {
+			private final Map<PackSource, Integer> ranks = new HashMap<>();
+			private int counter;
+
+			/**
+			 * Add a collection of sources that should sort as equal.
+			 * <p>
+			 * Sources in the input will sort after sources listed in previous calls
+			 * to this method.
+			 *
+			 * @param sources
+			 *            sources in this equivalence class.
+			 * @return this.
+			 */
+			public ComparatorBuilder add(PackSource... sources) {
+				for (PackSource s : sources) {
+					ranks.put(s, Integer.valueOf(counter));
+				}
+				counter++;
+				return this;
+			}
+
+			/**
+			 * Build the comparator.
+			 *
+			 * @return new comparator instance.
+			 * @throws IllegalArgumentException
+			 *             not all {@link PackSource} instances were explicitly assigned
+			 *             an equivalence class.
+			 */
+			public Comparator<PackSource> build() {
+				return new PackSourceComparator(ranks);
+			}
+		}
+
+		private static class PackSourceComparator implements Comparator<PackSource> {
+			private final Map<PackSource, Integer> ranks;
+
+			private PackSourceComparator(Map<PackSource, Integer> ranks) {
+				if (!ranks.keySet().equals(
+							new HashSet<>(Arrays.asList(PackSource.values())))) {
+					throw new IllegalArgumentException();
+				}
+				this.ranks = new HashMap<>(ranks);
+			}
+
+			@Override
+			public int compare(PackSource a, PackSource b) {
+				return ranks.get(a).compareTo(ranks.get(b));
+			}
+
+			@Override
+			public String toString() {
+				return Arrays.stream(PackSource.values())
+						.map(s -> s + "=" + ranks.get(s)) //$NON-NLS-1$
+						.collect(joining(", ", getClass().getSimpleName() + "{", "}")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+			}
 		}
 	}
 
@@ -156,6 +240,8 @@ public static enum PackSource {
 
 	private DfsReaderOptions readerOptions;
 
+	private Comparator<DfsPackDescription> packComparator;
+
 	/**
 	 * Initialize an object database for our repository.
 	 *
@@ -169,6 +255,7 @@ protected DfsObjDatabase(DfsRepository repository,
 		this.repository = repository;
 		this.packList = new AtomicReference<>(NO_PACKS);
 		this.readerOptions = options;
+		this.packComparator = DfsPackDescription.objectLookupComparator();
 	}
 
 	/**
@@ -180,6 +267,21 @@ public DfsReaderOptions getReaderOptions() {
 		return readerOptions;
 	}
 
+	/**
+	 * Set the comparator used when searching for objects across packs.
+	 * <p>
+	 * An optimal comparator will find more objects without having to load large
+	 * idx files from storage only to find that they don't contain the object.
+	 * See {@link DfsPackDescription#objectLookupComparator()} for the default
+	 * heuristics.
+	 *
+	 * @param packComparator
+	 *            comparator.
+	 */
+	public void setPackComparator(Comparator<DfsPackDescription> packComparator) {
+		this.packComparator = packComparator;
+	}
+
 	/** {@inheritDoc} */
 	@Override
 	public DfsReader newReader() {
@@ -523,7 +625,7 @@ private PackList scanPacksImpl(PackList old) throws IOException {
 		Map<DfsPackDescription, DfsReftable> reftables = reftableMap(old);
 
 		List<DfsPackDescription> scanned = listPacks();
-		Collections.sort(scanned);
+		Collections.sort(scanned, packComparator);
 
 		List<DfsPackFile> newPacks = new ArrayList<>(scanned.size());
 		List<DfsReftable> newReftables = new ArrayList<>(scanned.size());
@@ -584,30 +686,9 @@ private static Map<DfsPackDescription, DfsReftable> reftableMap(PackList old) {
 	 * @return comparator to sort {@link DfsReftable} by priority.
 	 */
 	protected Comparator<DfsReftable> reftableComparator() {
-		return (fa, fb) -> {
-			DfsPackDescription a = fa.getPackDescription();
-			DfsPackDescription b = fb.getPackDescription();
-
-			// GC, COMPACT reftables first by higher category.
-			int c = category(b) - category(a);
-			if (c != 0) {
-				return c;
-			}
-
-			// Lower maxUpdateIndex first.
-			c = Long.signum(a.getMaxUpdateIndex() - b.getMaxUpdateIndex());
-			if (c != 0) {
-				return c;
-			}
-
-			// Older reftable first.
-			return Long.signum(a.getLastModified() - b.getLastModified());
-		};
-	}
-
-	static int category(DfsPackDescription d) {
-		PackSource s = d.getPackSource();
-		return s != null ? s.category : 0;
+		return Comparator.comparing(
+				DfsReftable::getPackDescription,
+				DfsPackDescription.reftableComparator());
 	}
 
 	/**
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackCompactor.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackCompactor.java
index b43b9b1..127ee6b 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackCompactor.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackCompactor.java
@@ -404,12 +404,11 @@ private void addObjectsToPack(PackWriter pw, DfsReader ctx,
 		// Sort packs by description ordering, this places newer packs before
 		// older packs, allowing the PackWriter to be handed newer objects
 		// first and older objects last.
-		Collections.sort(srcPacks, new Comparator<DfsPackFile>() {
-			@Override
-			public int compare(DfsPackFile a, DfsPackFile b) {
-				return a.getPackDescription().compareTo(b.getPackDescription());
-			}
-		});
+		Collections.sort(
+				srcPacks,
+				Comparator.comparing(
+						DfsPackFile::getPackDescription,
+						DfsPackDescription.objectLookupComparator()));
 
 		rw = new RevWalk(ctx);
 		added = rw.newFlag("ADDED"); //$NON-NLS-1$
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackDescription.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackDescription.java
index 45eb7b0..5a1ac02 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackDescription.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackDescription.java
@@ -47,7 +47,9 @@
 import static org.eclipse.jgit.internal.storage.pack.PackExt.REFTABLE;
 
 import java.util.Arrays;
+import java.util.Comparator;
 
+import org.eclipse.jgit.annotations.NonNull;
 import org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource;
 import org.eclipse.jgit.internal.storage.pack.PackExt;
 import org.eclipse.jgit.internal.storage.reftable.ReftableWriter;
@@ -61,7 +63,107 @@
  * Instances of this class are cached with the DfsPackFile, and should not be
  * modified once initialized and presented to the JGit DFS library.
  */
-public class DfsPackDescription implements Comparable<DfsPackDescription> {
+public class DfsPackDescription {
+	/**
+	 * Comparator for packs when looking up objects in indexes.
+	 * <p>
+	 * This comparator tries to position packs in the order readers should examine
+	 * them when looking for objects by SHA-1. The default tries to sort packs
+	 * with more recent modification dates before older packs, and packs with
+	 * fewer objects before packs with more objects.
+	 * <p>
+	 * Uses {@link PackSource#DEFAULT_COMPARATOR} for the portion of comparison
+	 * where packs are sorted by source.
+	 *
+	 * @return comparator.
+	 */
+	public static Comparator<DfsPackDescription> objectLookupComparator() {
+		return objectLookupComparator(PackSource.DEFAULT_COMPARATOR);
+	}
+
+	/**
+	 * Comparator for packs when looking up objects in indexes.
+	 * <p>
+	 * This comparator tries to position packs in the order readers should examine
+	 * them when looking for objects by SHA-1. The default tries to sort packs
+	 * with more recent modification dates before older packs, and packs with
+	 * fewer objects before packs with more objects.
+	 *
+	 * @param packSourceComparator
+	 *            comparator for the {@link PackSource}, used as the first step in
+	 *            comparison.
+	 * @return comparator.
+	 */
+	public static Comparator<DfsPackDescription> objectLookupComparator(
+			Comparator<PackSource> packSourceComparator) {
+		return Comparator.comparing(
+					DfsPackDescription::getPackSource, packSourceComparator)
+			.thenComparing((a, b) -> {
+				PackSource as = a.getPackSource();
+				PackSource bs = b.getPackSource();
+
+				// Tie break GC type packs by smallest first. There should be at most
+				// one of each source, but when multiple exist concurrent GCs may have
+				// run. Preferring the smaller file selects higher quality delta
+				// compression, placing less demand on the DfsBlockCache.
+				if (as == bs && isGC(as)) {
+					int cmp = Long.signum(a.getFileSize(PACK) - b.getFileSize(PACK));
+					if (cmp != 0) {
+						return cmp;
+					}
+				}
+
+				// Newer packs should sort first.
+				int cmp = Long.signum(b.getLastModified() - a.getLastModified());
+				if (cmp != 0) {
+					return cmp;
+				}
+
+				// Break ties on smaller index. Readers may get lucky and find
+				// the object they care about in the smaller index. This also pushes
+				// big historical packs to the end of the list, due to more objects.
+				return Long.signum(a.getObjectCount() - b.getObjectCount());
+			});
+	}
+
+	static Comparator<DfsPackDescription> reftableComparator() {
+		return (a, b) -> {
+				// GC, COMPACT reftables first by reversing default order.
+				int c = PackSource.DEFAULT_COMPARATOR.reversed()
+						.compare(a.getPackSource(), b.getPackSource());
+				if (c != 0) {
+					return c;
+				}
+
+				// Lower maxUpdateIndex first.
+				c = Long.signum(a.getMaxUpdateIndex() - b.getMaxUpdateIndex());
+				if (c != 0) {
+					return c;
+				}
+
+				// Older reftable first.
+				return Long.signum(a.getLastModified() - b.getLastModified());
+			};
+	}
+
+	static Comparator<DfsPackDescription> reuseComparator() {
+		return (a, b) -> {
+			PackSource as = a.getPackSource();
+			PackSource bs = b.getPackSource();
+
+			if (as == bs && DfsPackDescription.isGC(as)) {
+				// Push smaller GC files last; these likely have higher quality
+				// delta compression and the contained representation should be
+				// favored over other files.
+				return Long.signum(b.getFileSize(PACK) - a.getFileSize(PACK));
+			}
+
+			// DfsPackDescription.compareTo already did a reasonable sort.
+			// Rely on Arrays.sort being stable, leaving equal elements.
+			return 0;
+		};
+	}
+
 	private final DfsRepositoryDescription repoDesc;
 	private final String packName;
 	private PackSource packSource;
@@ -93,11 +195,15 @@ public class DfsPackDescription implements Comparable<DfsPackDescription> {
 	 *            name of the pack file. Must end with ".pack".
 	 * @param repoDesc
 	 *            description of the repo containing the pack file.
+	 * @param packSource
+	 *            the source of the pack.
 	 */
-	public DfsPackDescription(DfsRepositoryDescription repoDesc, String name) {
+	public DfsPackDescription(DfsRepositoryDescription repoDesc, String name,
+			@NonNull PackSource packSource) {
 		this.repoDesc = repoDesc;
 		int dot = name.lastIndexOf('.');
 		this.packName = (dot < 0) ? name : name.substring(0, dot);
+		this.packSource = packSource;
 
 		int extCnt = PackExt.values().length;
 		sizeMap = new long[extCnt];
@@ -162,6 +268,7 @@ public DfsStreamKey getStreamKey(PackExt ext) {
 	 *
 	 * @return the source of the pack.
 	 */
+	@NonNull
 	public PackSource getPackSource() {
 		return packSource;
 	}
@@ -173,7 +280,7 @@ public PackSource getPackSource() {
 	 *            the source of the pack.
 	 * @return {@code this}
 	 */
-	public DfsPackDescription setPackSource(PackSource source) {
+	public DfsPackDescription setPackSource(@NonNull PackSource source) {
 		packSource = source;
 		return this;
 	}
@@ -455,49 +562,6 @@ public boolean equals(Object b) {
 		return false;
 	}
 
-	/**
-	 * {@inheritDoc}
-	 * <p>
-	 * Sort packs according to the optimal lookup ordering.
-	 * <p>
-	 * This method tries to position packs in the order readers should examine
-	 * them when looking for objects by SHA-1. The default tries to sort packs
-	 * with more recent modification dates before older packs, and packs with
-	 * fewer objects before packs with more objects.
-	 */
-	@Override
-	public int compareTo(DfsPackDescription b) {
-		// Cluster by PackSource, pushing UNREACHABLE_GARBAGE to the end.
-		PackSource as = getPackSource();
-		PackSource bs = b.getPackSource();
-		if (as != null && bs != null) {
-			int cmp = as.category - bs.category;
-			if (cmp != 0)
-				return cmp;
-		}
-
-		// Tie break GC type packs by smallest first. There should be at most
-		// one of each source, but when multiple exist concurrent GCs may have
-		// run. Preferring the smaller file selects higher quality delta
-		// compression, placing less demand on the DfsBlockCache.
-		if (as != null && as == bs && isGC(as)) {
-			int cmp = Long.signum(getFileSize(PACK) - b.getFileSize(PACK));
-			if (cmp != 0) {
-				return cmp;
-			}
-		}
-
-		// Newer packs should sort first.
-		int cmp = Long.signum(b.getLastModified() - getLastModified());
-		if (cmp != 0)
-			return cmp;
-
-		// Break ties on smaller index. Readers may get lucky and find
-		// the object they care about in the smaller index. This also pushes
-		// big historical packs to the end of the list, due to more objects.
-		return Long.signum(getObjectCount() - b.getObjectCount());
-	}
-
 	static boolean isGC(PackSource s) {
 		switch (s) {
 		case GC:
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReader.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReader.java
index 197114b..d04709f 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReader.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReader.java
@@ -45,7 +45,6 @@
 package org.eclipse.jgit.internal.storage.dfs;
 
 import static org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource.UNREACHABLE_GARBAGE;
-import static org.eclipse.jgit.internal.storage.pack.PackExt.PACK;
 import static org.eclipse.jgit.lib.Constants.OBJECT_ID_LENGTH;
 
 import java.io.IOException;
@@ -66,7 +65,6 @@
 import org.eclipse.jgit.errors.StoredObjectRepresentationNotAvailableException;
 import org.eclipse.jgit.internal.JGitText;
 import org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackList;
-import org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource;
 import org.eclipse.jgit.internal.storage.file.BitmapIndexImpl;
 import org.eclipse.jgit.internal.storage.file.PackBitmapIndex;
 import org.eclipse.jgit.internal.storage.file.PackIndex;
@@ -611,26 +609,9 @@ private void trySelectRepresentation(PackWriter packer,
 		}
 	}
 
-	private static final Comparator<DfsPackFile> PACK_SORT_FOR_REUSE = new Comparator<DfsPackFile>() {
-		@Override
-		public int compare(DfsPackFile af, DfsPackFile bf) {
-			DfsPackDescription ad = af.getPackDescription();
-			DfsPackDescription bd = bf.getPackDescription();
-			PackSource as = ad.getPackSource();
-			PackSource bs = bd.getPackSource();
-
-			if (as != null && as == bs && DfsPackDescription.isGC(as)) {
-				// Push smaller GC files last; these likely have higher quality
-				// delta compression and the contained representation should be
-				// favored over other files.
-				return Long.signum(bd.getFileSize(PACK) - ad.getFileSize(PACK));
-			}
-
-			// DfsPackDescription.compareTo already did a reasonable sort.
-			// Rely on Arrays.sort being stable, leaving equal elements.
-			return 0;
-		}
-	};
+	private static final Comparator<DfsPackFile> PACK_SORT_FOR_REUSE =
+		Comparator.comparing(
+				DfsPackFile::getPackDescription, DfsPackDescription.reuseComparator());
 
 	private List<DfsPackFile> sortPacksForSelectRepresentation()
 			throws IOException {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReftableDatabase.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReftableDatabase.java
index 40cfb71..7081630 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReftableDatabase.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReftableDatabase.java
@@ -45,6 +45,9 @@
 
 import java.io.IOException;
 import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
 import java.util.Map;
 import java.util.concurrent.locks.ReentrantLock;
 
@@ -196,7 +199,7 @@ public boolean isNameConflicting(String refName) throws IOException {
 			}
 
 			// Cannot be the container of an existing reference.
-			return table.hasRef(refName + '/');
+			return table.hasRefsWithPrefix(refName + '/');
 		} finally {
 			lock.unlock();
 		}
@@ -238,7 +241,8 @@ public Map<String, Ref> getRefs(String prefix) throws IOException {
 		try {
 			Reftable table = reader();
 			try (RefCursor rc = ALL.equals(prefix) ? table.allRefs()
-					: table.seekRef(prefix)) {
+					: (prefix.endsWith("/") ? table.seekRefsWithPrefix(prefix) //$NON-NLS-1$
+							: table.seekRef(prefix))) {
 				while (rc.next()) {
 					Ref ref = table.resolve(rc.getRef());
 					if (ref != null && ref.getObjectId() != null) {
@@ -256,6 +260,29 @@ public Map<String, Ref> getRefs(String prefix) throws IOException {
 
 	/** {@inheritDoc} */
 	@Override
+	public List<Ref> getRefsByPrefix(String prefix) throws IOException {
+		List<Ref> all = new ArrayList<>();
+		lock.lock();
+		try {
+			Reftable table = reader();
+			try (RefCursor rc = ALL.equals(prefix) ? table.allRefs()
+					: table.seekRefsWithPrefix(prefix)) {
+				while (rc.next()) {
+					Ref ref = table.resolve(rc.getRef());
+					if (ref != null && ref.getObjectId() != null) {
+						all.add(ref);
+					}
+				}
+			}
+		} finally {
+			lock.unlock();
+		}
+
+		return Collections.unmodifiableList(all);
+	}
+
+	/** {@inheritDoc} */
+	@Override
 	public Ref peel(Ref ref) throws IOException {
 		Ref oldLeaf = ref.getLeaf();
 		if (oldLeaf.isPeeled() || oldLeaf.getObjectId() == null) {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/InMemoryRepository.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/InMemoryRepository.java
index 662c3fe..5b6894d 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/InMemoryRepository.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/InMemoryRepository.java
@@ -10,6 +10,7 @@
 import java.util.concurrent.atomic.AtomicInteger;
 
 import org.eclipse.jgit.annotations.Nullable;
+import org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource;
 import org.eclipse.jgit.internal.storage.pack.PackExt;
 import org.eclipse.jgit.internal.storage.reftable.ReftableConfig;
 import org.eclipse.jgit.lib.RefDatabase;
@@ -118,10 +119,10 @@ protected synchronized List<DfsPackDescription> listPacks() {
 		@Override
 		protected DfsPackDescription newPack(PackSource source) {
 			int id = packId.incrementAndGet();
-			DfsPackDescription desc = new MemPack(
+			return new MemPack(
 					"pack-" + id + "-" + source.name(), //$NON-NLS-1$ //$NON-NLS-2$
-					getRepository().getDescription());
-			return desc.setPackSource(source);
+					getRepository().getDescription(),
+					source);
 		}
 
 		@Override
@@ -169,8 +170,8 @@ public void flush() {
 	private static class MemPack extends DfsPackDescription {
 		final byte[][] fileMap = new byte[PackExt.values().length][];
 
-		MemPack(String name, DfsRepositoryDescription repoDesc) {
-			super(repoDesc, name);
+		MemPack(String name, DfsRepositoryDescription repoDesc, PackSource source) {
+			super(repoDesc, name, source);
 		}
 
 		void put(PackExt ext, byte[] data) {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/ReftableBatchRefUpdate.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/ReftableBatchRefUpdate.java
index e0c056a..47ac4ec 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/ReftableBatchRefUpdate.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/ReftableBatchRefUpdate.java
@@ -70,7 +70,6 @@
 import org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource;
 import org.eclipse.jgit.internal.storage.io.BlockSource;
 import org.eclipse.jgit.internal.storage.pack.PackExt;
-import org.eclipse.jgit.internal.storage.reftable.RefCursor;
 import org.eclipse.jgit.internal.storage.reftable.Reftable;
 import org.eclipse.jgit.internal.storage.reftable.ReftableCompactor;
 import org.eclipse.jgit.internal.storage.reftable.ReftableConfig;
@@ -240,11 +239,7 @@ private boolean checkConflicting(List<ReceiveCommand> pending)
 	private boolean checkExpected(Reftable table, List<ReceiveCommand> pending)
 			throws IOException {
 		for (ReceiveCommand cmd : pending) {
-			Ref ref;
-			try (RefCursor rc = table.seekRef(cmd.getRefName())) {
-				ref = rc.next() ? rc.getRef() : null;
-			}
-			if (!matchOld(cmd, ref)) {
+			if (!matchOld(cmd, table.exactRef(cmd.getRefName()))) {
 				cmd.setResult(LOCK_FAILURE);
 				if (isAtomic()) {
 					ReceiveCommand.abort(pending);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/BasePackBitmapIndex.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/BasePackBitmapIndex.java
index 407061f..3884180 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/BasePackBitmapIndex.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/BasePackBitmapIndex.java
@@ -104,6 +104,7 @@ EWAHCompressedBitmap getBitmap() {
 				r = xb.xorBitmap.bitmapContainer;
 				if (r instanceof EWAHCompressedBitmap) {
 					out = out.xor((EWAHCompressedBitmap) r);
+					out.trim();
 					bitmapContainer = out;
 					return out;
 				}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileRepository.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileRepository.java
index d02888a..5ced686 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileRepository.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileRepository.java
@@ -480,7 +480,7 @@ private File descriptionFile() {
 	/**
 	 * {@inheritDoc}
 	 * <p>
-	 * Objects known to exist but not expressed by {@link #getAllRefs()}.
+	 * Objects known to exist but not expressed by {@code #getAllRefs()}.
 	 * <p>
 	 * When a repository borrows objects from another repository, it can
 	 * advertise that it safely has that other repository's references, without
@@ -493,12 +493,12 @@ public Set<ObjectId> getAdditionalHaves() {
 	}
 
 	/**
-	 * Objects known to exist but not expressed by {@link #getAllRefs()}.
+	 * Objects known to exist but not expressed by {@code #getAllRefs()}.
 	 * <p>
 	 * When a repository borrows objects from another repository, it can
 	 * advertise that it safely has that other repository's references, without
-	 * exposing any other details about the other repository.  This may help
-	 * a client trying to push changes avoid pushing more than it needs to.
+	 * exposing any other details about the other repository. This may help a
+	 * client trying to push changes avoid pushing more than it needs to.
 	 *
 	 * @param skips
 	 *            Set of AlternateHandle Ids already seen
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackBitmapIndexBuilder.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackBitmapIndexBuilder.java
index 70eb10e..eff7958 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackBitmapIndexBuilder.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackBitmapIndexBuilder.java
@@ -351,6 +351,7 @@ public StoredEntry next() {
 						PositionEntry entry = positionEntries.get(item);
 						if (entry == null)
 							throw new IllegalStateException();
+						bestBitmap.trim();
 						return new StoredEntry(entry.namePosition, bestBitmap,
 								bestXorOffset, item.getFlags());
 					}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackBitmapIndexRemapper.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackBitmapIndexRemapper.java
index c04c90f..7069588 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackBitmapIndexRemapper.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackBitmapIndexRemapper.java
@@ -200,6 +200,7 @@ public EWAHCompressedBitmap getBitmap(AnyObjectId objectId) {
 		for (IntIterator i = oldBitmap.getBitmap().intIterator(); i.hasNext();)
 			inflated.set(prevToNewMapping[i.next()]);
 		bitmap = inflated.toEWAHCompressedBitmap();
+		bitmap.trim();
 		convertedBitmaps.add(
 				new StoredBitmap(objectId, bitmap, null, oldBitmap.getFlags()));
 		return bitmap;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java
index 36d6f0a..24af8a7 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java
@@ -1970,7 +1970,7 @@ private void findObjectsToPack(@NonNull ProgressMonitor countingMonitor,
 				byte[] pathBuf = walker.getPathBuffer();
 				int pathLen = walker.getPathLength();
 				bases.addBase(o.getType(), pathBuf, pathLen, pathHash);
-				filterAndAddObject(o, o.getType(), pathHash);
+				filterAndAddObject(o, o.getType(), pathHash, want);
 				countingMonitor.update(1);
 			}
 		} else {
@@ -1980,7 +1980,7 @@ private void findObjectsToPack(@NonNull ProgressMonitor countingMonitor,
 					continue;
 				if (exclude(o))
 					continue;
-				filterAndAddObject(o, o.getType(), walker.getPathHashCode());
+				filterAndAddObject(o, o.getType(), walker.getPathHashCode(), want);
 				countingMonitor.update(1);
 			}
 		}
@@ -2013,7 +2013,7 @@ private void findObjectsToPackUsingBitmaps(
 				needBitmap.remove(objectId);
 				continue;
 			}
-			filterAndAddObject(objectId, obj.getType(), 0);
+			filterAndAddObject(objectId, obj.getType(), 0, want);
 		}
 
 		if (thin)
@@ -2075,12 +2075,14 @@ private void addObject(
 	// Adds the given object as an object to be packed, first performing
 	// filtering on blobs at or exceeding a given size.
 	private void filterAndAddObject(@NonNull AnyObjectId src, int type,
-			int pathHashCode) throws IOException {
+			int pathHashCode, @NonNull Set<? extends AnyObjectId> want)
+			throws IOException {
 
 		// Check if this object needs to be rejected, doing the cheaper
 		// checks first.
 		boolean reject = filterBlobLimit >= 0 &&
 			type == OBJ_BLOB &&
+			!want.contains(src) &&
 			reader.getObjectSize(src, OBJ_BLOB) > filterBlobLimit;
 		if (!reject) {
 			addObject(src, type, pathHashCode);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriterBitmapPreparer.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriterBitmapPreparer.java
index 38d3458..99db749 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriterBitmapPreparer.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriterBitmapPreparer.java
@@ -91,11 +91,10 @@ class PackWriterBitmapPreparer {
 
 	private static final int DAY_IN_SECONDS = 24 * 60 * 60;
 
-	private static final Comparator<BitmapBuilderEntry> ORDER_BY_CARDINALITY = new Comparator<BitmapBuilderEntry>() {
+	private static final Comparator<RevCommit> ORDER_BY_REVERSE_TIMESTAMP = new Comparator<RevCommit>() {
 		@Override
-		public int compare(BitmapBuilderEntry a, BitmapBuilderEntry b) {
-			return Integer.signum(a.getBuilder().cardinality()
-					- b.getBuilder().cardinality());
+		public int compare(RevCommit a, RevCommit b) {
+			return Integer.signum(b.getCommitTime() - a.getCommitTime());
 		}
 	};
 
@@ -164,154 +163,177 @@ Collection<BitmapCommit> selectCommits(int expectedCommitCount,
 		 * the cache hits for clients that are close to HEAD, which is the
 		 * majority of calculations performed.
 		 */
-		pm.beginTask(JGitText.get().selectingCommits, ProgressMonitor.UNKNOWN);
-		RevWalk rw = new RevWalk(reader);
-		rw.setRetainBody(false);
-		CommitSelectionHelper selectionHelper = setupTipCommitBitmaps(rw,
-				expectedCommitCount, excludeFromBitmapSelection);
-		pm.endTask();
+		try (RevWalk rw = new RevWalk(reader);
+				RevWalk rw2 = new RevWalk(reader)) {
+			pm.beginTask(JGitText.get().selectingCommits,
+					ProgressMonitor.UNKNOWN);
+			rw.setRetainBody(false);
+			CommitSelectionHelper selectionHelper = captureOldAndNewCommits(rw,
+					expectedCommitCount, excludeFromBitmapSelection);
+			pm.endTask();
 
-		int totCommits = selectionHelper.getCommitCount();
-		BlockList<BitmapCommit> selections = new BlockList<>(
-				totCommits / recentCommitSpan + 1);
-		for (BitmapCommit reuse : selectionHelper.reusedCommits) {
-			selections.add(reuse);
-		}
-
-		if (totCommits == 0) {
-			for (AnyObjectId id : selectionHelper.peeledWants) {
-				selections.add(new BitmapCommit(id, false, 0));
-			}
-			return selections;
-		}
-
-		pm.beginTask(JGitText.get().selectingCommits, totCommits);
-		int totalWants = selectionHelper.peeledWants.size();
-
-		for (BitmapBuilderEntry entry : selectionHelper.tipCommitBitmaps) {
-			BitmapBuilder bitmap = entry.getBuilder();
-			int cardinality = bitmap.cardinality();
-
-			// Within this branch, keep ordered lists of commits representing
-			// chains in its history, where each chain is a "sub-branch".
-			// Ordering commits by these chains makes for fewer differences
-			// between consecutive selected commits, which in turn provides
-			// better compression/on the run-length encoding of the XORs between
-			// them.
-			List<List<BitmapCommit>> chains =
-					new ArrayList<>();
-
-			// Mark the current branch as inactive if its tip commit isn't
-			// recent and there are an excessive number of branches, to
-			// prevent memory bloat of computing too many bitmaps for stale
-			// branches.
-			boolean isActiveBranch = true;
-			if (totalWants > excessiveBranchCount
-					&& !isRecentCommit(entry.getCommit())) {
-				isActiveBranch = false;
+			// Add reused bitmaps from the previous GC pack's bitmap indices.
+			// Currently they are always fully reused, even if their spans don't
+			// match this run's PackConfig values.
+			int newCommits = selectionHelper.getCommitCount();
+			BlockList<BitmapCommit> selections = new BlockList<>(
+					selectionHelper.reusedCommits.size()
+							+ newCommits / recentCommitSpan + 1);
+			for (BitmapCommit reuse : selectionHelper.reusedCommits) {
+				selections.add(reuse);
 			}
 
-			// Insert bitmaps at the offsets suggested by the
-			// nextSelectionDistance() heuristic. Only reuse bitmaps created
-			// for more distant commits.
-			int index = -1;
-			int nextIn = nextSpan(cardinality);
-			int nextFlg = nextIn == distantCommitSpan
-					? PackBitmapIndex.FLAG_REUSE : 0;
+			if (newCommits == 0) {
+				for (AnyObjectId id : selectionHelper.newWants) {
+					selections.add(new BitmapCommit(id, false, 0));
+				}
+				return selections;
+			}
 
-			// For the current branch, iterate through all commits from oldest
-			// to newest.
-			for (RevCommit c : selectionHelper) {
-				// Optimization: if we have found all the commits for this
-				// branch, stop searching
-				int distanceFromTip = cardinality - index - 1;
-				if (distanceFromTip == 0) {
-					break;
+			pm.beginTask(JGitText.get().selectingCommits, newCommits);
+			int totalWants = want.size();
+			BitmapBuilder seen = commitBitmapIndex.newBitmapBuilder();
+			seen.or(selectionHelper.reusedCommitsBitmap);
+			rw2.setRetainBody(false);
+			rw2.setRevFilter(new NotInBitmapFilter(seen));
+
+			// For each branch, do a revwalk to enumerate its commits. Exclude
+			// both reused commits and any commits seen in a previous branch.
+			// Then iterate through all new commits from oldest to newest,
+			// selecting well-spaced commits in this branch.
+			for (RevCommit rc : selectionHelper.newWantsByNewest) {
+				BitmapBuilder tipBitmap = commitBitmapIndex.newBitmapBuilder();
+				rw2.markStart((RevCommit) rw2.peel(rw2.parseAny(rc)));
+				RevCommit rc2;
+				while ((rc2 = rw2.next()) != null) {
+					tipBitmap.addObject(rc2, Constants.OBJ_COMMIT);
+				}
+				int cardinality = tipBitmap.cardinality();
+				seen.or(tipBitmap);
+
+				// Within this branch, keep ordered lists of commits
+				// representing chains in its history, where each chain is a
+				// "sub-branch". Ordering commits by these chains makes for
+				// fewer differences between consecutive selected commits, which
+				// in turn provides better compression/on the run-length
+				// encoding of the XORs between them.
+				List<List<BitmapCommit>> chains = new ArrayList<>();
+
+				// Mark the current branch as inactive if its tip commit isn't
+				// recent and there are an excessive number of branches, to
+				// prevent memory bloat of computing too many bitmaps for stale
+				// branches.
+				boolean isActiveBranch = true;
+				if (totalWants > excessiveBranchCount && !isRecentCommit(rc)) {
+					isActiveBranch = false;
 				}
 
-				// Ignore commits that are not in this branch
-				if (!bitmap.contains(c)) {
-					continue;
-				}
+				// Insert bitmaps at the offsets suggested by the
+				// nextSelectionDistance() heuristic. Only reuse bitmaps created
+				// for more distant commits.
+				int index = -1;
+				int nextIn = nextSpan(cardinality);
+				int nextFlg = nextIn == distantCommitSpan
+						? PackBitmapIndex.FLAG_REUSE
+						: 0;
 
-				index++;
-				nextIn--;
-				pm.update(1);
-
-				// Always pick the items in wants, prefer merge commits.
-				if (selectionHelper.peeledWants.remove(c)) {
-					if (nextIn > 0) {
-						nextFlg = 0;
+				// For the current branch, iterate through all commits from
+				// oldest to newest.
+				for (RevCommit c : selectionHelper) {
+					// Optimization: if we have found all the commits for this
+					// branch, stop searching
+					int distanceFromTip = cardinality - index - 1;
+					if (distanceFromTip == 0) {
+						break;
 					}
-				} else {
-					boolean stillInSpan = nextIn >= 0;
-					boolean isMergeCommit = c.getParentCount() > 1;
-					// Force selection if:
-					// a) we have exhausted the window looking for merges
-					// b) we are in the top commits of an active branch
-					// c) we are at a branch tip
-					boolean mustPick = (nextIn <= -recentCommitSpan)
-							|| (isActiveBranch
-									&& (distanceFromTip <= contiguousCommitCount))
-							|| (distanceFromTip == 1); // most recent commit
-					if (!mustPick && (stillInSpan || !isMergeCommit)) {
+
+					// Ignore commits that are not in this branch
+					if (!tipBitmap.contains(c)) {
 						continue;
 					}
-				}
 
-				// This commit is selected.
-				// Calculate where to look for the next one.
-				int flags = nextFlg;
-				nextIn = nextSpan(distanceFromTip);
-				nextFlg = nextIn == distantCommitSpan
-						? PackBitmapIndex.FLAG_REUSE : 0;
+					index++;
+					nextIn--;
+					pm.update(1);
 
-				BitmapBuilder fullBitmap = commitBitmapIndex.newBitmapBuilder();
-				rw.reset();
-				rw.markStart(c);
-				rw.setRevFilter(new AddUnseenToBitmapFilter(
-						selectionHelper.reusedCommitsBitmap, fullBitmap));
-
-				while (rw.next() != null) {
-					// The RevFilter adds the reachable commits from this
-					// selected commit to fullBitmap.
-				}
-
-				// Sort the commits by independent chains in this branch's
-				// history, yielding better compression when building bitmaps.
-				List<BitmapCommit> longestAncestorChain = null;
-				for (List<BitmapCommit> chain : chains) {
-					BitmapCommit mostRecentCommit = chain.get(chain.size() - 1);
-					if (fullBitmap.contains(mostRecentCommit)) {
-						if (longestAncestorChain == null
-								|| longestAncestorChain.size() < chain.size()) {
-							longestAncestorChain = chain;
+					// Always pick the items in wants, prefer merge commits.
+					if (selectionHelper.newWants.remove(c)) {
+						if (nextIn > 0) {
+							nextFlg = 0;
+						}
+					} else {
+						boolean stillInSpan = nextIn >= 0;
+						boolean isMergeCommit = c.getParentCount() > 1;
+						// Force selection if:
+						// a) we have exhausted the window looking for merges
+						// b) we are in the top commits of an active branch
+						// c) we are at a branch tip
+						boolean mustPick = (nextIn <= -recentCommitSpan)
+								|| (isActiveBranch
+										&& (distanceFromTip <= contiguousCommitCount))
+								|| (distanceFromTip == 1); // most recent commit
+						if (!mustPick && (stillInSpan || !isMergeCommit)) {
+							continue;
 						}
 					}
+
+					// This commit is selected.
+					// Calculate where to look for the next one.
+					int flags = nextFlg;
+					nextIn = nextSpan(distanceFromTip);
+					nextFlg = nextIn == distantCommitSpan
+							? PackBitmapIndex.FLAG_REUSE
+							: 0;
+
+					// Create the commit bitmap for the current commit
+					BitmapBuilder bitmap = commitBitmapIndex.newBitmapBuilder();
+					rw.reset();
+					rw.markStart(c);
+					rw.setRevFilter(new AddUnseenToBitmapFilter(
+							selectionHelper.reusedCommitsBitmap, bitmap));
+					while (rw.next() != null) {
+						// The filter adds the reachable commits to bitmap.
+					}
+
+					// Sort the commits by independent chains in this branch's
+					// history, yielding better compression when building
+					// bitmaps.
+					List<BitmapCommit> longestAncestorChain = null;
+					for (List<BitmapCommit> chain : chains) {
+						BitmapCommit mostRecentCommit = chain
+								.get(chain.size() - 1);
+						if (bitmap.contains(mostRecentCommit)) {
+							if (longestAncestorChain == null
+									|| longestAncestorChain.size() < chain
+											.size()) {
+								longestAncestorChain = chain;
+							}
+						}
+					}
+
+					if (longestAncestorChain == null) {
+						longestAncestorChain = new ArrayList<>();
+						chains.add(longestAncestorChain);
+					}
+					longestAncestorChain.add(new BitmapCommit(c,
+							!longestAncestorChain.isEmpty(), flags));
+					writeBitmaps.addBitmap(c, bitmap, 0);
 				}
 
-				if (longestAncestorChain == null) {
-					longestAncestorChain = new ArrayList<>();
-					chains.add(longestAncestorChain);
+				for (List<BitmapCommit> chain : chains) {
+					selections.addAll(chain);
 				}
-				longestAncestorChain.add(new BitmapCommit(
-						c, !longestAncestorChain.isEmpty(), flags));
-				writeBitmaps.addBitmap(c, fullBitmap, 0);
+			}
+			writeBitmaps.clearBitmaps(); // Remove the temporary commit bitmaps.
+
+			// Add the remaining peeledWant
+			for (AnyObjectId remainingWant : selectionHelper.newWants) {
+				selections.add(new BitmapCommit(remainingWant, false, 0));
 			}
 
-			for (List<BitmapCommit> chain : chains) {
-				selections.addAll(chain);
-			}
+			pm.endTask();
+			return selections;
 		}
-		writeBitmaps.clearBitmaps(); // Remove the temporary commit bitmaps.
-
-		// Add the remaining peeledWant
-		for (AnyObjectId remainingWant : selectionHelper.peeledWants) {
-			selections.add(new BitmapCommit(remainingWant, false, 0));
-		}
-
-		pm.endTask();
-		return selections;
 	}
 
 	private boolean isRecentCommit(RevCommit revCommit) {
@@ -358,9 +380,8 @@ public final boolean requiresCommitBody() {
 	}
 
 	/**
-	 * For each of the {@code want}s, which represent the tip commit of each
-	 * branch, set up an initial {@link BitmapBuilder}. Reuse previously built
-	 * bitmaps if possible.
+	 * Records which of the {@code wants} can be found in the previous GC pack's
+	 * bitmap indices and which are new.
 	 *
 	 * @param rw
 	 *            a {@link RevWalk} to find reachable objects in this repository
@@ -369,8 +390,9 @@ public final boolean requiresCommitBody() {
 	 *            unreachable garbage.
 	 * @param excludeFromBitmapSelection
 	 *            commits that should be excluded from bitmap selection
-	 * @return a {@link CommitSelectionHelper} containing bitmaps for the tip
-	 *         commits
+	 * @return a {@link CommitSelectionHelper} capturing which commits are
+	 *         covered by a previous pack's bitmaps and which new commits need
+	 *         bitmap coverage
 	 * @throws IncorrectObjectTypeException
 	 *             if any of the processed objects is not a commit
 	 * @throws IOException
@@ -378,11 +400,12 @@ public final boolean requiresCommitBody() {
 	 * @throws MissingObjectException
 	 *             if an expected object is missing
 	 */
-	private CommitSelectionHelper setupTipCommitBitmaps(RevWalk rw,
+	private CommitSelectionHelper captureOldAndNewCommits(RevWalk rw,
 			int expectedCommitCount,
 			Set<? extends ObjectId> excludeFromBitmapSelection)
 			throws IncorrectObjectTypeException, IOException,
 			MissingObjectException {
+		// Track bitmaps and commits from the previous GC pack bitmap indices.
 		BitmapBuilder reuse = commitBitmapIndex.newBitmapBuilder();
 		List<BitmapCommit> reuseCommits = new ArrayList<>();
 		for (PackBitmapIndexRemapper.Entry entry : bitmapRemapper) {
@@ -404,11 +427,10 @@ private CommitSelectionHelper setupTipCommitBitmaps(RevWalk rw,
 			}
 		}
 
-		// Add branch tips that are not represented in old bitmap indices. Set
-		// up the RevWalk to walk the new commits not in the old packs.
-		List<BitmapBuilderEntry> tipCommitBitmaps = new ArrayList<>(
-				want.size());
-		Set<RevCommit> peeledWant = new HashSet<>(want.size());
+		// Add branch tips that are not represented in a previous pack's bitmap
+		// indices. Set up a RevWalk to find new commits not in the old packs.
+		List<RevCommit> newWantsByNewest = new ArrayList<>(want.size());
+		Set<RevCommit> newWants = new HashSet<>(want.size());
 		for (AnyObjectId objectId : want) {
 			RevObject ro = rw.peel(rw.parseAny(objectId));
 			if (!(ro instanceof RevCommit) || reuse.contains(ro)
@@ -417,59 +439,26 @@ private CommitSelectionHelper setupTipCommitBitmaps(RevWalk rw,
 			}
 
 			RevCommit rc = (RevCommit) ro;
-			peeledWant.add(rc);
 			rw.markStart(rc);
-
-			BitmapBuilder bitmap = commitBitmapIndex.newBitmapBuilder();
-			bitmap.addObject(rc, Constants.OBJ_COMMIT);
-			tipCommitBitmaps.add(new BitmapBuilderEntry(rc, bitmap));
+			newWants.add(rc);
+			newWantsByNewest.add(rc);
 		}
 
-		// Create a list of commits in reverse order (older to newer).
-		// For each branch that contains the commit, mark its parents as being
-		// in the bitmap.
+		// Create a list of commits in reverse order (older to newer) that are
+		// not in the previous bitmap indices and are reachable.
 		rw.setRevFilter(new NotInBitmapFilter(reuse));
 		RevCommit[] commits = new RevCommit[expectedCommitCount];
 		int pos = commits.length;
 		RevCommit rc;
 		while ((rc = rw.next()) != null && pos > 0) {
 			commits[--pos] = rc;
-			for (BitmapBuilderEntry entry : tipCommitBitmaps) {
-				BitmapBuilder bitmap = entry.getBuilder();
-				if (!bitmap.contains(rc)) {
-					continue;
-				}
-				for (RevCommit c : rc.getParents()) {
-					if (reuse.contains(c)) {
-						continue;
-					}
-					bitmap.addObject(c, Constants.OBJ_COMMIT);
-				}
-			}
 			pm.update(1);
 		}
 
-		// Sort the tip commit bitmaps. Find the one containing the most
-		// commits, remove those commits from the remaining bitmaps, resort and
-		// repeat.
-		List<BitmapBuilderEntry> orderedTipCommitBitmaps = new ArrayList<>(
-				tipCommitBitmaps.size());
-		while (!tipCommitBitmaps.isEmpty()) {
-			BitmapBuilderEntry largest =
-					Collections.max(tipCommitBitmaps, ORDER_BY_CARDINALITY);
-			tipCommitBitmaps.remove(largest);
-			orderedTipCommitBitmaps.add(largest);
-
-			// Update the remaining paths, by removing the objects from
-			// the path that was just added.
-			for (int i = tipCommitBitmaps.size() - 1; i >= 0; i--) {
-				tipCommitBitmaps.get(i).getBuilder()
-						.andNot(largest.getBuilder());
-			}
-		}
-
-		return new CommitSelectionHelper(peeledWant, commits, pos,
-				orderedTipCommitBitmaps, reuse, reuseCommits);
+		// Sort the new wants by reverse commit time.
+		Collections.sort(newWantsByNewest, ORDER_BY_REVERSE_TIMESTAMP);
+		return new CommitSelectionHelper(newWants, commits, pos,
+				newWantsByNewest, reuse, reuseCommits);
 	}
 
 	/*-
@@ -537,54 +526,36 @@ int getFlags() {
 	}
 
 	/**
-	 * A POJO representing a Pair<RevCommit, BitmapBuidler>.
-	 */
-	private static final class BitmapBuilderEntry {
-		private final RevCommit commit;
-		private final BitmapBuilder builder;
-
-		BitmapBuilderEntry(RevCommit commit, BitmapBuilder builder) {
-			this.commit = commit;
-			this.builder = builder;
-		}
-
-		RevCommit getCommit() {
-			return commit;
-		}
-
-		BitmapBuilder getBuilder() {
-			return builder;
-		}
-	}
-
-	/**
 	 * Container for state used in the first phase of selecting commits, which
-	 * walks all of the reachable commits via the branch tips (
-	 * {@code peeledWants}), stores them in {@code commitsByOldest}, and sets up
-	 * bitmaps for each branch tip ({@code tipCommitBitmaps}).
-	 * {@code commitsByOldest} is initialized with an expected size of all
-	 * commits, but may be smaller if some commits are unreachable, in which
-	 * case {@code commitStartPos} will contain a positive offset to the root
-	 * commit.
+	 * walks all of the reachable commits via the branch tips that are not
+	 * covered by a previous pack's bitmaps ({@code newWants}) and stores them
+	 * in {@code newCommitsByOldest}. {@code newCommitsByOldest} is initialized
+	 * with an expected size of all commits, but may be smaller if some commits
+	 * are unreachable and/or some commits are covered by a previous pack's
+	 * bitmaps. {@code commitStartPos} will contain a positive offset to either
+	 * the root commit or the oldest commit not covered by previous bitmaps.
 	 */
 	private static final class CommitSelectionHelper implements Iterable<RevCommit> {
-		final Set<? extends ObjectId> peeledWants;
-		final List<BitmapBuilderEntry> tipCommitBitmaps;
+		final Set<? extends ObjectId> newWants;
 
+		final List<RevCommit> newWantsByNewest;
 		final BitmapBuilder reusedCommitsBitmap;
-		final Iterable<BitmapCommit> reusedCommits;
-		final RevCommit[] commitsByOldest;
-		final int commitStartPos;
 
-		CommitSelectionHelper(Set<? extends ObjectId> peeledWant,
+		final List<BitmapCommit> reusedCommits;
+
+		final RevCommit[] newCommitsByOldest;
+
+		final int newCommitStartPos;
+
+		CommitSelectionHelper(Set<? extends ObjectId> newWants,
 				RevCommit[] commitsByOldest, int commitStartPos,
-				List<BitmapBuilderEntry> bitmapEntries,
+				List<RevCommit> newWantsByNewest,
 				BitmapBuilder reusedCommitsBitmap,
-				Iterable<BitmapCommit> reuse) {
-			this.peeledWants = peeledWant;
-			this.commitsByOldest = commitsByOldest;
-			this.commitStartPos = commitStartPos;
-			this.tipCommitBitmaps = bitmapEntries;
+				List<BitmapCommit> reuse) {
+			this.newWants = newWants;
+			this.newCommitsByOldest = commitsByOldest;
+			this.newCommitStartPos = commitStartPos;
+			this.newWantsByNewest = newWantsByNewest;
 			this.reusedCommitsBitmap = reusedCommitsBitmap;
 			this.reusedCommits = reuse;
 		}
@@ -594,16 +565,16 @@ public Iterator<RevCommit> iterator() {
 			// Member variables referenced by this iterator will have synthetic
 			// accessors generated for them if they are made private.
 			return new Iterator<RevCommit>() {
-				int pos = commitStartPos;
+				int pos = newCommitStartPos;
 
 				@Override
 				public boolean hasNext() {
-					return pos < commitsByOldest.length;
+					return pos < newCommitsByOldest.length;
 				}
 
 				@Override
 				public RevCommit next() {
-					return commitsByOldest[pos++];
+					return newCommitsByOldest[pos++];
 				}
 
 				@Override
@@ -614,7 +585,7 @@ public void remove() {
 		}
 
 		int getCommitCount() {
-			return commitsByOldest.length - commitStartPos;
+			return newCommitsByOldest.length - newCommitStartPos;
 		}
 	}
 }
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/MergedReftable.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/MergedReftable.java
index ef686a3..17894b1 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/MergedReftable.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/MergedReftable.java
@@ -113,6 +113,16 @@ public RefCursor seekRef(String name) throws IOException {
 
 	/** {@inheritDoc} */
 	@Override
+	public RefCursor seekRefsWithPrefix(String prefix) throws IOException {
+		MergedRefCursor m = new MergedRefCursor();
+		for (int i = 0; i < tables.length; i++) {
+			m.add(new RefQueueEntry(tables[i].seekRefsWithPrefix(prefix), i));
+		}
+		return m;
+	}
+
+	/** {@inheritDoc} */
+	@Override
 	public RefCursor byObjectId(AnyObjectId name) throws IOException {
 		MergedRefCursor m = new MergedRefCursor();
 		for (int i = 0; i < tables.length; i++) {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/Reftable.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/Reftable.java
index 510c1a1..a1087e2 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/Reftable.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/Reftable.java
@@ -108,18 +108,14 @@ public void setIncludeDeletes(boolean deletes) {
 	public abstract RefCursor allRefs() throws IOException;
 
 	/**
-	 * Seek either to a reference, or a reference subtree.
+	 * Seek to a reference.
 	 * <p>
-	 * If {@code refName} ends with {@code "/"} the method will seek to the
-	 * subtree of all references starting with {@code refName} as a prefix. If
-	 * no references start with this prefix, an empty cursor is returned.
-	 * <p>
-	 * Otherwise exactly {@code refName} will be looked for. If present, the
+	 * This method will seek to the reference {@code refName}. If present, the
 	 * returned cursor will iterate exactly one entry. If not found, an empty
 	 * cursor is returned.
 	 *
 	 * @param refName
-	 *            reference name or subtree to find.
+	 *            reference name.
 	 * @return cursor to iterate; empty cursor if no references match.
 	 * @throws java.io.IOException
 	 *             if references cannot be read.
@@ -127,6 +123,21 @@ public void setIncludeDeletes(boolean deletes) {
 	public abstract RefCursor seekRef(String refName) throws IOException;
 
 	/**
+	 * Seek references with prefix.
+	 * <p>
+	 * The method will seek all the references starting with {@code prefix} as a
+	 * prefix. If no references start with this prefix, an empty cursor is
+	 * returned.
+	 *
+	 * @param prefix
+	 *            prefix to find.
+	 * @return cursor to iterate; empty cursor if no references match.
+	 * @throws java.io.IOException
+	 *             if references cannot be read.
+	 */
+	public abstract RefCursor seekRefsWithPrefix(String prefix) throws IOException;
+
+	/**
 	 * Match references pointing to a specific object.
 	 *
 	 * @param id
@@ -191,17 +202,11 @@ public Ref exactRef(String refName) throws IOException {
 	}
 
 	/**
-	 * Test if a reference or reference subtree exists.
-	 * <p>
-	 * If {@code refName} ends with {@code "/"}, the method tests if any
-	 * reference starts with {@code refName} as a prefix.
-	 * <p>
-	 * Otherwise, the method checks if {@code refName} exists.
+	 * Test if a reference exists.
 	 *
 	 * @param refName
 	 *            reference name or subtree to find.
-	 * @return {@code true} if the reference exists, or at least one reference
-	 *         exists in the subtree.
+	 * @return {@code true} if the reference exists.
 	 * @throws java.io.IOException
 	 *             if references cannot be read.
 	 */
@@ -212,6 +217,21 @@ public boolean hasRef(String refName) throws IOException {
 	}
 
 	/**
+	 * Test if any reference starts with {@code prefix} as a prefix.
+	 *
+	 * @param prefix
+	 *            prefix to find.
+	 * @return {@code true} if at least one reference exists with prefix.
+	 * @throws java.io.IOException
+	 *             if references cannot be read.
+	 */
+	public boolean hasRefsWithPrefix(String prefix) throws IOException {
+		try (RefCursor rc = seekRefsWithPrefix(prefix)) {
+			return rc.next();
+		}
+	}
+
+	/**
 	 * Test if any reference directly refers to the object.
 	 *
 	 * @param id
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/ReftableReader.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/ReftableReader.java
index 5356952..bd52256 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/ReftableReader.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/ReftableReader.java
@@ -183,9 +183,18 @@ public RefCursor seekRef(String refName) throws IOException {
 		initRefIndex();
 
 		byte[] key = refName.getBytes(CHARSET);
-		boolean prefix = key[key.length - 1] == '/';
+		RefCursorImpl i = new RefCursorImpl(refEnd, key, false);
+		i.block = seek(REF_BLOCK_TYPE, key, refIndex, 0, refEnd);
+		return i;
+	}
 
-		RefCursorImpl i = new RefCursorImpl(refEnd, key, prefix);
+	/** {@inheritDoc} */
+	@Override
+	public RefCursor seekRefsWithPrefix(String prefix) throws IOException {
+		initRefIndex();
+
+		byte[] key = prefix.getBytes(CHARSET);
+		RefCursorImpl i = new RefCursorImpl(refEnd, key, true);
 		i.block = seek(REF_BLOCK_TYPE, key, refIndex, 0, refEnd);
 		return i;
 	}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java
index 5a79035..d4a0280 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java
@@ -49,7 +49,7 @@
  * configuration keys
  */
 @SuppressWarnings("nls")
-public class ConfigConstants {
+public final class ConfigConstants {
 	/** The "core" section */
 	public static final String CONFIG_CORE_SECTION = "core";
 
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Constants.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Constants.java
index ecebd54..9a4a3a2 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Constants.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Constants.java
@@ -687,11 +687,23 @@ public static int decodeTypeString(final AnyObjectId id,
 	 */
 	public static final String COMMIT_EDITMSG = "COMMIT_EDITMSG";
 
-	/** objectid for the empty blob */
+	/**
+	 * Well-known object ID for the empty blob.
+	 *
+	 * @since 0.9.1
+	 */
 	public static final ObjectId EMPTY_BLOB_ID = ObjectId
 			.fromString("e69de29bb2d1d6434b8b29ae775ad8c2e48c5391");
 
 	/**
+	 * Well-known object ID for the empty tree.
+	 *
+	 * @since 5.1
+	 */
+	public static final ObjectId EMPTY_TREE_ID = ObjectId
+			.fromString("4b825dc642cb6eb9a060e54bf8d69288fbee4904");
+
+	/**
 	 * Suffix of lock file name
 	 *
 	 * @since 5.0
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java
index 29cc19c..d73c05e 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java
@@ -1094,7 +1094,9 @@ public final Ref findRef(String name) throws IOException {
 	 * not point to any object yet.
 	 *
 	 * @return mutable map of all known refs (heads, tags, remotes).
+	 * @deprecated use {@code getRefDatabase().getRefs()} instead.
 	 */
+	@Deprecated
 	@NonNull
 	public Map<String, Ref> getAllRefs() {
 		try {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java b/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java
index da6a3da..f60c95f 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java
@@ -78,6 +78,7 @@
 import org.eclipse.jgit.dircache.DirCacheBuildIterator;
 import org.eclipse.jgit.dircache.DirCacheBuilder;
 import org.eclipse.jgit.dircache.DirCacheCheckout;
+import org.eclipse.jgit.dircache.DirCacheCheckout.CheckoutMetadata;
 import org.eclipse.jgit.dircache.DirCacheEntry;
 import org.eclipse.jgit.errors.BinaryBlobException;
 import org.eclipse.jgit.errors.CorruptObjectException;
@@ -297,6 +298,12 @@ public enum MergeFailureReason {
 	 */
 	private int inCoreLimit;
 
+	/**
+	 * Keeps {@link CheckoutMetadata} for {@link #checkout()} and
+	 * {@link #cleanUp()}.
+	 */
+	private Map<String, CheckoutMetadata> checkoutMetadata;
+
 	private static MergeAlgorithm getMergeAlgorithm(Config config) {
 		SupportedAlgorithm diffAlg = config.getEnum(
 				CONFIG_DIFF_SECTION, null, CONFIG_KEY_ALGORITHM,
@@ -313,6 +320,8 @@ private static int getInCoreLimit(Config config) {
 		return new String[] { "BASE", "OURS", "THEIRS" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
 	}
 
+	private static final Attributes NO_ATTRIBUTES = new Attributes();
+
 	/**
 	 * Constructor for ResolveMerger.
 	 *
@@ -369,15 +378,20 @@ protected ResolveMerger(ObjectInserter inserter, Config config) {
 	/** {@inheritDoc} */
 	@Override
 	protected boolean mergeImpl() throws IOException {
-		if (implicitDirCache)
+		if (implicitDirCache) {
 			dircache = nonNullRepo().lockDirCache();
-
+		}
+		if (!inCore) {
+			checkoutMetadata = new HashMap<>();
+		}
 		try {
 			return mergeTrees(mergeBase(), sourceTrees[0], sourceTrees[1],
 					false);
 		} finally {
-			if (implicitDirCache)
+			checkoutMetadata = null;
+			if (implicitDirCache) {
 				dircache.unlock();
+			}
 		}
 	}
 
@@ -400,7 +414,8 @@ private void checkout() throws NoWorkTreeException, IOException {
 			if (cacheEntry.getFileMode() == FileMode.GITLINK) {
 				new File(nonNullRepo().getWorkTree(), entry.getKey()).mkdirs();
 			} else {
-				DirCacheCheckout.checkoutEntry(db, cacheEntry, reader);
+				DirCacheCheckout.checkoutEntry(db, cacheEntry, reader, false,
+						checkoutMetadata.get(entry.getKey()));
 				modifiedFiles.add(entry.getKey());
 			}
 		}
@@ -428,10 +443,12 @@ protected void cleanUp() throws NoWorkTreeException,
 		DirCache dc = nonNullRepo().readDirCache();
 		Iterator<String> mpathsIt=modifiedFiles.iterator();
 		while(mpathsIt.hasNext()) {
-			String mpath=mpathsIt.next();
+			String mpath = mpathsIt.next();
 			DirCacheEntry entry = dc.getEntry(mpath);
-			if (entry != null)
-				DirCacheCheckout.checkoutEntry(db, entry, reader);
+			if (entry != null) {
+				DirCacheCheckout.checkoutEntry(db, entry, reader, false,
+						checkoutMetadata.get(mpath));
+			}
 			mpathsIt.remove();
 		}
 	}
@@ -481,6 +498,71 @@ private DirCacheEntry keep(DirCacheEntry e) {
 	}
 
 	/**
+	 * Remembers the {@link CheckoutMetadata} for the given path; it may be
+	 * needed in {@link #checkout()} or in {@link #cleanUp()}.
+	 *
+	 * @param path
+	 *            of the current node
+	 * @param attributes
+	 *            for the current node
+	 * @throws IOException
+	 *             if the smudge filter cannot be determined
+	 * @since 5.1
+	 */
+	protected void addCheckoutMetadata(String path, Attributes attributes)
+			throws IOException {
+		if (checkoutMetadata != null) {
+			EolStreamType eol = EolStreamTypeUtil.detectStreamType(
+					OperationType.CHECKOUT_OP, workingTreeOptions, attributes);
+			CheckoutMetadata data = new CheckoutMetadata(eol,
+					tw.getFilterCommand(Constants.ATTR_FILTER_TYPE_SMUDGE));
+			checkoutMetadata.put(path, data);
+		}
+	}
+
+	/**
+	 * Adds a {@link DirCacheEntry} for direct checkout and remembers its
+	 * {@link CheckoutMetadata}.
+	 *
+	 * @param path
+	 *            of the entry
+	 * @param entry
+	 *            to add
+	 * @param attributes
+	 *            for the current entry
+	 * @throws IOException
+	 *             if the {@link CheckoutMetadata} cannot be determined
+	 * @since 5.1
+	 */
+	protected void addToCheckout(String path, DirCacheEntry entry,
+			Attributes attributes) throws IOException {
+		toBeCheckedOut.put(path, entry);
+		addCheckoutMetadata(path, attributes);
+	}
+
+	/**
+	 * Remember a path for deletion, and remember its {@link CheckoutMetadata}
+	 * in case it has to be restored in {@link #cleanUp()}.
+	 *
+	 * @param path
+	 *            of the entry
+	 * @param isFile
+	 *            whether it is a file
+	 * @param attributes
+	 *            for the entry
+	 * @throws IOException
+	 *             if the {@link CheckoutMetadata} cannot be determined
+	 * @since 5.1
+	 */
+	protected void addDeletion(String path, boolean isFile,
+			Attributes attributes) throws IOException {
+		toBeDeleted.add(path);
+		if (isFile) {
+			addCheckoutMetadata(path, attributes);
+		}
+	}
+
+	/**
 	 * Processes one path and tries to merge taking git attributes in account.
 	 * This method will do all trivial (not content) merges and will also detect
 	 * if a merge will fail. The merge will fail when one of the following is
@@ -586,7 +668,7 @@ protected boolean processEntry(CanonicalTreeParser base,
 						// This will happen later. Set these values to 0 for know.
 						DirCacheEntry e = add(tw.getRawPath(), theirs,
 								DirCacheEntry.STAGE_0, 0, 0);
-						toBeCheckedOut.put(tw.getPathString(), e);
+						addToCheckout(tw.getPathString(), e, attributes);
 					}
 					return true;
 				} else {
@@ -627,18 +709,23 @@ protected boolean processEntry(CanonicalTreeParser base,
 				// This will happen later. Set these values to 0 for know.
 				DirCacheEntry e = add(tw.getRawPath(), theirs,
 						DirCacheEntry.STAGE_0, 0, 0);
-				if (e != null)
-					toBeCheckedOut.put(tw.getPathString(), e);
+				if (e != null) {
+					addToCheckout(tw.getPathString(), e, attributes);
+				}
 				return true;
 			} else {
 				// we want THEIRS ... but THEIRS contains a folder or the
-				// deletion of the path. Delete what's in the workingtree (the
-				// workingtree is clean) but do not complain if the file is
-				// already deleted locally. This complements the test in
-				// isWorktreeDirty() for the same case.
-				if (tw.getTreeCount() > T_FILE && tw.getRawMode(T_FILE) == 0)
+				// deletion of the path. Delete what's in the working tree,
+				// which we know to be clean.
+				if (tw.getTreeCount() > T_FILE && tw.getRawMode(T_FILE) == 0) {
+					// Not present in working tree, so nothing to delete
 					return true;
-				toBeDeleted.add(tw.getPathString());
+				}
+				if (modeT != 0 && modeT == modeB) {
+					// Base, ours, and theirs all contain a folder: don't delete
+					return true;
+				}
+				addDeletion(tw.getPathString(), nonTree(modeO), attributes);
 				return true;
 			}
 		}
@@ -722,9 +809,12 @@ protected boolean processEntry(CanonicalTreeParser base,
 				result.setContainsConflicts(false);
 			}
 			updateIndex(base, ours, theirs, result, attributes);
-			if (result.containsConflicts() && !ignoreConflicts)
-				unmergedPaths.add(tw.getPathString());
-			modifiedFiles.add(tw.getPathString());
+			String currentPath = tw.getPathString();
+			if (result.containsConflicts() && !ignoreConflicts) {
+				unmergedPaths.add(currentPath);
+			}
+			modifiedFiles.add(currentPath);
+			addCheckoutMetadata(currentPath, attributes);
 		} else if (modeO != modeT) {
 			// OURS or THEIRS has been deleted
 			if (((modeO != 0 && !tw.idEqual(T_BASE, T_OURS)) || (modeT != 0 && !tw
@@ -743,8 +833,9 @@ protected boolean processEntry(CanonicalTreeParser base,
 					if (isWorktreeDirty(work, ourDce))
 						return false;
 					if (nonTree(modeT)) {
-						if (e != null)
-							toBeCheckedOut.put(tw.getPathString(), e);
+						if (e != null) {
+							addToCheckout(tw.getPathString(), e, attributes);
+						}
 					}
 				}
 
@@ -1245,7 +1336,8 @@ protected boolean mergeTreeWalk(TreeWalk treeWalk, boolean ignoreConflicts)
 					hasWorkingTreeIterator ? treeWalk.getTree(T_FILE,
 							WorkingTreeIterator.class) : null,
 					ignoreConflicts, hasAttributeNodeProvider
-							? treeWalk.getAttributes() : new Attributes())) {
+							? treeWalk.getAttributes()
+							: NO_ATTRIBUTES)) {
 				cleanUp();
 				return false;
 			}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revplot/PlotWalk.java b/org.eclipse.jgit/src/org/eclipse/jgit/revplot/PlotWalk.java
index f27f356..aff2a43 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/revplot/PlotWalk.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/revplot/PlotWalk.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008-2009, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2008-2018, Robin Rosenberg <robin.rosenberg@dewire.com>
  * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
  * and other copyright owners as documented in the project's IP log.
  *
@@ -53,6 +53,7 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
@@ -75,13 +76,25 @@
  */
 public class PlotWalk extends RevWalk {
 
+	private Map<AnyObjectId, Set<Ref>> additionalRefMap;
+
 	private Map<AnyObjectId, Set<Ref>> reverseRefMap;
 
+	private Repository repository;
+
 	/** {@inheritDoc} */
 	@Override
 	public void dispose() {
 		super.dispose();
-		reverseRefMap.clear();
+		if (reverseRefMap != null) {
+			reverseRefMap.clear();
+			reverseRefMap = null;
+		}
+		if (additionalRefMap != null) {
+			additionalRefMap.clear();
+			additionalRefMap = null;
+		}
+		repository = null;
 	}
 
 	/**
@@ -93,7 +106,8 @@ public void dispose() {
 	public PlotWalk(Repository repo) {
 		super(repo);
 		super.sort(RevSort.TOPO, true);
-		reverseRefMap = repo.getAllRefsByPeeledObjectId();
+		additionalRefMap = new HashMap<>();
+		repository = repo;
 	}
 
 	/**
@@ -105,14 +119,14 @@ public PlotWalk(Repository repo) {
 	 */
 	public void addAdditionalRefs(Iterable<Ref> refs) throws IOException {
 		for (Ref ref : refs) {
-			Set<Ref> set = reverseRefMap.get(ref.getObjectId());
+			Set<Ref> set = additionalRefMap.get(ref.getObjectId());
 			if (set == null)
 				set = Collections.singleton(ref);
 			else {
 				set = new HashSet<>(set);
 				set.add(ref);
 			}
-			reverseRefMap.put(ref.getObjectId(), set);
+			additionalRefMap.put(ref.getObjectId(), set);
 		}
 	}
 
@@ -141,10 +155,28 @@ public RevCommit next() throws MissingObjectException,
 	}
 
 	private Ref[] getRefs(AnyObjectId commitId) {
+		if (reverseRefMap == null) {
+			reverseRefMap = repository.getAllRefsByPeeledObjectId();
+			for (Map.Entry<AnyObjectId, Set<Ref>> entry : additionalRefMap
+					.entrySet()) {
+				Set<Ref> set = reverseRefMap.get(entry.getKey());
+				Set<Ref> additional = entry.getValue();
+				if (set != null) {
+					if (additional.size() == 1) {
+						// It's an unmodifiable singleton set...
+						additional = new HashSet<>(additional);
+					}
+					additional.addAll(set);
+				}
+				reverseRefMap.put(entry.getKey(), additional);
+			}
+			additionalRefMap.clear();
+			additionalRefMap = null;
+		}
 		Collection<Ref> list = reverseRefMap.get(commitId);
-		if (list == null)
+		if (list == null) {
 			return PlotCommit.NO_REFS;
-		else {
+		} else {
 			Ref[] tags = list.toArray(new Ref[list.size()]);
 			Arrays.sort(tags, new PlotRefComparator());
 			return tags;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevCommit.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevCommit.java
index b67f934..3de442a 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevCommit.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevCommit.java
@@ -168,10 +168,10 @@ void parseBody(RevWalk walk) throws MissingObjectException,
 		}
 	}
 
-	void parseCanonical(RevWalk walk, byte[] raw)
-			throws IOException {
-		if (!walk.shallowCommitsInitialized)
-			walk.initializeShallowCommits();
+	void parseCanonical(RevWalk walk, byte[] raw) throws IOException {
+		if (!walk.shallowCommitsInitialized) {
+			walk.initializeShallowCommits(this);
+		}
 
 		final MutableObjectId idBuffer = walk.idBuffer;
 		idBuffer.fromString(raw, 5);
@@ -182,13 +182,14 @@ void parseCanonical(RevWalk walk, byte[] raw)
 			RevCommit[] pList = new RevCommit[1];
 			int nParents = 0;
 			for (;;) {
-				if (raw[ptr] != 'p')
+				if (raw[ptr] != 'p') {
 					break;
+				}
 				idBuffer.fromString(raw, ptr + 7);
 				final RevCommit p = walk.lookupCommit(idBuffer);
-				if (nParents == 0)
+				if (nParents == 0) {
 					pList[nParents++] = p;
-				else if (nParents == 1) {
+				} else if (nParents == 1) {
 					pList = new RevCommit[] { pList[0], p };
 					nParents = 2;
 				} else {
@@ -218,8 +219,9 @@ else if (nParents == 1) {
 			commitTime = RawParseUtils.parseBase10(raw, ptr, null);
 		}
 
-		if (walk.isRetainBody())
+		if (walk.isRetainBody()) {
 			buffer = raw;
+		}
 		flags |= PARSED;
 	}
 
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java
index a986cfd..4d555d2 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java
@@ -1460,17 +1460,44 @@ public void assumeShallow(Collection<? extends ObjectId> ids) {
 			lookupCommit(id).parents = RevCommit.NO_PARENTS;
 	}
 
-	void initializeShallowCommits() throws IOException {
-		if (shallowCommitsInitialized)
+	/**
+	 * Reads the "shallow" file and applies it by setting the parents of shallow
+	 * commits to an empty array.
+	 * <p>
+	 * There is a sequencing problem if the first commit being parsed is a
+	 * shallow commit, since {@link RevCommit#parseCanonical(RevWalk, byte[])}
+	 * calls this method before its callers add the new commit to the
+	 * {@link RevWalk#objects} map. That means a call from this method to
+	 * {@link #lookupCommit(AnyObjectId)} fails to find that commit and creates
+	 * a new one, which is promptly discarded.
+	 * <p>
+	 * To avoid that, {@link RevCommit#parseCanonical(RevWalk, byte[])} passes
+	 * its commit to this method, so that this method can apply the shallow
+	 * state to it directly and avoid creating the duplicate commit object.
+	 *
+	 * @param rc
+	 *            the initial commit being parsed
+	 * @throws IOException
+	 *             if the shallow commits file can't be read
+	 */
+	void initializeShallowCommits(RevCommit rc) throws IOException {
+		if (shallowCommitsInitialized) {
 			throw new IllegalStateException(
 					JGitText.get().shallowCommitsAlreadyInitialized);
+		}
 
 		shallowCommitsInitialized = true;
 
-		if (reader == null)
+		if (reader == null) {
 			return;
+		}
 
-		for (ObjectId id : reader.getShallowCommits())
-			lookupCommit(id).parents = RevCommit.NO_PARENTS;
+		for (ObjectId id : reader.getShallowCommits()) {
+			if (id.equals(rc.getId())) {
+				rc.parents = RevCommit.NO_PARENTS;
+			} else {
+				lookupCommit(id).parents = RevCommit.NO_PARENTS;
+			}
+		}
 	}
 }
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/CapabilitiesV2Request.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/CapabilitiesV2Request.java
new file mode 100644
index 0000000..b133ab5
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/CapabilitiesV2Request.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2018, Google LLC.
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ *   copyright notice, this list of conditions and the following
+ *   disclaimer in the documentation and/or other materials provided
+ *   with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ *   names of its contributors may be used to endorse or promote
+ *   products derived from this software without specific prior
+ *   written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.eclipse.jgit.transport;
+
+/**
+ * Capabilities protocol v2 request.
+ *
+ * <p>
+ * This is used as an input to {@link ProtocolV2Hook}.
+ *
+ * @since 5.1
+ */
+public final class CapabilitiesV2Request {
+	private CapabilitiesV2Request() {
+	}
+
+	/** @return A builder of {@link CapabilitiesV2Request}. */
+	public static Builder builder() {
+		return new Builder();
+	}
+
+	/** A builder for {@link CapabilitiesV2Request}. */
+	public static final class Builder {
+		private Builder() {
+		}
+
+		/** @return CapabilitiesV2Request */
+		public CapabilitiesV2Request build() {
+			return new CapabilitiesV2Request();
+		}
+	}
+}
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 10cd775..760ac6c 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/GitProtocolConstants.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/GitProtocolConstants.java
@@ -50,7 +50,7 @@
  *
  * @since 3.2
  */
-public class GitProtocolConstants {
+public final class GitProtocolConstants {
 	/**
 	 * Include tags if we are also including the referenced objects.
 	 *
@@ -167,6 +167,13 @@ public class GitProtocolConstants {
 	public static final String OPTION_FILTER = "filter"; //$NON-NLS-1$
 
 	/**
+	 * The client specified a want-ref expression.
+	 *
+	 * @since 5.1
+	 */
+	public static final String OPTION_WANT_REF = "want-ref"; //$NON-NLS-1$
+
+	/**
 	 * The client supports atomic pushes. If this option is used, the server
 	 * will update all refs within one atomic transaction.
 	 *
@@ -231,6 +238,13 @@ public class GitProtocolConstants {
 	public static final String CAPABILITY_PUSH_OPTIONS = "push-options"; //$NON-NLS-1$
 
 	/**
+	 * The server supports the client specifying ref names.
+	 *
+	 * @since 5.1
+	 */
+	public static final String CAPABILITY_REF_IN_WANT = "ref-in-want"; //$NON-NLS-1$
+
+	/**
 	 * The server supports listing refs using protocol v2.
 	 *
 	 * @since 5.0
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/LsRefsV2Request.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/LsRefsV2Request.java
new file mode 100644
index 0000000..3aff584
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/LsRefsV2Request.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2018, Google LLC.
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ *   copyright notice, this list of conditions and the following
+ *   disclaimer in the documentation and/or other materials provided
+ *   with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ *   names of its contributors may be used to endorse or promote
+ *   products derived from this software without specific prior
+ *   written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.eclipse.jgit.transport;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * ls-refs protocol v2 request.
+ *
+ * <p>
+ * This is used as an input to {@link ProtocolV2Hook}.
+ *
+ * @since 5.1
+ */
+public final class LsRefsV2Request {
+	private final List<String> refPrefixes;
+
+	private final boolean symrefs;
+
+	private final boolean peel;
+
+	private LsRefsV2Request(List<String> refPrefixes, boolean symrefs,
+			boolean peel) {
+		this.refPrefixes = refPrefixes;
+		this.symrefs = symrefs;
+		this.peel = peel;
+	}
+
+	/** @return ref prefixes that the client requested. */
+	public List<String> getRefPrefixes() {
+		return refPrefixes;
+	}
+
+	/** @return true if the client requests symbolic references. */
+	public boolean getSymrefs() {
+		return symrefs;
+	}
+
+	/** @return true if the client requests tags to be peeled. */
+	public boolean getPeel() {
+		return peel;
+	}
+
+	/** @return A builder of {@link LsRefsV2Request}. */
+	public static Builder builder() {
+		return new Builder();
+	}
+
+	/** A builder for {@link LsRefsV2Request}. */
+	public static final class Builder {
+		private List<String> refPrefixes = Collections.emptyList();
+
+		private boolean symrefs;
+
+		private boolean peel;
+
+		private Builder() {
+		}
+
+		/**
+		 * @param value
+		 * @return the Builder
+		 */
+		public Builder setRefPrefixes(List<String> value) {
+			refPrefixes = value;
+			return this;
+		}
+
+		/**
+		 * @param value
+		 * @return the Builder
+		 */
+		public Builder setSymrefs(boolean value) {
+			symrefs = value;
+			return this;
+		}
+
+		/**
+		 * @param value
+		 * @return the Builder
+		 */
+		public Builder setPeel(boolean value) {
+			peel = value;
+			return this;
+		}
+
+		/** @return LsRefsV2Request */
+		public LsRefsV2Request build() {
+			return new LsRefsV2Request(
+					Collections.unmodifiableList(refPrefixes), symrefs, peel);
+		}
+	}
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ProtocolV2Hook.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ProtocolV2Hook.java
new file mode 100644
index 0000000..02760fd
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ProtocolV2Hook.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2018, Google LLC.
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ *   copyright notice, this list of conditions and the following
+ *   disclaimer in the documentation and/or other materials provided
+ *   with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ *   names of its contributors may be used to endorse or promote
+ *   products derived from this software without specific prior
+ *   written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.eclipse.jgit.transport;
+
+/**
+ * Hook to allow callers to be notified on Git protocol v2 requests.
+ *
+ * @see UploadPack#setProtocolV2Hook(ProtocolV2Hook)
+ * @since 5.1
+ */
+public interface ProtocolV2Hook {
+	/**
+	 * The default hook implementation that does nothing.
+	 */
+	static ProtocolV2Hook DEFAULT = new ProtocolV2Hook() {
+		// No override.
+	};
+
+	/**
+	 * @param req
+	 *            the capabilities request
+	 * @throws ServiceMayNotContinueException
+	 *             abort; the message will be sent to the user
+	 * @since 5.1
+	 */
+	default void onCapabilities(CapabilitiesV2Request req)
+			throws ServiceMayNotContinueException {
+		// Do nothing by default.
+	}
+
+	/**
+	 * @param req
+	 *            the ls-refs request
+	 * @throws ServiceMayNotContinueException
+	 *             abort; the message will be sent to the user
+	 * @since 5.1
+	 */
+	default void onLsRefs(LsRefsV2Request req)
+			throws ServiceMayNotContinueException {
+		// Do nothing by default.
+	}
+}
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 4ae1ccb..6b8d5c5 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransferConfig.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransferConfig.java
@@ -126,6 +126,7 @@ enum ProtocolVersion {
 	private final boolean allowInvalidPersonIdent;
 	private final boolean safeForWindows;
 	private final boolean safeForMacOS;
+	private final boolean allowRefInWant;
 	private final boolean allowTipSha1InWant;
 	private final boolean allowReachableSha1InWant;
 	private final boolean allowFilter;
@@ -180,6 +181,7 @@ enum ProtocolVersion {
 			ignore.add(ObjectChecker.ErrorType.ZERO_PADDED_FILEMODE);
 		}
 
+		allowRefInWant = rc.getBoolean("uploadpack", "allowrefinwant", false);
 		allowTipSha1InWant = rc.getBoolean(
 				"uploadpack", "allowtipsha1inwant", false);
 		allowReachableSha1InWant = rc.getBoolean(
@@ -262,6 +264,14 @@ public boolean isAllowFilter() {
 	}
 
 	/**
+	 * @return true if clients are allowed to specify a "want-ref" line
+	 * @since 5.1
+	 */
+	public boolean isAllowRefInWant() {
+		return allowRefInWant;
+	}
+
+	/**
 	 * Get {@link org.eclipse.jgit.transport.RefFilter} respecting configured
 	 * hidden refs.
 	 *
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 c08f400..ee64a87 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java
@@ -483,6 +483,18 @@ public void setAdditionalHeaders(Map<String, String> headers) {
 		this.headers = headers;
 	}
 
+	private NoRemoteRepositoryException createNotFoundException(URIish u,
+			URL url, String msg) {
+		String text;
+		if (msg != null && !msg.isEmpty()) {
+			text = MessageFormat.format(JGitText.get().uriNotFoundWithMessage,
+					url, msg);
+		} else {
+			text = MessageFormat.format(JGitText.get().uriNotFound, url);
+		}
+		return new NoRemoteRepositoryException(u, text);
+	}
+
 	private HttpConnection connect(String service)
 			throws TransportException, NotSupportedException {
 		URL u = getServiceURL(service);
@@ -511,8 +523,8 @@ private HttpConnection connect(String service)
 					return conn;
 
 				case HttpConnection.HTTP_NOT_FOUND:
-					throw new NoRemoteRepositoryException(uri,
-							MessageFormat.format(JGitText.get().uriNotFound, u));
+					throw createNotFoundException(uri, u,
+							conn.getResponseMessage());
 
 				case HttpConnection.HTTP_UNAUTHORIZED:
 					authMethod = HttpAuthMethod.scanResponse(conn, ignoreTypes);
@@ -1180,9 +1192,8 @@ void sendRequest() throws IOException {
 						return;
 
 					case HttpConnection.HTTP_NOT_FOUND:
-						throw new NoRemoteRepositoryException(uri,
-								MessageFormat.format(JGitText.get().uriNotFound,
-										conn.getURL()));
+						throw createNotFoundException(uri, conn.getURL(),
+								conn.getResponseMessage());
 
 					case HttpConnection.HTTP_FORBIDDEN:
 						throw new TransportException(uri,
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 7de0506..de7be6d 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java
@@ -45,6 +45,7 @@
 
 import static org.eclipse.jgit.lib.Constants.R_TAGS;
 import static org.eclipse.jgit.lib.RefDatabase.ALL;
+import static org.eclipse.jgit.transport.GitProtocolConstants.CAPABILITY_REF_IN_WANT;
 import static org.eclipse.jgit.transport.GitProtocolConstants.COMMAND_FETCH;
 import static org.eclipse.jgit.transport.GitProtocolConstants.COMMAND_LS_REFS;
 import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_AGENT;
@@ -62,6 +63,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.OPTION_WANT_REF;
 
 import java.io.ByteArrayOutputStream;
 import java.io.EOFException;
@@ -77,6 +79,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.TreeMap;
 
 import org.eclipse.jgit.annotations.Nullable;
 import org.eclipse.jgit.errors.CorruptObjectException;
@@ -264,6 +267,9 @@ public Set<String> getOptions() {
 	/** The refs we advertised as existing at the start of the connection. */
 	private Map<String, Ref> refs;
 
+	/** Hook used while processing Git protocol v2 requests. */
+	private ProtocolV2Hook protocolV2Hook = ProtocolV2Hook.DEFAULT;
+
 	/** Hook used while advertising the refs to the client. */
 	private AdvertiseRefsHook advertiseRefsHook = AdvertiseRefsHook.DEFAULT;
 
@@ -576,6 +582,16 @@ public void setAdvertiseRefsHook(AdvertiseRefsHook advertiseRefsHook) {
 	}
 
 	/**
+	 * Set the protocol V2 hook.
+	 *
+	 * @param hook
+	 * @since 5.1
+	 */
+	public void setProtocolV2Hook(ProtocolV2Hook hook) {
+		this.protocolV2Hook = hook;
+	}
+
+	/**
 	 * Set the filter used while advertising the refs to the client.
 	 * <p>
 	 * Only refs allowed by this filter will be sent to the client. The filter
@@ -877,25 +893,19 @@ else if (requestValidator instanceof AnyRequestValidator)
 	}
 
 	private void lsRefsV2() throws IOException {
-		PacketLineOutRefAdvertiser adv = new PacketLineOutRefAdvertiser(pckOut);
-		String line;
-		ArrayList<String> refPrefixes = new ArrayList<>();
-		boolean needToFindSymrefs = false;
-
-		adv.setUseProtocolV2(true);
-
-		line = pckIn.readString();
-
+		LsRefsV2Request.Builder builder = LsRefsV2Request.builder();
+		List<String> prefixes = new ArrayList<>();
+		String line = pckIn.readString();
 		// Currently, we do not support any capabilities, so the next
 		// line is DELIM if there are arguments or END if not.
 		if (line == PacketLineIn.DELIM) {
 			while ((line = pckIn.readString()) != PacketLineIn.END) {
 				if (line.equals("peel")) { //$NON-NLS-1$
-					adv.setDerefTags(true);
+					builder.setPeel(true);
 				} else if (line.equals("symrefs")) { //$NON-NLS-1$
-					needToFindSymrefs = true;
+					builder.setSymrefs(true);
 				} else if (line.startsWith("ref-prefix ")) { //$NON-NLS-1$
-					refPrefixes.add(line.substring("ref-prefix ".length())); //$NON-NLS-1$
+					prefixes.add(line.substring("ref-prefix ".length())); //$NON-NLS-1$
 				} else {
 					throw new PackProtocolException(MessageFormat
 							.format(JGitText.get().unexpectedPacketLine, line));
@@ -905,21 +915,28 @@ private void lsRefsV2() throws IOException {
 			throw new PackProtocolException(MessageFormat
 					.format(JGitText.get().unexpectedPacketLine, line));
 		}
-		rawOut.stopBuffering();
+		LsRefsV2Request req = builder.setRefPrefixes(prefixes).build();
 
+		protocolV2Hook.onLsRefs(req);
+
+		rawOut.stopBuffering();
+		PacketLineOutRefAdvertiser adv = new PacketLineOutRefAdvertiser(pckOut);
+		adv.setUseProtocolV2(true);
+		if (req.getPeel()) {
+			adv.setDerefTags(true);
+		}
 		Map<String, Ref> refsToSend;
-		if (refPrefixes.isEmpty()) {
+		if (req.getRefPrefixes().isEmpty()) {
 			refsToSend = getAdvertisedOrDefaultRefs();
 		} else {
 			refsToSend = new HashMap<>();
-			for (String refPrefix : refPrefixes) {
+			for (String refPrefix : req.getRefPrefixes()) {
 				for (Ref ref : db.getRefDatabase().getRefsByPrefix(refPrefix)) {
 					refsToSend.put(ref.getName(), ref);
 				}
 			}
 		}
-
-		if (needToFindSymrefs) {
+		if (req.getSymrefs()) {
 			findSymrefs(adv, refsToSend);
 		}
 
@@ -959,9 +976,27 @@ private void fetchV2() throws IOException {
 
 		boolean includeTag = false;
 		boolean filterReceived = false;
+		TreeMap<String, ObjectId> wantedRefs = new TreeMap<>();
 		while ((line = pckIn.readString()) != PacketLineIn.END) {
 			if (line.startsWith("want ")) { //$NON-NLS-1$
 				wantIds.add(ObjectId.fromString(line.substring(5)));
+			} else if (transferConfig.isAllowRefInWant() &&
+					line.startsWith(OPTION_WANT_REF + " ")) { //$NON-NLS-1$
+				String refName = line.substring(OPTION_WANT_REF.length() + 1);
+				Ref ref = db.getRefDatabase().exactRef(refName);
+				if (ref == null) {
+					throw new PackProtocolException(
+							MessageFormat.format(JGitText.get().invalidRefName,
+								refName));
+				}
+				ObjectId oid = ref.getObjectId();
+				if (oid == null) {
+					throw new PackProtocolException(
+							MessageFormat.format(JGitText.get().invalidRefName,
+								refName));
+				}
+				wantedRefs.put(refName, oid);
+				wantIds.add(oid);
 			} else if (line.startsWith("have ")) { //$NON-NLS-1$
 				peerHas.add(ObjectId.fromString(line.substring(5)));
 			} else if (line.equals("done")) { //$NON-NLS-1$
@@ -1075,6 +1110,18 @@ private void fetchV2() throws IOException {
 				sectionSent = true;
 			}
 
+			if (!wantedRefs.isEmpty()) {
+				if (sectionSent) {
+					pckOut.writeDelim();
+				}
+				pckOut.writeString("wanted-refs\n"); //$NON-NLS-1$
+				for (Map.Entry<String, ObjectId> entry : wantedRefs.entrySet()) {
+					pckOut.writeString(entry.getValue().getName() + ' ' +
+							entry.getKey() + '\n');
+				}
+				sectionSent = true;
+			}
+
 			if (sectionSent)
 				pckOut.writeDelim();
 			pckOut.writeString("packfile\n"); //$NON-NLS-1$
@@ -1083,8 +1130,12 @@ private void fetchV2() throws IOException {
 						? db.getRefDatabase().getRefsByPrefix(R_TAGS)
 						: null,
 					unshallowCommits);
+			// sendPack invokes pckOut.end() for us, so we do not
+			// need to invoke it here.
+		} else {
+			// Invoke pckOut.end() by ourselves.
+			pckOut.end();
 		}
-		pckOut.end();
 	}
 
 	/*
@@ -1121,9 +1172,12 @@ private List<String> getV2CapabilityAdvertisement() {
 		ArrayList<String> caps = new ArrayList<>();
 		caps.add("version 2"); //$NON-NLS-1$
 		caps.add(COMMAND_LS_REFS);
+		boolean advertiseRefInWant = transferConfig.isAllowRefInWant() &&
+			db.getConfig().getBoolean("uploadpack", null, "advertiserefinwant", true);
 		caps.add(
 				COMMAND_FETCH + '=' +
 				(transferConfig.isAllowFilter() ? OPTION_FILTER + ' ' : "") + //$NON-NLS-1$
+				(advertiseRefInWant ? CAPABILITY_REF_IN_WANT + ' ' : "") + //$NON-NLS-1$
 				OPTION_SHALLOW);
 		return caps;
 	}
@@ -1134,6 +1188,8 @@ private void serviceV2() throws IOException {
 			// is sent only if this is a bidirectional pipe. (If
 			// not, the client is expected to call
 			// sendAdvertisedRefs() on its own.)
+			protocolV2Hook
+					.onCapabilities(CapabilitiesV2Request.builder().build());
 			for (String s : getV2CapabilityAdvertisement()) {
 				pckOut.writeString(s + "\n"); //$NON-NLS-1$
 			}
@@ -1298,6 +1354,8 @@ public void sendAdvertisedRefs(RefAdvertiser adv,
 		if (useProtocolV2()) {
 			// The equivalent in v2 is only the capabilities
 			// advertisement.
+			protocolV2Hook
+					.onCapabilities(CapabilitiesV2Request.builder().build());
 			for (String s : getV2CapabilityAdvertisement()) {
 				adv.writeOne(s);
 			}
diff --git a/pom.xml b/pom.xml
index 3a5db7b..37c22d6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -51,7 +51,7 @@
   <groupId>org.eclipse.jgit</groupId>
   <artifactId>org.eclipse.jgit-parent</artifactId>
   <packaging>pom</packaging>
-  <version>5.0.3-SNAPSHOT</version>
+  <version>5.1.0-SNAPSHOT</version>
 
   <name>JGit - Parent</name>
   <url>${jgit-url}</url>
@@ -208,16 +208,16 @@
     <osgi-core-version>4.3.1</osgi-core-version>
     <servlet-api-version>3.1.0</servlet-api-version>
     <jetty-version>9.4.8.v20171121</jetty-version>
-    <japicmp-version>0.11.0</japicmp-version>
-    <httpclient-version>4.5.2</httpclient-version>
-    <httpcore-version>4.4.6</httpcore-version>
+    <japicmp-version>0.12.0</japicmp-version>
+    <httpclient-version>4.5.5</httpclient-version>
+    <httpcore-version>4.4.9</httpcore-version>
     <slf4j-version>1.7.2</slf4j-version>
     <log4j-version>1.2.15</log4j-version>
     <maven-javadoc-plugin-version>3.0.1</maven-javadoc-plugin-version>
-    <tycho-extras-version>1.1.0</tycho-extras-version>
+    <tycho-extras-version>1.2.0</tycho-extras-version>
     <gson-version>2.8.2</gson-version>
-    <spotbugs-maven-plugin-version>3.1.2</spotbugs-maven-plugin-version>
-    <maven-surefire-report-plugin-version>2.20.1</maven-surefire-report-plugin-version>
+    <spotbugs-maven-plugin-version>3.1.5</spotbugs-maven-plugin-version>
+    <maven-surefire-report-plugin-version>2.21.0</maven-surefire-report-plugin-version>
 
     <!-- Properties to enable jacoco code coverage analysis -->
     <sonar.core.codeCoveragePlugin>jacoco</sonar.core.codeCoveragePlugin>
@@ -249,7 +249,7 @@
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-jar-plugin</artifactId>
-          <version>3.0.2</version>
+          <version>3.1.0</version>
           <configuration>
             <archive>
               <manifestEntries>
@@ -268,13 +268,13 @@
 
         <plugin>
           <artifactId>maven-clean-plugin</artifactId>
-          <version>3.0.0</version>
+          <version>3.1.0</version>
         </plugin>
 
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-shade-plugin</artifactId>
-          <version>3.1.0</version>
+          <version>3.1.1</version>
         </plugin>
 
         <plugin>
@@ -304,7 +304,7 @@
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-surefire-plugin</artifactId>
-          <version>2.20.1</version>
+          <version>2.21.0</version>
           <configuration>
             <forkCount>${test-fork-count}</forkCount>
             <reuseForks>true</reuseForks>
@@ -337,7 +337,7 @@
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-pmd-plugin</artifactId>
-          <version>3.8</version>
+          <version>3.10.0</version>
           <configuration>
             <sourceEncoding>utf-8</sourceEncoding>
             <minimumTokens>100</minimumTokens>
@@ -360,7 +360,7 @@
         <plugin>
           <groupId>org.eclipse.cbi.maven.plugins</groupId>
           <artifactId>eclipse-jarsigner-plugin</artifactId>
-          <version>1.1.4</version>
+          <version>1.1.5</version>
         </plugin>
         <plugin>
           <groupId>org.eclipse.tycho.extras</groupId>
@@ -375,17 +375,17 @@
         <plugin>
           <groupId>org.jacoco</groupId>
           <artifactId>jacoco-maven-plugin</artifactId>
-          <version>0.7.9</version>
+          <version>0.8.1</version>
         </plugin>
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-site-plugin</artifactId>
-          <version>3.6</version>
+          <version>3.7.1</version>
           <dependencies>
             <dependency><!-- add support for ssh/scp -->
               <groupId>org.apache.maven.wagon</groupId>
               <artifactId>wagon-ssh</artifactId>
-              <version>2.12</version>
+              <version>3.1.0</version>
             </dependency>
           </dependencies>
         </plugin>
@@ -772,6 +772,9 @@
                 <configuration>
                   <compilerId>javac-with-errorprone</compilerId>
                   <forceJavacCompilerUse>true</forceJavacCompilerUse>
+                  <compilerArgs>
+                    <arg>-Xep:ExpectedExceptionChecker:ERROR</arg>
+                  </compilerArgs>
                   <excludes>
                     <exclude>org/eclipse/jgit/transport/InsecureCipherFactory.java</exclude>
                   </excludes>
@@ -782,7 +785,7 @@
               <dependency>
                 <groupId>org.codehaus.plexus</groupId>
                 <artifactId>plexus-compiler-javac</artifactId>
-                <version>2.8.2</version>
+                <version>2.8.4</version>
               </dependency>
               <dependency>
                 <groupId>org.codehaus.plexus</groupId>