Merge branch 'stable-5.4'

* stable-5.4: (82 commits)
  Export all packages of o.e.j.ant and o.e.j.archive bundles
  Do not require test bundles to export all packages
  Fix API problem filters
  Increase severity of AmbiguousMethodReference to ERROR
  [error prone] suppress AmbiguousMethodReference in AnyLongObjectId
  [error prone] fix ReferenceEquality warning in CommitBuilder
  [error prone] suppress NonAtomicVolatileUpdate warning in SimpleLruCache
  [error prone] fix ReferenceEquality warning in CommitGraphPane#authorFor
  [error prone] fix ReferenceEquality warning in RevWalk#isMergedInto
  [error prone] fix ReferenceEquality warning in RefUpdate#updateImpl
  [error prone] fix ReferenceEquality warning in static equals methods
  [error prone] suppress AmbiguousMethodReference in AnyObjectId
  [error prone] fix "FutureReturnValueIgnored" error in FS
  Fix formatting and add missing braces in Repository#stripWorkDir
  Repository: fix reference comparison of Files
  MergeAlgorithm: Suppress Error Prone warning about reference equality
  Fix NarrowingCompoundAssignment warnings from Error Prone
  FS_POSIX: handle Files.getFileStore() failures
  Fix OpenSshConfigTest#config
  FileSnapshot: fix bug with timestamp thresholding
  In LockFile#waitForStatChange wait in units of file time resolution
  Cache FileStoreAttributeCache per directory
  Fix FileSnapshot#save(long) and FileSnapshot#save(Instant)
  Persist minimal racy threshold and allow manual configuration
  Measure minimum racy interval to auto-configure FileSnapshot
  Reuse FileUtils to recursively delete files created by tests
  Fix FileAttributeCache.toString()
  Add test for racy git detection in FileSnapshot
  Repeat RefDirectoryTest.testGetRef_DiscoversModifiedLoose 100 times
  Fix org.eclipse.jdt.core.prefs of org.eclipse.jgit.junit
  Add missing javadoc in org.eclipse.jgit.junit
  Enhance RepeatRule to report number of failures at the end
  Fix FileSnapshotTests for filesystem with high timestamp resolution
  Retry deleting test files in FileBasedConfigTest
  Measure filesystem timestamp resolution already in test setup
  Refactor FileSnapshotTest to use NIO APIs
  Measure stored timestamp resolution instead of time to touch file
  Handle CancellationException in FileStoreAttributeCache
  Fix FileSnapshot#saveNoConfig
  Use Instant for smudge time in DirCache and DirCacheEntry
  Use Instant instead of milliseconds for filesystem timestamp handling
  Workaround SecurityException in FS#getFsTimestampResolution
  Fix NPE in FS$FileStoreAttributeCache.getFsTimestampResolution
  FS: ignore AccessDeniedException when measuring timestamp resolution
  Add debug trace for FileSnapshot
  Use FileChannel.open to touch file and set mtime to now
  Persist filesystem timestamp resolution and allow manual configuration
  Increase bazel timeout for long running tests
  Bazel: Fix lint warning flagged by buildifier
  Update bazlets to latest version
  Bazel: Add missing dependencies for ArchiveCommandTest
  Bazel: Remove FileTreeIteratorWithTimeControl from BUILD file
  Add support for nanoseconds and microseconds for Config#getTimeUnit
  Optionally measure filesystem timestamp resolution asynchronously
  Delete unused FileTreeIteratorWithTimeControl
  FileSnapshot#equals: consider UNKNOWN_SIZE
  Timeout measuring file timestamp resolution after 2 seconds
  Fix RacyGitTests#testRacyGitDetection
  GlobalBundleCache: Fix ClassNewInstance warning from Error Prone
  IncorrectObjectTypeException: Fix typos in constructors' Javadoc
  Change RacyGitTests to create a racy git situation in a stable way
  Deprecate Constants.CHARACTER_ENCODING in favor of StandardCharsets.UTF_8
  Fix non-deterministic hash of archives created by ArchiveCommand
  Update Maven plugins ecj, plexus, error-prone
  Update Maven plugins and cleanup Maven warnings
  Make inner classes static where possible
  Error Prone: Increase severity of NonOverridingEquals to ERROR
  Error Prone: Increase severity of ImmutableEnumChecker to ERROR
  GitDateParser#ParseableSimpleDateFormat: Make formatStr private final
  BatchRefUpdateTest: Suppress ImmutableEnumChecker warning
  PacketLineIn: Suppress comparison warnings for END and DELIM
  FileSnapshot#toString: Suppress ReferenceEquality warnings
  Blame: Suppress ReferenceEquality warning for RevCommit instances
  Fix API problem filters
  pgm: add missing optional dependency to org.tukaani:xz
  NetscapeCookieFile: Make hash static and group overloaded write
  NetscapeCookieFile: Javadoc fixes
  Config: Handle reference-equality warning (and empty javadoc)
  Error Prone: Increase severity of ShortCircuitBoolean to ERROR
  ObjectWalk: Prefer boolean operators over logical operators in comparisons
  BasePackFetchConnection: Prefer boolean operators over logical operators in comparisons
  PackWriter: Prefer boolean operators over logical operators in comparisons

Change-Id: I825fd55bcb5345fb7afe066bf54ca50325f40acb
Signed-off-by: David Pursehouse <david.pursehouse@gmail.com>
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
diff --git a/BUILD b/BUILD
index 5fea669..be6dd76 100644
--- a/BUILD
+++ b/BUILD
@@ -1,12 +1,5 @@
 package(default_visibility = ["//visibility:public"])
 
-config_setting(
-    name = "jdk9",
-    values = {
-        "java_toolchain": "@bazel_tools//tools/jdk:toolchain_jdk9",
-    },
-)
-
 genrule(
     name = "all",
     testonly = 1,
diff --git a/WORKSPACE b/WORKSPACE
index 93c34b5..40fe8b2 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -138,22 +138,22 @@
 
 maven_jar(
     name = "mockito",
-    artifact = "org.mockito:mockito-core:2.13.0",
-    sha1 = "8e372943974e4a121fb8617baced8ebfe46d54f0",
+    artifact = "org.mockito:mockito-core:2.23.0",
+    sha1 = "497ddb32fd5d01f9dbe99a2ec790aeb931dff1b1",
 )
 
-BYTE_BUDDY_VERSION = "1.7.9"
+BYTE_BUDDY_VERSION = "1.9.0"
 
 maven_jar(
     name = "byte_buddy",
     artifact = "net.bytebuddy:byte-buddy:" + BYTE_BUDDY_VERSION,
-    sha1 = "51218a01a882c04d0aba8c028179cce488bbcb58",
+    sha1 = "8cb0d5baae526c9df46ae17693bbba302640538b",
 )
 
 maven_jar(
     name = "byte_buddy_agent",
     artifact = "net.bytebuddy:byte-buddy-agent:" + BYTE_BUDDY_VERSION,
-    sha1 = "a6c65f9da7f467ee1f02ff2841ffd3155aee2fc9",
+    sha1 = "37b5703b4a6290be3fffc63ae9c6bcaaee0ff856",
 )
 
 maven_jar(
diff --git a/org.eclipse.jgit.ant.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.ant.test/META-INF/MANIFEST.MF
index 9e38b43..6603455 100644
--- a/org.eclipse.jgit.ant.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.ant.test/META-INF/MANIFEST.MF
@@ -1,16 +1,17 @@
 Bundle-Localization: plugin
 Manifest-Version: 1.0
 Bundle-ManifestVersion: 2
-Bundle-Name: %plugin_name
+Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.ant.test
 Bundle-SymbolicName: org.eclipse.jgit.ant.test
-Bundle-Version: 5.4.1.qualifier
+Bundle-Vendor: %Bundle-Vendor
+Bundle-Version: 5.5.0.qualifier
 Bundle-ActivationPolicy: lazy
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
 Import-Package: org.apache.tools.ant,
- org.eclipse.jgit.ant.tasks;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.junit;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.lib;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.util;version="[5.4.1,5.5.0)",
+ org.eclipse.jgit.ant.tasks;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.junit;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.lib;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.util;version="[5.5.0,5.6.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/plugin.properties b/org.eclipse.jgit.ant.test/plugin.properties
index 4f849eb..412f392 100644
--- a/org.eclipse.jgit.ant.test/plugin.properties
+++ b/org.eclipse.jgit.ant.test/plugin.properties
@@ -1,2 +1,2 @@
-plugin_name=JGit Ant Tasks Tests
-provider_name=Eclipse JGit
+Bundle-Name=JGit Ant Tasks Tests
+Bundle-Vendor=Eclipse JGit
diff --git a/org.eclipse.jgit.ant.test/pom.xml b/org.eclipse.jgit.ant.test/pom.xml
index 8e8208f..873f3a7 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.4.1-SNAPSHOT</version>
+    <version>5.5.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 15359e7..41a0422 100644
--- a/org.eclipse.jgit.ant/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.ant/META-INF/MANIFEST.MF
@@ -3,13 +3,13 @@
 Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.ant
 Bundle-SymbolicName: org.eclipse.jgit.ant
-Bundle-Version: 5.4.1.qualifier
+Bundle-Version: 5.5.0.qualifier
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
 Import-Package: org.apache.tools.ant,
-  org.eclipse.jgit.storage.file;version="[5.4.1,5.5.0)"
+  org.eclipse.jgit.storage.file;version="[5.5.0,5.6.0)"
 Bundle-Localization: plugin
-Bundle-Vendor: %Provider-Name
-Export-Package: org.eclipse.jgit.ant;version="5.4.1",
- org.eclipse.jgit.ant.tasks;version="5.4.1";
+Bundle-Vendor: %Bundle-Vendor
+Export-Package: org.eclipse.jgit.ant;version="5.5.0",
+ org.eclipse.jgit.ant.tasks;version="5.5.0";
   uses:="org.apache.tools.ant,
    org.apache.tools.ant.types"
diff --git a/org.eclipse.jgit.ant/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.ant/META-INF/SOURCE-MANIFEST.MF
index 8e62fb4..708d297 100644
--- a/org.eclipse.jgit.ant/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.ant/META-INF/SOURCE-MANIFEST.MF
@@ -3,5 +3,5 @@
 Bundle-Name: org.eclipse.jgit.ant - Sources
 Bundle-SymbolicName: org.eclipse.jgit.ant.source
 Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 5.4.1.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit.ant;version="5.4.1.qualifier";roots="."
+Bundle-Version: 5.5.0.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit.ant;version="5.5.0.qualifier";roots="."
diff --git a/org.eclipse.jgit.ant/plugin.properties b/org.eclipse.jgit.ant/plugin.properties
index 47725bc..7c9e5f0 100644
--- a/org.eclipse.jgit.ant/plugin.properties
+++ b/org.eclipse.jgit.ant/plugin.properties
@@ -1,3 +1,3 @@
 #Properties file for org.eclipse.jgit.ant
 Bundle-Name = JGit Ant Tasks
-Provider-Name = Eclipse JGit
\ No newline at end of file
+Bundle-Vendor = Eclipse JGit
\ No newline at end of file
diff --git a/org.eclipse.jgit.ant/pom.xml b/org.eclipse.jgit.ant/pom.xml
index c7fb95a..e97d18d 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.4.1-SNAPSHOT</version>
+    <version>5.5.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 0eb38eb..965c798 100644
--- a/org.eclipse.jgit.archive/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.archive/META-INF/MANIFEST.MF
@@ -1,10 +1,10 @@
 Manifest-Version: 1.0
 Bundle-ManifestVersion: 2
-Bundle-Name: %plugin_name
+Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.archive
 Bundle-SymbolicName: org.eclipse.jgit.archive
-Bundle-Version: 5.4.1.qualifier
-Bundle-Vendor: %provider_name
+Bundle-Version: 5.5.0.qualifier
+Bundle-Vendor: %Bundle-Vendor
 Bundle-Localization: plugin
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
 Import-Package: org.apache.commons.compress.archivers;version="[1.4,2.0)",
@@ -13,17 +13,17 @@
  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.4.1,5.5.0)",
- org.eclipse.jgit.lib;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.nls;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.revwalk;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.util;version="[5.4.1,5.5.0)",
+ org.eclipse.jgit.api;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.lib;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.nls;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.revwalk;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.util;version="[5.5.0,5.6.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.4.1";
+Export-Package: org.eclipse.jgit.archive;version="5.5.0";
   uses:="org.eclipse.jgit.lib,
    org.eclipse.jgit.api,
    org.apache.commons.compress.archivers,
    org.osgi.framework",
- org.eclipse.jgit.archive.internal;version="5.4.1";x-internal:=true
+ org.eclipse.jgit.archive.internal;version="5.5.0";x-internal:=true
diff --git a/org.eclipse.jgit.archive/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.archive/META-INF/SOURCE-MANIFEST.MF
index 30928f8..be1bc5d 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.4.1.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit.archive;version="5.4.1.qualifier";roots="."
+Bundle-Version: 5.5.0.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit.archive;version="5.5.0.qualifier";roots="."
diff --git a/org.eclipse.jgit.archive/plugin.properties b/org.eclipse.jgit.archive/plugin.properties
index f4269b7..fe22ce8 100644
--- a/org.eclipse.jgit.archive/plugin.properties
+++ b/org.eclipse.jgit.archive/plugin.properties
@@ -1,2 +1,2 @@
-plugin_name=JGit Archive Formats
-provider_name=Eclipse JGit
+Bundle-Name=JGit Archive Formats
+Bundle-Vendor=Eclipse JGit
diff --git a/org.eclipse.jgit.archive/pom.xml b/org.eclipse.jgit.archive/pom.xml
index a3f9520..bc80fa7 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.4.1-SNAPSHOT</version>
+    <version>5.5.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.archive</artifactId>
diff --git a/org.eclipse.jgit.coverage/pom.xml b/org.eclipse.jgit.coverage/pom.xml
index 12c7552..2134c7f 100644
--- a/org.eclipse.jgit.coverage/pom.xml
+++ b/org.eclipse.jgit.coverage/pom.xml
@@ -5,7 +5,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>org.eclipse.jgit-parent</artifactId>
-    <version>5.4.1-SNAPSHOT</version>
+    <version>5.5.0-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
 
@@ -18,88 +18,88 @@
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit</artifactId>
-      <version>5.4.1-SNAPSHOT</version>
+      <version>5.5.0-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit.ant</artifactId>
-      <version>5.4.1-SNAPSHOT</version>
+      <version>5.5.0-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit.archive</artifactId>
-      <version>5.4.1-SNAPSHOT</version>
+      <version>5.5.0-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit.http.apache</artifactId>
-      <version>5.4.1-SNAPSHOT</version>
+      <version>5.5.0-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit.http.server</artifactId>
-      <version>5.4.1-SNAPSHOT</version>
+      <version>5.5.0-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit.lfs</artifactId>
-      <version>5.4.1-SNAPSHOT</version>
+      <version>5.5.0-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit.lfs.server</artifactId>
-      <version>5.4.1-SNAPSHOT</version>
+      <version>5.5.0-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit.pgm</artifactId>
-      <version>5.4.1-SNAPSHOT</version>
+      <version>5.5.0-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit.ui</artifactId>
-      <version>5.4.1-SNAPSHOT</version>
+      <version>5.5.0-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit.ssh.apache</artifactId>
-      <version>5.4.1-SNAPSHOT</version>
+      <version>5.5.0-SNAPSHOT</version>
     </dependency>
 
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit.test</artifactId>
-      <version>5.4.1-SNAPSHOT</version>
+      <version>5.5.0-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit.ant.test</artifactId>
-      <version>5.4.1-SNAPSHOT</version>
+      <version>5.5.0-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit.http.test</artifactId>
-      <version>5.4.1-SNAPSHOT</version>
+      <version>5.5.0-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit.pgm.test</artifactId>
-      <version>5.4.1-SNAPSHOT</version>
+      <version>5.5.0-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit.lfs.test</artifactId>
-      <version>5.4.1-SNAPSHOT</version>
+      <version>5.5.0-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit.lfs.server.test</artifactId>
-      <version>5.4.1-SNAPSHOT</version>
+      <version>5.5.0-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit.ssh.apache.test</artifactId>
-      <version>5.4.1-SNAPSHOT</version>
+      <version>5.5.0-SNAPSHOT</version>
     </dependency>
   </dependencies>
 
diff --git a/org.eclipse.jgit.http.apache/META-INF/MANIFEST.MF b/org.eclipse.jgit.http.apache/META-INF/MANIFEST.MF
index 8206e8a..5c95636 100644
--- a/org.eclipse.jgit.http.apache/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.http.apache/META-INF/MANIFEST.MF
@@ -3,10 +3,10 @@
 Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.http.apache
 Bundle-SymbolicName: org.eclipse.jgit.http.apache
-Bundle-Version: 5.4.1.qualifier
+Bundle-Version: 5.5.0.qualifier
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
 Bundle-Localization: plugin
-Bundle-Vendor: %Provider-Name
+Bundle-Vendor: %Bundle-Vendor
 Bundle-ActivationPolicy: lazy
 Import-Package: org.apache.http;version="[4.3.0,5.0.0)",
  org.apache.http.client;version="[4.3.0,5.0.0)",
@@ -23,11 +23,11 @@
  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.annotations;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.nls;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.transport.http;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.util;version="[5.4.1,5.5.0)"
-Export-Package: org.eclipse.jgit.transport.http.apache;version="5.4.1";
+ org.eclipse.jgit.annotations;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.nls;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.transport.http;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.util;version="[5.5.0,5.6.0)"
+Export-Package: org.eclipse.jgit.transport.http.apache;version="5.5.0";
   uses:="org.apache.http.client,
    org.eclipse.jgit.transport.http,
    org.apache.http.entity,
diff --git a/org.eclipse.jgit.http.apache/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.http.apache/META-INF/SOURCE-MANIFEST.MF
index 5aeb331..ad279f8 100644
--- a/org.eclipse.jgit.http.apache/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.http.apache/META-INF/SOURCE-MANIFEST.MF
@@ -3,5 +3,5 @@
 Bundle-Name: org.eclipse.jgit.http.apache - Sources
 Bundle-SymbolicName: org.eclipse.jgit.http.apache.source
 Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 5.4.1.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit.http.apache;version="5.4.1.qualifier";roots="."
+Bundle-Version: 5.5.0.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit.http.apache;version="5.5.0.qualifier";roots="."
diff --git a/org.eclipse.jgit.http.apache/plugin.properties b/org.eclipse.jgit.http.apache/plugin.properties
index f87497a..e242829 100644
--- a/org.eclipse.jgit.http.apache/plugin.properties
+++ b/org.eclipse.jgit.http.apache/plugin.properties
@@ -1,3 +1,3 @@
 #Properties file for org.eclipse.jgit.http.apache
 Bundle-Name = JGit Apache httpclient based HTTP support
-Provider-Name = Eclipse JGit
\ No newline at end of file
+Bundle-Vendor = Eclipse JGit
\ No newline at end of file
diff --git a/org.eclipse.jgit.http.apache/pom.xml b/org.eclipse.jgit.http.apache/pom.xml
index d2665c0..69ab575 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.4.1-SNAPSHOT</version>
+    <version>5.5.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.http.apache</artifactId>
diff --git a/org.eclipse.jgit.http.server/META-INF/MANIFEST.MF b/org.eclipse.jgit.http.server/META-INF/MANIFEST.MF
index a231f58..0a7fa84 100644
--- a/org.eclipse.jgit.http.server/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.http.server/META-INF/MANIFEST.MF
@@ -1,15 +1,15 @@
 Manifest-Version: 1.0
 Bundle-ManifestVersion: 2
-Bundle-Name: %plugin_name
+Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.http.server
 Bundle-SymbolicName: org.eclipse.jgit.http.server
-Bundle-Version: 5.4.1.qualifier
+Bundle-Version: 5.5.0.qualifier
 Bundle-Localization: plugin
-Bundle-Vendor: %provider_name
-Export-Package: org.eclipse.jgit.http.server;version="5.4.1",
- org.eclipse.jgit.http.server.glue;version="5.4.1";
+Bundle-Vendor: %Bundle-Vendor
+Export-Package: org.eclipse.jgit.http.server;version="5.5.0",
+ org.eclipse.jgit.http.server.glue;version="5.5.0";
   uses:="javax.servlet,javax.servlet.http",
- org.eclipse.jgit.http.server.resolver;version="5.4.1";
+ org.eclipse.jgit.http.server.resolver;version="5.5.0";
   uses:="org.eclipse.jgit.transport.resolver,
    org.eclipse.jgit.lib,
    org.eclipse.jgit.transport,
@@ -18,13 +18,13 @@
 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.4.1,5.5.0)",
- org.eclipse.jgit.internal.storage.dfs;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.internal.storage.file;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.internal.transport.parser;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.lib;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.nls;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.revwalk;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.transport;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.transport.resolver;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.util;version="[5.4.1,5.5.0)"
+ org.eclipse.jgit.errors;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.internal.storage.dfs;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.internal.storage.file;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.internal.transport.parser;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.lib;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.nls;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.revwalk;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.transport;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.transport.resolver;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.util;version="[5.5.0,5.6.0)"
diff --git a/org.eclipse.jgit.http.server/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.http.server/META-INF/SOURCE-MANIFEST.MF
index 3a06552..0fbcd98 100644
--- a/org.eclipse.jgit.http.server/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.http.server/META-INF/SOURCE-MANIFEST.MF
@@ -3,5 +3,5 @@
 Bundle-Name: org.eclipse.jgit.http.server - Sources
 Bundle-SymbolicName: org.eclipse.jgit.http.server.source
 Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 5.4.1.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit.http.server;version="5.4.1.qualifier";roots="."
+Bundle-Version: 5.5.0.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit.http.server;version="5.5.0.qualifier";roots="."
diff --git a/org.eclipse.jgit.http.server/plugin.properties b/org.eclipse.jgit.http.server/plugin.properties
index d891b50..bcec310 100644
--- a/org.eclipse.jgit.http.server/plugin.properties
+++ b/org.eclipse.jgit.http.server/plugin.properties
@@ -1,2 +1,2 @@
-plugin_name=JGit HTTP Server
-provider_name=Eclipse JGit
+Bundle-Name=JGit HTTP Server
+Bundle-Vendor=Eclipse JGit
diff --git a/org.eclipse.jgit.http.server/pom.xml b/org.eclipse.jgit.http.server/pom.xml
index f795038..4ccdb91 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.4.1-SNAPSHOT</version>
+    <version>5.5.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.http.server</artifactId>
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/GitFilter.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/GitFilter.java
index 51de8ab..1c5e7ec 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/GitFilter.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/GitFilter.java
@@ -248,13 +248,13 @@
 					.through(enabled)//
 					.with(new TextFileServlet(Constants.HEAD));
 
-			final String info_alternates = "objects/info/alternates";
+			final String info_alternates = Constants.OBJECTS + "/" + Constants.INFO_ALTERNATES;
 			serve("*/" + info_alternates)//
 					.through(mustBeLocal)//
 					.through(enabled)//
 					.with(new TextFileServlet(info_alternates));
 
-			final String http_alternates = "objects/info/http-alternates";
+			final String http_alternates = Constants.OBJECTS + "/" + Constants.INFO_HTTP_ALTERNATES;
 			serve("*/" + http_alternates)//
 					.through(mustBeLocal)//
 					.through(enabled)//
diff --git a/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF
index 4d4b3e4..a3afc0d 100644
--- a/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF
@@ -1,10 +1,10 @@
 Manifest-Version: 1.0
 Bundle-ManifestVersion: 2
-Bundle-Name: %plugin_name
+Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.http.test
 Bundle-SymbolicName: org.eclipse.jgit.http.test
-Bundle-Version: 5.4.1.qualifier
-Bundle-Vendor: %provider_name
+Bundle-Version: 5.5.0.qualifier
+Bundle-Vendor: %Bundle-Vendor
 Bundle-Localization: plugin
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
 Import-Package: javax.servlet;version="[2.5.0,3.2.0)",
@@ -28,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.4.1,5.5.0)",
- org.eclipse.jgit.http.server;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.http.server.glue;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.http.server.resolver;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.internal;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.internal.storage.dfs;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.internal.storage.file;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.internal.storage.reftable;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.junit;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.junit.http;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.lib;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.nls;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.revwalk;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.storage.file;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.transport;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.transport.http;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.transport.http.apache;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.transport.resolver;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.util;version="[5.4.1,5.5.0)",
+ org.eclipse.jgit.errors;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.http.server;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.http.server.glue;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.http.server.resolver;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.internal;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.internal.storage.dfs;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.internal.storage.file;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.internal.storage.reftable;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.junit;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.junit.http;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.lib;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.nls;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.revwalk;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.storage.file;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.transport;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.transport.http;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.transport.http.apache;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.transport.resolver;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.util;version="[5.5.0,5.6.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/plugin.properties b/org.eclipse.jgit.http.test/plugin.properties
index 0a620aa..d574f0d 100644
--- a/org.eclipse.jgit.http.test/plugin.properties
+++ b/org.eclipse.jgit.http.test/plugin.properties
@@ -1,2 +1,2 @@
-plugin_name=JGit HTTP Tests
-provider_name=Eclipse JGit
+Bundle-Name=JGit HTTP Tests
+Bundle-Vendor=Eclipse JGit
diff --git a/org.eclipse.jgit.http.test/pom.xml b/org.eclipse.jgit.http.test/pom.xml
index df99448..020039d 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.4.1-SNAPSHOT</version>
+    <version>5.5.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.http.test</artifactId>
diff --git a/org.eclipse.jgit.junit.http/META-INF/MANIFEST.MF b/org.eclipse.jgit.junit.http/META-INF/MANIFEST.MF
index ba38a8b..2d97d26 100644
--- a/org.eclipse.jgit.junit.http/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.junit.http/META-INF/MANIFEST.MF
@@ -1,11 +1,11 @@
 Manifest-Version: 1.0
 Bundle-ManifestVersion: 2
-Bundle-Name: %plugin_name
+Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.junit.http
 Bundle-SymbolicName: org.eclipse.jgit.junit.http
-Bundle-Version: 5.4.1.qualifier
+Bundle-Version: 5.5.0.qualifier
 Bundle-Localization: plugin
-Bundle-Vendor: %provider_name
+Bundle-Vendor: %Bundle-Vendor
 Bundle-ActivationPolicy: lazy
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
 Import-Package: javax.servlet;version="[2.5.0,3.2.0)",
@@ -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.4.1,5.5.0)",
- org.eclipse.jgit.http.server;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.internal.storage.file;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.junit;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.lib;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.revwalk;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.transport;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.transport.resolver;version="[5.4.1,5.5.0)",
+ org.eclipse.jgit.errors;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.http.server;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.internal.storage.file;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.junit;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.lib;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.revwalk;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.transport;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.transport.resolver;version="[5.5.0,5.6.0)",
  org.junit;version="[4.12,5.0.0)"
-Export-Package: org.eclipse.jgit.junit.http;version="5.4.1";
+Export-Package: org.eclipse.jgit.junit.http;version="5.5.0";
   uses:="org.eclipse.jgit.transport,
    org.eclipse.jgit.junit,
    javax.servlet.http,
diff --git a/org.eclipse.jgit.junit.http/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.junit.http/META-INF/SOURCE-MANIFEST.MF
index 0243f2f..1bf4a31 100644
--- a/org.eclipse.jgit.junit.http/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.junit.http/META-INF/SOURCE-MANIFEST.MF
@@ -3,5 +3,5 @@
 Bundle-Name: org.eclipse.jgit.junit.http - Sources
 Bundle-SymbolicName: org.eclipse.jgit.junit.http.source
 Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 5.4.1.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit.junit.http;version="5.4.1.qualifier";roots="."
+Bundle-Version: 5.5.0.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit.junit.http;version="5.5.0.qualifier";roots="."
diff --git a/org.eclipse.jgit.junit.http/plugin.properties b/org.eclipse.jgit.junit.http/plugin.properties
index 7a96b09..2ec05e1 100644
--- a/org.eclipse.jgit.junit.http/plugin.properties
+++ b/org.eclipse.jgit.junit.http/plugin.properties
@@ -1,2 +1,2 @@
-plugin_name=JGit JUnit Http Utility Classes
-provider_name=Eclipse JGit
+Bundle-Name=JGit JUnit Http Utility Classes
+Bundle-Vendor=Eclipse JGit
diff --git a/org.eclipse.jgit.junit.http/pom.xml b/org.eclipse.jgit.junit.http/pom.xml
index 9bf2a21..7cdae3a 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.4.1-SNAPSHOT</version>
+    <version>5.5.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.junit.http</artifactId>
diff --git a/org.eclipse.jgit.junit.ssh/META-INF/MANIFEST.MF b/org.eclipse.jgit.junit.ssh/META-INF/MANIFEST.MF
index 6b443f3..67e8c63 100644
--- a/org.eclipse.jgit.junit.ssh/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.junit.ssh/META-INF/MANIFEST.MF
@@ -1,11 +1,11 @@
 Manifest-Version: 1.0
 Bundle-ManifestVersion: 2
-Bundle-Name: %plugin_name
+Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.junit.ssh
 Bundle-SymbolicName: org.eclipse.jgit.junit.ssh
-Bundle-Version: 5.4.1.qualifier
+Bundle-Version: 5.5.0.qualifier
 Bundle-Localization: plugin
-Bundle-Vendor: %provider_name
+Bundle-Vendor: %Bundle-Vendor
 Bundle-ActivationPolicy: lazy
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
 Import-Package: org.apache.sshd.common;version="[2.2.0,2.3.0)",
@@ -30,8 +30,8 @@
  org.apache.sshd.server.shell;version="[2.2.0,2.3.0)",
  org.apache.sshd.server.subsystem;version="[2.2.0,2.3.0)",
  org.apache.sshd.server.subsystem.sftp;version="[2.2.0,2.3.0)",
- org.eclipse.jgit.annotations;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.lib;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.transport;version="[5.4.1,5.5.0)",
+ org.eclipse.jgit.annotations;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.lib;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.transport;version="[5.5.0,5.6.0)",
  org.slf4j;version="[1.7.0,2.0.0)"
-Export-Package: org.eclipse.jgit.junit.ssh;version="5.4.1"
+Export-Package: org.eclipse.jgit.junit.ssh;version="5.5.0"
diff --git a/org.eclipse.jgit.junit.ssh/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.junit.ssh/META-INF/SOURCE-MANIFEST.MF
index 62fb41b..1890ab5 100644
--- a/org.eclipse.jgit.junit.ssh/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.junit.ssh/META-INF/SOURCE-MANIFEST.MF
@@ -3,5 +3,5 @@
 Bundle-Name: org.eclipse.jgit.junit.ssh - Sources
 Bundle-SymbolicName: org.eclipse.jgit.junit.ssh.source
 Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 5.4.1.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit.junit.ssh;version="5.4.1.qualifier";roots="."
+Bundle-Version: 5.5.0.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit.junit.ssh;version="5.5.0.qualifier";roots="."
diff --git a/org.eclipse.jgit.junit.ssh/plugin.properties b/org.eclipse.jgit.junit.ssh/plugin.properties
index 5689b94..3af91ed 100644
--- a/org.eclipse.jgit.junit.ssh/plugin.properties
+++ b/org.eclipse.jgit.junit.ssh/plugin.properties
@@ -1,2 +1,2 @@
-plugin_name=JGit JUnit Ssh Utility Classes
-provider_name=Eclipse JGit
+Bundle-Name=JGit JUnit Ssh Utility Classes
+Bundle-Vendor=Eclipse JGit
diff --git a/org.eclipse.jgit.junit.ssh/pom.xml b/org.eclipse.jgit.junit.ssh/pom.xml
index 92fd161..50e666c 100644
--- a/org.eclipse.jgit.junit.ssh/pom.xml
+++ b/org.eclipse.jgit.junit.ssh/pom.xml
@@ -50,7 +50,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>org.eclipse.jgit-parent</artifactId>
-    <version>5.4.1-SNAPSHOT</version>
+    <version>5.5.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.junit.ssh</artifactId>
diff --git a/org.eclipse.jgit.junit.ssh/src/org/eclipse/jgit/junit/ssh/SshTestGitServer.java b/org.eclipse.jgit.junit.ssh/src/org/eclipse/jgit/junit/ssh/SshTestGitServer.java
index 25d952f..f54c279 100644
--- a/org.eclipse.jgit.junit.ssh/src/org/eclipse/jgit/junit/ssh/SshTestGitServer.java
+++ b/org.eclipse.jgit.junit.ssh/src/org/eclipse/jgit/junit/ssh/SshTestGitServer.java
@@ -58,6 +58,7 @@
 
 import org.apache.sshd.common.NamedFactory;
 import org.apache.sshd.common.NamedResource;
+import org.apache.sshd.common.PropertyResolverUtils;
 import org.apache.sshd.common.SshConstants;
 import org.apache.sshd.common.config.keys.AuthorizedKeyEntry;
 import org.apache.sshd.common.config.keys.KeyUtils;
@@ -69,6 +70,7 @@
 import org.apache.sshd.common.util.threads.CloseableExecutorService;
 import org.apache.sshd.common.util.threads.ThreadUtils;
 import org.apache.sshd.server.ServerAuthenticationManager;
+import org.apache.sshd.server.ServerFactoryManager;
 import org.apache.sshd.server.SshServer;
 import org.apache.sshd.server.auth.UserAuth;
 import org.apache.sshd.server.auth.gss.GSSAuthenticator;
@@ -336,12 +338,38 @@
 		server.stop(true);
 	}
 
+	/**
+	 * Sets the test user's public key on the server.
+	 *
+	 * @param key
+	 *            to set
+	 * @throws IOException
+	 *             if the file cannot be read
+	 * @throws GeneralSecurityException
+	 *             if the public key cannot be extracted from the file
+	 */
 	public void setTestUserPublicKey(Path key)
 			throws IOException, GeneralSecurityException {
 		this.testKey = AuthorizedKeyEntry.readAuthorizedKeys(key).get(0)
 				.resolvePublicKey(null, PublicKeyEntryResolver.IGNORING);
 	}
 
+	/**
+	 * Sets the lines the server sends before its server identification in the
+	 * initial protocol version exchange.
+	 *
+	 * @param lines
+	 *            to send
+	 * @since 5.5
+	 */
+	public void setPreamble(String... lines) {
+		if (lines != null && lines.length > 0) {
+			PropertyResolverUtils.updateProperty(this.server,
+					ServerFactoryManager.SERVER_EXTRA_IDENTIFICATION_LINES,
+					String.join("|", lines));
+		}
+	}
+
 	private class GitUploadPackCommand extends AbstractCommandSupport {
 
 		protected GitUploadPackCommand(String command,
diff --git a/org.eclipse.jgit.junit/META-INF/MANIFEST.MF b/org.eclipse.jgit.junit/META-INF/MANIFEST.MF
index 637fad0..e63a8c4 100644
--- a/org.eclipse.jgit.junit/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.junit/META-INF/MANIFEST.MF
@@ -1,36 +1,36 @@
 Manifest-Version: 1.0
 Bundle-ManifestVersion: 2
-Bundle-Name: %plugin_name
+Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.junit
 Bundle-SymbolicName: org.eclipse.jgit.junit
-Bundle-Version: 5.4.1.qualifier
+Bundle-Version: 5.5.0.qualifier
 Bundle-Localization: plugin
-Bundle-Vendor: %provider_name
+Bundle-Vendor: %Bundle-Vendor
 Bundle-ActivationPolicy: lazy
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
-Import-Package: org.eclipse.jgit.annotations;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.api;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.api.errors;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.dircache;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.errors;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.internal.storage.file;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.internal.storage.pack;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.lib;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.merge;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.revwalk;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.storage.file;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.transport;version="5.4.1",
- org.eclipse.jgit.treewalk;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.treewalk.filter;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.util;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.util.io;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.util.time;version="[5.4.1,5.5.0)",
+Import-Package: org.eclipse.jgit.annotations;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.api;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.api.errors;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.dircache;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.errors;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.internal.storage.file;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.internal.storage.pack;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.lib;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.merge;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.revwalk;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.storage.file;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.transport;version="5.5.0",
+ org.eclipse.jgit.treewalk;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.treewalk.filter;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.util;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.util.io;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.util.time;version="[5.5.0,5.6.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)",
  org.slf4j;version="[1.7.0,2.0.0)"
-Export-Package: org.eclipse.jgit.junit;version="5.4.1";
+Export-Package: org.eclipse.jgit.junit;version="5.5.0";
   uses:="org.eclipse.jgit.dircache,
    org.eclipse.jgit.lib,
    org.eclipse.jgit.revwalk,
@@ -43,4 +43,4 @@
    org.junit.runners.model,
    org.junit.runner,
    org.eclipse.jgit.util.time",
- org.eclipse.jgit.junit.time;version="5.4.1";uses:="org.eclipse.jgit.util.time"
+ org.eclipse.jgit.junit.time;version="5.5.0";uses:="org.eclipse.jgit.util.time"
diff --git a/org.eclipse.jgit.junit/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.junit/META-INF/SOURCE-MANIFEST.MF
index f244ece..ff15a73 100644
--- a/org.eclipse.jgit.junit/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.junit/META-INF/SOURCE-MANIFEST.MF
@@ -3,5 +3,5 @@
 Bundle-Name: org.eclipse.jgit.junit - Sources
 Bundle-SymbolicName: org.eclipse.jgit.junit.source
 Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 5.4.1.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit.junit;version="5.4.1.qualifier";roots="."
+Bundle-Version: 5.5.0.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit.junit;version="5.5.0.qualifier";roots="."
diff --git a/org.eclipse.jgit.junit/plugin.properties b/org.eclipse.jgit.junit/plugin.properties
index 9842967..f40f8e1 100644
--- a/org.eclipse.jgit.junit/plugin.properties
+++ b/org.eclipse.jgit.junit/plugin.properties
@@ -1,2 +1,2 @@
-plugin_name=JGit JUnit Utility Classes
-provider_name=Eclipse JGit
+Bundle-Name=JGit JUnit Utility Classes
+Bundle-Vendor=Eclipse JGit
diff --git a/org.eclipse.jgit.junit/pom.xml b/org.eclipse.jgit.junit/pom.xml
index 392fd51..ed0a82c 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.4.1-SNAPSHOT</version>
+    <version>5.5.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.junit</artifactId>
diff --git a/org.eclipse.jgit.lfs.server.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.lfs.server.test/META-INF/MANIFEST.MF
index d5bf494..237b732 100644
--- a/org.eclipse.jgit.lfs.server.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.lfs.server.test/META-INF/MANIFEST.MF
@@ -1,10 +1,10 @@
 Manifest-Version: 1.0
 Bundle-ManifestVersion: 2
-Bundle-Name: %plugin_name
+Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.lfs.server.test
 Bundle-SymbolicName: org.eclipse.jgit.lfs.server.test
-Bundle-Version: 5.4.1.qualifier
-Bundle-Vendor: %provider_name
+Bundle-Version: 5.5.0.qualifier
+Bundle-Vendor: %Bundle-Vendor
 Bundle-Localization: plugin
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
 Import-Package: javax.servlet;version="[3.1.0,4.0.0)",
@@ -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.4.1,5.5.0)",
- org.eclipse.jgit.api.errors;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.internal.storage.file;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.junit;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.junit.http;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.lfs;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.lfs.errors;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.lfs.lib;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.lfs.server;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.lfs.server.fs;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.lfs.test;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.lib;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.revwalk;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.storage.file;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.transport;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.treewalk;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.treewalk.filter;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.util;version="[5.4.1,5.5.0)",
+ org.eclipse.jgit.api;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.api.errors;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.internal.storage.file;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.junit;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.junit.http;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.lfs;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.lfs.errors;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.lfs.lib;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.lfs.server;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.lfs.server.fs;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.lfs.test;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.lib;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.revwalk;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.storage.file;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.transport;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.treewalk;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.treewalk.filter;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.util;version="[5.5.0,5.6.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/plugin.properties b/org.eclipse.jgit.lfs.server.test/plugin.properties
index 4a8e642..b6dd7c0 100644
--- a/org.eclipse.jgit.lfs.server.test/plugin.properties
+++ b/org.eclipse.jgit.lfs.server.test/plugin.properties
@@ -1,2 +1,2 @@
-plugin_name=JGit LFS Server Tests
-provider_name=Eclipse JGit
+Bundle-Name=JGit LFS Server Tests
+Bundle-Vendor=Eclipse JGit
diff --git a/org.eclipse.jgit.lfs.server.test/pom.xml b/org.eclipse.jgit.lfs.server.test/pom.xml
index 7194449..d6075fe 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.4.1-SNAPSHOT</version>
+    <version>5.5.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 ab14a16..e130a8d 100644
--- a/org.eclipse.jgit.lfs.server/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.lfs.server/META-INF/MANIFEST.MF
@@ -1,21 +1,21 @@
 Manifest-Version: 1.0
 Bundle-ManifestVersion: 2
-Bundle-Name: %plugin_name
+Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.lfs.server
 Bundle-SymbolicName: org.eclipse.jgit.lfs.server
-Bundle-Version: 5.4.1.qualifier
+Bundle-Version: 5.5.0.qualifier
 Bundle-Localization: plugin
-Bundle-Vendor: %provider_name
-Export-Package: org.eclipse.jgit.lfs.server;version="5.4.1";
+Bundle-Vendor: %Bundle-Vendor
+Export-Package: org.eclipse.jgit.lfs.server;version="5.5.0";
   uses:="javax.servlet.http,
    org.eclipse.jgit.lfs.lib",
- org.eclipse.jgit.lfs.server.fs;version="5.4.1";
+ org.eclipse.jgit.lfs.server.fs;version="5.5.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.4.1";x-internal:=true,
- org.eclipse.jgit.lfs.server.s3;version="5.4.1";
+ org.eclipse.jgit.lfs.server.internal;version="5.5.0";x-internal:=true,
+ org.eclipse.jgit.lfs.server.s3;version="5.5.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.4.1,5.5.0)",
- org.eclipse.jgit.internal;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.internal.storage.file;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.lfs.errors;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.lfs.internal;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.lfs.lib;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.lib;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.nls;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.transport.http;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.transport.http.apache;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.util;version="[5.4.1,5.5.0)",
+ org.eclipse.jgit.annotations;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.internal;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.internal.storage.file;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.lfs.errors;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.lfs.internal;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.lfs.lib;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.lib;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.nls;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.transport.http;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.transport.http.apache;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.util;version="[5.5.0,5.6.0)",
  org.slf4j;version="[1.7.0,2.0.0)"
diff --git a/org.eclipse.jgit.lfs.server/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.lfs.server/META-INF/SOURCE-MANIFEST.MF
index abf1dd2..916329a 100644
--- a/org.eclipse.jgit.lfs.server/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.lfs.server/META-INF/SOURCE-MANIFEST.MF
@@ -3,5 +3,5 @@
 Bundle-Name: org.eclipse.jgit.lfs.server - Sources
 Bundle-SymbolicName: org.eclipse.jgit.lfs.server.source
 Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 5.4.1.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit.lfs.server;version="5.4.1.qualifier";roots="."
+Bundle-Version: 5.5.0.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit.lfs.server;version="5.5.0.qualifier";roots="."
diff --git a/org.eclipse.jgit.lfs.server/plugin.properties b/org.eclipse.jgit.lfs.server/plugin.properties
index 59f0139..4b9ee82 100644
--- a/org.eclipse.jgit.lfs.server/plugin.properties
+++ b/org.eclipse.jgit.lfs.server/plugin.properties
@@ -1,2 +1,2 @@
-plugin_name=JGit Large File Storage Server
-provider_name=Eclipse JGit
+Bundle-Name=JGit Large File Storage Server
+Bundle-Vendor=Eclipse JGit
diff --git a/org.eclipse.jgit.lfs.server/pom.xml b/org.eclipse.jgit.lfs.server/pom.xml
index 8a954bb..a00d2b9 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.4.1-SNAPSHOT</version>
+    <version>5.5.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 a4f55a6..c8b48d6 100644
--- a/org.eclipse.jgit.lfs.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.lfs.test/META-INF/MANIFEST.MF
@@ -1,24 +1,24 @@
 Manifest-Version: 1.0
 Bundle-ManifestVersion: 2
-Bundle-Name: %plugin_name
+Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.lfs.test
 Bundle-SymbolicName: org.eclipse.jgit.lfs.test
-Bundle-Version: 5.4.1.qualifier
-Bundle-Vendor: %provider_name
+Bundle-Version: 5.5.0.qualifier
+Bundle-Vendor: %Bundle-Vendor
 Bundle-Localization: plugin
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
-Import-Package: org.eclipse.jgit.internal.storage.dfs;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.junit;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.lfs;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.lfs.errors;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.lfs.lib;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.lib;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.revwalk;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.treewalk;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.treewalk.filter;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.util;version="[5.4.1,5.5.0)",
+Import-Package: org.eclipse.jgit.internal.storage.dfs;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.junit;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.lfs;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.lfs.errors;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.lfs.lib;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.lib;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.revwalk;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.treewalk;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.treewalk.filter;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.util;version="[5.5.0,5.6.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.4.1";x-friends:="org.eclipse.jgit.lfs.server.test"
+Export-Package: org.eclipse.jgit.lfs.test;version="5.5.0";x-friends:="org.eclipse.jgit.lfs.server.test"
diff --git a/org.eclipse.jgit.lfs.test/plugin.properties b/org.eclipse.jgit.lfs.test/plugin.properties
index f900780..ab78575 100644
--- a/org.eclipse.jgit.lfs.test/plugin.properties
+++ b/org.eclipse.jgit.lfs.test/plugin.properties
@@ -1,2 +1,2 @@
-plugin_name=JGit LFS Tests
-provider_name=Eclipse JGit
+Bundle-Name=JGit LFS Tests
+Bundle-Vendor=Eclipse JGit
diff --git a/org.eclipse.jgit.lfs.test/pom.xml b/org.eclipse.jgit.lfs.test/pom.xml
index ee74f0e..ea1b6d5 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.4.1-SNAPSHOT</version>
+    <version>5.5.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.lfs.test</artifactId>
diff --git a/org.eclipse.jgit.lfs/.settings/.api_filters b/org.eclipse.jgit.lfs/.settings/.api_filters
index 5b8ece6..9747df8 100644
--- a/org.eclipse.jgit.lfs/.settings/.api_filters
+++ b/org.eclipse.jgit.lfs/.settings/.api_filters
@@ -1,10 +1,11 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <component id="org.eclipse.jgit.lfs" version="2">
-    <resource path="META-INF/MANIFEST.MF">
-        <filter id="924844039">
+    <resource path="src/org/eclipse/jgit/lfs/lib/AnyLongObjectId.java" type="org.eclipse.jgit.lfs.lib.AnyLongObjectId">
+        <filter id="1141899266">
             <message_arguments>
-                <message_argument value="5.4.1"/>
-                <message_argument value="5.4.0"/>
+                <message_argument value="5.4"/>
+                <message_argument value="5.5"/>
+                <message_argument value="isEqual(AnyLongObjectId, AnyLongObjectId)"/>
             </message_arguments>
         </filter>
     </resource>
diff --git a/org.eclipse.jgit.lfs/META-INF/MANIFEST.MF b/org.eclipse.jgit.lfs/META-INF/MANIFEST.MF
index ad36094..ce2cc58 100644
--- a/org.eclipse.jgit.lfs/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.lfs/META-INF/MANIFEST.MF
@@ -1,35 +1,35 @@
 Manifest-Version: 1.0
 Bundle-ManifestVersion: 2
-Bundle-Name: %plugin_name
+Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.lfs
 Bundle-SymbolicName: org.eclipse.jgit.lfs
-Bundle-Version: 5.4.1.qualifier
+Bundle-Version: 5.5.0.qualifier
 Bundle-Localization: plugin
-Bundle-Vendor: %provider_name
-Export-Package: org.eclipse.jgit.lfs;version="5.4.1",
- org.eclipse.jgit.lfs.errors;version="5.4.1",
- org.eclipse.jgit.lfs.internal;version="5.4.1";x-friends:="org.eclipse.jgit.lfs.test,org.eclipse.jgit.lfs.server.fs,org.eclipse.jgit.lfs.server",
- org.eclipse.jgit.lfs.lib;version="5.4.1"
+Bundle-Vendor: %Bundle-Vendor
+Export-Package: org.eclipse.jgit.lfs;version="5.5.0",
+ org.eclipse.jgit.lfs.errors;version="5.5.0",
+ org.eclipse.jgit.lfs.internal;version="5.5.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.5.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.4.1,5.5.0)";resolution:=optional,
- org.eclipse.jgit.api.errors;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.attributes;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.diff;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.errors;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.hooks;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.internal.storage.file;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.lib;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.nls;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.revwalk;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.storage.file;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.storage.pack;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.transport;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.transport.http;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.treewalk;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.treewalk.filter;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.util;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.util.io;version="[5.4.1,5.5.0)"
+ org.eclipse.jgit.annotations;version="[5.5.0,5.6.0)";resolution:=optional,
+ org.eclipse.jgit.api.errors;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.attributes;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.diff;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.errors;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.hooks;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.internal.storage.file;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.lib;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.nls;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.revwalk;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.storage.file;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.storage.pack;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.transport;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.transport.http;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.treewalk;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.treewalk.filter;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.util;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.util.io;version="[5.5.0,5.6.0)"
diff --git a/org.eclipse.jgit.lfs/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.lfs/META-INF/SOURCE-MANIFEST.MF
index 517ec19..d401066 100644
--- a/org.eclipse.jgit.lfs/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.lfs/META-INF/SOURCE-MANIFEST.MF
@@ -3,5 +3,5 @@
 Bundle-Name: org.eclipse.jgit.lfs - Sources
 Bundle-SymbolicName: org.eclipse.jgit.lfs.source
 Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 5.4.1.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit.lfs;version="5.4.1.qualifier";roots="."
+Bundle-Version: 5.5.0.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit.lfs;version="5.5.0.qualifier";roots="."
diff --git a/org.eclipse.jgit.lfs/plugin.properties b/org.eclipse.jgit.lfs/plugin.properties
index 7c22ddb..76ead9b 100644
--- a/org.eclipse.jgit.lfs/plugin.properties
+++ b/org.eclipse.jgit.lfs/plugin.properties
@@ -1,2 +1,2 @@
-plugin_name=JGit Large File Storage
-provider_name=Eclipse JGit
+Bundle-Name=JGit Large File Storage
+Bundle-Vendor=Eclipse JGit
diff --git a/org.eclipse.jgit.lfs/pom.xml b/org.eclipse.jgit.lfs/pom.xml
index 65532f1..d299479 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.4.1-SNAPSHOT</version>
+    <version>5.5.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.lfs</artifactId>
diff --git a/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/Lfs.java b/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/Lfs.java
index 4c46bbd..8dba09c 100644
--- a/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/Lfs.java
+++ b/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/Lfs.java
@@ -42,6 +42,8 @@
  */
 package org.eclipse.jgit.lfs;
 
+import static org.eclipse.jgit.lib.Constants.OBJECTS;
+
 import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
@@ -104,7 +106,7 @@
 	 */
 	public Path getLfsObjDir() {
 		if (objDir == null) {
-			objDir = root.resolve("objects"); //$NON-NLS-1$
+			objDir = root.resolve(OBJECTS);
 		}
 		return objDir;
 	}
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 3a4c048..732f4a3 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.4.1.qualifier"
+      version="5.5.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 33d8567..e4d107f 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.4.1-SNAPSHOT</version>
+    <version>5.5.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 91264db..5edb75c 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.4.1.qualifier"
+      version="5.5.0.qualifier"
       provider-name="%providerName">
 
    <description url="http://www.eclipse.org/jgit/">
@@ -23,7 +23,7 @@
    </url>
 
    <requires>
-      <import plugin="org.eclipse.jgit" version="5.4.1" match="equivalent"/>
+      <import plugin="org.eclipse.jgit" version="5.5.0" match="equivalent"/>
    </requires>
 
    <plugin
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.http.apache.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.http.apache.feature/pom.xml
index cdf1cbd..72f7253 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.4.1-SNAPSHOT</version>
+    <version>5.5.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 52faeec..0e45f98 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.4.1.qualifier"
+      version="5.5.0.qualifier"
       provider-name="%providerName">
 
    <description url="http://www.eclipse.org/jgit/">
@@ -24,7 +24,7 @@
 
    <requires>
       <import plugin="com.jcraft.jsch"/>
-      <import plugin="org.eclipse.jgit" version="5.4.1" match="equivalent"/>
+      <import plugin="org.eclipse.jgit" version="5.5.0" match="equivalent"/>
    </requires>
 
    <plugin
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/pom.xml
index 79a2e84..004de58 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.4.1-SNAPSHOT</version>
+    <version>5.5.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 39db64a..7db8c38 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.4.1.qualifier"
+      version="5.5.0.qualifier"
       provider-name="%providerName">
 
    <description url="http://www.eclipse.org/jgit/">
@@ -23,7 +23,7 @@
    </url>
 
    <requires>
-      <import feature="org.eclipse.jgit" version="5.4.1" match="equivalent"/>
+      <import feature="org.eclipse.jgit" version="5.5.0" match="equivalent"/>
    </requires>
 
    <plugin
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.lfs.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.lfs.feature/pom.xml
index 2825df6..bf14a8b 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.4.1-SNAPSHOT</version>
+    <version>5.5.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 14bfd01..4569798 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.4.1.qualifier"
+      version="5.5.0.qualifier"
       provider-name="%providerName">
 
    <description url="http://www.eclipse.org/jgit/">
@@ -35,9 +35,9 @@
          version="0.0.0"/>
 
    <requires>
-      <import feature="org.eclipse.jgit" version="5.4.1" match="equivalent"/>
-      <import feature="org.eclipse.jgit.lfs" version="5.4.1" match="equivalent"/>
-      <import feature="org.eclipse.jgit.ssh.apache" version="5.4.1" match="equivalent"/>
+      <import feature="org.eclipse.jgit" version="5.5.0" match="equivalent"/>
+      <import feature="org.eclipse.jgit.lfs" version="5.5.0" match="equivalent"/>
+      <import feature="org.eclipse.jgit.ssh.apache" version="5.5.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 39772c7..6d61c40 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.4.1-SNAPSHOT</version>
+    <version>5.5.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 dc2ad15..d66bac6 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.4.1-SNAPSHOT</version>
+    <version>5.5.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 8e8fd8a..5154d44 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.4.1.qualifier"
+      version="5.5.0.qualifier"
       provider-name="%providerName">
 
    <description url="http://www.eclipse.org/jgit/">
@@ -23,7 +23,7 @@
    </url>
 
    <requires>
-      <import feature="org.eclipse.jgit" version="5.4.1" match="equivalent"/>
+      <import feature="org.eclipse.jgit" version="5.5.0" match="equivalent"/>
    </requires>
 
    <plugin
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/pom.xml
index 8132710..9fe2854 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.4.1-SNAPSHOT</version>
+    <version>5.5.0-SNAPSHOT</version>
   </parent>
 
   <groupId>org.eclipse.jgit.feature</groupId>
@@ -63,7 +63,7 @@
     <dependency>
       <groupId>org.eclipse.jgit.feature</groupId>
       <artifactId>org.eclipse.jgit</artifactId>
-      <version>5.4.1-SNAPSHOT</version>
+      <version>5.5.0-SNAPSHOT</version>
     </dependency>
   </dependencies>
 
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.feature/feature.xml
index b7420dc..5cf2c74 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.feature/feature.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.feature/feature.xml
@@ -2,7 +2,7 @@
 <feature
       id="org.eclipse.jgit.ssh.apache"
       label="%featureName"
-      version="5.4.1.qualifier"
+      version="5.5.0.qualifier"
       provider-name="%providerName">
 
    <description url="http://www.eclipse.org/jgit/">
@@ -23,7 +23,7 @@
    </url>
 
    <requires>
-      <import feature="org.eclipse.jgit" version="5.4.1" match="equivalent"/>
+      <import feature="org.eclipse.jgit" version="5.5.0" match="equivalent"/>
    </requires>
 
    <plugin
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.feature/pom.xml
index 167b295..2c1de89 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.feature/pom.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.feature/pom.xml
@@ -50,7 +50,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>jgit.tycho.parent</artifactId>
-    <version>5.4.1-SNAPSHOT</version>
+    <version>5.5.0-SNAPSHOT</version>
   </parent>
 
   <groupId>org.eclipse.jgit.feature</groupId>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.10.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.10.target
index 1915747..f5eca33 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.10.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.10.target
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <?pde?>
 <!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
-<target name="jgit-4.10" sequenceNumber="1559548426">
+<target name="jgit-4.10" sequenceNumber="1560816180">
   <locations>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
       <unit id="org.eclipse.jetty.client" version="9.4.14.v20181114"/>
@@ -54,12 +54,12 @@
       <unit id="javaewah.source" version="1.1.6.v20160919-1400"/>
       <unit id="org.objenesis" version="2.6.0.v20180420-1519"/>
       <unit id="org.objenesis.source" version="2.6.0.v20180420-1519"/>
-      <unit id="org.mockito" version="2.13.0.v20180426-1843"/>
-      <unit id="org.mockito.source" version="2.13.0.v20180426-1843"/>
-      <unit id="net.bytebuddy.byte-buddy" version="1.7.9.v20180420-1519"/>
-      <unit id="net.bytebuddy.byte-buddy.source" version="1.7.9.v20180420-1519"/>
-      <unit id="net.bytebuddy.byte-buddy-agent" version="1.7.9.v20180420-1519"/>
-      <unit id="net.bytebuddy.byte-buddy-agent.source" version="1.7.9.v20180420-1519"/>
+      <unit id="org.mockito" version="2.23.0.v20190527-1420"/>
+      <unit id="org.mockito.source" version="2.23.0.v20190527-1420"/>
+      <unit id="net.bytebuddy.byte-buddy" version="1.9.0.v20181107-1410"/>
+      <unit id="net.bytebuddy.byte-buddy.source" version="1.9.0.v20181107-1410"/>
+      <unit id="net.bytebuddy.byte-buddy-agent" version="1.9.0.v20181106-1534"/>
+      <unit id="net.bytebuddy.byte-buddy-agent.source" version="1.9.0.v20181106-1534"/>
       <unit id="com.google.gson" version="2.8.2.v20180104-1110"/>
       <unit id="com.google.gson.source" version="2.8.2.v20180104-1110"/>
       <unit id="com.jcraft.jsch" version="0.1.55.v20190404-1902"/>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.11.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.11.target
index e5ea331..bdbc75a 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.11.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.11.target
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <?pde?>
 <!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
-<target name="jgit-4.11" sequenceNumber="1559548429">
+<target name="jgit-4.11" sequenceNumber="1560816197">
   <locations>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
       <unit id="org.eclipse.jetty.client" version="9.4.14.v20181114"/>
@@ -54,12 +54,12 @@
       <unit id="javaewah.source" version="1.1.6.v20160919-1400"/>
       <unit id="org.objenesis" version="2.6.0.v20180420-1519"/>
       <unit id="org.objenesis.source" version="2.6.0.v20180420-1519"/>
-      <unit id="org.mockito" version="2.13.0.v20180426-1843"/>
-      <unit id="org.mockito.source" version="2.13.0.v20180426-1843"/>
-      <unit id="net.bytebuddy.byte-buddy" version="1.7.9.v20180420-1519"/>
-      <unit id="net.bytebuddy.byte-buddy.source" version="1.7.9.v20180420-1519"/>
-      <unit id="net.bytebuddy.byte-buddy-agent" version="1.7.9.v20180420-1519"/>
-      <unit id="net.bytebuddy.byte-buddy-agent.source" version="1.7.9.v20180420-1519"/>
+      <unit id="org.mockito" version="2.23.0.v20190527-1420"/>
+      <unit id="org.mockito.source" version="2.23.0.v20190527-1420"/>
+      <unit id="net.bytebuddy.byte-buddy" version="1.9.0.v20181107-1410"/>
+      <unit id="net.bytebuddy.byte-buddy.source" version="1.9.0.v20181107-1410"/>
+      <unit id="net.bytebuddy.byte-buddy-agent" version="1.9.0.v20181106-1534"/>
+      <unit id="net.bytebuddy.byte-buddy-agent.source" version="1.9.0.v20181106-1534"/>
       <unit id="com.google.gson" version="2.8.2.v20180104-1110"/>
       <unit id="com.google.gson.source" version="2.8.2.v20180104-1110"/>
       <unit id="com.jcraft.jsch" version="0.1.55.v20190404-1902"/>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.12-staging.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.12-staging.target
index 5daa8e8..e98c89e 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.12-staging.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.12-staging.target
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <?pde?>
 <!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
-<target name="jgit-4.12-staging" sequenceNumber="1559548433">
+<target name="jgit-4.12-staging" sequenceNumber="1560816219">
   <locations>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
       <unit id="org.eclipse.jetty.client" version="9.4.14.v20181114"/>
@@ -54,12 +54,12 @@
       <unit id="javaewah.source" version="1.1.6.v20160919-1400"/>
       <unit id="org.objenesis" version="2.6.0.v20180420-1519"/>
       <unit id="org.objenesis.source" version="2.6.0.v20180420-1519"/>
-      <unit id="org.mockito" version="2.13.0.v20180426-1843"/>
-      <unit id="org.mockito.source" version="2.13.0.v20180426-1843"/>
-      <unit id="net.bytebuddy.byte-buddy" version="1.7.9.v20180420-1519"/>
-      <unit id="net.bytebuddy.byte-buddy.source" version="1.7.9.v20180420-1519"/>
-      <unit id="net.bytebuddy.byte-buddy-agent" version="1.7.9.v20180420-1519"/>
-      <unit id="net.bytebuddy.byte-buddy-agent.source" version="1.7.9.v20180420-1519"/>
+      <unit id="org.mockito" version="2.23.0.v20190527-1420"/>
+      <unit id="org.mockito.source" version="2.23.0.v20190527-1420"/>
+      <unit id="net.bytebuddy.byte-buddy" version="1.9.0.v20181107-1410"/>
+      <unit id="net.bytebuddy.byte-buddy.source" version="1.9.0.v20181107-1410"/>
+      <unit id="net.bytebuddy.byte-buddy-agent" version="1.9.0.v20181106-1534"/>
+      <unit id="net.bytebuddy.byte-buddy-agent.source" version="1.9.0.v20181106-1534"/>
       <unit id="com.google.gson" version="2.8.2.v20180104-1110"/>
       <unit id="com.google.gson.source" version="2.8.2.v20180104-1110"/>
       <unit id="com.jcraft.jsch" version="0.1.55.v20190404-1902"/>
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 0638b46..308f9f9 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/eclipse-cbi/targetplatform-dsl -->
-<target name="jgit-4.6" sequenceNumber="1559548436">
+<target name="jgit-4.6" sequenceNumber="1560816227">
   <locations>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
       <unit id="org.eclipse.jetty.client" version="9.4.14.v20181114"/>
@@ -54,12 +54,12 @@
       <unit id="javaewah.source" version="1.1.6.v20160919-1400"/>
       <unit id="org.objenesis" version="2.6.0.v20180420-1519"/>
       <unit id="org.objenesis.source" version="2.6.0.v20180420-1519"/>
-      <unit id="org.mockito" version="2.13.0.v20180426-1843"/>
-      <unit id="org.mockito.source" version="2.13.0.v20180426-1843"/>
-      <unit id="net.bytebuddy.byte-buddy" version="1.7.9.v20180420-1519"/>
-      <unit id="net.bytebuddy.byte-buddy.source" version="1.7.9.v20180420-1519"/>
-      <unit id="net.bytebuddy.byte-buddy-agent" version="1.7.9.v20180420-1519"/>
-      <unit id="net.bytebuddy.byte-buddy-agent.source" version="1.7.9.v20180420-1519"/>
+      <unit id="org.mockito" version="2.23.0.v20190527-1420"/>
+      <unit id="org.mockito.source" version="2.23.0.v20190527-1420"/>
+      <unit id="net.bytebuddy.byte-buddy" version="1.9.0.v20181107-1410"/>
+      <unit id="net.bytebuddy.byte-buddy.source" version="1.9.0.v20181107-1410"/>
+      <unit id="net.bytebuddy.byte-buddy-agent" version="1.9.0.v20181106-1534"/>
+      <unit id="net.bytebuddy.byte-buddy-agent.source" version="1.9.0.v20181106-1534"/>
       <unit id="com.google.gson" version="2.8.2.v20180104-1110"/>
       <unit id="com.google.gson.source" version="2.8.2.v20180104-1110"/>
       <unit id="com.jcraft.jsch" version="0.1.55.v20190404-1902"/>
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 1044299..eeae219 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/eclipse-cbi/targetplatform-dsl -->
-<target name="jgit-4.7" sequenceNumber="1559548440">
+<target name="jgit-4.7" sequenceNumber="1560816219">
   <locations>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
       <unit id="org.eclipse.jetty.client" version="9.4.14.v20181114"/>
@@ -54,12 +54,12 @@
       <unit id="javaewah.source" version="1.1.6.v20160919-1400"/>
       <unit id="org.objenesis" version="2.6.0.v20180420-1519"/>
       <unit id="org.objenesis.source" version="2.6.0.v20180420-1519"/>
-      <unit id="org.mockito" version="2.13.0.v20180426-1843"/>
-      <unit id="org.mockito.source" version="2.13.0.v20180426-1843"/>
-      <unit id="net.bytebuddy.byte-buddy" version="1.7.9.v20180420-1519"/>
-      <unit id="net.bytebuddy.byte-buddy.source" version="1.7.9.v20180420-1519"/>
-      <unit id="net.bytebuddy.byte-buddy-agent" version="1.7.9.v20180420-1519"/>
-      <unit id="net.bytebuddy.byte-buddy-agent.source" version="1.7.9.v20180420-1519"/>
+      <unit id="org.mockito" version="2.23.0.v20190527-1420"/>
+      <unit id="org.mockito.source" version="2.23.0.v20190527-1420"/>
+      <unit id="net.bytebuddy.byte-buddy" version="1.9.0.v20181107-1410"/>
+      <unit id="net.bytebuddy.byte-buddy.source" version="1.9.0.v20181107-1410"/>
+      <unit id="net.bytebuddy.byte-buddy-agent" version="1.9.0.v20181106-1534"/>
+      <unit id="net.bytebuddy.byte-buddy-agent.source" version="1.9.0.v20181106-1534"/>
       <unit id="com.google.gson" version="2.8.2.v20180104-1110"/>
       <unit id="com.google.gson.source" version="2.8.2.v20180104-1110"/>
       <unit id="com.jcraft.jsch" version="0.1.55.v20190404-1902"/>
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 a5f948f..4ada70f 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/eclipse-cbi/targetplatform-dsl -->
-<target name="jgit-4.8" sequenceNumber="1559548443">
+<target name="jgit-4.8" sequenceNumber="1560816217">
   <locations>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
       <unit id="org.eclipse.jetty.client" version="9.4.14.v20181114"/>
@@ -54,12 +54,12 @@
       <unit id="javaewah.source" version="1.1.6.v20160919-1400"/>
       <unit id="org.objenesis" version="2.6.0.v20180420-1519"/>
       <unit id="org.objenesis.source" version="2.6.0.v20180420-1519"/>
-      <unit id="org.mockito" version="2.13.0.v20180426-1843"/>
-      <unit id="org.mockito.source" version="2.13.0.v20180426-1843"/>
-      <unit id="net.bytebuddy.byte-buddy" version="1.7.9.v20180420-1519"/>
-      <unit id="net.bytebuddy.byte-buddy.source" version="1.7.9.v20180420-1519"/>
-      <unit id="net.bytebuddy.byte-buddy-agent" version="1.7.9.v20180420-1519"/>
-      <unit id="net.bytebuddy.byte-buddy-agent.source" version="1.7.9.v20180420-1519"/>
+      <unit id="org.mockito" version="2.23.0.v20190527-1420"/>
+      <unit id="org.mockito.source" version="2.23.0.v20190527-1420"/>
+      <unit id="net.bytebuddy.byte-buddy" version="1.9.0.v20181107-1410"/>
+      <unit id="net.bytebuddy.byte-buddy.source" version="1.9.0.v20181107-1410"/>
+      <unit id="net.bytebuddy.byte-buddy-agent" version="1.9.0.v20181106-1534"/>
+      <unit id="net.bytebuddy.byte-buddy-agent.source" version="1.9.0.v20181106-1534"/>
       <unit id="com.google.gson" version="2.8.2.v20180104-1110"/>
       <unit id="com.google.gson.source" version="2.8.2.v20180104-1110"/>
       <unit id="com.jcraft.jsch" version="0.1.55.v20190404-1902"/>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.9.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.9.target
index e0afda3..97c9de3 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.9.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.9.target
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <?pde?>
 <!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
-<target name="jgit-4.9" sequenceNumber="1559548447">
+<target name="jgit-4.9" sequenceNumber="1560816222">
   <locations>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
       <unit id="org.eclipse.jetty.client" version="9.4.14.v20181114"/>
@@ -54,12 +54,12 @@
       <unit id="javaewah.source" version="1.1.6.v20160919-1400"/>
       <unit id="org.objenesis" version="2.6.0.v20180420-1519"/>
       <unit id="org.objenesis.source" version="2.6.0.v20180420-1519"/>
-      <unit id="org.mockito" version="2.13.0.v20180426-1843"/>
-      <unit id="org.mockito.source" version="2.13.0.v20180426-1843"/>
-      <unit id="net.bytebuddy.byte-buddy" version="1.7.9.v20180420-1519"/>
-      <unit id="net.bytebuddy.byte-buddy.source" version="1.7.9.v20180420-1519"/>
-      <unit id="net.bytebuddy.byte-buddy-agent" version="1.7.9.v20180420-1519"/>
-      <unit id="net.bytebuddy.byte-buddy-agent.source" version="1.7.9.v20180420-1519"/>
+      <unit id="org.mockito" version="2.23.0.v20190527-1420"/>
+      <unit id="org.mockito.source" version="2.23.0.v20190527-1420"/>
+      <unit id="net.bytebuddy.byte-buddy" version="1.9.0.v20181107-1410"/>
+      <unit id="net.bytebuddy.byte-buddy.source" version="1.9.0.v20181107-1410"/>
+      <unit id="net.bytebuddy.byte-buddy-agent" version="1.9.0.v20181106-1534"/>
+      <unit id="net.bytebuddy.byte-buddy-agent.source" version="1.9.0.v20181106-1534"/>
       <unit id="com.google.gson" version="2.8.2.v20180104-1110"/>
       <unit id="com.google.gson.source" version="2.8.2.v20180104-1110"/>
       <unit id="com.jcraft.jsch" version="0.1.55.v20190404-1902"/>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20190602212107-2019-06.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20190602212107-2019-06.tpd
index df9a810..e2f975e 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20190602212107-2019-06.tpd
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20190602212107-2019-06.tpd
@@ -33,12 +33,12 @@
 	javaewah.source [1.1.6.v20160919-1400,1.1.6.v20160919-1400]
 	org.objenesis [2.6.0.v20180420-1519,2.6.0.v20180420-1519]
 	org.objenesis.source [2.6.0.v20180420-1519,2.6.0.v20180420-1519]
-	org.mockito [2.13.0.v20180426-1843,2.13.0.v20180426-1843]
-	org.mockito.source [2.13.0.v20180426-1843,2.13.0.v20180426-1843]
-	net.bytebuddy.byte-buddy [1.7.9.v20180420-1519,1.7.9.v20180420-1519]
-	net.bytebuddy.byte-buddy.source [1.7.9.v20180420-1519,1.7.9.v20180420-1519]
-	net.bytebuddy.byte-buddy-agent [1.7.9.v20180420-1519,1.7.9.v20180420-1519]
-	net.bytebuddy.byte-buddy-agent.source [1.7.9.v20180420-1519,1.7.9.v20180420-1519]
+	org.mockito [2.23.0.v20190527-1420,2.23.0.v20190527-1420]
+	org.mockito.source [2.23.0.v20190527-1420,2.23.0.v20190527-1420]
+	net.bytebuddy.byte-buddy [1.9.0.v20181107-1410,1.9.0.v20181107-1410]
+	net.bytebuddy.byte-buddy.source [1.9.0.v20181107-1410,1.9.0.v20181107-1410]
+	net.bytebuddy.byte-buddy-agent [1.9.0.v20181106-1534,1.9.0.v20181106-1534]
+	net.bytebuddy.byte-buddy-agent.source [1.9.0.v20181106-1534,1.9.0.v20181106-1534]
 	com.google.gson [2.8.2.v20180104-1110,2.8.2.v20180104-1110]
 	com.google.gson.source [2.8.2.v20180104-1110,2.8.2.v20180104-1110]
 	com.jcraft.jsch [0.1.55.v20190404-1902,0.1.55.v20190404-1902]
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 e632224..44355f0 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.4.1-SNAPSHOT</version>
+    <version>5.5.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 6c5ced3..1e17c9d 100644
--- a/org.eclipse.jgit.packaging/pom.xml
+++ b/org.eclipse.jgit.packaging/pom.xml
@@ -49,7 +49,7 @@
 
   <groupId>org.eclipse.jgit</groupId>
   <artifactId>jgit.tycho.parent</artifactId>
-  <version>5.4.1-SNAPSHOT</version>
+  <version>5.5.0-SNAPSHOT</version>
   <packaging>pom</packaging>
 
   <name>JGit Tycho Parent</name>
diff --git a/org.eclipse.jgit.pgm.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.pgm.test/META-INF/MANIFEST.MF
index 920c0cf..4f74752 100644
--- a/org.eclipse.jgit.pgm.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.pgm.test/META-INF/MANIFEST.MF
@@ -1,30 +1,30 @@
 Manifest-Version: 1.0
 Bundle-ManifestVersion: 2
-Bundle-Name: %plugin_name
+Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.pgm.test
 Bundle-SymbolicName: org.eclipse.jgit.pgm.test
-Bundle-Version: 5.4.1.qualifier
-Bundle-Vendor: %provider_name
+Bundle-Version: 5.5.0.qualifier
+Bundle-Vendor: %Bundle-Vendor
 Bundle-Localization: plugin
 Bundle-ActivationPolicy: lazy
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
-Import-Package: org.eclipse.jgit.api;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.api.errors;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.diff;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.dircache;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.internal.storage.file;version="5.4.1",
- org.eclipse.jgit.junit;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.lib;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.merge;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.pgm;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.pgm.internal;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.pgm.opt;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.revwalk;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.storage.file;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.transport;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.treewalk;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.util;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.util.io;version="[5.4.1,5.5.0)",
+Import-Package: org.eclipse.jgit.api;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.api.errors;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.diff;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.dircache;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.internal.storage.file;version="5.5.0",
+ org.eclipse.jgit.junit;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.lib;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.merge;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.pgm;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.pgm.internal;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.pgm.opt;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.revwalk;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.storage.file;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.transport;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.treewalk;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.util;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.util.io;version="[5.5.0,5.6.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/plugin.properties b/org.eclipse.jgit.pgm.test/plugin.properties
index e131c69..61cae8e 100644
--- a/org.eclipse.jgit.pgm.test/plugin.properties
+++ b/org.eclipse.jgit.pgm.test/plugin.properties
@@ -1,2 +1,2 @@
-plugin_name=JGit Command Line Interface Tests
-provider_name=Eclipse JGit
+Bundle-Name=JGit Command Line Interface Tests
+Bundle-Vendor=Eclipse JGit
diff --git a/org.eclipse.jgit.pgm.test/pom.xml b/org.eclipse.jgit.pgm.test/pom.xml
index fb493f8..1d1c03b 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.4.1-SNAPSHOT</version>
+    <version>5.5.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.pgm.test</artifactId>
diff --git a/org.eclipse.jgit.pgm.test/src/org/eclipse/jgit/lib/CLIRepositoryTestCase.java b/org.eclipse.jgit.pgm.test/src/org/eclipse/jgit/lib/CLIRepositoryTestCase.java
index a830ff2..befb7f6 100644
--- a/org.eclipse.jgit.pgm.test/src/org/eclipse/jgit/lib/CLIRepositoryTestCase.java
+++ b/org.eclipse.jgit.pgm.test/src/org/eclipse/jgit/lib/CLIRepositoryTestCase.java
@@ -211,6 +211,14 @@
 				.replaceAll("\t", "\\\\t");
 	}
 
+	protected String shellQuote(String s) {
+		return "'" + s.replace("'", "'\\''") + "'";
+	}
+
+	protected String shellQuote(File f) {
+		return "'" + f.getPath().replace("'", "'\\''") + "'";
+	}
+
 	protected void assertStringArrayEquals(String expected, String[] actual) {
 		// if there is more than one line, ignore last one if empty
 		assertEquals(1,
diff --git a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/ArchiveTest.java b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/ArchiveTest.java
index e07fdd5..03aa469 100644
--- a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/ArchiveTest.java
+++ b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/ArchiveTest.java
@@ -139,10 +139,6 @@
 				listTarEntries(result));
 	}
 
-	private static String shellQuote(String s) {
-		return "'" + s.replace("'", "'\\''") + "'";
-	}
-
 	@Test
 	public void testFormatOverridesFilename() throws Exception {
 		File archive = new File(db.getWorkTree(), "format-overrides-name.tar");
diff --git a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/CloneTest.java b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/CloneTest.java
index 2c0abd7..c31f28c 100644
--- a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/CloneTest.java
+++ b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/CloneTest.java
@@ -78,9 +78,9 @@
 		File gitDir = db.getDirectory();
 		String sourceURI = gitDir.toURI().toString();
 		File target = createTempDirectory("target");
-		StringBuilder cmd = new StringBuilder("git clone ").append(sourceURI
-				+ " " + target.getPath());
-		String[] result = execute(cmd.toString());
+		String cmd = "git clone " + sourceURI + " "
+				+ shellQuote(target.getPath());
+		String[] result = execute(cmd);
 		assertArrayEquals(new String[] {
 				"Cloning into '" + target.getPath() + "'...",
 						"", "" }, result);
@@ -101,9 +101,9 @@
 		File gitDir = db.getDirectory();
 		String sourceURI = gitDir.toURI().toString();
 		File target = createTempDirectory("target");
-		StringBuilder cmd = new StringBuilder("git clone ").append(sourceURI
-				+ " " + target.getPath());
-		String[] result = execute(cmd.toString());
+		String cmd = "git clone " + sourceURI + " "
+				+ shellQuote(target.getPath());
+		String[] result = execute(cmd);
 		assertArrayEquals(new String[] {
 				"Cloning into '" + target.getPath() + "'...",
 				"warning: You appear to have cloned an empty repository.", "",
@@ -125,8 +125,8 @@
 		File gitDir = db.getDirectory();
 		String sourceURI = gitDir.toURI().toString();
 		String name = new URIish(sourceURI).getHumanishName();
-		StringBuilder cmd = new StringBuilder("git clone ").append(sourceURI);
-		String[] result = execute(cmd.toString());
+		String cmd = "git clone " + sourceURI;
+		String[] result = execute(cmd);
 		assertArrayEquals(new String[] {
 				"Cloning into '" + new File(target, name).getName() + "'...",
 				"", "" }, result);
@@ -143,10 +143,10 @@
 		String sourcePath = gitDir.getAbsolutePath();
 		String targetPath = (new File(sourcePath)).getParentFile()
 				.getParentFile().getAbsolutePath()
-				+ "/target.git";
-		StringBuilder cmd = new StringBuilder("git clone --bare ")
-				.append(sourcePath + " " + targetPath);
-		String[] result = execute(cmd.toString());
+				+ File.separator + "target.git";
+		String cmd = "git clone --bare " + shellQuote(sourcePath) + " "
+				+ shellQuote(targetPath);
+		String[] result = execute(cmd);
 		assertArrayEquals(new String[] {
 				"Cloning into '" + targetPath + "'...", "", "" }, result);
 		Git git2 = Git.open(new File(targetPath));
diff --git a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/LsRemoteTest.java b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/LsRemoteTest.java
index ba6b771..fd3c383 100644
--- a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/LsRemoteTest.java
+++ b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/LsRemoteTest.java
@@ -80,7 +80,7 @@
 	@Test
 	public void testLsRemote() throws Exception {
 		final List<String> result = CLIGitCommand.execute(
-				"git ls-remote " + db.getDirectory(), db);
+				"git ls-remote " + shellQuote(db.getDirectory()), db);
 		assertArrayEquals(new String[] {
 				"d0b1ef2b3dea02bb2ca824445c04e6def012c32c	HEAD",
 				"d0b1ef2b3dea02bb2ca824445c04e6def012c32c	refs/heads/master",
@@ -98,7 +98,8 @@
 	public void testLsRemoteHeads() throws Exception {
 		final List<String> result = CLIGitCommand.execute(
 				"git ls-remote --heads "
-				+ db.getDirectory(), db);
+						+ shellQuote(db.getDirectory()),
+				db);
 		assertArrayEquals(new String[] {
 				"d0b1ef2b3dea02bb2ca824445c04e6def012c32c	refs/heads/master",
 				"d0b1ef2b3dea02bb2ca824445c04e6def012c32c	refs/heads/test",
@@ -108,7 +109,7 @@
 	@Test
 	public void testLsRemoteTags() throws Exception {
 		final List<String> result = CLIGitCommand.execute(
-				"git ls-remote --tags " + db.getDirectory(), db);
+				"git ls-remote --tags " + shellQuote(db.getDirectory()), db);
 		assertArrayEquals(new String[] {
 				"efc02078d83a5226986ae917323acec7e1e8b7cb	refs/tags/tag1",
 				"d0b1ef2b3dea02bb2ca824445c04e6def012c32c	refs/tags/tag1^{}",
@@ -122,7 +123,8 @@
 	@Test
 	public void testLsRemoteHeadsTags() throws Exception {
 		final List<String> result = CLIGitCommand.execute(
-				"git ls-remote --heads --tags " + db.getDirectory(), db);
+				"git ls-remote --heads --tags " + shellQuote(db.getDirectory()),
+				db);
 		assertArrayEquals(new String[] {
 				"d0b1ef2b3dea02bb2ca824445c04e6def012c32c	refs/heads/master",
 				"d0b1ef2b3dea02bb2ca824445c04e6def012c32c	refs/heads/test",
diff --git a/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF b/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF
index 9c313aa..14a14b2 100644
--- a/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF
@@ -1,10 +1,10 @@
 Manifest-Version: 1.0
 Bundle-ManifestVersion: 2
-Bundle-Name: %plugin_name
+Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.pgm
 Bundle-SymbolicName: org.eclipse.jgit.pgm
-Bundle-Version: 5.4.1.qualifier
-Bundle-Vendor: %provider_name
+Bundle-Version: 5.5.0.qualifier
+Bundle-Vendor: %Bundle-Vendor
 Bundle-ActivationPolicy: lazy
 Bundle-Localization: plugin
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
@@ -28,50 +28,50 @@
  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.4.1,5.5.0)",
- org.eclipse.jgit.api.errors;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.archive;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.awtui;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.blame;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.diff;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.dircache;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.errors;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.gitrepo;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.internal.ketch;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.internal.storage.dfs;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.internal.storage.file;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.internal.storage.io;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.internal.storage.pack;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.internal.storage.reftable;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.internal.storage.reftree;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.lfs;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.lfs.lib;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.lfs.server;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.lfs.server.fs;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.lfs.server.s3;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.lib;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.merge;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.nls;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.notes;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.revplot;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.revwalk;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.revwalk.filter;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.storage.file;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.storage.pack;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.transport;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.transport.http.apache;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.transport.resolver;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.transport.sshd;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.treewalk;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.treewalk.filter;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.util;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.util.io;version="[5.4.1,5.5.0)",
+ org.eclipse.jgit.api;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.api.errors;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.archive;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.awtui;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.blame;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.diff;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.dircache;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.errors;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.gitrepo;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.internal.ketch;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.internal.storage.dfs;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.internal.storage.file;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.internal.storage.io;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.internal.storage.pack;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.internal.storage.reftable;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.internal.storage.reftree;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.lfs;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.lfs.lib;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.lfs.server;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.lfs.server.fs;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.lfs.server.s3;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.lib;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.merge;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.nls;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.notes;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.revplot;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.revwalk;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.revwalk.filter;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.storage.file;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.storage.pack;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.transport;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.transport.http.apache;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.transport.resolver;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.transport.sshd;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.treewalk;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.treewalk.filter;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.util;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.util.io;version="[5.5.0,5.6.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.4.1";
+Export-Package: org.eclipse.jgit.console;version="5.5.0";
   uses:="org.eclipse.jgit.transport,
    org.eclipse.jgit.util",
- org.eclipse.jgit.pgm;version="5.4.1";
+ org.eclipse.jgit.pgm;version="5.5.0";
   uses:="org.eclipse.jgit.revwalk,
    org.eclipse.jgit.treewalk.filter,
    org.eclipse.jgit.pgm.opt,
@@ -82,11 +82,11 @@
    org.eclipse.jgit.treewalk,
    javax.swing,
    org.eclipse.jgit.transport",
- org.eclipse.jgit.pgm.debug;version="5.4.1";
+ org.eclipse.jgit.pgm.debug;version="5.5.0";
   uses:="org.eclipse.jgit.util.io,
    org.eclipse.jgit.pgm",
- org.eclipse.jgit.pgm.internal;version="5.4.1";x-friends:="org.eclipse.jgit.pgm.test,org.eclipse.jgit.test",
- org.eclipse.jgit.pgm.opt;version="5.4.1";
+ org.eclipse.jgit.pgm.internal;version="5.5.0";x-friends:="org.eclipse.jgit.pgm.test,org.eclipse.jgit.test",
+ org.eclipse.jgit.pgm.opt;version="5.5.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 9be8fb2..d5323ba 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.4.1.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit.pgm;version="5.4.1.qualifier";roots="."
+Bundle-Version: 5.5.0.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit.pgm;version="5.5.0.qualifier";roots="."
diff --git a/org.eclipse.jgit.pgm/plugin.properties b/org.eclipse.jgit.pgm/plugin.properties
index 118fe47..bfa216c 100644
--- a/org.eclipse.jgit.pgm/plugin.properties
+++ b/org.eclipse.jgit.pgm/plugin.properties
@@ -1,2 +1,2 @@
-plugin_name=JGit Command Line Interface
-provider_name=Eclipse JGit
+Bundle-Name=JGit Command Line Interface
+Bundle-Vendor=Eclipse JGit
diff --git a/org.eclipse.jgit.pgm/pom.xml b/org.eclipse.jgit.pgm/pom.xml
index 389b180..c6af997 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.4.1-SNAPSHOT</version>
+    <version>5.5.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.pgm</artifactId>
diff --git a/org.eclipse.jgit.ssh.apache.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.ssh.apache.test/META-INF/MANIFEST.MF
index a97bf78..504a20e 100644
--- a/org.eclipse.jgit.ssh.apache.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.ssh.apache.test/META-INF/MANIFEST.MF
@@ -3,17 +3,19 @@
 Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.ssh.apache.test
 Bundle-SymbolicName: org.eclipse.jgit.ssh.apache.test
-Bundle-Version: 5.4.1.qualifier
-Bundle-Vendor: %Provider-Name
+Bundle-Version: 5.5.0.qualifier
+Bundle-Vendor: %Bundle-Vendor
+Bundle-Localization: plugin
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
-Import-Package: org.eclipse.jgit.internal.transport.sshd.proxy;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.junit;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.junit.ssh;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.lib;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.transport;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.transport.ssh;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.transport.sshd;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.util;version="[5.4.1,5.5.0)",
+Import-Package: org.eclipse.jgit.api.errors;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.internal.transport.sshd.proxy;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.junit;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.junit.ssh;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.lib;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.transport;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.transport.ssh;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.transport.sshd;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.util;version="[5.5.0,5.6.0)",
  org.junit;version="[4.12,5.0.0)",
  org.junit.experimental.theories;version="[4.12,5.0.0)",
  org.junit.runner;version="[4.12,5.0.0)"
diff --git a/org.eclipse.jgit.ssh.apache.test/plugin.properties b/org.eclipse.jgit.ssh.apache.test/plugin.properties
index 67c296d..b279c8f 100644
--- a/org.eclipse.jgit.ssh.apache.test/plugin.properties
+++ b/org.eclipse.jgit.ssh.apache.test/plugin.properties
@@ -1,2 +1,2 @@
-plugin_name=JGit Tests for SSH with Apache MINA sshd
-provider_name=Eclipse JGit
+Bundle-Name=JGit Tests for SSH with Apache MINA sshd
+Bundle-Vendor=Eclipse JGit
diff --git a/org.eclipse.jgit.ssh.apache.test/pom.xml b/org.eclipse.jgit.ssh.apache.test/pom.xml
index 00bd403..23d6f8f 100644
--- a/org.eclipse.jgit.ssh.apache.test/pom.xml
+++ b/org.eclipse.jgit.ssh.apache.test/pom.xml
@@ -50,7 +50,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>org.eclipse.jgit-parent</artifactId>
-    <version>5.4.1-SNAPSHOT</version>
+    <version>5.5.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.ssh.apache.test</artifactId>
diff --git a/org.eclipse.jgit.ssh.apache.test/tst/org/eclipse/jgit/transport/sshd/ApacheSshTest.java b/org.eclipse.jgit.ssh.apache.test/tst/org/eclipse/jgit/transport/sshd/ApacheSshTest.java
index ee58083..df0b832 100644
--- a/org.eclipse.jgit.ssh.apache.test/tst/org/eclipse/jgit/transport/sshd/ApacheSshTest.java
+++ b/org.eclipse.jgit.ssh.apache.test/tst/org/eclipse/jgit/transport/sshd/ApacheSshTest.java
@@ -47,7 +47,7 @@
 import java.io.UncheckedIOException;
 import java.nio.file.Files;
 import java.util.Arrays;
-
+import org.eclipse.jgit.api.errors.TransportException;
 import org.eclipse.jgit.lib.Constants;
 import org.eclipse.jgit.transport.SshSessionFactory;
 import org.eclipse.jgit.transport.ssh.SshTestBase;
@@ -82,11 +82,10 @@
 		}
 	}
 
-	// Using an ed25519 (unencrypted) user key is tested in the super class in
-	// testSshKeys(). sshd 2.0.0 cannot yet read encrypted ed25519 keys.
-
 	@Test
 	public void testEd25519HostKey() throws Exception {
+		// Using ed25519 user identities is tested in the super class in
+		// testSshKeys().
 		File newHostKey = new File(getTemporaryDirectory(), "newhostkey");
 		copyTestResource("id_ed25519", newHostKey);
 		server.addHostKey(newHostKey.toPath(), true);
@@ -102,4 +101,60 @@
 				"IdentityFile " + privateKey1.getAbsolutePath());
 	}
 
+	@Test
+	public void testPreamble() throws Exception {
+		// Test that the client can deal with strange lines being sent before
+		// the server identification string.
+		StringBuilder b = new StringBuilder();
+		for (int i = 0; i < 257; i++) {
+			b.append('a');
+		}
+		server.setPreamble("A line with a \000 NUL",
+				"A long line: " + b.toString());
+		cloneWith(
+				"ssh://" + TEST_USER + "@localhost:" + testPort
+						+ "/doesntmatter",
+				defaultCloneDir, null,
+				"IdentityFile " + privateKey1.getAbsolutePath());
+	}
+
+	@Test
+	public void testLongPreamble() throws Exception {
+		// Test that the client can deal with a long (about 60k) preamble.
+		StringBuilder b = new StringBuilder();
+		for (int i = 0; i < 1024; i++) {
+			b.append('a');
+		}
+		String line = b.toString();
+		String[] lines = new String[60];
+		for (int i = 0; i < lines.length; i++) {
+			lines[i] = line;
+		}
+		server.setPreamble(lines);
+		cloneWith(
+				"ssh://" + TEST_USER + "@localhost:" + testPort
+						+ "/doesntmatter",
+				defaultCloneDir, null,
+				"IdentityFile " + privateKey1.getAbsolutePath());
+	}
+
+	@Test (expected = TransportException.class)
+	public void testHugePreamble() throws Exception {
+		// Test that the connection fails when the preamble is longer than 64k.
+		StringBuilder b = new StringBuilder();
+		for (int i = 0; i < 1024; i++) {
+			b.append('a');
+		}
+		String line = b.toString();
+		String[] lines = new String[70];
+		for (int i = 0; i < lines.length; i++) {
+			lines[i] = line;
+		}
+		server.setPreamble(lines);
+		cloneWith(
+				"ssh://" + TEST_USER + "@localhost:" + testPort
+						+ "/doesntmatter",
+				defaultCloneDir, null,
+				"IdentityFile " + privateKey1.getAbsolutePath());
+	}
 }
diff --git a/org.eclipse.jgit.ssh.apache/META-INF/MANIFEST.MF b/org.eclipse.jgit.ssh.apache/META-INF/MANIFEST.MF
index 1aecee0..e9f5302 100644
--- a/org.eclipse.jgit.ssh.apache/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.ssh.apache/META-INF/MANIFEST.MF
@@ -3,11 +3,12 @@
 Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.ssh.apache
 Bundle-SymbolicName: org.eclipse.jgit.ssh.apache
-Bundle-Vendor: %Provider-Name
+Bundle-Vendor: %Bundle-Vendor
+Bundle-Localization: plugin
 Bundle-ActivationPolicy: lazy
-Bundle-Version: 5.4.1.qualifier
+Bundle-Version: 5.5.0.qualifier
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
-Export-Package: org.eclipse.jgit.internal.transport.sshd;version="5.4.1";x-internal:=true;
+Export-Package: org.eclipse.jgit.internal.transport.sshd;version="5.5.0";x-internal:=true;
   uses:="org.apache.sshd.client,
    org.apache.sshd.client.auth,
    org.apache.sshd.client.auth.keyboard,
@@ -22,9 +23,9 @@
    org.apache.sshd.common.signature,
    org.apache.sshd.common.util.buffer,
    org.eclipse.jgit.transport",
- org.eclipse.jgit.internal.transport.sshd.auth;version="5.4.1";x-internal:=true,
- org.eclipse.jgit.internal.transport.sshd.proxy;version="5.4.1";x-friends:="org.eclipse.jgit.ssh.apache.test",
- org.eclipse.jgit.transport.sshd;version="5.4.1";
+ org.eclipse.jgit.internal.transport.sshd.auth;version="5.5.0";x-internal:=true,
+ org.eclipse.jgit.internal.transport.sshd.proxy;version="5.5.0";x-friends:="org.eclipse.jgit.ssh.apache.test",
+ org.eclipse.jgit.transport.sshd;version="5.5.0";
   uses:="org.eclipse.jgit.transport,
    org.apache.sshd.client.config.hosts,
    org.apache.sshd.common.keyprovider,
@@ -74,12 +75,12 @@
  org.apache.sshd.common.util.net;version="[2.2.0,2.3.0)",
  org.apache.sshd.common.util.security;version="[2.2.0,2.3.0)",
  org.apache.sshd.server.auth;version="[2.2.0,2.3.0)",
- org.eclipse.jgit.annotations;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.errors;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.fnmatch;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.internal.storage.file;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.internal.transport.ssh;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.nls;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.transport;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.util;version="[5.4.1,5.5.0)",
+ org.eclipse.jgit.annotations;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.errors;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.fnmatch;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.internal.storage.file;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.internal.transport.ssh;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.nls;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.transport;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.util;version="[5.5.0,5.6.0)",
  org.slf4j;version="[1.7.0,2.0.0)"
diff --git a/org.eclipse.jgit.ssh.apache/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.ssh.apache/META-INF/SOURCE-MANIFEST.MF
index deae0d4..4e69a1d 100644
--- a/org.eclipse.jgit.ssh.apache/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.ssh.apache/META-INF/SOURCE-MANIFEST.MF
@@ -3,5 +3,5 @@
 Bundle-Name: org.eclipse.jgit.ssh.apache - Sources
 Bundle-SymbolicName: org.eclipse.jgit.ssh.apache.source
 Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 5.4.1.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit.ssh.apache;version="5.4.1.qualifier";roots="."
+Bundle-Version: 5.5.0.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit.ssh.apache;version="5.5.0.qualifier";roots="."
diff --git a/org.eclipse.jgit.ssh.apache/plugin.properties b/org.eclipse.jgit.ssh.apache/plugin.properties
index 8f3540c..8358cc1 100644
--- a/org.eclipse.jgit.ssh.apache/plugin.properties
+++ b/org.eclipse.jgit.ssh.apache/plugin.properties
@@ -1,2 +1,2 @@
-plugin_name=JGit SSH support based on Apache MINA sshd
-provider_name=Eclipse JGit
+Bundle-Name=JGit SSH support based on Apache MINA sshd
+Bundle-Vendor=Eclipse JGit
diff --git a/org.eclipse.jgit.ssh.apache/pom.xml b/org.eclipse.jgit.ssh.apache/pom.xml
index a7f5bae..9ec2f61 100644
--- a/org.eclipse.jgit.ssh.apache/pom.xml
+++ b/org.eclipse.jgit.ssh.apache/pom.xml
@@ -50,7 +50,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>org.eclipse.jgit-parent</artifactId>
-    <version>5.4.1-SNAPSHOT</version>
+    <version>5.5.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.ssh.apache</artifactId>
diff --git a/org.eclipse.jgit.ssh.apache/resources/org/eclipse/jgit/internal/transport/sshd/SshdText.properties b/org.eclipse.jgit.ssh.apache/resources/org/eclipse/jgit/internal/transport/sshd/SshdText.properties
index bdb4a7d..4f85ebe 100644
--- a/org.eclipse.jgit.ssh.apache/resources/org/eclipse/jgit/internal/transport/sshd/SshdText.properties
+++ b/org.eclipse.jgit.ssh.apache/resources/org/eclipse/jgit/internal/transport/sshd/SshdText.properties
@@ -71,6 +71,9 @@
 proxySocksUnexpectedMessage=Unexpected message received from SOCKS5 proxy {0}; client state {1}: {2}
 proxySocksUnexpectedVersion=Expected SOCKS version 5, got {0}
 proxySocksUsernameTooLong=User name for proxy {0} must be at most 255 bytes long, is {1} bytes: {2}
+serverIdNotReceived=No server identification received within {0} bytes
+serverIdTooLong=Server identification is longer than 255 characters (including line ending): {0}
+serverIdWithNul=Server identification contains a NUL character: {0}
 sessionCloseFailed=Closing the session failed
 sshClosingDown=Apache MINA sshd session factory is closing down; cannot create new ssh sessions on this factory
 sshCommandTimeout={0} timed out after {1} seconds while opening the channel
diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitClientSession.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitClientSession.java
index 56f8ade..4ce4f6a 100644
--- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitClientSession.java
+++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitClientSession.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018, Thomas Wolf <thomas.wolf@paranor.ch>
+ * Copyright (C) 2018, 2019 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
@@ -46,6 +46,7 @@
 
 import java.io.IOException;
 import java.net.SocketAddress;
+import java.nio.charset.StandardCharsets;
 import java.security.GeneralSecurityException;
 import java.security.PublicKey;
 import java.util.ArrayList;
@@ -60,11 +61,13 @@
 import org.apache.sshd.client.keyverifier.ServerKeyVerifier;
 import org.apache.sshd.client.session.ClientSessionImpl;
 import org.apache.sshd.common.FactoryManager;
+import org.apache.sshd.common.PropertyResolverUtils;
 import org.apache.sshd.common.SshException;
 import org.apache.sshd.common.config.keys.KeyUtils;
 import org.apache.sshd.common.io.IoSession;
 import org.apache.sshd.common.io.IoWriteFuture;
 import org.apache.sshd.common.util.Readable;
+import org.apache.sshd.common.util.buffer.Buffer;
 import org.eclipse.jgit.errors.InvalidPatternException;
 import org.eclipse.jgit.fnmatch.FileNameMatcher;
 import org.eclipse.jgit.internal.transport.sshd.proxy.StatefulProxyConnector;
@@ -82,11 +85,20 @@
  */
 public class JGitClientSession extends ClientSessionImpl {
 
+	/**
+	 * Default setting for the maximum number of bytes to read in the initial
+	 * protocol version exchange. 64kb is what OpenSSH < 8.0 read; OpenSSH 8.0
+	 * changed it to 8Mb, but that seems excessive for the purpose stated in RFC
+	 * 4253. The Apache MINA sshd default in
+	 * {@link FactoryManager#DEFAULT_MAX_IDENTIFICATION_SIZE} is 16kb.
+	 */
+	private static final int DEFAULT_MAX_IDENTIFICATION_SIZE = 64 * 1024;
+
 	private HostConfigEntry hostConfig;
 
 	private CredentialsProvider credentialsProvider;
 
-	private StatefulProxyConnector proxyHandler;
+	private volatile StatefulProxyConnector proxyHandler;
 
 	/**
 	 * @param manager
@@ -332,4 +344,123 @@
 		return newNames;
 	}
 
+	@Override
+	protected boolean readIdentification(Buffer buffer) throws IOException {
+		// Propagate a failure from doReadIdentification.
+		// TODO: remove for sshd > 2.3.0; its doReadIdentification throws
+		// StreamCorruptedException instead of IllegalStateException.
+		try {
+			return super.readIdentification(buffer);
+		} catch (IllegalStateException e) {
+			throw new IOException(e.getLocalizedMessage(), e);
+		}
+	}
+
+	/**
+	 * Reads the RFC 4253, section 4.2 protocol version identification. The
+	 * Apache MINA sshd default implementation checks for NUL bytes also in any
+	 * preceding lines, whereas RFC 4253 requires such a check only for the
+	 * actual identification string starting with "SSH-". Likewise, the 255
+	 * character limit exists only for the identification string, not for the
+	 * preceding lines. CR-LF handling is also relaxed.
+	 *
+	 * @param buffer
+	 *            to read from
+	 * @param server
+	 *            whether we're an SSH server (should always be {@code false})
+	 * @return the lines read, with the server identification line last, or
+	 *         {@code null} if no identification line was found and more bytes
+	 *         are needed
+	 *
+	 * @see <a href="https://tools.ietf.org/html/rfc4253#section-4.2">RFC 4253,
+	 *      section 4.2</a>
+	 */
+	@Override
+	protected List<String> doReadIdentification(Buffer buffer, boolean server) {
+		if (server) {
+			// Should never happen. No translation; internal bug.
+			throw new IllegalStateException(
+					"doReadIdentification of client called with server=true"); //$NON-NLS-1$
+		}
+		int maxIdentSize = PropertyResolverUtils.getIntProperty(this,
+				FactoryManager.MAX_IDENTIFICATION_SIZE,
+				DEFAULT_MAX_IDENTIFICATION_SIZE);
+		int current = buffer.rpos();
+		int end = current + buffer.available();
+		if (current >= end) {
+			return null;
+		}
+		byte[] raw = buffer.array();
+		List<String> ident = new ArrayList<>();
+		int start = current;
+		boolean hasNul = false;
+		for (int i = current; i < end; i++) {
+			switch (raw[i]) {
+			case 0:
+				hasNul = true;
+				break;
+			case '\n':
+				int eol = 1;
+				if (i > start && raw[i - 1] == '\r') {
+					eol++;
+				}
+				String line = new String(raw, start, i + 1 - eol - start,
+						StandardCharsets.UTF_8);
+				start = i + 1;
+				if (log.isDebugEnabled()) {
+					log.debug(format("doReadIdentification({0}) line: ", this) + //$NON-NLS-1$
+							escapeControls(line));
+				}
+				ident.add(line);
+				if (line.startsWith("SSH-")) { //$NON-NLS-1$
+					if (hasNul) {
+						throw new IllegalStateException(
+								format(SshdText.get().serverIdWithNul,
+										escapeControls(line)));
+					}
+					if (line.length() + eol > 255) {
+						throw new IllegalStateException(
+								format(SshdText.get().serverIdTooLong,
+										escapeControls(line)));
+					}
+					buffer.rpos(start);
+					return ident;
+				}
+				// If this were a server, we could throw an exception here: a
+				// client is not supposed to send any extra lines before its
+				// identification string.
+				hasNul = false;
+				break;
+			default:
+				break;
+			}
+			if (i - current + 1 >= maxIdentSize) {
+				String msg = format(SshdText.get().serverIdNotReceived,
+						Integer.toString(maxIdentSize));
+				if (log.isDebugEnabled()) {
+					log.debug(msg);
+					log.debug(buffer.toHex());
+				}
+				throw new IllegalStateException(msg);
+			}
+		}
+		// Need more data
+		return null;
+	}
+
+	private static String escapeControls(String s) {
+		StringBuilder b = new StringBuilder();
+		int l = s.length();
+		for (int i = 0; i < l; i++) {
+			char ch = s.charAt(i);
+			if (Character.isISOControl(ch)) {
+				b.append(ch <= 0xF ? "\\u000" : "\\u00") //$NON-NLS-1$ //$NON-NLS-2$
+						.append(Integer.toHexString(ch));
+			} else {
+				b.append(ch);
+			}
+		}
+		return b.toString();
+	}
+
 }
diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/SshdText.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/SshdText.java
index bf432be..f67170e 100644
--- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/SshdText.java
+++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/SshdText.java
@@ -83,6 +83,9 @@
 	/***/ public String proxySocksUnexpectedMessage;
 	/***/ public String proxySocksUnexpectedVersion;
 	/***/ public String proxySocksUsernameTooLong;
+	/***/ public String serverIdNotReceived;
+	/***/ public String serverIdTooLong;
+	/***/ public String serverIdWithNul;
 	/***/ public String sessionCloseFailed;
 	/***/ public String sshClosingDown;
 	/***/ public String sshCommandTimeout;
diff --git a/org.eclipse.jgit.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.test/META-INF/MANIFEST.MF
index e92d6a7..53b79b0 100644
--- a/org.eclipse.jgit.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.test/META-INF/MANIFEST.MF
@@ -1,11 +1,11 @@
 Manifest-Version: 1.0
 Bundle-ManifestVersion: 2
-Bundle-Name: %plugin_name
+Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.test
 Bundle-SymbolicName: org.eclipse.jgit.test
-Bundle-Version: 5.4.1.qualifier
+Bundle-Version: 5.5.0.qualifier
 Bundle-Localization: plugin
-Bundle-Vendor: %provider_name
+Bundle-Vendor: %Bundle-Vendor
 Bundle-ActivationPolicy: lazy
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
 Import-Package: com.googlecode.javaewah;version="[1.1.6,2.0.0)",
@@ -18,57 +18,57 @@
  org.apache.commons.compress.compressors.gzip;version="[1.15.0,2.0)",
  org.apache.commons.compress.compressors.xz;version="[1.15.0,2.0)",
  org.bouncycastle.util.encoders;version="[1.61.0,2.0.0)",
- org.eclipse.jgit.annotations;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.api;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.api.errors;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.archive;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.attributes;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.awtui;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.blame;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.diff;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.dircache;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.errors;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.events;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.fnmatch;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.gitrepo;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.hooks;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.ignore;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.ignore.internal;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.internal;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.internal.fsck;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.internal.storage.dfs;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.internal.storage.file;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.internal.storage.io;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.internal.storage.pack;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.internal.storage.reftable;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.internal.storage.reftree;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.internal.transport.http;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.internal.transport.parser;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.junit;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.junit.ssh;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.junit.time;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.lfs;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.lib;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.merge;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.nls;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.notes;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.patch;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.pgm;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.pgm.internal;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.revplot;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.revwalk;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.revwalk.filter;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.storage.file;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.storage.pack;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.submodule;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.transport;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.transport.http;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.transport.resolver;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.treewalk;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.treewalk.filter;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.util;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.util.io;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.util.sha1;version="[5.4.1,5.5.0)",
+ org.eclipse.jgit.annotations;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.api;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.api.errors;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.archive;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.attributes;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.awtui;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.blame;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.diff;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.dircache;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.errors;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.events;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.fnmatch;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.gitrepo;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.hooks;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.ignore;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.ignore.internal;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.internal;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.internal.fsck;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.internal.storage.dfs;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.internal.storage.file;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.internal.storage.io;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.internal.storage.pack;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.internal.storage.reftable;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.internal.storage.reftree;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.internal.transport.http;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.internal.transport.parser;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.junit;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.junit.ssh;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.junit.time;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.lfs;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.lib;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.merge;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.nls;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.notes;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.patch;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.pgm;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.pgm.internal;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.revplot;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.revwalk;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.revwalk.filter;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.storage.file;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.storage.pack;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.submodule;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.transport;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.transport.http;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.transport.resolver;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.treewalk;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.treewalk.filter;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.util;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.util.io;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.util.sha1;version="[5.5.0,5.6.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)",
@@ -83,4 +83,4 @@
  org.tukaani.xz;version="[1.6.0,2.0)"
 Require-Bundle: org.hamcrest.core;bundle-version="[1.1.0,2.0.0)",
  org.hamcrest.library;bundle-version="[1.1.0,2.0.0)"
-Export-Package: org.eclipse.jgit.transport.ssh;version="5.4.1";x-friends:="org.eclipse.jgit.ssh.apache.test"
+Export-Package: org.eclipse.jgit.transport.ssh;version="5.5.0";x-friends:="org.eclipse.jgit.ssh.apache.test"
diff --git a/org.eclipse.jgit.test/plugin.properties b/org.eclipse.jgit.test/plugin.properties
index 1d32644..4e353cd 100644
--- a/org.eclipse.jgit.test/plugin.properties
+++ b/org.eclipse.jgit.test/plugin.properties
@@ -1,2 +1,2 @@
-plugin_name=JGit Core Tests
-provider_name=Eclipse JGit
+Bundle-Name=JGit Core Tests
+Bundle-Vendor=Eclipse JGit
diff --git a/org.eclipse.jgit.test/pom.xml b/org.eclipse.jgit.test/pom.xml
index 19ce890..5e8a3e6 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.4.1-SNAPSHOT</version>
+    <version>5.5.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.test</artifactId>
@@ -101,7 +101,7 @@
     <dependency>
       <groupId>org.mockito</groupId>
       <artifactId>mockito-core</artifactId>
-      <version>2.13.0</version>
+      <version>2.23.0</version>
     </dependency>
 
     <dependency>
diff --git a/org.eclipse.jgit.test/src/org/eclipse/jgit/lib/MoreAsserts.java b/org.eclipse.jgit.test/src/org/eclipse/jgit/lib/MoreAsserts.java
new file mode 100644
index 0000000..5945e7e
--- /dev/null
+++ b/org.eclipse.jgit.test/src/org/eclipse/jgit/lib/MoreAsserts.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2019, 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.lib;
+
+/** Assertion methods. */
+public class MoreAsserts {
+	/**
+	 * Simple version of assertThrows that will be introduced in JUnit 4.13.
+	 *
+	 * @param expected
+	 *            Expected throwable class
+	 * @param r
+	 *            Runnable that is expected to throw an exception.
+	 * @return The thrown exception.
+	 */
+	public static <T extends Throwable> T assertThrows(Class<T> expected,
+			ThrowingRunnable r) {
+		try {
+			r.run();
+		} catch (Throwable actual) {
+			if (expected.isAssignableFrom(actual.getClass())) {
+				@SuppressWarnings("unchecked")
+				T toReturn = (T) actual;
+				return toReturn;
+			}
+			throw new AssertionError("Expected " + expected.getSimpleName()
+					+ ", but got " + actual.getClass().getSimpleName(), actual);
+		}
+		throw new AssertionError(
+				"Expected " + expected.getSimpleName() + " to be thrown");
+	}
+
+	public interface ThrowingRunnable {
+		void run() throws Throwable;
+	}
+
+	private MoreAsserts() {
+	}
+}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/ResetCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/ResetCommandTest.java
index dd7230b..563b32d 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/ResetCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/ResetCommandTest.java
@@ -194,6 +194,42 @@
 	}
 
 	@Test
+	public void testHardResetWithConflicts_CreateFolder_UnstagedChanges() throws Exception {
+		setupRepository();
+
+		writeTrashFile("dir-or-file/c.txt", "content");
+		git.add().addFilepattern("dir-or-file/c.txt").call();
+		git.commit().setMessage("adding dir-or-file/c.txt").call();
+
+		FileUtils.delete(new File(db.getWorkTree(), "dir-or-file"), FileUtils.RECURSIVE);
+		writeTrashFile("dir-or-file", "content");
+
+		// bug 479266: cannot create folder "dir-or-file"
+		git.reset().setMode(ResetType.HARD).setRef(Constants.HEAD).call();
+		assertTrue(new File(db.getWorkTree(), "dir-or-file/c.txt").exists());
+	}
+
+	@Test
+	public void testHardResetWithConflicts_DeleteFolder_UnstagedChanges() throws Exception {
+		setupRepository();
+		ObjectId prevHead = db.resolve(Constants.HEAD);
+
+		writeTrashFile("dir-or-file/c.txt", "content");
+		git.add().addFilepattern("dir-or-file/c.txt").call();
+		git.commit().setMessage("adding dir-or-file/c.txt").call();
+
+		writeTrashFile("dir-or-file-2/d.txt", "content");
+		git.add().addFilepattern("dir-or-file-2/d.txt").call();
+		FileUtils.delete(new File(db.getWorkTree(), "dir-or-file-2"), FileUtils.RECURSIVE);
+		writeTrashFile("dir-or-file-2", "content");
+
+		// bug 479266: cannot delete folder "dir-or-file"
+		git.reset().setMode(ResetType.HARD).setRef(prevHead.getName()).call();
+		assertFalse(new File(db.getWorkTree(), "dir-or-file").exists());
+		assertFalse(new File(db.getWorkTree(), "dir-or-file-2").exists());
+	}
+
+	@Test
 	public void testResetToNonexistingHEAD() throws JGitInternalException,
 			AmbiguousObjectException, IOException, GitAPIException {
 
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/AlternatesTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/AlternatesTest.java
index b09db03..2306e0b 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/AlternatesTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/AlternatesTest.java
@@ -42,6 +42,7 @@
  */
 package org.eclipse.jgit.internal.storage.file;
 
+import static org.eclipse.jgit.lib.Constants.INFO_ALTERNATES;
 import static org.junit.Assert.assertTrue;
 
 import java.io.File;
@@ -76,7 +77,7 @@
 	private void setAlternate(FileRepository from, FileRepository to)
 			throws IOException {
 		File alt = new File(from.getObjectDatabase().getDirectory(),
-				"info/alternates");
+				INFO_ALTERNATES);
 		alt.getParentFile().mkdirs();
 		File fromDir = from.getObjectDatabase().getDirectory();
 		File toDir = to.getObjectDatabase().getDirectory();
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackWriterTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackWriterTest.java
index 5d0a7e2..1e2341b 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackWriterTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackWriterTest.java
@@ -44,6 +44,7 @@
 package org.eclipse.jgit.internal.storage.file;
 
 import static org.eclipse.jgit.internal.storage.pack.PackWriter.NONE;
+import static org.eclipse.jgit.lib.Constants.INFO_ALTERNATES;
 import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -138,7 +139,7 @@
 		config = new PackConfig(db);
 
 		dst = createBareRepository();
-		File alt = new File(dst.getObjectDatabase().getDirectory(), "info/alternates");
+		File alt = new File(dst.getObjectDatabase().getDirectory(), INFO_ALTERNATES);
 		alt.getParentFile().mkdirs();
 		write(alt, db.getObjectDatabase().getDirectory().getAbsolutePath() + "\n");
 	}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/T0003_BasicTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/T0003_BasicTest.java
index e2887d9..43f30d8 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/T0003_BasicTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/T0003_BasicTest.java
@@ -98,7 +98,7 @@
 	public void test001_Initalize() {
 		final File gitdir = new File(trash, Constants.DOT_GIT);
 		final File hooks = new File(gitdir, "hooks");
-		final File objects = new File(gitdir, "objects");
+		final File objects = new File(gitdir, Constants.OBJECTS);
 		final File objects_pack = new File(objects, "pack");
 		final File objects_info = new File(objects, "info");
 		final File refs = new File(gitdir, "refs");
@@ -150,7 +150,7 @@
 		assertEqualsPath(theDir, r.getDirectory());
 		assertEqualsPath(repo1Parent, r.getWorkTree());
 		assertEqualsPath(new File(theDir, "index"), r.getIndexFile());
-		assertEqualsPath(new File(theDir, "objects"), r.getObjectDatabase()
+		assertEqualsPath(new File(theDir, Constants.OBJECTS), r.getObjectDatabase()
 				.getDirectory());
 	}
 
@@ -176,7 +176,7 @@
 		assertEqualsPath(theDir, r.getDirectory());
 		assertEqualsPath(repo1Parent.getParentFile(), r.getWorkTree());
 		assertEqualsPath(new File(theDir, "index"), r.getIndexFile());
-		assertEqualsPath(new File(theDir, "objects"), r.getObjectDatabase()
+		assertEqualsPath(new File(theDir, Constants.OBJECTS), r.getObjectDatabase()
 				.getDirectory());
 	}
 
@@ -200,7 +200,7 @@
 		assertEqualsPath(theDir, r.getDirectory());
 		assertEqualsPath(repo1Parent, r.getWorkTree());
 		assertEqualsPath(new File(theDir, "index"), r.getIndexFile());
-		assertEqualsPath(new File(theDir, "objects"), r.getObjectDatabase()
+		assertEqualsPath(new File(theDir, Constants.OBJECTS), r.getObjectDatabase()
 				.getDirectory());
 	}
 
@@ -229,7 +229,7 @@
 		assertEqualsPath(theDir, r.getDirectory());
 		assertEqualsPath(workdir, r.getWorkTree());
 		assertEqualsPath(new File(theDir, "index"), r.getIndexFile());
-		assertEqualsPath(new File(theDir, "objects"), r.getObjectDatabase()
+		assertEqualsPath(new File(theDir, Constants.OBJECTS), r.getObjectDatabase()
 				.getDirectory());
 	}
 
@@ -258,7 +258,7 @@
 		assertEqualsPath(theDir, r.getDirectory());
 		assertEqualsPath(workdir, r.getWorkTree());
 		assertEqualsPath(new File(theDir, "index"), r.getIndexFile());
-		assertEqualsPath(new File(theDir, "objects"), r.getObjectDatabase()
+		assertEqualsPath(new File(theDir, Constants.OBJECTS), r.getObjectDatabase()
 				.getDirectory());
 	}
 
@@ -314,7 +314,7 @@
 		}
 
 		final File o = new File(new File(new File(newdb.getDirectory(),
-				"objects"), "4b"), "825dc642cb6eb9a060e54bf8d69288fbee4904");
+				Constants.OBJECTS), "4b"), "825dc642cb6eb9a060e54bf8d69288fbee4904");
 		assertTrue("Exists " + o, o.isFile());
 		assertTrue("Read-only " + o, !o.canWrite());
 	}
@@ -326,7 +326,7 @@
 		final ObjectId treeId = insertTree(new TreeFormatter());
 		assertEquals("4b825dc642cb6eb9a060e54bf8d69288fbee4904", treeId.name());
 		final File o = new File(new File(
-				new File(db.getDirectory(), "objects"), "4b"),
+				new File(db.getDirectory(), Constants.OBJECTS), "4b"),
 				"825dc642cb6eb9a060e54bf8d69288fbee4904");
 		assertFalse("Exists " + o, o.isFile());
 	}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/DirCacheCheckoutTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/DirCacheCheckoutTest.java
index 483051c..8092c31 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/DirCacheCheckoutTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/DirCacheCheckoutTest.java
@@ -1977,6 +1977,29 @@
 		}
 	}
 
+	@Test
+	public void testCheckoutWithEmptyIndexDoesntOverwrite() throws Exception {
+		try (Git git = new Git(db);
+				TestRepository<Repository> db_t = new TestRepository<>(db)) {
+			// prepare the commits
+			BranchBuilder master = db_t.branch("master");
+			RevCommit mergeCommit = master.commit()
+					.add("p/x", "headContent")
+					.message("m0").create();
+			master.commit().add("p/x", "headContent").message("m1").create();
+			git.checkout().setName("master").call();
+
+			// empty index and write unsaved data in 'p'
+			git.rm().addFilepattern("p").call();
+			writeTrashFile("p", "important data");
+
+			git.checkout().setName(mergeCommit.getName()).call();
+
+			assertEquals("", indexState(CONTENT));
+			assertEquals("important data", read("p"));
+		}
+	}
+
 	private static class TestFileTreeIterator extends FileTreeIterator {
 
 		// For assertions only
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RebaseTodoFileTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RebaseTodoFileTest.java
index 5cfc75c..3d3c697 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RebaseTodoFileTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RebaseTodoFileTest.java
@@ -68,7 +68,7 @@
 	@Test
 	public void testReadTodoFile() throws Exception {
 		String[] expected = { "reword " + ObjectId.zeroId().name() + " Foo",
-				"# A comment in the the todo list",
+				"# A comment in the todo list",
 				"pick " + ObjectId.zeroId().name() + " Foo fie",
 				"squash " + ObjectId.zeroId().name() + " F",
 				"fixup " + ObjectId.zeroId().name(),
@@ -93,7 +93,7 @@
 				assertEquals("Expected COMMENT", RebaseTodoLine.Action.COMMENT,
 						line.getAction());
 				assertEquals("Unexpected Message",
-						"# A comment in the the todo list",
+						"# A comment in the todo list",
 						line.getComment());
 				break;
 			case 2:
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/FirstParentRevWalkTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/FirstParentRevWalkTest.java
new file mode 100644
index 0000000..474ff7a
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/FirstParentRevWalkTest.java
@@ -0,0 +1,338 @@
+/*
+ * Copyright (C) 2019, 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.revwalk;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import org.eclipse.jgit.revwalk.filter.MessageRevFilter;
+import org.eclipse.jgit.revwalk.filter.RevFilter;
+import org.junit.Test;
+
+public class FirstParentRevWalkTest extends RevWalkTestCase {
+	@Test
+	public void testStringOfPearls() throws Exception {
+		RevCommit a = commit();
+		RevCommit b = commit(a);
+		RevCommit c = commit(b);
+
+		rw.reset();
+		rw.setFirstParent(true);
+		markStart(c);
+		assertCommit(c, rw.next());
+		assertCommit(b, rw.next());
+		assertCommit(a, rw.next());
+		assertNull(rw.next());
+	}
+
+	@Test
+	public void testSideBranch() throws Exception {
+		RevCommit a = commit();
+		RevCommit b1 = commit(a);
+		RevCommit b2 = commit(a);
+		RevCommit c1 = commit(b1);
+		RevCommit c2 = commit(b2);
+		RevCommit d = commit(c1, c2);
+
+		rw.reset();
+		rw.setFirstParent(true);
+		markStart(d);
+		assertCommit(d, rw.next());
+		assertCommit(c1, rw.next());
+		assertCommit(b1, rw.next());
+		assertCommit(a, rw.next());
+		assertNull(rw.next());
+	}
+
+	@Test
+	public void testSecondParentAncestorOfFirstParent() throws Exception {
+		RevCommit a = commit();
+		RevCommit b = commit(a);
+		RevCommit c = commit(b, a);
+
+		rw.reset();
+		rw.setFirstParent(true);
+		markStart(c);
+		assertCommit(c, rw.next());
+		assertCommit(b, rw.next());
+		assertCommit(a, rw.next());
+		assertNull(rw.next());
+	}
+
+	@Test
+	public void testFirstParentMultipleOccurrences() throws Exception {
+		RevCommit a = commit();
+		RevCommit b = commit(a);
+		RevCommit c = commit(b);
+		RevCommit d = commit(b);
+
+		rw.reset();
+		rw.setFirstParent(true);
+		markStart(c);
+		markStart(d);
+		assertCommit(d, rw.next());
+		assertCommit(c, rw.next());
+		assertCommit(b, rw.next());
+		assertCommit(a, rw.next());
+		assertNull(rw.next());
+	}
+
+	@Test
+	public void testReachableAlongFirstAndLaterParents() throws Exception {
+		RevCommit a = commit();
+		RevCommit b1 = commit(a);
+		RevCommit b2 = commit(a);
+		RevCommit b3 = commit(a);
+		RevCommit c = commit(b1, b2);
+		RevCommit d = commit(b2, b3);
+
+		rw.reset();
+		rw.setFirstParent(true);
+		markStart(c);
+		markStart(d);
+		assertCommit(d, rw.next());
+		assertCommit(c, rw.next());
+		// b3 is only reachable from c's second parent.
+		// b2 is reachable from c's second parent but d's first parent.
+		assertCommit(b2, rw.next());
+		assertCommit(b1, rw.next());
+		assertCommit(a, rw.next());
+		assertNull(rw.next());
+	}
+
+	@Test
+	public void testStartCommitReachableOnlyFromLaterParents()
+			throws Exception {
+		RevCommit a = commit();
+		RevCommit b1 = commit(a);
+		RevCommit b2 = commit(a);
+		RevCommit c = commit(b1, b2);
+
+		rw.reset();
+		rw.setFirstParent(true);
+		markStart(c);
+		markStart(b2);
+		assertCommit(c, rw.next());
+		// b2 is only reachable from second parent, but is itself a start
+		// commit.
+		assertCommit(b2, rw.next());
+		assertCommit(b1, rw.next());
+		assertCommit(a, rw.next());
+		assertNull(rw.next());
+	}
+
+	@Test
+	public void testRevFilter() throws Exception {
+		RevCommit a = commit();
+		RevCommit b1 = commitBuilder().parent(a).message("commit b1").create();
+		RevCommit b2 = commitBuilder().parent(a).message("commit b2").create();
+		RevCommit c = commit(b1, b2);
+
+		rw.reset();
+		rw.setFirstParent(true);
+		rw.setRevFilter(MessageRevFilter.create("commit b"));
+		rw.markStart(c);
+		assertCommit(b1, rw.next());
+		assertNull(rw.next());
+	}
+
+	@Test
+	public void testTopoSort() throws Exception {
+		RevCommit a = commit();
+		RevCommit b1 = commit(a);
+		RevCommit b2 = commit(a);
+		RevCommit c = commit(b1, b2);
+
+		rw.reset();
+		rw.sort(RevSort.TOPO);
+		rw.setFirstParent(true);
+		markStart(c);
+		assertCommit(c, rw.next());
+		assertCommit(b1, rw.next());
+		assertCommit(a, rw.next());
+		assertNull(rw.next());
+	}
+
+	@Test
+	public void testCommitTimeSort() throws Exception {
+		RevCommit a = commit();
+		RevCommit b1 = commit(a);
+		RevCommit b2 = commit(a);
+		RevCommit c = commit(b1, b2);
+
+		rw.reset();
+		rw.sort(RevSort.COMMIT_TIME_DESC);
+		rw.setFirstParent(true);
+		markStart(c);
+		assertCommit(c, rw.next());
+		assertCommit(b1, rw.next());
+		assertCommit(a, rw.next());
+		assertNull(rw.next());
+	}
+
+	@Test
+	public void testReverseSort() throws Exception {
+		RevCommit a = commit();
+		RevCommit b1 = commit(a);
+		RevCommit b2 = commit(a);
+		RevCommit c = commit(b1, b2);
+
+		rw.reset();
+		rw.sort(RevSort.REVERSE);
+		rw.setFirstParent(true);
+		markStart(c);
+		assertCommit(a, rw.next());
+		assertCommit(b1, rw.next());
+		assertCommit(c, rw.next());
+		assertNull(rw.next());
+	}
+
+	@Test
+	public void testBoundarySort() throws Exception {
+		RevCommit a = commit();
+		RevCommit b = commit(a);
+		RevCommit c1 = commit(b);
+		RevCommit c2 = commit(b);
+		RevCommit d = commit(c1, c2);
+
+		rw.reset();
+		rw.sort(RevSort.BOUNDARY);
+		rw.setFirstParent(true);
+		markStart(d);
+		markUninteresting(a);
+		assertCommit(d, rw.next());
+		assertCommit(c1, rw.next());
+		assertCommit(b, rw.next());
+		assertCommit(a, rw.next());
+		assertNull(rw.next());
+	}
+
+	@Test
+	public void testFirstParentOfFirstParentMarkedUninteresting()
+			throws Exception {
+		RevCommit a = commit();
+		RevCommit b1 = commit(a);
+		RevCommit b2 = commit(a);
+		RevCommit c1 = commit(b1);
+		RevCommit c2 = commit(b2);
+		RevCommit d = commit(c1, c2);
+
+		rw.reset();
+		rw.setFirstParent(true);
+		markStart(d);
+		markUninteresting(b1);
+		assertCommit(d, rw.next());
+		assertCommit(c1, rw.next());
+		assertNull(rw.next());
+	}
+
+	@Test
+	public void testFirstParentMarkedUninteresting() throws Exception {
+		RevCommit a = commit();
+		RevCommit b1 = commit(a);
+		RevCommit b2 = commit(a);
+		RevCommit c = commit(b1, b2);
+
+		rw.reset();
+		rw.setFirstParent(true);
+		markStart(c);
+		markUninteresting(b1);
+		assertCommit(c, rw.next());
+		assertNull(rw.next());
+	}
+
+	@Test
+	public void testDepthWalk() throws Exception {
+		RevCommit a = commit();
+		RevCommit b1 = commit(a);
+		RevCommit b2 = commit(a);
+		RevCommit c = commit(b1, b2);
+
+		try (DepthWalk.RevWalk dw = new DepthWalk.RevWalk(db, 1)) {
+			dw.setFirstParent(true);
+			dw.markRoot(dw.parseCommit(c));
+			dw.markStart(dw.parseCommit(c));
+			assertEquals(c, dw.next());
+			assertEquals(b1, dw.next());
+			assertNull(dw.next());
+		}
+	}
+
+	@Test
+	public void testDoNotRewriteParents() throws Exception {
+		RevCommit a = commit();
+		RevCommit b1 = commit(a);
+		RevCommit b2 = commit(a);
+		RevCommit c = commit(b1, b2);
+
+		rw.reset();
+		rw.setFirstParent(true);
+		rw.setRewriteParents(false);
+		markStart(c);
+		assertCommit(c, rw.next());
+		assertCommit(b1, rw.next());
+		assertCommit(a, rw.next());
+		assertNull(rw.next());
+	}
+
+	@Test(expected = IllegalStateException.class)
+	public void testMarkStartBeforeSetFirstParent() throws Exception {
+		RevCommit a = commit();
+
+		rw.reset();
+		markStart(a);
+		rw.setFirstParent(true);
+	}
+
+	@Test(expected = IllegalStateException.class)
+	public void testMergeBaseWithFirstParentNotAllowed() throws Exception {
+		RevCommit a = commit();
+
+		rw.reset();
+		rw.setFirstParent(true);
+		rw.setRevFilter(RevFilter.MERGE_BASE);
+		markStart(a);
+		assertNull(rw.next());
+	}
+}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PostUploadHookChainTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PostUploadHookChainTest.java
new file mode 100644
index 0000000..ea7e8ed
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PostUploadHookChainTest.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2019, 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Arrays;
+
+import org.eclipse.jgit.storage.pack.PackStatistics;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class PostUploadHookChainTest {
+
+	@Test
+	public void testDefaultIfEmpty() {
+		PostUploadHook[] noHooks = {};
+		PostUploadHook newChain = PostUploadHookChain
+				.newChain(Arrays.asList(noHooks));
+		assertEquals(newChain, PostUploadHook.NULL);
+	}
+
+	@Test
+	public void testFlattenChainIfOnlyOne() {
+		FakePostUploadHook hook1 = new FakePostUploadHook();
+		PostUploadHook newChain = PostUploadHookChain
+				.newChain(Arrays.asList(PostUploadHook.NULL, hook1));
+		assertEquals(newChain, hook1);
+	}
+
+	@Test
+	public void testMultipleHooks() {
+		FakePostUploadHook hook1 = new FakePostUploadHook();
+		FakePostUploadHook hook2 = new FakePostUploadHook();
+
+		PostUploadHook chained = PostUploadHookChain
+				.newChain(Arrays.asList(hook1, hook2));
+		chained.onPostUpload(null);
+
+		assertTrue(hook1.wasInvoked());
+		assertTrue(hook2.wasInvoked());
+	}
+
+	private static final class FakePostUploadHook implements PostUploadHook {
+		boolean invoked;
+
+		public boolean wasInvoked() {
+			return invoked;
+		}
+
+		@Override
+		public void onPostUpload(PackStatistics stats) {
+			invoked = true;
+		}
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PreUploadHookChainTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PreUploadHookChainTest.java
new file mode 100644
index 0000000..2a36d8a
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PreUploadHookChainTest.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2019, 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.eclipse.jgit.lib.ObjectId;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class PreUploadHookChainTest {
+
+	@Test
+	public void testDefaultIfEmpty() {
+		PreUploadHook[] noHooks = {};
+		PreUploadHook newChain = PreUploadHookChain
+				.newChain(Arrays.asList(noHooks));
+		assertEquals(newChain, PreUploadHook.NULL);
+	}
+
+	@Test
+	public void testFlattenChainIfOnlyOne() {
+		FakePreUploadHook hook1 = new FakePreUploadHook();
+		PreUploadHook newChain = PreUploadHookChain
+				.newChain(Arrays.asList(PreUploadHook.NULL, hook1));
+		assertEquals(newChain, hook1);
+	}
+
+	@Test
+	public void testMultipleHooks() throws ServiceMayNotContinueException {
+		FakePreUploadHook hook1 = new FakePreUploadHook();
+		FakePreUploadHook hook2 = new FakePreUploadHook();
+
+		PreUploadHook chained = PreUploadHookChain
+				.newChain(Arrays.asList(hook1, hook2));
+		chained.onBeginNegotiateRound(null, null, 0);
+
+		assertTrue(hook1.wasInvoked());
+		assertTrue(hook2.wasInvoked());
+	}
+
+	private static final class FakePreUploadHook implements PreUploadHook {
+		boolean invoked;
+
+		@Override
+		public void onBeginNegotiateRound(UploadPack up,
+				Collection<? extends ObjectId> wants, int cntOffered)
+				throws ServiceMayNotContinueException {
+			invoked = true;
+		}
+
+		@Override
+		public void onEndNegotiateRound(UploadPack up,
+				Collection<? extends ObjectId> wants, int cntCommon,
+				int cntNotFound, boolean ready)
+				throws ServiceMayNotContinueException {
+			throw new UnsupportedOperationException();
+		}
+
+		@Override
+		public void onSendPack(UploadPack up,
+				Collection<? extends ObjectId> wants,
+				Collection<? extends ObjectId> haves)
+				throws ServiceMayNotContinueException {
+			throw new UnsupportedOperationException();
+		}
+
+		public boolean wasInvoked() {
+			return invoked;
+		}
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ProtocolV2HookChainTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ProtocolV2HookChainTest.java
new file mode 100644
index 0000000..8fb1ca8
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ProtocolV2HookChainTest.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2019, 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Arrays;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class ProtocolV2HookChainTest {
+
+	@Test
+	public void testDefaultIfEmpty() {
+		ProtocolV2Hook[] noHooks = {};
+		ProtocolV2Hook newChain = ProtocolV2HookChain
+				.newChain(Arrays.asList(noHooks));
+		assertEquals(newChain, ProtocolV2Hook.DEFAULT);
+	}
+
+	@Test
+	public void testFlattenChainIfOnlyOne() {
+		FakeProtocolV2Hook hook1 = new FakeProtocolV2Hook();
+		ProtocolV2Hook newChain = ProtocolV2HookChain
+				.newChain(Arrays.asList(ProtocolV2Hook.DEFAULT, hook1));
+		assertEquals(newChain, hook1);
+	}
+
+	@Test
+	public void testMultipleHooks() throws ServiceMayNotContinueException {
+		FakeProtocolV2Hook hook1 = new FakeProtocolV2Hook();
+		FakeProtocolV2Hook hook2 = new FakeProtocolV2Hook();
+
+		ProtocolV2Hook chained = ProtocolV2HookChain
+				.newChain(Arrays.asList(hook1, hook2));
+		chained.onLsRefs(LsRefsV2Request.builder().build());
+
+		assertTrue(hook1.wasInvoked());
+		assertTrue(hook2.wasInvoked());
+	}
+
+	private static final class FakeProtocolV2Hook implements ProtocolV2Hook {
+		boolean invoked;
+
+		@Override
+		public void onLsRefs(LsRefsV2Request req)
+				throws ServiceMayNotContinueException {
+			invoked = true;
+		}
+
+		@Override
+		public void onCapabilities(CapabilitiesV2Request req)
+				throws ServiceMayNotContinueException {
+			throw new UnsupportedOperationException();
+		}
+
+		@Override
+		public void onFetch(FetchV2Request req)
+				throws ServiceMayNotContinueException {
+			throw new UnsupportedOperationException();
+		}
+
+		public boolean wasInvoked() {
+			return invoked;
+		}
+	}
+}
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 260130b..22c67c1 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,5 +1,7 @@
 package org.eclipse.jgit.transport;
 
+import static org.eclipse.jgit.lib.MoreAsserts.assertThrows;
+import static org.hamcrest.Matchers.containsInAnyOrder;
 import static org.hamcrest.Matchers.containsString;
 import static org.hamcrest.Matchers.hasItems;
 import static org.hamcrest.Matchers.is;
@@ -9,27 +11,30 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.StringWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
+import java.util.function.Consumer;
 
 import org.eclipse.jgit.dircache.DirCache;
 import org.eclipse.jgit.dircache.DirCacheBuilder;
 import org.eclipse.jgit.dircache.DirCacheEntry;
-import org.eclipse.jgit.errors.PackProtocolException;
 import org.eclipse.jgit.errors.TransportException;
 import org.eclipse.jgit.internal.storage.dfs.DfsGarbageCollector;
 import org.eclipse.jgit.internal.storage.dfs.DfsRepositoryDescription;
 import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
+import org.eclipse.jgit.internal.storage.file.PackLock;
 import org.eclipse.jgit.junit.TestRepository;
 import org.eclipse.jgit.lib.NullProgressMonitor;
 import org.eclipse.jgit.lib.ObjectId;
@@ -47,25 +52,19 @@
 import org.eclipse.jgit.storage.pack.PackStatistics;
 import org.eclipse.jgit.transport.UploadPack.RequestPolicy;
 import org.eclipse.jgit.util.io.NullOutputStream;
-import org.hamcrest.Matchers;
 import org.junit.After;
 import org.junit.Before;
-import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.ExpectedException;
 
 /**
  * Tests for server upload-pack utilities.
  */
 public class UploadPackTest {
-	@Rule
-	public ExpectedException thrown = ExpectedException.none();
-
 	private URIish uri;
 
 	private TestProtocol<Object> testProtocol;
 
-	private Object ctx = new Object();
+	private final Object ctx = new Object();
 
 	private InMemoryRepository server;
 
@@ -144,11 +143,11 @@
 		assertFalse(client.getObjectDatabase().has(blob.toObjectId()));
 
 		try (Transport tn = testProtocol.open(uri, client, "server")) {
-			thrown.expect(TransportException.class);
-			thrown.expectMessage(Matchers.containsString(
-						"want " + blob.name() + " not valid"));
-			tn.fetch(NullProgressMonitor.INSTANCE,
-					Collections.singletonList(new RefSpec(blob.name())));
+			TransportException e = assertThrows(TransportException.class,
+					() -> tn.fetch(NullProgressMonitor.INSTANCE, Collections
+							.singletonList(new RefSpec(blob.name()))));
+			assertThat(e.getMessage(),
+					containsString("want " + blob.name() + " not valid"));
 		}
 	}
 
@@ -183,11 +182,41 @@
 		assertFalse(client.getObjectDatabase().has(blob.toObjectId()));
 
 		try (Transport tn = testProtocol.open(uri, client, "server")) {
-			thrown.expect(TransportException.class);
-			thrown.expectMessage(Matchers.containsString(
+			TransportException e = assertThrows(TransportException.class,
+					() -> tn.fetch(NullProgressMonitor.INSTANCE, Collections
+							.singletonList(new RefSpec(blob.name()))));
+			assertThat(e.getMessage(),
+					containsString(
 						"want " + blob.name() + " not valid"));
-			tn.fetch(NullProgressMonitor.INSTANCE,
-					Collections.singletonList(new RefSpec(blob.name())));
+		}
+	}
+
+	@Test
+	public void testFetchReachableBlobWithoutBitmapButFilterAllowed() throws Exception {
+		InMemoryRepository server2 = newRepo("server2");
+		try (TestRepository<InMemoryRepository> remote2 = new TestRepository<>(
+				server2)) {
+			RevBlob blob = remote2.blob("foo");
+			RevCommit commit = remote2.commit(remote2.tree(remote2.file("foo", blob)));
+			remote2.update("master", commit);
+
+			server2.getConfig().setBoolean("uploadpack", null, "allowfilter",
+					true);
+
+			testProtocol = new TestProtocol<>((Object req, Repository db) -> {
+				UploadPack up = new UploadPack(db);
+				up.setRequestPolicy(RequestPolicy.REACHABLE_COMMIT);
+				return up;
+			}, null);
+			uri = testProtocol.register(ctx, server2);
+
+			assertFalse(client.getObjectDatabase().has(blob.toObjectId()));
+
+			try (Transport tn = testProtocol.open(uri, client, "server2")) {
+				tn.fetch(NullProgressMonitor.INSTANCE,
+						Collections.singletonList(new RefSpec(blob.name())));
+				assertTrue(client.getObjectDatabase().has(blob.toObjectId()));
+			}
 		}
 	}
 
@@ -384,12 +413,11 @@
 			try (Transport tn = testProtocol.open(uri, client, "server2")) {
 				tn.setFilterSpec(FilterSpec.withBlobLimit(0));
 
-				thrown.expect(TransportException.class);
-				thrown.expectMessage(
-						"filter requires server to advertise that capability");
-
-				tn.fetch(NullProgressMonitor.INSTANCE,
-						Collections.singletonList(new RefSpec(commit.name())));
+				TransportException e = assertThrows(TransportException.class,
+						() -> tn.fetch(NullProgressMonitor.INSTANCE, Collections
+								.singletonList(new RefSpec(commit.name()))));
+				assertThat(e.getMessage(), containsString(
+						"filter requires server to advertise that capability"));
 			}
 		}
 	}
@@ -398,22 +426,18 @@
 	 * Invokes UploadPack with protocol v2 and sends it the given lines,
 	 * and returns UploadPack's output stream.
 	 */
-	private ByteArrayInputStream uploadPackV2Setup(RequestPolicy requestPolicy,
-			RefFilter refFilter, ProtocolV2Hook hook, String... inputLines)
+	private ByteArrayInputStream uploadPackV2Setup(
+			Consumer<UploadPack> postConstructionSetup, String... inputLines)
 			throws Exception {
 
 		ByteArrayInputStream send = linesAsInputStream(inputLines);
 
 		server.getConfig().setString("protocol", null, "version", "2");
 		UploadPack up = new UploadPack(server);
-		if (requestPolicy != null)
-			up.setRequestPolicy(requestPolicy);
-		if (refFilter != null)
-			up.setRefFilter(refFilter);
-		up.setExtraParameters(Sets.of("version=2"));
-		if (hook != null) {
-			up.setProtocolV2Hook(hook);
+		if (postConstructionSetup != null) {
+			postConstructionSetup.accept(up);
 		}
+		up.setExtraParameters(Sets.of("version=2"));
 
 		ByteArrayOutputStream recv = new ByteArrayOutputStream();
 		up.upload(send, recv, null);
@@ -427,6 +451,7 @@
 		try (ByteArrayOutputStream send = new ByteArrayOutputStream()) {
 			PacketLineOut pckOut = new PacketLineOut(send);
 			for (String line : inputLines) {
+				Objects.requireNonNull(line);
 				if (PacketLineIn.isEnd(line)) {
 					pckOut.end();
 				} else if (PacketLineIn.isDelimiter(line)) {
@@ -444,11 +469,12 @@
 	 * Returns UploadPack's output stream, not including the capability
 	 * advertisement by the server.
 	 */
-	private ByteArrayInputStream uploadPackV2(RequestPolicy requestPolicy,
-			RefFilter refFilter, ProtocolV2Hook hook, String... inputLines)
+	private ByteArrayInputStream uploadPackV2(
+			Consumer<UploadPack> postConstructionSetup,
+			String... inputLines)
 			throws Exception {
 		ByteArrayInputStream recvStream =
-				uploadPackV2Setup(requestPolicy, refFilter, hook, inputLines);
+				uploadPackV2Setup(postConstructionSetup, inputLines);
 		PacketLineIn pckIn = new PacketLineIn(recvStream);
 
 		// drain capabilities
@@ -459,7 +485,7 @@
 	}
 
 	private ByteArrayInputStream uploadPackV2(String... inputLines) throws Exception {
-		return uploadPackV2(null, null, null, inputLines);
+		return uploadPackV2(null, inputLines);
 	}
 
 	private static class TestV2Hook implements ProtocolV2Hook {
@@ -488,8 +514,9 @@
 	@Test
 	public void testV2Capabilities() throws Exception {
 		TestV2Hook hook = new TestV2Hook();
-		ByteArrayInputStream recvStream =
-				uploadPackV2Setup(null, null, hook, PacketLineIn.end());
+		ByteArrayInputStream recvStream = uploadPackV2Setup(
+				(UploadPack up) -> {up.setProtocolV2Hook(hook);},
+				PacketLineIn.end());
 		PacketLineIn pckIn = new PacketLineIn(recvStream);
 		assertThat(hook.capabilitiesRequest, notNullValue());
 		assertThat(pckIn.readString(), is("version 2"));
@@ -506,54 +533,72 @@
 		assertTrue(PacketLineIn.isEnd(pckIn.readString()));
 	}
 
-	@Test
-	public void testV2CapabilitiesAllowFilter() throws Exception {
-		server.getConfig().setBoolean("uploadpack", null, "allowfilter", true);
+	private void checkAdvertisedIfAllowed(String configSection, String configName,
+			String fetchCapability) throws Exception {
+		server.getConfig().setBoolean(configSection, null, configName, true);
 		ByteArrayInputStream recvStream =
-				uploadPackV2Setup(null, null, null, PacketLineIn.end());
+				uploadPackV2Setup(null, PacketLineIn.end());
 		PacketLineIn pckIn = new PacketLineIn(recvStream);
 
 		assertThat(pckIn.readString(), is("version 2"));
-		assertThat(
-				Arrays.asList(pckIn.readString(), pckIn.readString(),
-						pckIn.readString()),
-				// TODO(jonathantanmy) This check overspecifies the
-				// order of the capabilities of "fetch".
-				hasItems("ls-refs", "fetch=filter shallow", "server-option"));
-		assertTrue(PacketLineIn.isEnd(pckIn.readString()));
+
+		ArrayList<String> lines = new ArrayList<>();
+		String line;
+		while (!PacketLineIn.isEnd((line = pckIn.readString()))) {
+			if (line.startsWith("fetch=")) {
+				assertThat(
+					Arrays.asList(line.substring(6).split(" ")),
+					containsInAnyOrder(fetchCapability, "shallow"));
+				lines.add("fetch");
+			} else {
+				lines.add(line);
+			}
+		}
+		assertThat(lines, containsInAnyOrder("ls-refs", "fetch", "server-option"));
+	}
+
+	private void checkUnadvertisedIfUnallowed(String fetchCapability) throws Exception {
+		ByteArrayInputStream recvStream =
+				uploadPackV2Setup(null, PacketLineIn.end());
+		PacketLineIn pckIn = new PacketLineIn(recvStream);
+
+		assertThat(pckIn.readString(), is("version 2"));
+
+		ArrayList<String> lines = new ArrayList<>();
+		String line;
+		while (!PacketLineIn.isEnd((line = pckIn.readString()))) {
+			if (line.startsWith("fetch=")) {
+				assertThat(
+					Arrays.asList(line.substring(6).split(" ")),
+					hasItems("shallow"));
+				lines.add("fetch");
+			} else {
+				lines.add(line);
+			}
+		}
+		assertThat(lines, hasItems("ls-refs", "fetch", "server-option"));
+	}
+
+	@Test
+	public void testV2CapabilitiesAllowFilter() throws Exception {
+		checkAdvertisedIfAllowed("uploadpack", "allowfilter", "filter");
+		checkUnadvertisedIfUnallowed("filter");
 	}
 
 	@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(),
-						pckIn.readString()),
-				// TODO(jonathantanmy) This check overspecifies the
-				// order of the capabilities of "fetch".
-				hasItems("ls-refs", "fetch=ref-in-want shallow",
-						"server-option"));
-		assertTrue(PacketLineIn.isEnd(pckIn.readString()));
+		checkAdvertisedIfAllowed("uploadpack", "allowrefinwant", "ref-in-want");
 	}
 
 	@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);
+		checkUnadvertisedIfUnallowed("ref-in-want");
+	}
 
-		assertThat(pckIn.readString(), is("version 2"));
-		assertThat(
-				Arrays.asList(pckIn.readString(), pckIn.readString(),
-						pckIn.readString()),
-				hasItems("ls-refs", "fetch=shallow", "server-option"));
-		assertTrue(PacketLineIn.isEnd(pckIn.readString()));
+	@Test
+	public void testV2CapabilitiesAllowSidebandAll() throws Exception {
+		checkAdvertisedIfAllowed("uploadpack", "allowsidebandall", "sideband-all");
+		checkUnadvertisedIfUnallowed("sideband-all");
 	}
 
 	@Test
@@ -561,7 +606,7 @@
 		server.getConfig().setBoolean("uploadpack", null, "allowrefinwant", true);
 		server.getConfig().setBoolean("uploadpack", null, "advertiserefinwant", false);
 		ByteArrayInputStream recvStream =
-				uploadPackV2Setup(null, null, null, PacketLineIn.end());
+				uploadPackV2Setup(null, PacketLineIn.end());
 		PacketLineIn pckIn = new PacketLineIn(recvStream);
 
 		assertThat(pckIn.readString(), is("version 2"));
@@ -589,7 +634,8 @@
 		remote.update("refs/tags/tag", tag);
 
 		TestV2Hook hook = new TestV2Hook();
-		ByteArrayInputStream recvStream = uploadPackV2(null, null, hook,
+		ByteArrayInputStream recvStream = uploadPackV2(
+				(UploadPack up) -> {up.setProtocolV2Hook(hook);},
 				"command=ls-refs\n", PacketLineIn.end());
 		PacketLineIn pckIn = new PacketLineIn(recvStream);
 
@@ -707,13 +753,13 @@
 
 	@Test
 	public void testV2LsRefsUnrecognizedArgument() throws Exception {
-		thrown.expect(PackProtocolException.class);
-		thrown.expectMessage("unexpected invalid-argument");
-		uploadPackV2(
-			"command=ls-refs\n",
-			PacketLineIn.delimiter(),
-			"invalid-argument\n",
-				PacketLineIn.end());
+		UploadPackInternalServerErrorException e = assertThrows(
+				UploadPackInternalServerErrorException.class,
+				() -> uploadPackV2("command=ls-refs\n",
+						PacketLineIn.delimiter(), "invalid-argument\n",
+						PacketLineIn.end()));
+		assertThat(e.getCause().getMessage(),
+				containsString("unexpected invalid-argument"));
 	}
 
 	@Test
@@ -724,7 +770,7 @@
 				PacketLineIn.end() };
 
 		TestV2Hook testHook = new TestV2Hook();
-		uploadPackV2Setup(null, null, testHook, lines);
+		uploadPackV2Setup((UploadPack up) -> {up.setProtocolV2Hook(testHook);}, lines);
 
 		LsRefsV2Request req = testHook.lsRefsRequest;
 		assertEquals(2, req.getServerOptions().size());
@@ -761,118 +807,117 @@
 
 		// This works
 		uploadPackV2(
-			RequestPolicy.ADVERTISED,
-			null,
-			null,
+			(UploadPack up) -> {up.setRequestPolicy(RequestPolicy.ADVERTISED);},
 			"command=fetch\n",
 			PacketLineIn.delimiter(),
 			"want " + advertized.name() + "\n",
-				PacketLineIn.end());
+			PacketLineIn.end());
 
 		// This doesn't
-		thrown.expect(TransportException.class);
-		thrown.expectMessage(Matchers.containsString(
-					"want " + unadvertized.name() + " not valid"));
-		uploadPackV2(
-			RequestPolicy.ADVERTISED,
-			null,
-			null,
-			"command=fetch\n",
-			PacketLineIn.delimiter(),
-			"want " + unadvertized.name() + "\n",
-				PacketLineIn.end());
+		UploadPackInternalServerErrorException e = assertThrows(
+				UploadPackInternalServerErrorException.class,
+				() -> uploadPackV2(
+						(UploadPack up) -> {up.setRequestPolicy(RequestPolicy.ADVERTISED);},
+						"command=fetch\n", PacketLineIn.delimiter(),
+						"want " + unadvertized.name() + "\n",
+						PacketLineIn.end()));
+		assertThat(e.getCause().getMessage(),
+				containsString("want " + unadvertized.name() + " not valid"));
 	}
 
 	@Test
 	public void testV2FetchRequestPolicyReachableCommit() throws Exception {
 		RevCommit reachable = remote.commit().message("x").create();
-		RevCommit advertized = remote.commit().message("x").parent(reachable).create();
+		RevCommit advertized = remote.commit().message("x").parent(reachable)
+				.create();
 		RevCommit unreachable = remote.commit().message("y").create();
 		remote.update("branch1", advertized);
 
 		// This works
 		uploadPackV2(
-			RequestPolicy.REACHABLE_COMMIT,
-			null,
-			null,
+			(UploadPack up) -> {up.setRequestPolicy(RequestPolicy.REACHABLE_COMMIT);},
 			"command=fetch\n",
 			PacketLineIn.delimiter(),
 			"want " + reachable.name() + "\n",
 				PacketLineIn.end());
 
 		// This doesn't
-		thrown.expect(TransportException.class);
-		thrown.expectMessage(Matchers.containsString(
-					"want " + unreachable.name() + " not valid"));
-		uploadPackV2(
-			RequestPolicy.REACHABLE_COMMIT,
-			null,
-			null,
-			"command=fetch\n",
-			PacketLineIn.delimiter(),
-			"want " + unreachable.name() + "\n",
-				PacketLineIn.end());
+		UploadPackInternalServerErrorException e = assertThrows(
+				UploadPackInternalServerErrorException.class,
+				() -> uploadPackV2(
+						(UploadPack up) -> {up.setRequestPolicy(RequestPolicy.REACHABLE_COMMIT);},
+						"command=fetch\n", PacketLineIn.delimiter(),
+						"want " + unreachable.name() + "\n",
+						PacketLineIn.end()));
+		assertThat(e.getCause().getMessage(),
+				containsString("want " + unreachable.name() + " not valid"));
 	}
 
 	@Test
 	public void testV2FetchRequestPolicyTip() throws Exception {
 		RevCommit parentOfTip = remote.commit().message("x").create();
-		RevCommit tip = remote.commit().message("y").parent(parentOfTip).create();
+		RevCommit tip = remote.commit().message("y").parent(parentOfTip)
+				.create();
 		remote.update("secret", tip);
 
 		// This works
 		uploadPackV2(
-			RequestPolicy.TIP,
-			new RejectAllRefFilter(),
-			null,
+			(UploadPack up) -> {
+				up.setRequestPolicy(RequestPolicy.TIP);
+				up.setRefFilter(new RejectAllRefFilter());
+			},
 			"command=fetch\n",
 			PacketLineIn.delimiter(),
 			"want " + tip.name() + "\n",
 				PacketLineIn.end());
 
 		// This doesn't
-		thrown.expect(TransportException.class);
-		thrown.expectMessage(Matchers.containsString(
-					"want " + parentOfTip.name() + " not valid"));
-		uploadPackV2(
-			RequestPolicy.TIP,
-			new RejectAllRefFilter(),
-			null,
-			"command=fetch\n",
-			PacketLineIn.delimiter(),
-			"want " + parentOfTip.name() + "\n",
-				PacketLineIn.end());
+		UploadPackInternalServerErrorException e = assertThrows(
+				UploadPackInternalServerErrorException.class,
+				() -> uploadPackV2(
+						(UploadPack up) -> {
+							up.setRequestPolicy(RequestPolicy.TIP);
+							up.setRefFilter(new RejectAllRefFilter());
+						},
+						"command=fetch\n", PacketLineIn.delimiter(),
+						"want " + parentOfTip.name() + "\n",
+						PacketLineIn.end()));
+		assertThat(e.getCause().getMessage(),
+				containsString("want " + parentOfTip.name() + " not valid"));
 	}
 
 	@Test
 	public void testV2FetchRequestPolicyReachableCommitTip() throws Exception {
 		RevCommit parentOfTip = remote.commit().message("x").create();
-		RevCommit tip = remote.commit().message("y").parent(parentOfTip).create();
+		RevCommit tip = remote.commit().message("y").parent(parentOfTip)
+				.create();
 		RevCommit unreachable = remote.commit().message("y").create();
 		remote.update("secret", tip);
 
 		// This works
 		uploadPackV2(
-			RequestPolicy.REACHABLE_COMMIT_TIP,
-			new RejectAllRefFilter(),
-			null,
-			"command=fetch\n",
-			PacketLineIn.delimiter(),
-			"want " + parentOfTip.name() + "\n",
+				(UploadPack up) -> {
+					up.setRequestPolicy(RequestPolicy.REACHABLE_COMMIT_TIP);
+					up.setRefFilter(new RejectAllRefFilter());
+				},
+				"command=fetch\n",
+				PacketLineIn.delimiter(), "want " + parentOfTip.name() + "\n",
 				PacketLineIn.end());
 
 		// This doesn't
-		thrown.expect(TransportException.class);
-		thrown.expectMessage(Matchers.containsString(
-					"want " + unreachable.name() + " not valid"));
-		uploadPackV2(
-			RequestPolicy.REACHABLE_COMMIT_TIP,
-			new RejectAllRefFilter(),
-			null,
-			"command=fetch\n",
-			PacketLineIn.delimiter(),
-			"want " + unreachable.name() + "\n",
-				PacketLineIn.end());
+		UploadPackInternalServerErrorException e = assertThrows(
+				UploadPackInternalServerErrorException.class,
+				() -> uploadPackV2(
+						(UploadPack up) -> {
+							up.setRequestPolicy(RequestPolicy.REACHABLE_COMMIT_TIP);
+							up.setRefFilter(new RejectAllRefFilter());
+						},
+						"command=fetch\n",
+						PacketLineIn.delimiter(),
+						"want " + unreachable.name() + "\n",
+						PacketLineIn.end()));
+		assertThat(e.getCause().getMessage(),
+				containsString("want " + unreachable.name() + " not valid"));
 	}
 
 	@Test
@@ -881,9 +926,7 @@
 
 		// Exercise to make sure that even unreachable commits can be fetched
 		uploadPackV2(
-			RequestPolicy.ANY,
-			null,
-			null,
+			(UploadPack up) -> {up.setRequestPolicy(RequestPolicy.ANY);},
 			"command=fetch\n",
 			PacketLineIn.delimiter(),
 			"want " + unreachable.name() + "\n",
@@ -980,29 +1023,29 @@
 		String commonInBlob = "abcdefghijklmnopqrstuvwxyz";
 
 		RevBlob parentBlob = remote.blob(commonInBlob + "a");
-		RevCommit parent = remote.commit(remote.tree(remote.file("foo", parentBlob)));
+		RevCommit parent = remote
+				.commit(remote.tree(remote.file("foo", parentBlob)));
 		RevBlob childBlob = remote.blob(commonInBlob + "b");
-		RevCommit child = remote.commit(remote.tree(remote.file("foo", childBlob)), parent);
+		RevCommit child = remote
+				.commit(remote.tree(remote.file("foo", childBlob)), parent);
 		remote.update("branch1", child);
 
 		// Pretend that we have parent to get a thin pack based on it.
-		ByteArrayInputStream recvStream = uploadPackV2(
-			"command=fetch\n",
-			PacketLineIn.delimiter(),
-			"want " + child.toObjectId().getName() + "\n",
-			"have " + parent.toObjectId().getName() + "\n",
-			"thin-pack\n",
-			"done\n",
-				PacketLineIn.end());
+		ByteArrayInputStream recvStream = uploadPackV2("command=fetch\n",
+				PacketLineIn.delimiter(),
+				"want " + child.toObjectId().getName() + "\n",
+				"have " + parent.toObjectId().getName() + "\n", "thin-pack\n",
+				"done\n", PacketLineIn.end());
 		PacketLineIn pckIn = new PacketLineIn(recvStream);
 
 		assertThat(pckIn.readString(), is("packfile"));
 
 		// Verify that we received a thin pack by trying to apply it
 		// against the client repo, which does not have parent.
-		thrown.expect(IOException.class);
-		thrown.expectMessage("pack has unresolved deltas");
-		parsePack(recvStream);
+		IOException e = assertThrows(IOException.class,
+				() -> parsePack(recvStream));
+		assertThat(e.getMessage(),
+				containsString("pack has unresolved deltas"));
 	}
 
 	@Test
@@ -1303,19 +1346,18 @@
 		PersonIdent person = new PersonIdent(remote.getRepository());
 
 		RevCommit tooOld = remote.commit()
-			.committer(new PersonIdent(person, 1500000000, 0)).create();
+				.committer(new PersonIdent(person, 1500000000, 0)).create();
 
 		remote.update("branch1", tooOld);
 
-		thrown.expect(PackProtocolException.class);
-		thrown.expectMessage("No commits selected for shallow request");
-		uploadPackV2(
-			"command=fetch\n",
-			PacketLineIn.delimiter(),
-			"deepen-since 1510000\n",
-			"want " + tooOld.toObjectId().getName() + "\n",
-			"done\n",
-				PacketLineIn.end());
+		UploadPackInternalServerErrorException e = assertThrows(
+				UploadPackInternalServerErrorException.class,
+				() -> uploadPackV2("command=fetch\n", PacketLineIn.delimiter(),
+						"deepen-since 1510000\n",
+						"want " + tooOld.toObjectId().getName() + "\n",
+						"done\n", PacketLineIn.end()));
+		assertThat(e.getCause().getMessage(),
+				containsString("No commits selected for shallow request"));
 	}
 
 	@Test
@@ -1374,7 +1416,8 @@
 	}
 
 	@Test
-	public void testV2FetchDeepenNot_excludeDescendantOfWant() throws Exception {
+	public void testV2FetchDeepenNot_excludeDescendantOfWant()
+			throws Exception {
 		RevCommit one = remote.commit().message("one").create();
 		RevCommit two = remote.commit().message("two").parent(one).create();
 		RevCommit three = remote.commit().message("three").parent(two).create();
@@ -1383,15 +1426,14 @@
 		remote.update("two", two);
 		remote.update("four", four);
 
-		thrown.expect(PackProtocolException.class);
-		thrown.expectMessage("No commits selected for shallow request");
-		uploadPackV2(
-			"command=fetch\n",
-			PacketLineIn.delimiter(),
-			"deepen-not four\n",
-			"want " + two.toObjectId().getName() + "\n",
-			"done\n",
-				PacketLineIn.end());
+		UploadPackInternalServerErrorException e = assertThrows(
+				UploadPackInternalServerErrorException.class,
+				() -> uploadPackV2("command=fetch\n", PacketLineIn.delimiter(),
+						"deepen-not four\n",
+						"want " + two.toObjectId().getName() + "\n", "done\n",
+						PacketLineIn.end()));
+		assertThat(e.getCause().getMessage(),
+				containsString("No commits selected for shallow request"));
 	}
 
 	@Test
@@ -1469,13 +1511,12 @@
 
 	@Test
 	public void testV2FetchUnrecognizedArgument() throws Exception {
-		thrown.expect(PackProtocolException.class);
-		thrown.expectMessage("unexpected invalid-argument");
-		uploadPackV2(
-			"command=fetch\n",
-			PacketLineIn.delimiter(),
-			"invalid-argument\n",
-				PacketLineIn.end());
+		UploadPackInternalServerErrorException e = assertThrows(
+				UploadPackInternalServerErrorException.class,
+				() -> uploadPackV2("command=fetch\n", PacketLineIn.delimiter(),
+						"invalid-argument\n", PacketLineIn.end()));
+		assertThat(e.getCause().getMessage(),
+				containsString("unexpected invalid-argument"));
 	}
 
 	@Test
@@ -1485,7 +1526,7 @@
 				PacketLineIn.end() };
 
 		TestV2Hook testHook = new TestV2Hook();
-		uploadPackV2Setup(null, null, testHook, lines);
+		uploadPackV2Setup((UploadPack up) -> {up.setProtocolV2Hook(testHook);}, lines);
 
 		FetchV2Request req = testHook.fetchRequest;
 		assertNotNull(req);
@@ -1569,8 +1610,9 @@
 		input.add("done\n");
 		input.add(PacketLineIn.end());
 		ByteArrayInputStream recvStream =
-				uploadPackV2(RequestPolicy.ANY, /*refFilter=*/null,
-							 /*hook=*/null, input.toArray(new String[0]));
+				uploadPackV2(
+						(UploadPack up) -> {up.setRequestPolicy(RequestPolicy.ANY);},
+						input.toArray(new String[0]));
 		PacketLineIn pckIn = new PacketLineIn(recvStream);
 		assertThat(pckIn.readString(), is("packfile"));
 		parsePack(recvStream);
@@ -1837,43 +1879,39 @@
 				.has(preparator.subtree3.toObjectId()));
 	}
 
-	@Test
-	public void testV2FetchFilterWhenNotAllowed() throws Exception {
+	private void checkV2FetchWhenNotAllowed(String fetchLine, String expectedMessage)
+			throws Exception {
 		RevCommit commit = remote.commit().message("0").create();
 		remote.update("master", commit);
 
-		server.getConfig().setBoolean("uploadpack", null, "allowfilter", false);
+		UploadPackInternalServerErrorException e = assertThrows(
+				UploadPackInternalServerErrorException.class,
+				() -> uploadPackV2("command=fetch\n", PacketLineIn.delimiter(),
+						"want " + commit.toObjectId().getName() + "\n",
+						fetchLine, "done\n", PacketLineIn.end()));
+		assertThat(e.getCause().getMessage(),
+				containsString(expectedMessage));
+	}
 
-		thrown.expect(PackProtocolException.class);
-		thrown.expectMessage("unexpected filter blob:limit=5");
-		uploadPackV2(
-			"command=fetch\n",
-			PacketLineIn.delimiter(),
-			"want " + commit.toObjectId().getName() + "\n",
+	@Test
+	public void testV2FetchFilterWhenNotAllowed() throws Exception {
+		checkV2FetchWhenNotAllowed(
 			"filter blob:limit=5\n",
-			"done\n",
-				PacketLineIn.end());
+			"unexpected filter blob:limit=5");
 	}
 
 	@Test
 	public void testV2FetchWantRefIfNotAllowed() throws Exception {
-		RevCommit one = remote.commit().message("1").create();
-		remote.update("one", one);
+		checkV2FetchWhenNotAllowed(
+			"want-ref refs/heads/one\n",
+			"unexpected want-ref refs/heads/one");
+	}
 
-		try {
-			uploadPackV2(
-				"command=fetch\n",
-				PacketLineIn.delimiter(),
-				"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 testV2FetchSidebandAllIfNotAllowed() throws Exception {
+		checkV2FetchWhenNotAllowed(
+			"sideband-all\n",
+			"unexpected sideband-all");
 	}
 
 	@Test
@@ -1915,23 +1953,17 @@
 		RevCommit one = remote.commit().message("1").create();
 		remote.update("one", one);
 
-		server.getConfig().setBoolean("uploadpack", null, "allowrefinwant", true);
+		server.getConfig().setBoolean("uploadpack", null, "allowrefinwant",
+				true);
 
-		try {
-			uploadPackV2(
-				"command=fetch\n",
-				PacketLineIn.delimiter(),
-				"want-ref refs/heads/one\n",
-				"want-ref refs/heads/nonExistentRef\n",
-				"done\n",
-					PacketLineIn.end());
-		} catch (PackProtocolException e) {
-			assertThat(
-				e.getMessage(),
+		UploadPackInternalServerErrorException e = assertThrows(
+				UploadPackInternalServerErrorException.class,
+				() -> uploadPackV2("command=fetch\n", PacketLineIn.delimiter(),
+						"want-ref refs/heads/one\n",
+						"want-ref refs/heads/nonExistentRef\n", "done\n",
+						PacketLineIn.end()));
+		assertThat(e.getCause().getMessage(),
 				containsString("Invalid ref name: refs/heads/nonExistentRef"));
-			return;
-		}
-		fail("expected PackProtocolException");
 	}
 
 	@Test
@@ -2066,6 +2098,58 @@
 	}
 
 	@Test
+	public void testV2FetchSidebandAllNoPackfile() throws Exception {
+		RevCommit fooParent = remote.commit().message("x").create();
+		RevCommit fooChild = remote.commit().message("x").parent(fooParent).create();
+		RevCommit barParent = remote.commit().message("y").create();
+		RevCommit barChild = remote.commit().message("y").parent(barParent).create();
+		remote.update("branch1", fooChild);
+		remote.update("branch2", barChild);
+
+		server.getConfig().setBoolean("uploadpack", null, "allowsidebandall", true);
+
+		ByteArrayInputStream recvStream = uploadPackV2(
+			"command=fetch\n",
+			PacketLineIn.DELIM,
+			"sideband-all\n",
+			"want " + fooChild.toObjectId().getName() + "\n",
+			"want " + barChild.toObjectId().getName() + "\n",
+			"have " + fooParent.toObjectId().getName() + "\n",
+			PacketLineIn.END);
+		PacketLineIn pckIn = new PacketLineIn(recvStream);
+
+		assertThat(pckIn.readString(), is("\001acknowledgments"));
+		assertThat(pckIn.readString(), is("\001ACK " + fooParent.getName()));
+		assertTrue(PacketLineIn.isEnd(pckIn.readString()));
+	}
+
+	@Test
+	public void testV2FetchSidebandAllPackfile() throws Exception {
+		RevCommit commit = remote.commit().message("x").create();
+		remote.update("master", commit);
+
+		server.getConfig().setBoolean("uploadpack", null, "allowsidebandall", true);
+
+		ByteArrayInputStream recvStream = uploadPackV2("command=fetch\n",
+				PacketLineIn.DELIM,
+				"want " + commit.getName() + "\n",
+				"sideband-all\n",
+				"done\n",
+				PacketLineIn.END);
+		PacketLineIn pckIn = new PacketLineIn(recvStream);
+
+		String s;
+		// When sideband-all is used, object counting happens before
+		// "packfile" is written, and object counting outputs progress
+		// in sideband 2. Skip all these lines.
+		for (s = pckIn.readString(); s.startsWith("\002"); s = pckIn.readString()) {
+			// do nothing
+		}
+		assertThat(s, is("\001packfile"));
+		parsePack(recvStream);
+	}
+
+	@Test
 	public void testGetPeerAgentProtocolV0() throws Exception {
 		RevCommit one = remote.commit().message("1").create();
 		remote.update("one", one);
@@ -2110,4 +2194,84 @@
 			return new HashMap<>();
 		}
 	}
+
+	@Test
+	public void testSingleBranchCloneTagChain() throws Exception {
+		RevBlob blob0 = remote.blob("Initial content of first file");
+		RevBlob blob1 = remote.blob("Second file content");
+		RevCommit commit0 = remote
+				.commit(remote.tree(remote.file("prvni.txt", blob0)));
+		RevCommit commit1 = remote
+				.commit(remote.tree(remote.file("druhy.txt", blob1)), commit0);
+		remote.update("master", commit1);
+
+		RevTag heavyTag1 = remote.tag("commitTagRing", commit0);
+		remote.getRevWalk().parseHeaders(heavyTag1);
+		RevTag heavyTag2 = remote.tag("middleTagRing", heavyTag1);
+		remote.lightweightTag("refTagRing", heavyTag2);
+
+		UploadPack uploadPack = new UploadPack(remote.getRepository());
+
+		ByteArrayOutputStream cli = new ByteArrayOutputStream();
+		PacketLineOut clientWant = new PacketLineOut(cli);
+		clientWant.writeString("want " + commit1.name()
+				+ " multi_ack_detailed include-tag thin-pack ofs-delta agent=tempo/pflaska");
+		clientWant.end();
+		clientWant.writeString("done\n");
+
+		try (ByteArrayOutputStream serverResponse = new ByteArrayOutputStream()) {
+
+			uploadPack.setPreUploadHook(new PreUploadHook() {
+				@Override
+				public void onBeginNegotiateRound(UploadPack up,
+						Collection<? extends ObjectId> wants, int cntOffered)
+						throws ServiceMayNotContinueException {
+					// Do nothing.
+				}
+
+				@Override
+				public void onEndNegotiateRound(UploadPack up,
+						Collection<? extends ObjectId> wants, int cntCommon,
+						int cntNotFound, boolean ready)
+						throws ServiceMayNotContinueException {
+					// Do nothing.
+				}
+
+				@Override
+				public void onSendPack(UploadPack up,
+						Collection<? extends ObjectId> wants,
+						Collection<? extends ObjectId> haves)
+						throws ServiceMayNotContinueException {
+					// collect pack data
+					serverResponse.reset();
+				}
+			});
+			uploadPack.upload(new ByteArrayInputStream(cli.toByteArray()),
+					serverResponse, System.err);
+			InputStream packReceived = new ByteArrayInputStream(
+					serverResponse.toByteArray());
+			PackLock lock = null;
+			try (ObjectInserter ins = client.newObjectInserter()) {
+				PackParser parser = ins.newPackParser(packReceived);
+				parser.setAllowThin(true);
+				parser.setLockMessage("receive-tag-chain");
+				ProgressMonitor mlc = NullProgressMonitor.INSTANCE;
+				lock = parser.parse(mlc, mlc);
+				ins.flush();
+			} finally {
+				if (lock != null) {
+					lock.unlock();
+				}
+			}
+			InMemoryRepository.MemObjDatabase objDb = client
+					.getObjectDatabase();
+			assertTrue(objDb.has(blob0.toObjectId()));
+			assertTrue(objDb.has(blob1.toObjectId()));
+			assertTrue(objDb.has(commit0.toObjectId()));
+			assertTrue(objDb.has(commit1.toObjectId()));
+			assertTrue(objDb.has(heavyTag1.toObjectId()));
+			assertTrue(objDb.has(heavyTag2.toObjectId()));
+		}
+	}
+
 }
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/GitDateFormatterTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/GitDateFormatterTest.java
index d52166f..59ff2ad 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/GitDateFormatterTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/GitDateFormatterTest.java
@@ -44,6 +44,7 @@
 package org.eclipse.jgit.util;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
 import org.eclipse.jgit.junit.MockSystemReader;
 import org.eclipse.jgit.lib.PersonIdent;
@@ -120,13 +121,16 @@
 
 	@Test
 	public void LOCALE() {
-		assertEquals("Sep 20, 2011 7:09:25 PM -0400", new GitDateFormatter(
-				Format.LOCALE).formatDate(ident));
+		String date = new GitDateFormatter(Format.LOCALE).formatDate(ident);
+		assertTrue("Sep 20, 2011 7:09:25 PM -0400".equals(date)
+				|| "Sep 20, 2011, 7:09:25 PM -0400".equals(date)); // JDK-8206961
 	}
 
 	@Test
 	public void LOCALELOCAL() {
-		assertEquals("Sep 20, 2011 7:39:25 PM", new GitDateFormatter(
-				Format.LOCALELOCAL).formatDate(ident));
+		String date = new GitDateFormatter(Format.LOCALELOCAL)
+				.formatDate(ident);
+		assertTrue("Sep 20, 2011 7:39:25 PM".equals(date)
+				|| "Sep 20, 2011, 7:39:25 PM".equals(date)); // JDK-8206961
 	}
 }
diff --git a/org.eclipse.jgit.ui/META-INF/MANIFEST.MF b/org.eclipse.jgit.ui/META-INF/MANIFEST.MF
index 531d287..1e0d052 100644
--- a/org.eclipse.jgit.ui/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.ui/META-INF/MANIFEST.MF
@@ -1,17 +1,17 @@
 Bundle-Localization: plugin
 Manifest-Version: 1.0
 Bundle-ManifestVersion: 2
-Bundle-Name: %plugin_name
+Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit.ui
 Bundle-SymbolicName: org.eclipse.jgit.ui
-Bundle-Version: 5.4.1.qualifier
-Bundle-Vendor: %provider_name
+Bundle-Version: 5.5.0.qualifier
+Bundle-Vendor: %Bundle-Vendor
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
-Export-Package: org.eclipse.jgit.awtui;version="5.4.1"
-Import-Package: org.eclipse.jgit.errors;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.lib;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.nls;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.revplot;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.revwalk;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.transport;version="[5.4.1,5.5.0)",
- org.eclipse.jgit.util;version="[5.4.1,5.5.0)"
+Export-Package: org.eclipse.jgit.awtui;version="5.5.0"
+Import-Package: org.eclipse.jgit.errors;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.lib;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.nls;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.revplot;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.revwalk;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.transport;version="[5.5.0,5.6.0)",
+ org.eclipse.jgit.util;version="[5.5.0,5.6.0)"
diff --git a/org.eclipse.jgit.ui/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.ui/META-INF/SOURCE-MANIFEST.MF
index 2fdfc4e..f8818b3 100644
--- a/org.eclipse.jgit.ui/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.ui/META-INF/SOURCE-MANIFEST.MF
@@ -3,5 +3,5 @@
 Bundle-Name: org.eclipse.jgit.ui - Sources
 Bundle-SymbolicName: org.eclipse.jgit.ui.source
 Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 5.4.1.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit.ui;version="5.4.1.qualifier";roots="."
+Bundle-Version: 5.5.0.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit.ui;version="5.5.0.qualifier";roots="."
diff --git a/org.eclipse.jgit.ui/plugin.properties b/org.eclipse.jgit.ui/plugin.properties
index 006c8c2..ce004ac 100644
--- a/org.eclipse.jgit.ui/plugin.properties
+++ b/org.eclipse.jgit.ui/plugin.properties
@@ -1,2 +1,2 @@
-plugin_name=JGit AWT User Interface
-provider_name=Eclipse JGit
+Bundle-Name=JGit AWT User Interface
+Bundle-Vendor=Eclipse JGit
diff --git a/org.eclipse.jgit.ui/pom.xml b/org.eclipse.jgit.ui/pom.xml
index 990dfe4..6e9d3d5 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.4.1-SNAPSHOT</version>
+    <version>5.5.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 2f6d2fa..3a5dd11 100644
--- a/org.eclipse.jgit/.settings/.api_filters
+++ b/org.eclipse.jgit/.settings/.api_filters
@@ -1,13 +1,5 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <component id="org.eclipse.jgit" version="2">
-    <resource path="META-INF/MANIFEST.MF">
-        <filter id="924844039">
-            <message_arguments>
-                <message_argument value="5.4.1"/>
-                <message_argument value="5.4.0"/>
-            </message_arguments>
-        </filter>
-    </resource>
     <resource path="src/org/eclipse/jgit/dircache/DirCacheEntry.java" type="org.eclipse.jgit.dircache.DirCacheEntry">
         <filter id="1142947843">
             <message_arguments>
@@ -28,6 +20,15 @@
             </message_arguments>
         </filter>
     </resource>
+    <resource path="src/org/eclipse/jgit/lib/AnyObjectId.java" type="org.eclipse.jgit.lib.AnyObjectId">
+        <filter id="1141899266">
+            <message_arguments>
+                <message_argument value="5.4"/>
+                <message_argument value="5.5"/>
+                <message_argument value="isEqual(AnyObjectId, AnyObjectId)"/>
+            </message_arguments>
+        </filter>
+    </resource>
     <resource path="src/org/eclipse/jgit/lib/ConfigConstants.java" type="org.eclipse.jgit.lib.ConfigConstants">
         <filter id="1142947843">
             <message_arguments>
@@ -132,6 +133,15 @@
             </message_arguments>
         </filter>
     </resource>
+    <resource path="src/org/eclipse/jgit/util/References.java" type="org.eclipse.jgit.util.References">
+        <filter id="1108344834">
+            <message_arguments>
+                <message_argument value="5.4"/>
+                <message_argument value="5.5"/>
+                <message_argument value="org.eclipse.jgit.util.References"/>
+            </message_arguments>
+        </filter>
+    </resource>
     <resource path="src/org/eclipse/jgit/util/SimpleLruCache.java" type="org.eclipse.jgit.util.SimpleLruCache">
         <filter id="1109393411">
             <message_arguments>
diff --git a/org.eclipse.jgit/BUILD b/org.eclipse.jgit/BUILD
index b67bfac..814ecec 100644
--- a/org.eclipse.jgit/BUILD
+++ b/org.eclipse.jgit/BUILD
@@ -14,10 +14,6 @@
 java_library(
     name = "jgit",
     srcs = SRCS,
-    javacopts = select({
-        "//:jdk9": ["--add-modules=java.xml.bind"],
-        "//conditions:default": [],
-    }),
     resource_strip_prefix = "org.eclipse.jgit/resources",
     resources = RESOURCES,
     deps = [
diff --git a/org.eclipse.jgit/META-INF/MANIFEST.MF b/org.eclipse.jgit/META-INF/MANIFEST.MF
index 493cab4..4184a54 100644
--- a/org.eclipse.jgit/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit/META-INF/MANIFEST.MF
@@ -1,14 +1,14 @@
 Manifest-Version: 1.0
 Bundle-ManifestVersion: 2
-Bundle-Name: %plugin_name
+Bundle-Name: %Bundle-Name
 Automatic-Module-Name: org.eclipse.jgit
 Bundle-SymbolicName: org.eclipse.jgit
-Bundle-Version: 5.4.1.qualifier
+Bundle-Version: 5.5.0.qualifier
 Bundle-Localization: plugin
-Bundle-Vendor: %provider_name
+Bundle-Vendor: %Bundle-Vendor
 Bundle-ActivationPolicy: lazy
-Export-Package: org.eclipse.jgit.annotations;version="5.4.1",
- org.eclipse.jgit.api;version="5.4.1";
+Export-Package: org.eclipse.jgit.annotations;version="5.5.0",
+ org.eclipse.jgit.api;version="5.5.0";
   uses:="org.eclipse.jgit.revwalk,
    org.eclipse.jgit.treewalk.filter,
    org.eclipse.jgit.diff,
@@ -22,53 +22,53 @@
    org.eclipse.jgit.submodule,
    org.eclipse.jgit.transport,
    org.eclipse.jgit.merge",
- org.eclipse.jgit.api.errors;version="5.4.1";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.errors",
- org.eclipse.jgit.attributes;version="5.4.1",
- org.eclipse.jgit.blame;version="5.4.1";
+ org.eclipse.jgit.api.errors;version="5.5.0";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.errors",
+ org.eclipse.jgit.attributes;version="5.5.0",
+ org.eclipse.jgit.blame;version="5.5.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.4.1";
+ org.eclipse.jgit.diff;version="5.5.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.4.1";
+ org.eclipse.jgit.dircache;version="5.5.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.4.1";
+ org.eclipse.jgit.errors;version="5.5.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.4.1";uses:="org.eclipse.jgit.lib",
- org.eclipse.jgit.fnmatch;version="5.4.1",
- org.eclipse.jgit.gitrepo;version="5.4.1";
+ org.eclipse.jgit.events;version="5.5.0";uses:="org.eclipse.jgit.lib",
+ org.eclipse.jgit.fnmatch;version="5.5.0",
+ org.eclipse.jgit.gitrepo;version="5.5.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.4.1";x-internal:=true,
- org.eclipse.jgit.hooks;version="5.4.1";uses:="org.eclipse.jgit.lib",
- org.eclipse.jgit.ignore;version="5.4.1",
- org.eclipse.jgit.ignore.internal;version="5.4.1";x-friends:="org.eclipse.jgit.test",
- org.eclipse.jgit.internal;version="5.4.1";x-friends:="org.eclipse.jgit.test,org.eclipse.jgit.http.test",
- org.eclipse.jgit.internal.fsck;version="5.4.1";x-friends:="org.eclipse.jgit.test",
- org.eclipse.jgit.internal.ketch;version="5.4.1";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm",
- org.eclipse.jgit.internal.revwalk;version="5.4.1";x-internal:=true,
- org.eclipse.jgit.internal.storage.dfs;version="5.4.1";
+ org.eclipse.jgit.gitrepo.internal;version="5.5.0";x-internal:=true,
+ org.eclipse.jgit.hooks;version="5.5.0";uses:="org.eclipse.jgit.lib",
+ org.eclipse.jgit.ignore;version="5.5.0",
+ org.eclipse.jgit.ignore.internal;version="5.5.0";x-friends:="org.eclipse.jgit.test",
+ org.eclipse.jgit.internal;version="5.5.0";x-friends:="org.eclipse.jgit.test,org.eclipse.jgit.http.test",
+ org.eclipse.jgit.internal.fsck;version="5.5.0";x-friends:="org.eclipse.jgit.test",
+ org.eclipse.jgit.internal.ketch;version="5.5.0";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm",
+ org.eclipse.jgit.internal.revwalk;version="5.5.0";x-internal:=true,
+ org.eclipse.jgit.internal.storage.dfs;version="5.5.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.4.1";
+ org.eclipse.jgit.internal.storage.file;version="5.5.0";
   x-friends:="org.eclipse.jgit.test,
    org.eclipse.jgit.junit,
    org.eclipse.jgit.junit.http,
@@ -77,19 +77,19 @@
    org.eclipse.jgit.pgm,
    org.eclipse.jgit.pgm.test,
    org.eclipse.jgit.ssh.apache",
- org.eclipse.jgit.internal.storage.io;version="5.4.1";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm",
- org.eclipse.jgit.internal.storage.pack;version="5.4.1";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm",
- org.eclipse.jgit.internal.storage.reftable;version="5.4.1";
+ org.eclipse.jgit.internal.storage.io;version="5.5.0";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm",
+ org.eclipse.jgit.internal.storage.pack;version="5.5.0";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm",
+ org.eclipse.jgit.internal.storage.reftable;version="5.5.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.4.1";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm",
- org.eclipse.jgit.internal.submodule;version="5.4.1";x-internal:=true,
- org.eclipse.jgit.internal.transport.http;version="5.4.1";x-friends:="org.eclipse.jgit.test",
- org.eclipse.jgit.internal.transport.parser;version="5.4.1";x-friends:="org.eclipse.jgit.http.server,org.eclipse.jgit.test",
- org.eclipse.jgit.internal.transport.ssh;version="5.4.1";x-friends:="org.eclipse.jgit.ssh.apache",
- org.eclipse.jgit.lib;version="5.4.1";
+ org.eclipse.jgit.internal.storage.reftree;version="5.5.0";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm",
+ org.eclipse.jgit.internal.submodule;version="5.5.0";x-internal:=true,
+ org.eclipse.jgit.internal.transport.http;version="5.5.0";x-friends:="org.eclipse.jgit.test",
+ org.eclipse.jgit.internal.transport.parser;version="5.5.0";x-friends:="org.eclipse.jgit.http.server,org.eclipse.jgit.test",
+ org.eclipse.jgit.internal.transport.ssh;version="5.5.0";x-friends:="org.eclipse.jgit.ssh.apache",
+ org.eclipse.jgit.lib;version="5.5.0";
   uses:="org.eclipse.jgit.revwalk,
    org.eclipse.jgit.treewalk.filter,
    org.eclipse.jgit.util,
@@ -99,33 +99,33 @@
    org.eclipse.jgit.treewalk,
    org.eclipse.jgit.transport,
    org.eclipse.jgit.submodule",
- org.eclipse.jgit.lib.internal;version="5.4.1";x-internal:=true,
- org.eclipse.jgit.merge;version="5.4.1";
+ org.eclipse.jgit.lib.internal;version="5.5.0";x-internal:=true,
+ org.eclipse.jgit.merge;version="5.5.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.4.1",
- org.eclipse.jgit.notes;version="5.4.1";
+ org.eclipse.jgit.nls;version="5.5.0",
+ org.eclipse.jgit.notes;version="5.5.0";
   uses:="org.eclipse.jgit.lib,
    org.eclipse.jgit.treewalk,
    org.eclipse.jgit.revwalk,
    org.eclipse.jgit.merge",
- org.eclipse.jgit.patch;version="5.4.1";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.diff",
- org.eclipse.jgit.revplot;version="5.4.1";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.revwalk",
- org.eclipse.jgit.revwalk;version="5.4.1";
+ org.eclipse.jgit.patch;version="5.5.0";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.diff",
+ org.eclipse.jgit.revplot;version="5.5.0";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.revwalk",
+ org.eclipse.jgit.revwalk;version="5.5.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.4.1";uses:="org.eclipse.jgit.revwalk,org.eclipse.jgit.lib,org.eclipse.jgit.util",
- org.eclipse.jgit.storage.file;version="5.4.1";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.util",
- org.eclipse.jgit.storage.pack;version="5.4.1";uses:="org.eclipse.jgit.lib",
- org.eclipse.jgit.submodule;version="5.4.1";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.treewalk.filter,org.eclipse.jgit.treewalk",
- org.eclipse.jgit.transport;version="5.4.1";
+ org.eclipse.jgit.revwalk.filter;version="5.5.0";uses:="org.eclipse.jgit.revwalk,org.eclipse.jgit.lib,org.eclipse.jgit.util",
+ org.eclipse.jgit.storage.file;version="5.5.0";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.util",
+ org.eclipse.jgit.storage.pack;version="5.5.0";uses:="org.eclipse.jgit.lib",
+ org.eclipse.jgit.submodule;version="5.5.0";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.treewalk.filter,org.eclipse.jgit.treewalk",
+ org.eclipse.jgit.transport;version="5.5.0";
   uses:="org.eclipse.jgit.transport.resolver,
    org.eclipse.jgit.revwalk,
    org.eclipse.jgit.internal.storage.pack,
@@ -138,24 +138,24 @@
    org.eclipse.jgit.transport.http,
    org.eclipse.jgit.errors,
    org.eclipse.jgit.storage.pack",
- org.eclipse.jgit.transport.http;version="5.4.1";uses:="javax.net.ssl",
- org.eclipse.jgit.transport.resolver;version="5.4.1";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.transport",
- org.eclipse.jgit.treewalk;version="5.4.1";
+ org.eclipse.jgit.transport.http;version="5.5.0";uses:="javax.net.ssl",
+ org.eclipse.jgit.transport.resolver;version="5.5.0";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.transport",
+ org.eclipse.jgit.treewalk;version="5.5.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.4.1";uses:="org.eclipse.jgit.treewalk",
- org.eclipse.jgit.util;version="5.4.1";
+ org.eclipse.jgit.treewalk.filter;version="5.5.0";uses:="org.eclipse.jgit.treewalk",
+ org.eclipse.jgit.util;version="5.5.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.4.1",
- org.eclipse.jgit.util.sha1;version="5.4.1",
- org.eclipse.jgit.util.time;version="5.4.1"
+ org.eclipse.jgit.util.io;version="5.5.0",
+ org.eclipse.jgit.util.sha1;version="5.5.0",
+ org.eclipse.jgit.util.time;version="5.5.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 e21d207..780edcd 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.4.1.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit;version="5.4.1.qualifier";roots="."
+Bundle-Version: 5.5.0.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit;version="5.5.0.qualifier";roots="."
diff --git a/org.eclipse.jgit/plugin.properties b/org.eclipse.jgit/plugin.properties
index 3ce6709..3e132b0 100644
--- a/org.eclipse.jgit/plugin.properties
+++ b/org.eclipse.jgit/plugin.properties
@@ -1,2 +1,2 @@
-plugin_name=JGit Core
-provider_name=Eclipse JGit
+Bundle-Name=JGit Core
+Bundle-Vendor=Eclipse JGit
diff --git a/org.eclipse.jgit/pom.xml b/org.eclipse.jgit/pom.xml
index 1856716..cd187bf 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.4.1-SNAPSHOT</version>
+    <version>5.5.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 34faf31..e26163e 100644
--- a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
+++ b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
@@ -77,6 +77,7 @@
 cannotEnterObjectsPath=Cannot enter {0}/objects: {1}
 cannotEnterPathFromParent=Cannot enter {0} from {1}: {2}
 cannotExecute=cannot execute: {0}
+cannotFindMergeBaseUsingFirstParent=Cannot find merge bases using a first-parent walk.
 cannotGet=Cannot get {0}
 cannotGetObjectsPath=Cannot get {0}/{1}: {2}
 cannotListObjectsPath=Cannot ls {0}/{1}: {2}
@@ -135,6 +136,7 @@
 commitMessageNotSpecified=commit message not specified
 commitOnRepoWithoutHEADCurrentlyNotSupported=Commit on repo without HEAD currently not supported
 commitAmendOnInitialNotPossible=Amending is not possible on initial commit.
+commitsHaveAlreadyBeenMarkedAsStart=Commits have already been marked as walk starts.
 compressingObjects=Compressing objects
 configSubsectionContainsNewline=config subsection name contains newline
 configSubsectionContainsNullByte=config subsection name contains byte 0x00
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeCommand.java
index b8fa74d..f9a9baf 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeCommand.java
@@ -459,8 +459,8 @@
 	}
 
 	/**
-	 * Use values from the configuation if they have not been explicitly defined
-	 * via the setters
+	 * Use values from the configuration if they have not been explicitly
+	 * defined via the setters
 	 */
 	private void fallBackToConfiguration() {
 		MergeConfig config = MergeConfig.getConfigForCurrentBranch(repo);
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 22090f5..6bc2946 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java
@@ -1301,14 +1301,6 @@
 						JGitText.get().cannotDeleteFile, c));
 			removeEmptyParents(conflict);
 		}
-		for (String r : removed) {
-			File file = new File(repo.getWorkTree(), r);
-			if (!file.delete())
-				throw new CheckoutConflictException(
-						MessageFormat.format(JGitText.get().cannotDeleteFile,
-								file.getAbsolutePath()));
-			removeEmptyParents(file);
-		}
 	}
 
 	/**
@@ -1473,6 +1465,9 @@
 		ObjectLoader ol = or.open(entry.getObjectId());
 		File f = new File(repo.getWorkTree(), entry.getPathString());
 		File parentDir = f.getParentFile();
+		if (parentDir.isFile()) {
+			FileUtils.delete(parentDir);
+		}
 		FileUtils.mkdirs(parentDir, true);
 		FS fs = repo.getFS();
 		WorkingTreeOptions opt = repo.getConfig().get(WorkingTreeOptions.KEY);
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 3791850..320036c 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
@@ -138,6 +138,7 @@
 	/***/ public String cannotEnterObjectsPath;
 	/***/ public String cannotEnterPathFromParent;
 	/***/ public String cannotExecute;
+	/***/ public String cannotFindMergeBaseUsingFirstParent;
 	/***/ public String cannotGet;
 	/***/ public String cannotGetObjectsPath;
 	/***/ public String cannotListObjectsPath;
@@ -196,6 +197,7 @@
 	/***/ public String commitMessageNotSpecified;
 	/***/ public String commitOnRepoWithoutHEADCurrentlyNotSupported;
 	/***/ public String commitAmendOnInitialNotPossible;
+	/***/ public String commitsHaveAlreadyBeenMarkedAsStart;
 	/***/ public String compressingObjects;
 	/***/ public String configSubsectionContainsNewline;
 	/***/ public String configSubsectionContainsNullByte;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectory.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectory.java
index 258ccee..968ade6 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectory.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectory.java
@@ -171,7 +171,7 @@
 		infoDirectory = new File(objects, "info"); //$NON-NLS-1$
 		packDirectory = new File(objects, "pack"); //$NON-NLS-1$
 		preservedDirectory = new File(packDirectory, "preserved"); //$NON-NLS-1$
-		alternatesFile = new File(infoDirectory, "alternates"); //$NON-NLS-1$
+		alternatesFile = new File(objects, Constants.INFO_ALTERNATES);
 		packList = new AtomicReference<>(NO_PACKS);
 		unpackedObjectCache = new UnpackedObjectCache();
 		this.fs = fs;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/BaseRepositoryBuilder.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/BaseRepositoryBuilder.java
index d1cf1cd..96e5066 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/BaseRepositoryBuilder.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/BaseRepositoryBuilder.java
@@ -681,7 +681,7 @@
 	 */
 	protected void setupInternals() throws IOException {
 		if (getObjectDirectory() == null && getGitDir() != null)
-			setObjectDirectory(safeFS().resolve(getGitDir(), "objects")); //$NON-NLS-1$
+			setObjectDirectory(safeFS().resolve(getGitDir(), Constants.OBJECTS));
 	}
 
 	/**
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 8f4468e..a084c82 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Constants.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Constants.java
@@ -275,9 +275,27 @@
 	/** Logs folder name */
 	public static final String LOGS = "logs";
 
+	/**
+	 * Objects folder name
+	 * @since 5.5
+	 */
+	public static final String OBJECTS = "objects";
+
 	/** Info refs folder */
 	public static final String INFO_REFS = "info/refs";
 
+	/**
+	 * Info alternates file (goes under OBJECTS)
+	 * @since 5.5
+	 */
+	public static final String INFO_ALTERNATES = "info/alternates";
+
+	/**
+	 * HTTP alternates file (goes under OBJECTS)
+	 * @since 5.5
+	 */
+	public static final String INFO_HTTP_ALTERNATES = "info/http-alternates";
+
 	/** Packed refs file */
 	public static final String PACKED_REFS = "packed-refs";
 
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCache.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCache.java
index 27befba..fa113bf 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCache.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCache.java
@@ -474,7 +474,7 @@
 		 *         Git directory.
 		 */
 		public static boolean isGitRepository(File dir, FS fs) {
-			return fs.resolve(dir, "objects").exists() //$NON-NLS-1$
+			return fs.resolve(dir, Constants.OBJECTS).exists()
 					&& fs.resolve(dir, "refs").exists() //$NON-NLS-1$
 					&& isValidHead(new File(dir, Constants.HEAD));
 		}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/AbstractRevQueue.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/AbstractRevQueue.java
index 247a3bd..7b5e6fa 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/AbstractRevQueue.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/AbstractRevQueue.java
@@ -49,6 +49,10 @@
 	/** Current output flags set for this generator instance. */
 	int outputType;
 
+	AbstractRevQueue(boolean firstParent) {
+		super(firstParent);
+	}
+
 	/**
 	 * Add a commit to the queue.
 	 * <p>
@@ -96,10 +100,15 @@
 	 */
 	public final void addParents(RevCommit c, RevFlag queueControl) {
 		final RevCommit[] pList = c.parents;
-		if (pList == null)
+		if (pList == null) {
 			return;
-		for (RevCommit p : pList)
-			add(p, queueControl);
+		}
+		for (int i = 0; i < pList.length; i++) {
+			if (firstParent && i > 0) {
+				break;
+			}
+			add(pList[i], queueControl);
+		}
 	}
 
 	/**
@@ -138,6 +147,10 @@
 	}
 
 	private static class AlwaysEmptyQueue extends AbstractRevQueue {
+		private AlwaysEmptyQueue() {
+			super(false);
+		}
+
 		@Override
 		public void add(RevCommit c) {
 			throw new UnsupportedOperationException();
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/BlockRevQueue.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/BlockRevQueue.java
index 79307b5..64e9e03 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/BlockRevQueue.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/BlockRevQueue.java
@@ -53,13 +53,19 @@
 
 	/**
 	 * Create an empty revision queue.
+	 *
+	 * @param firstParent
+	 *            whether only first-parent links should be followed when
+	 *            walking
 	 */
-	protected BlockRevQueue() {
+	protected BlockRevQueue(boolean firstParent) {
+		super(firstParent);
 		free = new BlockFreeList();
 	}
 
 	BlockRevQueue(Generator s) throws MissingObjectException,
 			IncorrectObjectTypeException, IOException {
+		super(s.firstParent);
 		free = new BlockFreeList();
 		outputType = s.outputType();
 		s.shareFreeList(this);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/BoundaryGenerator.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/BoundaryGenerator.java
index 0fd6621..98c99e8 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/BoundaryGenerator.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/BoundaryGenerator.java
@@ -55,6 +55,7 @@
 	Generator g;
 
 	BoundaryGenerator(RevWalk w, Generator s) {
+		super(s.firstParent);
 		g = new InitialGenerator(w, s);
 	}
 
@@ -86,8 +87,9 @@
 		private final Generator source;
 
 		InitialGenerator(RevWalk w, Generator s) {
+			super(s.firstParent);
 			walk = w;
-			held = new FIFORevQueue();
+			held = new FIFORevQueue(firstParent);
 			source = s;
 			source.shareFreeList(held);
 		}
@@ -107,13 +109,19 @@
 				IncorrectObjectTypeException, IOException {
 			RevCommit c = source.next();
 			if (c != null) {
-				for (RevCommit p : c.parents)
-					if ((p.flags & UNINTERESTING) != 0)
+				for (int i = 0; i < c.parents.length; i++) {
+					if (firstParent && i > 0) {
+						break;
+					}
+					RevCommit p = c.parents[i];
+					if ((p.flags & UNINTERESTING) != 0) {
 						held.add(p);
+					}
+				}
 				return c;
 			}
 
-			final FIFORevQueue boundary = new FIFORevQueue();
+			final FIFORevQueue boundary = new FIFORevQueue(firstParent);
 			boundary.shareFreeList(held);
 			for (;;) {
 				c = held.next();
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/DateRevQueue.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/DateRevQueue.java
index b86e876..d77b055 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/DateRevQueue.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/DateRevQueue.java
@@ -69,15 +69,18 @@
 
 	private int last = -1;
 
-	/**
-	 * Create an empty date queue.
-	 */
+	/** Create an empty date queue. */
 	public DateRevQueue() {
-		super();
+		super(false);
+	}
+
+	DateRevQueue(boolean firstParent) {
+		super(firstParent);
 	}
 
 	DateRevQueue(Generator s) throws MissingObjectException,
 			IncorrectObjectTypeException, IOException {
+		super(s.firstParent);
 		for (;;) {
 			final RevCommit c = s.next();
 			if (c == null)
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/DelayRevQueue.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/DelayRevQueue.java
index c397a01..9134e08 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/DelayRevQueue.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/DelayRevQueue.java
@@ -70,6 +70,7 @@
 	private int size;
 
 	DelayRevQueue(Generator g) {
+		super(g.firstParent);
 		pending = g;
 		delay = new FIFORevQueue();
 	}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/DepthGenerator.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/DepthGenerator.java
index 5199a29..0b04d5d 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/DepthGenerator.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/DepthGenerator.java
@@ -95,7 +95,8 @@
 	 */
 	DepthGenerator(DepthWalk w, Generator s) throws MissingObjectException,
 			IncorrectObjectTypeException, IOException {
-		pending = new FIFORevQueue();
+		super(s.firstParent);
+		pending = new FIFORevQueue(firstParent);
 		walk = (RevWalk)w;
 
 		this.depth = w.getDepth();
@@ -196,7 +197,11 @@
 
 			int newDepth = c.depth + 1;
 
-			for (RevCommit p : c.parents) {
+			for (int i = 0; i < c.parents.length; i++) {
+				if (firstParent && i > 0) {
+					break;
+				}
+				RevCommit p = c.parents[i];
 				DepthWalk.Commit dp = (DepthWalk.Commit) p;
 
 				// If no depth has been assigned to this commit, assign
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/EndGenerator.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/EndGenerator.java
index 627e1c7..03916c8 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/EndGenerator.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/EndGenerator.java
@@ -47,7 +47,7 @@
 	static final EndGenerator INSTANCE = new EndGenerator();
 
 	private EndGenerator() {
-		// We have nothing to initialize.
+		super(false);
 	}
 
 	@Override
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/FIFORevQueue.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/FIFORevQueue.java
index cdb084c..40ee55c 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/FIFORevQueue.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/FIFORevQueue.java
@@ -56,11 +56,13 @@
 
 	private Block tail;
 
-	/**
-	 * Create an empty FIFO queue.
-	 */
+	/** Create an empty FIFO queue. */
 	public FIFORevQueue() {
-		super();
+		super(false);
+	}
+
+	FIFORevQueue(boolean firstParent) {
+		super(firstParent);
 	}
 
 	FIFORevQueue(Generator s) throws MissingObjectException,
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/FixUninterestingGenerator.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/FixUninterestingGenerator.java
index 4e6d7e6..289842a 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/FixUninterestingGenerator.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/FixUninterestingGenerator.java
@@ -62,6 +62,7 @@
 	private final Generator pending;
 
 	FixUninterestingGenerator(Generator g) {
+		super(g.firstParent);
 		pending = g;
 	}
 
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/Generator.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/Generator.java
index b2c92ea..59c5cce 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/Generator.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/Generator.java
@@ -75,6 +75,12 @@
 	/** Output may have {@link RevWalk#UNINTERESTING} marked on it. */
 	static final int HAS_UNINTERESTING = 1 << 4;
 
+	protected final boolean firstParent;
+
+	protected Generator(boolean firstParent) {
+		this.firstParent = firstParent;
+	}
+
 	/**
 	 * Connect the supplied queue to this generator's own free list (if any).
 	 *
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/LIFORevQueue.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/LIFORevQueue.java
index 846b8d9..5628d35 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/LIFORevQueue.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/LIFORevQueue.java
@@ -59,7 +59,7 @@
 	 * Create an empty LIFO queue.
 	 */
 	public LIFORevQueue() {
-		super();
+		super(false);
 	}
 
 	LIFORevQueue(Generator s) throws MissingObjectException,
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/MergeBaseGenerator.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/MergeBaseGenerator.java
index 2fe9531..4ea57cb 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/MergeBaseGenerator.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/MergeBaseGenerator.java
@@ -85,8 +85,9 @@
 	private CarryStack stack;
 
 	MergeBaseGenerator(RevWalk w) {
+		super(w.isFirstParent());
 		walker = w;
-		pending = new DateRevQueue();
+		pending = new DateRevQueue(firstParent);
 	}
 
 	void init(AbstractRevQueue p) throws IOException {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/PendingGenerator.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/PendingGenerator.java
index e607b7d..52dd56d 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/PendingGenerator.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/PendingGenerator.java
@@ -109,6 +109,7 @@
 
 	PendingGenerator(final RevWalk w, final DateRevQueue p,
 			final RevFilter f, final int out) {
+		super(w.isFirstParent());
 		walker = w;
 		pending = p;
 		filter = f;
@@ -140,7 +141,11 @@
 					produce = filter.include(walker, c);
 				}
 
-				for (RevCommit p : c.parents) {
+				for (int i = 0; i < c.parents.length; i++) {
+					RevCommit p = c.parents[i];
+					if (firstParent && i > 0) {
+						continue;
+					}
 					if ((p.flags & SEEN) != 0)
 						continue;
 					if ((p.flags & PARSED) == 0)
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 f50d189..4aa8325 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java
@@ -201,6 +201,8 @@
 
 	private boolean rewriteParents = true;
 
+	private boolean firstParent;
+
 	boolean shallowCommitsInitialized;
 
 	/**
@@ -233,7 +235,7 @@
 		idBuffer = new MutableObjectId();
 		objects = new ObjectIdOwnerMap<>();
 		roots = new ArrayList<>();
-		queue = new DateRevQueue();
+		queue = new DateRevQueue(false);
 		pending = new StartGenerator(this);
 		sorting = EnumSet.of(RevSort.NONE);
 		filter = RevFilter.ALL;
@@ -664,6 +666,35 @@
 	}
 
 	/**
+	 * @return whether only first-parent links should be followed when walking.
+	 *
+	 * @since 5.5
+	 */
+	public boolean isFirstParent() {
+		return firstParent;
+	}
+
+	/**
+	 * Set whether or not only first parent links should be followed.
+	 * <p>
+	 * If set, second- and higher-parent links are not traversed at all.
+	 * <p>
+	 * This must be called prior to {@link #markStart(RevCommit)}.
+	 *
+	 * @param enable
+	 *            true to walk only first-parent links.
+	 *
+	 * @since 5.5
+	 */
+	public void setFirstParent(boolean enable) {
+		assertNotStarted();
+		assertNoCommitsMarkedStart();
+		firstParent = enable;
+		queue = new DateRevQueue(firstParent);
+		pending = new StartGenerator(this);
+	}
+
+	/**
 	 * Locate a reference to a blob without loading it.
 	 * <p>
 	 * The blob may or may not exist in the repository. It is impossible to tell
@@ -1295,7 +1326,8 @@
 	 * <p>
 	 * Unlike {@link #dispose()} previously acquired RevObject (and RevCommit)
 	 * instances are not invalidated. RevFlag instances are not invalidated, but
-	 * are removed from all RevObjects.
+	 * are removed from all RevObjects. The value of {@code firstParent} is
+	 * retained.
 	 *
 	 * @param retainFlags
 	 *            application flags that should <b>not</b> be cleared from
@@ -1331,7 +1363,7 @@
 		}
 
 		roots.clear();
-		queue = new DateRevQueue();
+		queue = new DateRevQueue(firstParent);
 		pending = new StartGenerator(this);
 	}
 
@@ -1349,9 +1381,10 @@
 		delayFreeFlags = 0;
 		retainOnReset = 0;
 		carryFlags = UNINTERESTING;
+		firstParent = false;
 		objects.clear();
 		roots.clear();
-		queue = new DateRevQueue();
+		queue = new DateRevQueue(firstParent);
 		pending = new StartGenerator(this);
 		shallowCommitsInitialized = false;
 	}
@@ -1423,6 +1456,21 @@
 		throw new IllegalStateException(JGitText.get().outputHasAlreadyBeenStarted);
 	}
 
+	/**
+	 * Throws an exception if any commits have been marked as start.
+	 * <p>
+	 * If {@link #markStart(RevCommit)} has already been called,
+	 * {@link #reset()} can be called to satisfy this condition.
+	 *
+	 * @since 5.5
+	 */
+	protected void assertNoCommitsMarkedStart() {
+		if (roots.isEmpty())
+			return;
+		throw new IllegalStateException(
+				JGitText.get().commitsHaveAlreadyBeenMarkedAsStart);
+	}
+
 	private boolean isNotStarted() {
 		return pending instanceof StartGenerator;
 	}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RewriteGenerator.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RewriteGenerator.java
index 1c868ff..2e26641 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RewriteGenerator.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RewriteGenerator.java
@@ -77,6 +77,7 @@
 	private final Generator source;
 
 	RewriteGenerator(Generator s) {
+		super(s.firstParent);
 		source = s;
 	}
 
@@ -102,6 +103,10 @@
 		final int nParents = pList.length;
 		for (int i = 0; i < nParents; i++) {
 			final RevCommit oldp = pList[i];
+			if (firstParent && i > 0) {
+				c.parents = new RevCommit[] { rewrite(oldp) };
+				return c;
+			}
 			final RevCommit newp = rewrite(oldp);
 			if (oldp != newp) {
 				pList[i] = newp;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/StartGenerator.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/StartGenerator.java
index eb129a2..b309d6f 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/StartGenerator.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/StartGenerator.java
@@ -67,6 +67,7 @@
 	private final RevWalk walker;
 
 	StartGenerator(RevWalk w) {
+		super(w.isFirstParent());
 		walker = w;
 	}
 
@@ -89,9 +90,14 @@
 			// Computing for merge bases is a special case and does not
 			// use the bulk of the generator pipeline.
 			//
-			if (tf != TreeFilter.ALL)
+			if (tf != TreeFilter.ALL) {
 				throw new IllegalStateException(MessageFormat.format(
 						JGitText.get().cannotCombineTreeFilterWithRevFilter, tf, rf));
+			}
+			if (w.isFirstParent()) {
+				throw new IllegalStateException(
+						JGitText.get().cannotFindMergeBaseUsingFirstParent);
+			}
 
 			final MergeBaseGenerator mbg = new MergeBaseGenerator(w);
 			walker.pending = mbg;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/TopoSortGenerator.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/TopoSortGenerator.java
index 6450343..a2c9ef6 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/TopoSortGenerator.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/TopoSortGenerator.java
@@ -71,15 +71,21 @@
 	 */
 	TopoSortGenerator(Generator s) throws MissingObjectException,
 			IncorrectObjectTypeException, IOException {
-		pending = new FIFORevQueue();
+		super(s.firstParent);
+		pending = new FIFORevQueue(firstParent);
 		outputType = s.outputType() | SORT_TOPO;
 		s.shareFreeList(pending);
 		for (;;) {
 			final RevCommit c = s.next();
-			if (c == null)
+			if (c == null) {
 				break;
-			for (RevCommit p : c.parents)
-				p.inDegree++;
+			}
+			for (int i = 0; i < c.parents.length; i++) {
+				if (firstParent && i > 0) {
+					break;
+				}
+				c.parents[i].inDegree++;
+			}
 			pending.add(c);
 		}
 	}
@@ -113,7 +119,11 @@
 			// All of our children have already produced,
 			// so it is OK for us to produce now as well.
 			//
-			for (RevCommit p : c.parents) {
+			for (int i = 0; i < c.parents.length; i++) {
+				if (firstParent && i > 0) {
+					break;
+				}
+				RevCommit p = c.parents[i];
 				if (--p.inDegree == 0 && (p.flags & TOPO_DELAY) != 0) {
 					// This parent tried to come before us, but we are
 					// his last child. unpop the parent so it goes right
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/TreeRevFilter.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/TreeRevFilter.java
index 1130153..f7c3218 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/TreeRevFilter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/TreeRevFilter.java
@@ -116,8 +116,7 @@
 	 * @param rewriteFlag
 	 *            flag to color commits to be removed from the simplified DAT.
 	 */
-	TreeRevFilter(final RevWalk walker, final TreeFilter t,
-			final int rewriteFlag) {
+	TreeRevFilter(RevWalk walker, TreeFilter t, int rewriteFlag) {
 		pathFilter = new TreeWalk(walker.reader);
 		pathFilter.setFilter(t);
 		pathFilter.setRecursive(t.shouldBeRecursive());
@@ -137,14 +136,15 @@
 			IncorrectObjectTypeException, IOException {
 		// Reset the tree filter to scan this commit and parents.
 		//
-		final RevCommit[] pList = c.parents;
-		final int nParents = pList.length;
-		final TreeWalk tw = pathFilter;
-		final ObjectId[] trees = new ObjectId[nParents + 1];
+		RevCommit[] pList = c.parents;
+		int nParents = pList.length;
+		TreeWalk tw = pathFilter;
+		ObjectId[] trees = new ObjectId[nParents + 1];
 		for (int i = 0; i < nParents; i++) {
-			final RevCommit p = c.parents[i];
-			if ((p.flags & PARSED) == 0)
+			RevCommit p = c.parents[i];
+			if ((p.flags & PARSED) == 0) {
 				p.parseHeaders(walker);
+			}
 			trees[i] = p.getTree();
 		}
 		trees[nParents] = c.getTree();
@@ -156,10 +156,11 @@
 			int chgs = 0, adds = 0;
 			while (tw.next()) {
 				chgs++;
-				if (tw.getRawMode(0) == 0 && tw.getRawMode(1) != 0)
+				if (tw.getRawMode(0) == 0 && tw.getRawMode(1) != 0) {
 					adds++;
-				else
+				} else {
 					break; // no point in looking at this further.
+				}
 			}
 
 			if (chgs == 0) {
@@ -185,8 +186,9 @@
 			// We have no parents to compare against. Consider us to be
 			// REWRITE only if we have no paths matching our filter.
 			//
-			if (tw.next())
+			if (tw.next()) {
 				return true;
+			}
 			c.flags |= rewriteFlag;
 			return false;
 		}
@@ -196,18 +198,19 @@
 		// it does not contribute changes to us. Such a parent may be an
 		// uninteresting side branch.
 		//
-		final int[] chgs = new int[nParents];
-		final int[] adds = new int[nParents];
+		int[] chgs = new int[nParents];
+		int[] adds = new int[nParents];
 		while (tw.next()) {
-			final int myMode = tw.getRawMode(nParents);
+			int myMode = tw.getRawMode(nParents);
 			for (int i = 0; i < nParents; i++) {
-				final int pMode = tw.getRawMode(i);
-				if (myMode == pMode && tw.idEqual(i, nParents))
+				int pMode = tw.getRawMode(i);
+				if (myMode == pMode && tw.idEqual(i, nParents)) {
 					continue;
-
+				}
 				chgs[i]++;
-				if (pMode == 0 && myMode != 0)
+				if (pMode == 0 && myMode != 0) {
 					adds[i]++;
+				}
 			}
 		}
 
@@ -220,7 +223,7 @@
 				// parent commit.
 				//
 
-				final RevCommit p = pList[i];
+				RevCommit p = pList[i];
 				if ((p.flags & UNINTERESTING) != 0) {
 					// This parent was marked as not interesting by the
 					// application. We should look for another parent
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackFetchConnection.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackFetchConnection.java
index 57d6bc2..27cc205 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackFetchConnection.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackFetchConnection.java
@@ -129,13 +129,13 @@
 	public static final String OPTION_INCLUDE_TAG = GitProtocolConstants.OPTION_INCLUDE_TAG;
 
 	/**
-	 * Mutli-ACK support for improved negotiation.
+	 * Multi-ACK support for improved negotiation.
 	 * @since 2.0
 	 */
 	public static final String OPTION_MULTI_ACK = GitProtocolConstants.OPTION_MULTI_ACK;
 
 	/**
-	 * Mutli-ACK detailed support for improved negotiation.
+	 * Multi-ACK detailed support for improved negotiation.
 	 * @since 2.0
 	 */
 	public static final String OPTION_MULTI_ACK_DETAILED = GitProtocolConstants.OPTION_MULTI_ACK_DETAILED;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchV2Request.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchV2Request.java
index 6c24269..86574c1 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchV2Request.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchV2Request.java
@@ -72,6 +72,8 @@
 	@NonNull
 	private final List<String> serverOptions;
 
+	private final boolean sidebandAll;
+
 	FetchV2Request(@NonNull List<ObjectId> peerHas,
 			@NonNull List<String> wantedRefs,
 			@NonNull Set<ObjectId> wantIds,
@@ -79,7 +81,8 @@
 			@NonNull List<String> deepenNotRefs, int depth,
 			@NonNull FilterSpec filterSpec,
 			boolean doneReceived, @NonNull Set<String> clientCapabilities,
-			@Nullable String agent, @NonNull List<String> serverOptions) {
+			@Nullable String agent, @NonNull List<String> serverOptions,
+			boolean sidebandAll) {
 		super(wantIds, depth, clientShallowCommits, filterSpec,
 				clientCapabilities, deepenSince,
 				deepenNotRefs, agent);
@@ -87,6 +90,7 @@
 		this.wantedRefs = requireNonNull(wantedRefs);
 		this.doneReceived = doneReceived;
 		this.serverOptions = requireNonNull(serverOptions);
+		this.sidebandAll = sidebandAll;
 	}
 
 	/**
@@ -127,6 +131,13 @@
 		return serverOptions;
 	}
 
+	/**
+	 * @return true if "sideband-all" was received
+	 */
+	boolean getSidebandAll() {
+		return sidebandAll;
+	}
+
 	/** @return A builder of {@link FetchV2Request}. */
 	static Builder builder() {
 		return new Builder();
@@ -159,6 +170,8 @@
 
 		final List<String> serverOptions = new ArrayList<>();
 
+		boolean sidebandAll;
+
 		private Builder() {
 		}
 
@@ -318,13 +331,23 @@
 		}
 
 		/**
+		 * @param value true if client sent "sideband-all"
+		 * @return this builder
+		 */
+		Builder setSidebandAll(boolean value) {
+			sidebandAll = value;
+			return this;
+		}
+
+		/**
 		 * @return Initialized fetch request
 		 */
 		FetchV2Request build() {
 			return new FetchV2Request(peerHas, wantedRefs, wantIds,
 					clientShallowCommits, deepenSince, deepenNotRefs,
 					depth, filterSpec, doneReceived, clientCapabilities,
-					agent, Collections.unmodifiableList(serverOptions));
+					agent, Collections.unmodifiableList(serverOptions),
+					sidebandAll);
 		}
 	}
 }
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 1561c93..e3c0bc6 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/GitProtocolConstants.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/GitProtocolConstants.java
@@ -59,14 +59,14 @@
 	public static final String OPTION_INCLUDE_TAG = "include-tag"; //$NON-NLS-1$
 
 	/**
-	 * Mutli-ACK support for improved negotiation.
+	 * Multi-ACK support for improved negotiation.
 	 *
 	 * @since 3.2
 	 */
 	public static final String OPTION_MULTI_ACK = "multi_ack"; //$NON-NLS-1$
 
 	/**
-	 * Mutli-ACK detailed support for improved negotiation.
+	 * Multi-ACK detailed support for improved negotiation.
 	 *
 	 * @since 3.2
 	 */
@@ -174,6 +174,14 @@
 	public static final String OPTION_WANT_REF = "want-ref"; //$NON-NLS-1$
 
 	/**
+	 * The client requested that the whole response be multiplexed, with
+	 * each non-flush and non-delim pkt prefixed by a sideband designator.
+	 *
+	 * @since 5.5
+	 */
+	public static final String OPTION_SIDEBAND_ALL = "sideband-all"; //$NON-NLS-1$
+
+	/**
 	 * The client supports atomic pushes. If this option is used, the server
 	 * will update all refs within one atomic transaction.
 	 *
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/JschConfigSessionFactory.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/JschConfigSessionFactory.java
index 0bdd6ba..79af1eb 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/JschConfigSessionFactory.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/JschConfigSessionFactory.java
@@ -551,7 +551,7 @@
 	 * @param config
 	 *            to use
 	 */
-	void setConfig(OpenSshConfig config) {
+	synchronized void setConfig(OpenSshConfig config) {
 		this.config = config;
 	}
 }
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PacketLineOut.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PacketLineOut.java
index e940091..7f837bb 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PacketLineOut.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PacketLineOut.java
@@ -74,6 +74,8 @@
 
 	private boolean flushOnEnd;
 
+	private boolean usingSideband;
+
 	/**
 	 * Create a new packet line writer.
 	 *
@@ -98,6 +100,28 @@
 	}
 
 	/**
+	 * @return whether to add a sideband designator to each non-flush and
+	 *     non-delim packet
+	 * @see #setUsingSideband
+	 * @since 5.5
+	 */
+	public boolean isUsingSideband() {
+		return usingSideband;
+	}
+
+	/**
+	 * @param value If true, when writing packet lines, add, as the first
+	 *     byte, a sideband designator to each non-flush and non-delim
+	 *     packet. See pack-protocol.txt and protocol-v2.txt from the Git
+	 *     project for more information, specifically the "side-band" and
+	 *     "sideband-all" sections.
+	 * @since 5.5
+	 */
+	public void setUsingSideband(boolean value) {
+		this.usingSideband = value;
+	}
+
+	/**
 	 * Write a UTF-8 encoded string as a single length-delimited packet.
 	 *
 	 * @param s
@@ -139,8 +163,14 @@
 	 * @since 4.5
 	 */
 	public void writePacket(byte[] buf, int pos, int len) throws IOException {
-		formatLength(len + 4);
-		out.write(lenbuffer, 0, 4);
+		if (usingSideband) {
+			formatLength(len + 5);
+			out.write(lenbuffer, 0, 4);
+			out.write(1);
+		} else {
+			formatLength(len + 4);
+			out.write(lenbuffer, 0, 4);
+		}
 		out.write(buf, pos, len);
 		if (log.isDebugEnabled()) {
 			String s = RawParseUtils.decode(UTF_8, buf, pos, len);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PostUploadHookChain.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PostUploadHookChain.java
index 542abe7..4334888 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PostUploadHookChain.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PostUploadHookChain.java
@@ -42,7 +42,9 @@
 
 package org.eclipse.jgit.transport;
 
+import java.util.Collections;
 import java.util.List;
+import java.util.stream.Collectors;
 
 import org.eclipse.jgit.storage.pack.PackStatistics;
 
@@ -55,8 +57,7 @@
  * @since 4.1
  */
 public class PostUploadHookChain implements PostUploadHook {
-	private final PostUploadHook[] hooks;
-	private final int count;
+	private final List<PostUploadHook> hooks;
 
 	/**
 	 * Create a new hook chaining the given hooks together.
@@ -65,29 +66,29 @@
 	 *            hooks to execute, in order.
 	 * @return a new chain of the given hooks.
 	 */
-	public static PostUploadHook newChain(List<? extends PostUploadHook> hooks) {
-		PostUploadHook[] newHooks = new PostUploadHook[hooks.size()];
-		int i = 0;
-		for (PostUploadHook hook : hooks)
-			if (hook != PostUploadHook.NULL)
-				newHooks[i++] = hook;
-		if (i == 0)
+	public static PostUploadHook newChain(List<PostUploadHook> hooks) {
+		List<PostUploadHook> newHooks = hooks.stream()
+				.filter(hook -> !hook.equals(PostUploadHook.NULL))
+				.collect(Collectors.toList());
+
+		if (newHooks.isEmpty()) {
 			return PostUploadHook.NULL;
-		else if (i == 1)
-			return newHooks[0];
-		else
-			return new PostUploadHookChain(newHooks, i);
+		} else if (newHooks.size() == 1) {
+			return newHooks.get(0);
+		} else {
+			return new PostUploadHookChain(newHooks);
+		}
 	}
 
 	/** {@inheritDoc} */
 	@Override
 	public void onPostUpload(PackStatistics stats) {
-		for (int i = 0; i < count; i++)
-			hooks[i].onPostUpload(stats);
+		for (PostUploadHook hook : hooks) {
+			hook.onPostUpload(stats);
+		}
 	}
 
-	private PostUploadHookChain(PostUploadHook[] hooks, int count) {
-		this.hooks = hooks;
-		this.count = count;
+	private PostUploadHookChain(List<PostUploadHook> hooks) {
+		this.hooks = Collections.unmodifiableList(hooks);
 	}
 }
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PreUploadHookChain.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PreUploadHookChain.java
index bfd52af..2192654 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PreUploadHookChain.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PreUploadHookChain.java
@@ -44,7 +44,9 @@
 package org.eclipse.jgit.transport;
 
 import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
+import java.util.stream.Collectors;
 
 import org.eclipse.jgit.lib.ObjectId;
 
@@ -56,8 +58,7 @@
  * one hook throws an exception, execution of remaining hook methods is aborted.
  */
 public class PreUploadHookChain implements PreUploadHook {
-	private final PreUploadHook[] hooks;
-	private final int count;
+	private final List<PreUploadHook> hooks;
 
 	/**
 	 * Create a new hook chaining the given hooks together.
@@ -66,18 +67,18 @@
 	 *            hooks to execute, in order.
 	 * @return a new hook chain of the given hooks.
 	 */
-	public static PreUploadHook newChain(List<? extends PreUploadHook> hooks) {
-		PreUploadHook[] newHooks = new PreUploadHook[hooks.size()];
-		int i = 0;
-		for (PreUploadHook hook : hooks)
-			if (hook != PreUploadHook.NULL)
-				newHooks[i++] = hook;
-		if (i == 0)
+	public static PreUploadHook newChain(List<PreUploadHook> hooks) {
+		List<PreUploadHook> newHooks = hooks.stream()
+				.filter(hook -> !hook.equals(PreUploadHook.NULL))
+				.collect(Collectors.toList());
+
+		if (newHooks.isEmpty()) {
 			return PreUploadHook.NULL;
-		else if (i == 1)
-			return newHooks[0];
-		else
-			return new PreUploadHookChain(newHooks, i);
+		} else if (newHooks.size() == 1) {
+			return newHooks.get(0);
+		} else {
+			return new PreUploadHookChain(newHooks);
+		}
 	}
 
 	/** {@inheritDoc} */
@@ -85,8 +86,9 @@
 	public void onBeginNegotiateRound(UploadPack up,
 			Collection<? extends ObjectId> wants, int cntOffered)
 			throws ServiceMayNotContinueException {
-		for (int i = 0; i < count; i++)
-			hooks[i].onBeginNegotiateRound(up, wants, cntOffered);
+		for (PreUploadHook hook : hooks) {
+			hook.onBeginNegotiateRound(up, wants, cntOffered);
+		}
 	}
 
 	/** {@inheritDoc} */
@@ -95,8 +97,9 @@
 			Collection<? extends ObjectId> wants, int cntCommon,
 			int cntNotFound, boolean ready)
 			throws ServiceMayNotContinueException {
-		for (int i = 0; i < count; i++)
-			hooks[i].onEndNegotiateRound(up, wants, cntCommon, cntNotFound, ready);
+		for (PreUploadHook hook : hooks) {
+			hook.onEndNegotiateRound(up, wants, cntCommon, cntNotFound, ready);
+		}
 	}
 
 	/** {@inheritDoc} */
@@ -105,12 +108,12 @@
 			Collection<? extends ObjectId> wants,
 			Collection<? extends ObjectId> haves)
 			throws ServiceMayNotContinueException {
-		for (int i = 0; i < count; i++)
-			hooks[i].onSendPack(up, wants, haves);
+		for (PreUploadHook hook : hooks) {
+			hook.onSendPack(up, wants, haves);
+		}
 	}
 
-	private PreUploadHookChain(PreUploadHook[] hooks, int count) {
-		this.hooks = hooks;
-		this.count = count;
+	private PreUploadHookChain(List<PreUploadHook> hooks) {
+		this.hooks = Collections.unmodifiableList(hooks);
 	}
 }
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ProtocolV2HookChain.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ProtocolV2HookChain.java
new file mode 100644
index 0000000..cc36473
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ProtocolV2HookChain.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2019, 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;
+import java.util.stream.Collectors;
+
+/**
+ * {@link org.eclipse.jgit.transport.ProtocolV2Hook} that delegates to a list of
+ * other hooks.
+ * <p>
+ * Hooks are run in the order passed to the constructor. If running a method on
+ * one hook throws an exception, execution of remaining hook methods is aborted.
+ *
+ * @since 5.5
+ */
+public class ProtocolV2HookChain implements ProtocolV2Hook {
+	private final List<? extends ProtocolV2Hook> hooks;
+
+	/**
+	 * Create a new hook chaining the given hooks together.
+	 *
+	 * @param hooks
+	 *            hooks to execute, in order.
+	 * @return a new hook chain of the given hooks.
+	 */
+	public static ProtocolV2Hook newChain(
+			List<? extends ProtocolV2Hook> hooks) {
+		List<? extends ProtocolV2Hook> newHooks = hooks.stream()
+				.filter(hook -> !hook.equals(ProtocolV2Hook.DEFAULT))
+				.collect(Collectors.toList());
+
+		if (newHooks.isEmpty()) {
+			return ProtocolV2Hook.DEFAULT;
+		} else if (newHooks.size() == 1) {
+			return newHooks.get(0);
+		} else {
+			return new ProtocolV2HookChain(newHooks);
+		}
+	}
+
+	@Override
+	public void onCapabilities(CapabilitiesV2Request req)
+			throws ServiceMayNotContinueException {
+		for (ProtocolV2Hook hook : hooks) {
+			hook.onCapabilities(req);
+		}
+	}
+
+	@Override
+	public void onLsRefs(LsRefsV2Request req)
+			throws ServiceMayNotContinueException {
+		for (ProtocolV2Hook hook : hooks) {
+			hook.onLsRefs(req);
+		}
+	}
+
+	@Override
+	public void onFetch(FetchV2Request req)
+			throws ServiceMayNotContinueException {
+		for (ProtocolV2Hook hook : hooks) {
+			hook.onFetch(req);
+		}
+	}
+
+	private ProtocolV2HookChain(List<? extends ProtocolV2Hook> hooks) {
+		this.hooks = Collections.unmodifiableList(hooks);
+	}
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ProtocolV2Parser.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ProtocolV2Parser.java
index caba15f..453be7f 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ProtocolV2Parser.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ProtocolV2Parser.java
@@ -49,6 +49,7 @@
 import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_NO_PROGRESS;
 import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_OFS_DELTA;
 import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_SERVER_OPTION;
+import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_SIDEBAND_ALL;
 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;
@@ -210,6 +211,9 @@
 				filterReceived = true;
 				reqBuilder.setFilterSpec(FilterSpec.fromFilterLine(
 						line2.substring(OPTION_FILTER.length() + 1)));
+			} else if (transferConfig.isAllowSidebandAll()
+					&& line2.equals(OPTION_SIDEBAND_ALL)) {
+				reqBuilder.setSidebandAll(true);
 			} else {
 				throw new PackProtocolException(MessageFormat
 						.format(JGitText.get().unexpectedPacketLine, line2));
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 a3e655c..758d74c 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransferConfig.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransferConfig.java
@@ -131,6 +131,7 @@
 	private final boolean allowTipSha1InWant;
 	private final boolean allowReachableSha1InWant;
 	private final boolean allowFilter;
+	private final boolean allowSidebandAll;
 	final @Nullable ProtocolVersion protocolVersion;
 	final String[] hideRefs;
 
@@ -210,6 +211,8 @@
 				"uploadpack", "allowfilter", false);
 		protocolVersion = ProtocolVersion.parse(rc.getString("protocol", null, "version"));
 		hideRefs = rc.getStringList("uploadpack", null, "hiderefs");
+		allowSidebandAll = rc.getBoolean(
+				"uploadpack", "allowsidebandall", false);
 	}
 
 	/**
@@ -292,6 +295,14 @@
 	}
 
 	/**
+	 * @return true if clients are allowed to specify a "sideband-all" line
+	 * @since 5.5
+	 */
+	public boolean isAllowSidebandAll() {
+		return allowSidebandAll;
+	}
+
+	/**
 	 * Get {@link org.eclipse.jgit.transport.RefFilter} respecting configured
 	 * hidden refs.
 	 *
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportAmazonS3.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportAmazonS3.java
index 6118cb8..c0a70bc 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportAmazonS3.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportAmazonS3.java
@@ -259,7 +259,7 @@
 		@Override
 		Collection<WalkRemoteObjectDatabase> getAlternates() throws IOException {
 			try {
-				return readAlternates(INFO_ALTERNATES);
+				return readAlternates(Constants.INFO_ALTERNATES);
 			} catch (FileNotFoundException err) {
 				// Fall through.
 			}
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 27ab879..d5b06c1 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java
@@ -48,6 +48,8 @@
 
 import static java.nio.charset.StandardCharsets.UTF_8;
 import static org.eclipse.jgit.lib.Constants.HEAD;
+import static org.eclipse.jgit.lib.Constants.INFO_ALTERNATES;
+import static org.eclipse.jgit.lib.Constants.INFO_HTTP_ALTERNATES;
 import static org.eclipse.jgit.util.HttpSupport.ENCODING_GZIP;
 import static org.eclipse.jgit.util.HttpSupport.ENCODING_X_GZIP;
 import static org.eclipse.jgit.util.HttpSupport.HDR_ACCEPT;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportSftp.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportSftp.java
index 5c68308..8d91c60 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportSftp.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportSftp.java
@@ -43,7 +43,9 @@
 
 package org.eclipse.jgit.transport;
 
+import static org.eclipse.jgit.lib.Constants.INFO_ALTERNATES;
 import static org.eclipse.jgit.lib.Constants.LOCK_SUFFIX;
+import static org.eclipse.jgit.lib.Constants.OBJECTS;
 
 import java.io.BufferedReader;
 import java.io.FileNotFoundException;
@@ -172,7 +174,7 @@
 			try {
 				ftp = newSftp();
 				ftp.cd(path);
-				ftp.cd("objects"); //$NON-NLS-1$
+				ftp.cd(OBJECTS);
 				objectsPath = ftp.pwd();
 			} catch (FtpChannel.FtpException f) {
 				throw new TransportException(MessageFormat.format(
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 9278f42..2194f2f 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java
@@ -61,6 +61,7 @@
 import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_NO_PROGRESS;
 import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_OFS_DELTA;
 import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_SHALLOW;
+import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_SIDEBAND_ALL;
 import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_SIDE_BAND;
 import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_SIDE_BAND_64K;
 import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_THIN_PACK;
@@ -113,6 +114,7 @@
 import org.eclipse.jgit.revwalk.RevFlag;
 import org.eclipse.jgit.revwalk.RevFlagSet;
 import org.eclipse.jgit.revwalk.RevObject;
+import org.eclipse.jgit.revwalk.RevSort;
 import org.eclipse.jgit.revwalk.RevTag;
 import org.eclipse.jgit.revwalk.RevWalk;
 import org.eclipse.jgit.revwalk.filter.CommitTimeRevFilter;
@@ -277,8 +279,6 @@
 
 	private PacketLineIn pckIn;
 
-	private PacketLineOut pckOut;
-
 	private OutputStream msgOut = NullOutputStream.INSTANCE;
 
 	/**
@@ -602,6 +602,18 @@
 	}
 
 	/**
+	 * Get the currently installed protocol v2 hook.
+	 *
+	 * @return the hook or a default implementation if none installed.
+	 *
+	 * @since 5.5
+	 */
+	public ProtocolV2Hook getProtocolV2Hook() {
+		return this.protocolV2Hook != null ? this.protocolV2Hook
+				: ProtocolV2Hook.DEFAULT;
+	}
+
+	/**
 	 * 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
@@ -750,8 +762,9 @@
 	 *            other network connections this should be null.
 	 * @throws java.io.IOException
 	 */
-	public void upload(final InputStream input, OutputStream output,
-			final OutputStream messages) throws IOException {
+	public void upload(InputStream input, OutputStream output,
+			@Nullable OutputStream messages) throws IOException {
+		PacketLineOut pckOut = null;
 		try {
 			rawIn = input;
 			if (messages != null)
@@ -777,10 +790,40 @@
 			pckIn = new PacketLineIn(rawIn);
 			pckOut = new PacketLineOut(rawOut);
 			if (useProtocolV2()) {
-				serviceV2();
+				serviceV2(pckOut);
 			} else {
-				service();
+				service(pckOut);
 			}
+		} catch (UploadPackInternalServerErrorException err) {
+			// UploadPackInternalServerErrorException is a special exception
+			// that indicates an error is already written to the client. Do
+			// nothing.
+			throw err;
+		} catch (ServiceMayNotContinueException err) {
+			if (!err.isOutput() && err.getMessage() != null && pckOut != null) {
+				try {
+					pckOut.writeString("ERR " + err.getMessage() + "\n"); //$NON-NLS-1$ //$NON-NLS-2$
+				} catch (IOException e) {
+					err.addSuppressed(e);
+					throw err;
+				}
+				err.setOutput();
+			}
+			throw err;
+		} catch (IOException | RuntimeException | Error err) {
+			if (pckOut != null) {
+				String msg = err instanceof PackProtocolException
+						? err.getMessage()
+						: JGitText.get().internalServerError;
+				try {
+					pckOut.writeString("ERR " + msg + "\n"); //$NON-NLS-1$ //$NON-NLS-2$
+				} catch (IOException e) {
+					err.addSuppressed(e);
+					throw err;
+				}
+				throw new UploadPackInternalServerErrorException(err);
+			}
+			throw err;
 		} finally {
 			msgOut = NullOutputStream.INSTANCE;
 			walk.close();
@@ -941,7 +984,7 @@
 		return RefDatabase.findRef(getAdvertisedOrDefaultRefs(), name);
 	}
 
-	private void service() throws IOException {
+	private void service(PacketLineOut pckOut) throws IOException {
 		boolean sendPack = false;
 		// If it's a non-bidi request, we need to read the entire request before
 		// writing a response. Buffer the response until then.
@@ -997,7 +1040,7 @@
 
 			if (!req.getClientShallowCommits().isEmpty())
 				walk.assumeShallow(req.getClientShallowCommits());
-			sendPack = negotiate(req, accumulator);
+			sendPack = negotiate(req, accumulator, pckOut);
 			accumulator.timeNegotiating += System.currentTimeMillis()
 					- negotiateStart;
 
@@ -1012,31 +1055,6 @@
 							"\\x" + Integer.toHexString(eof))); //$NON-NLS-1$
 				}
 			}
-		} catch (ServiceMayNotContinueException err) {
-			if (!err.isOutput() && err.getMessage() != null) {
-				try {
-					pckOut.writeString("ERR " + err.getMessage() + "\n"); //$NON-NLS-1$ //$NON-NLS-2$
-					err.setOutput();
-				} catch (Throwable err2) {
-					// Ignore this secondary failure (and not mark output).
-				}
-			}
-			throw err;
-		} catch (IOException | RuntimeException | Error err) {
-			boolean output = false;
-			try {
-				String msg = err instanceof PackProtocolException
-						? err.getMessage()
-						: JGitText.get().internalServerError;
-				pckOut.writeString("ERR " + msg + "\n"); //$NON-NLS-1$ //$NON-NLS-2$
-				output = true;
-			} catch (Throwable err2) {
-				// Ignore this secondary failure, leave output false.
-			}
-			if (output) {
-				throw new UploadPackInternalServerErrorException(err);
-			}
-			throw err;
 		} finally {
 			if (!sendPack && !biDirectionalPipe) {
 				while (0 < rawIn.skip(2048) || 0 <= rawIn.read()) {
@@ -1048,11 +1066,11 @@
 
 		if (sendPack) {
 			sendPack(accumulator, req, refs == null ? null : refs.values(),
-					unshallowCommits, Collections.emptyList());
+					unshallowCommits, Collections.emptyList(), pckOut);
 		}
 	}
 
-	private void lsRefsV2() throws IOException {
+	private void lsRefsV2(PacketLineOut pckOut) throws IOException {
 		ProtocolV2Parser parser = new ProtocolV2Parser(transferConfig);
 		LsRefsV2Request req = parser.parseLsRefsRequest(pckIn);
 		protocolV2Hook.onLsRefs(req);
@@ -1097,7 +1115,7 @@
 		return result;
 	}
 
-	private void fetchV2() throws IOException {
+	private void fetchV2(PacketLineOut pckOut) throws IOException {
 		// Depending on the requestValidator, #processHaveLines may
 		// require that advertised be set. Set it only in the required
 		// circumstances (to avoid a full ref lookup in the case that
@@ -1117,6 +1135,10 @@
 
 		protocolV2Hook.onFetch(req);
 
+		if (req.getSidebandAll()) {
+			pckOut.setUsingSideband(true);
+		}
+
 		// TODO(ifrade): Refactor to pass around the Request object, instead of
 		// copying data back to class fields
 		List<ObjectId> deepenNots = new ArrayList<>();
@@ -1202,13 +1224,17 @@
 
 			if (sectionSent)
 				pckOut.writeDelim();
-			pckOut.writeString("packfile\n"); //$NON-NLS-1$
+			if (!pckOut.isUsingSideband()) {
+				// sendPack will write "packfile\n" for us if sideband-all is used.
+				// But sideband-all is not used, so we have to write it ourselves.
+				pckOut.writeString("packfile\n"); //$NON-NLS-1$
+			}
 			sendPack(new PackStatistics.Accumulator(),
 					req,
 					req.getClientCapabilities().contains(OPTION_INCLUDE_TAG)
 						? db.getRefDatabase().getRefsByPrefix(R_TAGS)
 						: null,
-					unshallowCommits, deepenNots);
+					unshallowCommits, deepenNots, pckOut);
 			// sendPack invokes pckOut.end() for us, so we do not
 			// need to invoke it here.
 		} else {
@@ -1221,7 +1247,7 @@
 	 * Returns true if this is the last command and we should tear down the
 	 * connection.
 	 */
-	private boolean serveOneCommandV2() throws IOException {
+	private boolean serveOneCommandV2(PacketLineOut pckOut) throws IOException {
 		String command;
 		try {
 			command = pckIn.readString();
@@ -1236,11 +1262,11 @@
 			return true;
 		}
 		if (command.equals("command=" + COMMAND_LS_REFS)) { //$NON-NLS-1$
-			lsRefsV2();
+			lsRefsV2(pckOut);
 			return false;
 		}
 		if (command.equals("command=" + COMMAND_FETCH)) { //$NON-NLS-1$
-			fetchV2();
+			fetchV2(pckOut);
 			return false;
 		}
 		throw new PackProtocolException(MessageFormat
@@ -1258,12 +1284,13 @@
 				COMMAND_FETCH + '=' +
 				(transferConfig.isAllowFilter() ? OPTION_FILTER + ' ' : "") + //$NON-NLS-1$
 				(advertiseRefInWant ? CAPABILITY_REF_IN_WANT + ' ' : "") + //$NON-NLS-1$
+				(transferConfig.isAllowSidebandAll() ? OPTION_SIDEBAND_ALL + ' ' : "") + //$NON-NLS-1$
 				OPTION_SHALLOW);
 		caps.add(CAPABILITY_SERVER_OPTION);
 		return caps;
 	}
 
-	private void serviceV2() throws IOException {
+	private void serviceV2(PacketLineOut pckOut) throws IOException {
 		if (biDirectionalPipe) {
 			// Just like in service(), the capability advertisement
 			// is sent only if this is a bidirectional pipe. (If
@@ -1276,14 +1303,14 @@
 			}
 			pckOut.end();
 
-			while (!serveOneCommandV2()) {
+			while (!serveOneCommandV2(pckOut)) {
 				// Repeat until an empty command or EOF.
 			}
 			return;
 		}
 
 		try {
-			serveOneCommandV2();
+			serveOneCommandV2(pckOut);
 		} finally {
 			while (0 < rawIn.skip(2048) || 0 <= rawIn.read()) {
 				// Discard until EOF.
@@ -1579,7 +1606,8 @@
 	}
 
 	private boolean negotiate(FetchRequest req,
-			PackStatistics.Accumulator accumulator)
+			PackStatistics.Accumulator accumulator,
+			PacketLineOut pckOut)
 			throws IOException {
 		okToGiveUp = Boolean.FALSE;
 
@@ -1868,6 +1896,36 @@
 		}
 	}
 
+	private static void checkReachabilityByWalkingObjects(ObjectWalk walk,
+			List<RevObject> wants, Set<ObjectId> reachableFrom) throws IOException {
+
+		walk.sort(RevSort.TOPO);
+		for (RevObject want : wants) {
+			walk.markStart(want);
+		}
+		for (ObjectId have : reachableFrom) {
+			RevObject o = walk.parseAny(have);
+			walk.markUninteresting(o);
+
+			RevObject peeled = walk.peel(o);
+			if (peeled instanceof RevCommit) {
+				// By default, for performance reasons, ObjectWalk does not mark a
+				// tree as uninteresting when we mark a commit. Mark it ourselves so
+				// that we can determine reachability exactly.
+				walk.markUninteresting(((RevCommit) peeled).getTree());
+			}
+		}
+
+		RevCommit commit = walk.next();
+		if (commit != null) {
+			throw new WantNotValidException(commit);
+		}
+		RevObject object = walk.nextObject();
+		if (object != null) {
+			throw new WantNotValidException(object);
+		}
+	}
+
 	private static void checkNotAdvertisedWants(UploadPack up,
 			List<ObjectId> notAdvertisedWants, Set<ObjectId> reachableFrom)
 			throws IOException {
@@ -1888,6 +1946,17 @@
 
 			if (!allWantsAreCommits) {
 				if (!repoHasBitmaps) {
+					if (up.transferConfig.isAllowFilter()) {
+						// Use allowFilter as an indication that the server
+						// operator is willing to pay the cost of these
+						// reachability checks.
+						try (ObjectWalk objWalk = walk.toObjectWalkWithSameObjects()) {
+							checkReachabilityByWalkingObjects(objWalk,
+									wantsAsObjs, reachableFrom);
+						}
+						return;
+					}
+
 					// If unadvertized non-commits are requested, use
 					// bitmaps. If there are no bitmaps, instead of
 					// incurring the expense of a manual walk, reject
@@ -2016,6 +2085,8 @@
 	 *            shallow commits on the client that are now becoming unshallow
 	 * @param deepenNots
 	 *            objects that the client specified using --shallow-exclude
+	 * @param pckOut
+	 *            output writer
 	 * @throws IOException
 	 *             if an error occurred while generating or writing the pack.
 	 */
@@ -2023,43 +2094,51 @@
 			FetchRequest req,
 			@Nullable Collection<Ref> allTags,
 			List<ObjectId> unshallowCommits,
-			List<ObjectId> deepenNots) throws IOException {
+			List<ObjectId> deepenNots,
+			PacketLineOut pckOut) throws IOException {
 		Set<String> caps = req.getClientCapabilities();
 		boolean sideband = caps.contains(OPTION_SIDE_BAND)
 				|| caps.contains(OPTION_SIDE_BAND_64K);
 		if (sideband) {
 			try {
 				sendPack(true, req, accumulator, allTags, unshallowCommits,
-						deepenNots);
-			} catch (ServiceMayNotContinueException noPack) {
-				// This was already reported on (below).
-				throw noPack;
-			} catch (IOException | RuntimeException | Error err) {
-				if (reportInternalServerErrorOverSideband()) {
-					throw new UploadPackInternalServerErrorException(err);
-				} else {
+						deepenNots, pckOut);
+			} catch (ServiceMayNotContinueException err) {
+				String message = err.getMessage();
+				if (message == null) {
+					message = JGitText.get().internalServerError;
+				}
+				try {
+					reportInternalServerErrorOverSideband(message);
+				} catch (IOException e) {
+					err.addSuppressed(e);
 					throw err;
 				}
+				throw new UploadPackInternalServerErrorException(err);
+			} catch (IOException | RuntimeException | Error err) {
+				try {
+					reportInternalServerErrorOverSideband(
+							JGitText.get().internalServerError);
+				} catch (IOException e) {
+					err.addSuppressed(e);
+					throw err;
+				}
+				throw new UploadPackInternalServerErrorException(err);
 			}
 		} else {
-			sendPack(false, req, accumulator, allTags, unshallowCommits, deepenNots);
+			sendPack(false, req, accumulator, allTags, unshallowCommits, deepenNots,
+					pckOut);
 		}
 	}
 
-	private boolean reportInternalServerErrorOverSideband() {
-		try {
-			@SuppressWarnings("resource" /* java 7 */)
-			SideBandOutputStream err = new SideBandOutputStream(
-					SideBandOutputStream.CH_ERROR,
-					SideBandOutputStream.SMALL_BUF,
-					rawOut);
-			err.write(Constants.encode(JGitText.get().internalServerError));
-			err.flush();
-			return true;
-		} catch (Throwable cannotReport) {
-			// Ignore the reason. This is a secondary failure.
-			return false;
-		}
+	private void reportInternalServerErrorOverSideband(String message)
+			throws IOException {
+		@SuppressWarnings("resource" /* java 7 */)
+		SideBandOutputStream err = new SideBandOutputStream(
+				SideBandOutputStream.CH_ERROR, SideBandOutputStream.SMALL_BUF,
+				rawOut);
+		err.write(Constants.encode(message));
+		err.flush();
 	}
 
 	/**
@@ -2079,6 +2158,8 @@
 	 *            shallow commits on the client that are now becoming unshallow
 	 * @param deepenNots
 	 *            objects that the client specified using --shallow-exclude
+	 * @param pckOut
+	 *            output writer
 	 * @throws IOException
 	 *             if an error occurred while generating or writing the pack.
 	 */
@@ -2087,7 +2168,8 @@
 			PackStatistics.Accumulator accumulator,
 			@Nullable Collection<Ref> allTags,
 			List<ObjectId> unshallowCommits,
-			List<ObjectId> deepenNots) throws IOException {
+			List<ObjectId> deepenNots,
+			PacketLineOut pckOut) throws IOException {
 		ProgressMonitor pm = NullProgressMonitor.INSTANCE;
 		OutputStream packOut = rawOut;
 
@@ -2105,25 +2187,12 @@
 			}
 		}
 
-		try {
-			if (wantAll.isEmpty()) {
-				preUploadHook.onSendPack(this, wantIds, commonBase);
-			} else {
-				preUploadHook.onSendPack(this, wantAll, commonBase);
-			}
-			msgOut.flush();
-		} catch (ServiceMayNotContinueException noPack) {
-			if (sideband && noPack.getMessage() != null) {
-				noPack.setOutput();
-				@SuppressWarnings("resource" /* java 7 */)
-				SideBandOutputStream err = new SideBandOutputStream(
-						SideBandOutputStream.CH_ERROR,
-						SideBandOutputStream.SMALL_BUF, rawOut);
-				err.write(Constants.encode(noPack.getMessage()));
-				err.flush();
-			}
-			throw noPack;
+		if (wantAll.isEmpty()) {
+			preUploadHook.onSendPack(this, wantIds, commonBase);
+		} else {
+			preUploadHook.onSendPack(this, wantAll, commonBase);
 		}
+		msgOut.flush();
 
 		PackConfig cfg = packConfig;
 		if (cfg == null)
@@ -2219,12 +2288,18 @@
 					if (peeledId == null || objectId == null)
 						continue;
 
+					objectId = ref.getObjectId();
 					if (pw.willInclude(peeledId) && !pw.willInclude(objectId)) {
-						pw.addObject(rw.parseAny(objectId));
+						RevObject o = rw.parseAny(objectId);
+						addTagChain(o, pw);
+						pw.addObject(o);
 					}
 				}
 			}
 
+			if (pckOut.isUsingSideband()) {
+				pckOut.writeString("packfile\n"); //$NON-NLS-1$
+			}
 			pw.writePack(pm, NullProgressMonitor.INSTANCE, packOut);
 
 			if (msgOut != NullOutputStream.INSTANCE) {
@@ -2253,6 +2328,18 @@
 		}
 	}
 
+	private void addTagChain(
+			RevObject o, PackWriter pw) throws IOException {
+		while (Constants.OBJ_TAG == o.getType()) {
+			RevTag t = (RevTag) o;
+			o = t.getObject();
+			if (o.getType() == Constants.OBJ_TAG && !pw.willInclude(o.getId())) {
+				walk.parseBody(o);
+				pw.addObject(o);
+			}
+		}
+	}
+
 	private static class ResponseBufferedOutputStream extends OutputStream {
 		private final OutputStream rawOut;
 
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkEncryption.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkEncryption.java
index b4248ee..7a973af 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkEncryption.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkEncryption.java
@@ -66,8 +66,8 @@
 import javax.crypto.spec.PBEKeySpec;
 import javax.crypto.spec.PBEParameterSpec;
 import javax.crypto.spec.SecretKeySpec;
-import javax.xml.bind.DatatypeConverter;
 
+import org.bouncycastle.util.encoders.Hex;
 import org.eclipse.jgit.internal.JGitText;
 import org.eclipse.jgit.util.Base64;
 
@@ -301,7 +301,7 @@
 		String DEFAULT_KEY_ALGO = JetS3tV2.ALGORITHM;
 		String DEFAULT_KEY_SIZE = Integer.toString(JetS3tV2.KEY_SIZE);
 		String DEFAULT_KEY_ITER = Integer.toString(JetS3tV2.ITERATIONS);
-		String DEFAULT_KEY_SALT = DatatypeConverter.printHexBinary(JetS3tV2.SALT);
+		String DEFAULT_KEY_SALT = Hex.toHexString(JetS3tV2.SALT);
 
 		String EMPTY = ""; //$NON-NLS-1$
 
@@ -377,8 +377,7 @@
 
 			final byte[] salt;
 			try {
-				salt = DatatypeConverter
-						.parseHexBinary(keySalt.replaceAll(REGEX_WS, EMPTY));
+				salt = Hex.decode(keySalt.replaceAll(REGEX_WS, EMPTY));
 			} catch (Exception e) {
 				throw securityError(X_KEY_SALT + EMPTY + keySalt);
 			}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkRemoteObjectDatabase.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkRemoteObjectDatabase.java
index 5c67253..4862d67 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkRemoteObjectDatabase.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkRemoteObjectDatabase.java
@@ -82,10 +82,6 @@
 
 	static final String INFO_PACKS = "info/packs"; //$NON-NLS-1$
 
-	static final String INFO_ALTERNATES = "info/alternates"; //$NON-NLS-1$
-
-	static final String INFO_HTTP_ALTERNATES = "info/http-alternates"; //$NON-NLS-1$
-
 	static final String INFO_REFS = ROOT_DIR + Constants.INFO_REFS;
 
 	abstract URIish getURI();
@@ -107,8 +103,10 @@
 	/**
 	 * Obtain alternate connections to alternate object databases (if any).
 	 * <p>
-	 * Alternates are typically read from the file {@link #INFO_ALTERNATES} or
-	 * {@link #INFO_HTTP_ALTERNATES}. The content of each line must be resolved
+         * Alternates are typically read from the file
+         * {@link org.eclipse.jgit.lib.Constants#INFO_ALTERNATES} or
+         * {@link org.eclipse.jgit.lib.Constants#INFO_HTTP_ALTERNATES}.
+         * The content of each line must be resolved
 	 * by the implementation and a new database reference should be returned to
 	 * represent the additional location.
 	 * <p>
diff --git a/pom.xml b/pom.xml
index 51e7b67..8da9a88 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.4.1-SNAPSHOT</version>
+  <version>5.5.0-SNAPSHOT</version>
 
   <name>JGit - Parent</name>
   <url>${jgit-url}</url>
@@ -182,7 +182,7 @@
     <maven.build.timestamp.format>yyyyMMddHHmm</maven.build.timestamp.format>
     <bundle-manifest>${project.build.directory}/META-INF/MANIFEST.MF</bundle-manifest>
 
-    <jgit-last-release-version>5.3.0.201903130848-r</jgit-last-release-version>
+    <jgit-last-release-version>5.4.0.201906121030-r</jgit-last-release-version>
     <apache-sshd-version>2.2.0</apache-sshd-version>
     <jsch-version>0.1.55</jsch-version>
     <jzlib-version>1.1.1</jzlib-version>
@@ -199,14 +199,13 @@
     <httpcore-version>4.4.10</httpcore-version>
     <slf4j-version>1.7.2</slf4j-version>
     <log4j-version>1.2.15</log4j-version>
-    <maven-javadoc-plugin-version>3.1.0</maven-javadoc-plugin-version>
+    <maven-javadoc-plugin-version>3.1.1</maven-javadoc-plugin-version>
     <tycho-extras-version>1.3.0</tycho-extras-version>
     <gson-version>2.8.2</gson-version>
     <bouncycastle-version>1.61</bouncycastle-version>
-    <spotbugs-maven-plugin-version>3.1.12</spotbugs-maven-plugin-version>
+    <spotbugs-maven-plugin-version>3.1.12.2</spotbugs-maven-plugin-version>
     <maven-project-info-reports-plugin-version>3.0.0</maven-project-info-reports-plugin-version>
     <maven-jxr-plugin-version>3.0.0</maven-jxr-plugin-version>
-    <spotbugs-maven-plugin-version>3.1.12</spotbugs-maven-plugin-version>
     <maven-surefire-plugin-version>3.0.0-M3</maven-surefire-plugin-version>
     <maven-surefire-report-plugin-version>${maven-surefire-plugin-version}</maven-surefire-report-plugin-version>
     <maven-compiler-plugin-version>3.8.1</maven-compiler-plugin-version>
@@ -353,7 +352,7 @@
         <plugin>
           <groupId>org.eclipse.cbi.maven.plugins</groupId>
           <artifactId>eclipse-jarsigner-plugin</artifactId>
-          <version>1.1.5</version>
+          <version>1.1.6</version>
         </plugin>
         <plugin>
           <groupId>org.eclipse.tycho.extras</groupId>
@@ -373,12 +372,12 @@
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-site-plugin</artifactId>
-          <version>3.7.1</version>
+          <version>3.8.2</version>
           <dependencies>
             <dependency><!-- add support for ssh/scp -->
               <groupId>org.apache.maven.wagon</groupId>
               <artifactId>wagon-ssh</artifactId>
-              <version>3.3.2</version>
+              <version>3.3.3</version>
             </dependency>
           </dependencies>
         </plugin>
@@ -927,7 +926,7 @@
               <dependency>
                 <groupId>org.eclipse.jdt</groupId>
                 <artifactId>ecj</artifactId>
-                <version>3.17.0</version>
+                <version>3.18.0</version>
               </dependency>
             </dependencies>
           </plugin>