Merge branch 'stable-4.5' into stable-4.6

* stable-4.5:
  Prepare 4.5.7-SNAPSHOT builds
  JGit v4.5.6.201903121547-r
  Check for packfile validity and fd before reading
  Move throw of PackInvalidException outside the catch
  Use FileSnapshot to get lastModified on PackFile
  Include size when comparing FileSnapshot
  Do not reuse packfiles when changed on filesystem
  Silence API warnings for new API introduced for fixes

Change-Id: I029e1797447e6729de68bd89d4d69b324dbb3f5f
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
diff --git a/.buckconfig b/.buckconfig
index 8d2572b..7986494 100644
--- a/.buckconfig
+++ b/.buckconfig
@@ -12,6 +12,8 @@
 
 [java]
   src_roots = src, resources, tst
+  source_level = 8
+  target_level = 8
 
 [project]
   ignore = .git
diff --git a/.buckversion b/.buckversion
index f5fe016..7eb591f 100644
--- a/.buckversion
+++ b/.buckversion
@@ -1 +1 @@
-e64a2e2ada022f81e42be750b774024469551398
+e27df656657f93f8d57a7aaac69a5ae0e298a292
diff --git a/.gitignore b/.gitignore
index 95ad174..e78f8fd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,3 +3,4 @@
 /buck-cache
 /buck-out
 /target
+infer-out
diff --git a/.mvn/jvm.config b/.mvn/jvm.config
new file mode 100644
index 0000000..9b109f3
--- /dev/null
+++ b/.mvn/jvm.config
@@ -0,0 +1 @@
+-Xmx1024m
\ No newline at end of file
diff --git a/.mvn/maven.config b/.mvn/maven.config
new file mode 100644
index 0000000..ebbe288
--- /dev/null
+++ b/.mvn/maven.config
@@ -0,0 +1 @@
+-T 1C
diff --git a/README.md b/README.md
index 9aca10f..54133e1 100644
--- a/README.md
+++ b/README.md
@@ -72,7 +72,7 @@
 - Only the timestamp of the index is used by jgit if the index is
   dirty.
 
-- JGit requires at least a Java 7 JDK.
+- JGit requires at least a Java 8 JDK.
 
 - CRLF conversion is performed depending on the core.autocrlf setting,
   however Git for Windows by default stores that setting during
diff --git a/lib/BUCK b/lib/BUCK
index 2421b40..d89af5d 100644
--- a/lib/BUCK
+++ b/lib/BUCK
@@ -9,11 +9,11 @@
 
 maven_jar(
   name = 'javaewah',
-  bin_sha1 = 'eceaf316a8faf0e794296ebe158ae110c7d72a5a',
-  src_sha1 = 'a50d78eb630e05439461f3130b94b3bcd1ea6f03',
+  bin_sha1 = '94ad16d728b374d65bd897625f3fbb3da223a2b6',
+  src_sha1 = 'ca2745e91c6a51f8e6809d1579bda36ad83f1f58',
   group = 'com.googlecode.javaewah',
   artifact = 'JavaEWAH',
-  version = '0.7.9',
+  version = '1.1.6',
 )
 
 maven_jar(
diff --git a/lib/jetty/BUCK b/lib/jetty/BUCK
index 6e7dec3..fbb37c1 100644
--- a/lib/jetty/BUCK
+++ b/lib/jetty/BUCK
@@ -1,10 +1,10 @@
-VERSION = '9.2.13.v20150730'
+VERSION = '9.3.17.v20170317'
 GROUP = 'org.eclipse.jetty'
 
 maven_jar(
   name = 'servlet',
-  bin_sha1 = '5ad6e38015a97ae9a60b6c2ad744ccfa9cf93a50',
-  src_sha1 = '78fbec19321150552d91f9e079c2f2ca33222b01',
+  bin_sha1 = 'ed6986b0d0ca7b9b0f9015c9efb80442e3043a8e',
+  src_sha1 = 'ee6b4784a00a92e5c1b6111033b7ae41ac6052a3',
   group = GROUP,
   artifact = 'jetty-servlet',
   version = VERSION,
@@ -12,8 +12,8 @@
 
 maven_jar(
   name = 'security',
-  bin_sha1 = 'cc7c7f27ec4cc279253be1675d9e47e58b995943',
-  src_sha1 = '75632ebdf8bd651faafb97106c92496db59e165d',
+  bin_sha1 = 'ca52535569445682d42aaa97c7039442719a0507',
+  src_sha1 = '2ff9f4fb18b320fd5a0272a427bacc4d5fe7bc86',
   group = GROUP,
   artifact = 'jetty-security',
   version = VERSION,
@@ -21,8 +21,8 @@
 
 maven_jar(
   name = 'server',
-  bin_sha1 = '5be7d1da0a7abffd142de3091d160717c120b6ab',
-  src_sha1 = '203e123f83efe2a5b8a9c74854c7897fe3563302',
+  bin_sha1 = '194e9a02e6ba249ef4a3f4bd56b4993087992299',
+  src_sha1 = '0c9bd572f530c411592aefb71781ecca0b3719a9',
   group = GROUP,
   artifact = 'jetty-server',
   version = VERSION,
@@ -30,8 +30,8 @@
 
 maven_jar(
   name = 'http',
-  bin_sha1 = '23a745d9177ef67ef53cc46b9b70c5870082efc2',
-  src_sha1 = '5f87f7ff2057cd4b0995bc4fffe17b2aff64c130',
+  bin_sha1 = '6c02d728e15d4868486254039c867a1ac3e4a52e',
+  src_sha1 = '3c0a2a82792f268631b4fefd77be9f126ec974b1',
   group = GROUP,
   artifact = 'jetty-http',
   version = VERSION,
@@ -39,8 +39,8 @@
 
 maven_jar(
   name = 'io',
-  bin_sha1 = '7a351e6a1b63dfd56b6632623f7ca2793ffb67ad',
-  src_sha1 = 'bbd61a84b748fc295456e1c5c3070aaf40a68f62',
+  bin_sha1 = '756a8cd2a1cbfb84a94973b6332dd3eccd47c0cd',
+  src_sha1 = 'a9afa99cccb19b441364fa805d027f457cbbb136',
   group = GROUP,
   artifact = 'jetty-io',
   version = VERSION,
@@ -48,8 +48,8 @@
 
 maven_jar(
   name = 'util',
-  bin_sha1 = 'c101476360a7cdd0670462de04053507d5e70c97',
-  src_sha1 = '15ceecce141971b4e0facb861b3d10120ad6ce03',
+  bin_sha1 = 'b8512ab02819de01f0f5a5c6026163041f579beb',
+  src_sha1 = '96f8e3dcdc3660a5c91f19c46695daa70ac95625',
   group = GROUP,
   artifact = 'jetty-util',
   version = VERSION,
diff --git a/org.eclipse.jgit.ant.test/.classpath b/org.eclipse.jgit.ant.test/.classpath
index 098194c..eca7bdb 100644
--- a/org.eclipse.jgit.ant.test/.classpath
+++ b/org.eclipse.jgit.ant.test/.classpath
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
 	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
 	<classpathentry kind="src" path="src"/>
 	<classpathentry kind="output" path="bin"/>
diff --git a/org.eclipse.jgit.ant.test/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit.ant.test/.settings/org.eclipse.jdt.core.prefs
index 87210fb..10c29d5 100644
--- a/org.eclipse.jgit.ant.test/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit.ant.test/.settings/org.eclipse.jdt.core.prefs
@@ -7,9 +7,9 @@
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.compliance=1.8
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -112,7 +112,7 @@
 org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
-org.eclipse.jdt.core.compiler.source=1.7
+org.eclipse.jdt.core.compiler.source=1.8
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
diff --git a/org.eclipse.jgit.ant.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.ant.test/META-INF/MANIFEST.MF
index d592cd3..3bf69c3 100644
--- a/org.eclipse.jgit.ant.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.ant.test/META-INF/MANIFEST.MF
@@ -3,14 +3,14 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %plugin_name
 Bundle-SymbolicName: org.eclipse.jgit.ant.test
-Bundle-Version: 4.5.7.qualifier
+Bundle-Version: 4.6.2.qualifier
 Bundle-ActivationPolicy: lazy
-Bundle-RequiredExecutionEnvironment: JavaSE-1.7
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
 Import-Package: org.apache.tools.ant,
- org.eclipse.jgit.ant.tasks;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.internal.storage.file;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.junit;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.lib;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.util;version="[4.5.7,4.6.0)",
+ org.eclipse.jgit.ant.tasks;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.internal.storage.file;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.junit;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.lib;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.util;version="[4.6.2,4.7.0)",
  org.hamcrest;version="[1.1.0,2.0.0)",
  org.junit;version="[4.0.0,5.0.0)"
diff --git a/org.eclipse.jgit.ant.test/build.properties b/org.eclipse.jgit.ant.test/build.properties
index e3effea..4a2d892 100644
--- a/org.eclipse.jgit.ant.test/build.properties
+++ b/org.eclipse.jgit.ant.test/build.properties
@@ -3,5 +3,5 @@
 bin.includes = plugin.properties,\
 			   META-INF/,\
 			   .
-jre.compilation.profile = JavaSE-1.7
+jre.compilation.profile = JavaSE-1.8
 additional.bundles = org.eclipse.jgit
diff --git a/org.eclipse.jgit.ant.test/pom.xml b/org.eclipse.jgit.ant.test/pom.xml
index d6fd61f..9592841 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>4.5.7-SNAPSHOT</version>
+    <version>4.6.2-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.ant.test</artifactId>
diff --git a/org.eclipse.jgit.ant/.classpath b/org.eclipse.jgit.ant/.classpath
index a14ade4..110168f 100644
--- a/org.eclipse.jgit.ant/.classpath
+++ b/org.eclipse.jgit.ant/.classpath
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
 	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
 	<classpathentry kind="src" path="src"/>
 	<classpathentry kind="src" path="resources"/>
diff --git a/org.eclipse.jgit.ant/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit.ant/.settings/org.eclipse.jdt.core.prefs
index cd620c3..80cfbbb 100644
--- a/org.eclipse.jgit.ant/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit.ant/.settings/org.eclipse.jdt.core.prefs
@@ -7,9 +7,9 @@
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.compliance=1.8
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -112,7 +112,7 @@
 org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
-org.eclipse.jdt.core.compiler.source=1.7
+org.eclipse.jdt.core.compiler.source=1.8
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
diff --git a/org.eclipse.jgit.ant/META-INF/MANIFEST.MF b/org.eclipse.jgit.ant/META-INF/MANIFEST.MF
index 2377188..6b008e1 100644
--- a/org.eclipse.jgit.ant/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.ant/META-INF/MANIFEST.MF
@@ -2,11 +2,11 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %Bundle-Name
 Bundle-SymbolicName: org.eclipse.jgit.ant
-Bundle-Version: 4.5.7.qualifier
-Bundle-RequiredExecutionEnvironment: JavaSE-1.7
+Bundle-Version: 4.6.2.qualifier
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
 Import-Package: org.apache.tools.ant,
-  org.eclipse.jgit.storage.file;version="[4.5.7,4.6.0)"
+  org.eclipse.jgit.storage.file;version="[4.6.2,4.7.0)"
 Bundle-Localization: plugin
 Bundle-Vendor: %Provider-Name
-Export-Package: org.eclipse.jgit.ant.tasks;version="4.5.7";
+Export-Package: org.eclipse.jgit.ant.tasks;version="4.6.2";
  uses:="org.apache.tools.ant.types,org.apache.tools.ant"
diff --git a/org.eclipse.jgit.ant/pom.xml b/org.eclipse.jgit.ant/pom.xml
index 4f07d7f..194c9dd 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>4.5.7-SNAPSHOT</version>
+		<version>4.6.2-SNAPSHOT</version>
 	</parent>
 
 	<artifactId>org.eclipse.jgit.ant</artifactId>
diff --git a/org.eclipse.jgit.ant/src/org/eclipse/jgit/ant/tasks/GitAddTask.java b/org.eclipse.jgit.ant/src/org/eclipse/jgit/ant/tasks/GitAddTask.java
index b9a8688..db6f008 100644
--- a/org.eclipse.jgit.ant/src/org/eclipse/jgit/ant/tasks/GitAddTask.java
+++ b/org.eclipse.jgit.ant/src/org/eclipse/jgit/ant/tasks/GitAddTask.java
@@ -53,9 +53,10 @@
 import org.apache.tools.ant.types.resources.Union;
 import org.eclipse.jgit.api.AddCommand;
 import org.eclipse.jgit.api.Git;
-import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
+import org.eclipse.jgit.api.errors.GitAPIException;
 import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.lib.RepositoryCache;
+import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
 import org.eclipse.jgit.util.FS;
 
 /**
@@ -135,7 +136,7 @@ public void execute() throws BuildException {
 				gitAdd.addFilepattern(toAdd);
 			}
 			gitAdd.call();
-		} catch (Exception e) {
+		} catch (IOException | GitAPIException e) {
 			throw new BuildException("Could not add files to index." + src, e);
 		}
 
diff --git a/org.eclipse.jgit.ant/src/org/eclipse/jgit/ant/tasks/GitCloneTask.java b/org.eclipse.jgit.ant/src/org/eclipse/jgit/ant/tasks/GitCloneTask.java
index f23f3b7..b2cb35c 100644
--- a/org.eclipse.jgit.ant/src/org/eclipse/jgit/ant/tasks/GitCloneTask.java
+++ b/org.eclipse.jgit.ant/src/org/eclipse/jgit/ant/tasks/GitCloneTask.java
@@ -49,12 +49,14 @@
 import org.apache.tools.ant.Task;
 import org.eclipse.jgit.api.CloneCommand;
 import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.errors.GitAPIException;
+import org.eclipse.jgit.api.errors.JGitInternalException;
 import org.eclipse.jgit.lib.Constants;
 import org.eclipse.jgit.transport.URIish;
 
 /**
  * Clone a repository into a new directory.
- * 
+ *
  * @see <a href="http://www.kernel.org/pub/software/scm/git/docs/git-clone.html"
  *      >git-clone(1)</a>
  */
@@ -76,9 +78,9 @@ public void setUri(String uri) {
 	/**
 	 * The optional directory associated with the clone operation. If the
 	 * directory isn't set, a name associated with the source uri will be used.
-	 * 
+	 *
 	 * @see URIish#getHumanishName()
-	 * 
+	 *
 	 * @param destination
 	 *            the directory to clone to
 	 */
@@ -105,12 +107,12 @@ public void setBranch(String branch) {
 	@Override
 	public void execute() throws BuildException {
 		log("Cloning repository " + uri);
-		
+
 		CloneCommand clone = Git.cloneRepository();
 		try {
 			clone.setURI(uri).setDirectory(destination).setBranch(branch).setBare(bare);
 			clone.call().getRepository().close();
-		} catch (Exception e) {
+		} catch (GitAPIException | JGitInternalException e) {
 			log("Could not clone repository: " + e, e, Project.MSG_ERR);
 			throw new BuildException("Could not clone repository: " + e.getMessage(), e);
 		}
diff --git a/org.eclipse.jgit.archive/.classpath b/org.eclipse.jgit.archive/.classpath
index 3bc2475..22f3064 100644
--- a/org.eclipse.jgit.archive/.classpath
+++ b/org.eclipse.jgit.archive/.classpath
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
 	<classpathentry kind="src" path="src"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
 	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>
diff --git a/org.eclipse.jgit.archive/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit.archive/.settings/org.eclipse.jdt.core.prefs
index bfaf736..4f1759f 100644
--- a/org.eclipse.jgit.archive/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit.archive/.settings/org.eclipse.jdt.core.prefs
@@ -7,9 +7,9 @@
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.compliance=1.8
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -112,7 +112,7 @@
 org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
-org.eclipse.jdt.core.compiler.source=1.7
+org.eclipse.jdt.core.compiler.source=1.8
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
diff --git a/org.eclipse.jgit.archive/META-INF/MANIFEST.MF b/org.eclipse.jgit.archive/META-INF/MANIFEST.MF
index 6e439c5..b2fe6b2 100644
--- a/org.eclipse.jgit.archive/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.archive/META-INF/MANIFEST.MF
@@ -2,24 +2,24 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %plugin_name
 Bundle-SymbolicName: org.eclipse.jgit.archive
-Bundle-Version: 4.5.7.qualifier
+Bundle-Version: 4.6.2.qualifier
 Bundle-Vendor: %provider_name
 Bundle-Localization: plugin
-Bundle-RequiredExecutionEnvironment: JavaSE-1.7
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
 Import-Package: org.apache.commons.compress.archivers;version="[1.4,2.0)",
  org.apache.commons.compress.archivers.tar;version="[1.4,2.0)",
  org.apache.commons.compress.archivers.zip;version="[1.4,2.0)",
  org.apache.commons.compress.compressors.bzip2;version="[1.4,2.0)",
  org.apache.commons.compress.compressors.gzip;version="[1.4,2.0)",
  org.apache.commons.compress.compressors.xz;version="[1.4,2.0)",
- org.eclipse.jgit.api;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.lib;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.nls;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.util;version="[4.5.7,4.6.0)",
+ org.eclipse.jgit.api;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.lib;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.nls;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.util;version="[4.6.2,4.7.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="4.5.7";
+Export-Package: org.eclipse.jgit.archive;version="4.6.2";
   uses:="org.eclipse.jgit.lib,
    org.eclipse.jgit.api,
    org.apache.commons.compress.archivers,
diff --git a/org.eclipse.jgit.archive/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.archive/META-INF/SOURCE-MANIFEST.MF
index 0fbe7c1..7d7477c 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: 4.5.7.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit.archive;version="4.5.7.qualifier";roots="."
+Bundle-Version: 4.6.2.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit.archive;version="4.6.2.qualifier";roots="."
diff --git a/org.eclipse.jgit.archive/pom.xml b/org.eclipse.jgit.archive/pom.xml
index 7070a58..9c38817 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>4.5.7-SNAPSHOT</version>
+    <version>4.6.2-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.archive</artifactId>
diff --git a/org.eclipse.jgit.http.apache/.classpath b/org.eclipse.jgit.http.apache/.classpath
index a14ade4..110168f 100644
--- a/org.eclipse.jgit.http.apache/.classpath
+++ b/org.eclipse.jgit.http.apache/.classpath
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
 	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
 	<classpathentry kind="src" path="src"/>
 	<classpathentry kind="src" path="resources"/>
diff --git a/org.eclipse.jgit.http.apache/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit.http.apache/.settings/org.eclipse.jdt.core.prefs
index cd620c3..80cfbbb 100644
--- a/org.eclipse.jgit.http.apache/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit.http.apache/.settings/org.eclipse.jdt.core.prefs
@@ -7,9 +7,9 @@
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.compliance=1.8
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -112,7 +112,7 @@
 org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
-org.eclipse.jdt.core.compiler.source=1.7
+org.eclipse.jdt.core.compiler.source=1.8
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
diff --git a/org.eclipse.jgit.http.apache/META-INF/MANIFEST.MF b/org.eclipse.jgit.http.apache/META-INF/MANIFEST.MF
index 59e0cc3..978be27 100644
--- a/org.eclipse.jgit.http.apache/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.http.apache/META-INF/MANIFEST.MF
@@ -2,30 +2,36 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %Bundle-Name
 Bundle-SymbolicName: org.eclipse.jgit.http.apache
-Bundle-Version: 4.5.7.qualifier
-Bundle-RequiredExecutionEnvironment: JavaSE-1.7
+Bundle-Version: 4.6.2.qualifier
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
 Bundle-Localization: plugin
 Bundle-Vendor: %Provider-Name
 Bundle-ActivationPolicy: lazy
-Import-Package: org.apache.http;version="[4.1.0,5.0.0)",
- org.apache.http.client;version="[4.1.0,5.0.0)",
- org.apache.http.client.methods;version="[4.1.0,5.0.0)",
- org.apache.http.client.params;version="[4.1.0,5.0.0)",
- org.apache.http.conn;version="[4.1.0,5.0.0)",
- org.apache.http.conn.params;version="[4.1.0,5.0.0)",
- org.apache.http.conn.scheme;version="[4.1.0,5.0.0)",
- org.apache.http.conn.ssl;version="[4.1.0,5.0.0)",
- org.apache.http.entity;version="[4.1.0,5.0.0)",
- org.apache.http.impl.client;version="[4.1.0,5.0.0)",
- org.apache.http.impl.client.cache;version="[4.1.0,5.0.0)",
- org.apache.http.params;version="[4.1.0,5.0.0)",
- org.eclipse.jgit.nls;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.transport.http;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.util;version="[4.5.7,4.6.0)"
-Export-Package: org.eclipse.jgit.transport.http.apache;version="4.5.7";
-  uses:="org.eclipse.jgit.transport.http,
-   javax.net.ssl,
-   org.apache.http.client,
+Import-Package: org.apache.http;version="[4.3.0,5.0.0)",
+ org.apache.http.client;version="[4.3.0,5.0.0)",
+ org.apache.http.client.config;version="[4.3.0,5.0.0)",
+ org.apache.http.client.methods;version="[4.3.0,5.0.0)",
+ org.apache.http.client.params;version="[4.3.0,5.0.0)",
+ org.apache.http.config;version="[4.3.0,5.0.0)",
+ org.apache.http.conn;version="[4.3.0,5.0.0)",
+ org.apache.http.conn.params;version="[4.3.0,5.0.0)",
+ org.apache.http.conn.scheme;version="[4.3.0,5.0.0)",
+ org.apache.http.conn.socket;version="[4.3.0,5.0.0)",
+ org.apache.http.conn.ssl;version="[4.3.0,5.0.0)",
+ org.apache.http.entity;version="[4.3.0,5.0.0)",
+ org.apache.http.impl.client;version="[4.3.0,5.0.0)",
+ org.apache.http.impl.client.cache;version="[4.3.0,5.0.0)",
+ org.apache.http.impl.conn;version="[4.3.0,5.0.0)",
+ org.apache.http.params;version="[4.3.0,5.0.0)",
+ org.eclipse.jgit.nls;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.transport.http;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.util;version="[4.6.2,4.7.0)"
+Export-Package: org.eclipse.jgit.transport.http.apache;version="4.6.2";
+  uses:="org.apache.http.client,
+   org.eclipse.jgit.transport.http,
+   org.apache.http.entity,
    org.apache.http.client.methods,
+   javax.net.ssl,
+   org.eclipse.jgit.util,
    org.apache.http",
  org.eclipse.jgit.transport.http.apache.internal;x-internal:=true
diff --git a/org.eclipse.jgit.http.apache/pom.xml b/org.eclipse.jgit.http.apache/pom.xml
index b1ce292..dfd8585 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>4.5.7-SNAPSHOT</version>
+		<version>4.6.2-SNAPSHOT</version>
 	</parent>
 
 	<artifactId>org.eclipse.jgit.http.apache</artifactId>
diff --git a/org.eclipse.jgit.http.apache/src/org/eclipse/jgit/transport/http/apache/HttpClientConnection.java b/org.eclipse.jgit.http.apache/src/org/eclipse/jgit/transport/http/apache/HttpClientConnection.java
index 2d9d17a..281154f 100644
--- a/org.eclipse.jgit.http.apache/src/org/eclipse/jgit/transport/http/apache/HttpClientConnection.java
+++ b/org.eclipse.jgit.http.apache/src/org/eclipse/jgit/transport/http/apache/HttpClientConnection.java
@@ -80,19 +80,21 @@
 import org.apache.http.HttpResponse;
 import org.apache.http.client.ClientProtocolException;
 import org.apache.http.client.HttpClient;
+import org.apache.http.client.config.RequestConfig;
 import org.apache.http.client.methods.HttpGet;
 import org.apache.http.client.methods.HttpHead;
 import org.apache.http.client.methods.HttpPost;
 import org.apache.http.client.methods.HttpPut;
 import org.apache.http.client.methods.HttpUriRequest;
-import org.apache.http.client.params.ClientPNames;
-import org.apache.http.conn.params.ConnRoutePNames;
-import org.apache.http.conn.scheme.Scheme;
-import org.apache.http.conn.ssl.SSLSocketFactory;
+import org.apache.http.config.Registry;
+import org.apache.http.config.RegistryBuilder;
+import org.apache.http.conn.socket.ConnectionSocketFactory;
+import org.apache.http.conn.socket.PlainConnectionSocketFactory;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
 import org.apache.http.conn.ssl.X509HostnameVerifier;
-import org.apache.http.impl.client.DefaultHttpClient;
-import org.apache.http.params.CoreConnectionPNames;
-import org.apache.http.params.HttpParams;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
 import org.eclipse.jgit.transport.http.HttpConnection;
 import org.eclipse.jgit.transport.http.apache.internal.HttpApacheText;
 import org.eclipse.jgit.util.TemporaryBuffer;
@@ -131,29 +133,39 @@ public class HttpClientConnection implements HttpConnection {
 	SSLContext ctx;
 
 	private HttpClient getClient() {
-		if (client == null)
-			client = new DefaultHttpClient();
-		HttpParams params = client.getParams();
-		if (proxy != null && !Proxy.NO_PROXY.equals(proxy)) {
-			isUsingProxy = true;
-			InetSocketAddress adr = (InetSocketAddress) proxy.address();
-			params.setParameter(ConnRoutePNames.DEFAULT_PROXY,
-					new HttpHost(adr.getHostName(), adr.getPort()));
-		}
-		if (timeout != null)
-			params.setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT,
-					timeout.intValue());
-		if (readTimeout != null)
-			params.setIntParameter(CoreConnectionPNames.SO_TIMEOUT,
-					readTimeout.intValue());
-		if (followRedirects != null)
-			params.setBooleanParameter(ClientPNames.HANDLE_REDIRECTS,
-					followRedirects.booleanValue());
-		if (hostnameverifier != null) {
-			SSLSocketFactory sf;
-			sf = new SSLSocketFactory(getSSLContext(), hostnameverifier);
-			Scheme https = new Scheme("https", 443, sf); //$NON-NLS-1$
-			client.getConnectionManager().getSchemeRegistry().register(https);
+		if (client == null) {
+			HttpClientBuilder clientBuilder = HttpClients.custom();
+			RequestConfig.Builder configBuilder = RequestConfig.custom();
+			if (proxy != null && !Proxy.NO_PROXY.equals(proxy)) {
+				isUsingProxy = true;
+				InetSocketAddress adr = (InetSocketAddress) proxy.address();
+				clientBuilder.setProxy(
+						new HttpHost(adr.getHostName(), adr.getPort()));
+			}
+			if (timeout != null) {
+				configBuilder.setConnectTimeout(timeout.intValue());
+			}
+			if (readTimeout != null) {
+				configBuilder.setSocketTimeout(readTimeout.intValue());
+			}
+			if (followRedirects != null) {
+				configBuilder
+						.setRedirectsEnabled(followRedirects.booleanValue());
+			}
+			if (hostnameverifier != null) {
+				SSLConnectionSocketFactory sslConnectionFactory = new SSLConnectionSocketFactory(
+						getSSLContext(), hostnameverifier);
+				clientBuilder.setSSLSocketFactory(sslConnectionFactory);
+				Registry<ConnectionSocketFactory> registry = RegistryBuilder
+						.<ConnectionSocketFactory> create()
+						.register("https", sslConnectionFactory)
+						.register("http", PlainConnectionSocketFactory.INSTANCE)
+						.build();
+				clientBuilder.setConnectionManager(
+						new BasicHttpClientConnectionManager(registry));
+			}
+			clientBuilder.setDefaultRequestConfig(configBuilder.build());
+			client = clientBuilder.build();
 		}
 
 		return client;
@@ -283,11 +295,11 @@ public void setUseCaches(boolean usecaches) {
 	}
 
 	public void setConnectTimeout(int timeout) {
-		this.timeout = new Integer(timeout);
+		this.timeout = Integer.valueOf(timeout);
 	}
 
 	public void setReadTimeout(int readTimeout) {
-		this.readTimeout = new Integer(readTimeout);
+		this.readTimeout = Integer.valueOf(readTimeout);
 	}
 
 	public String getContentType() {
@@ -311,12 +323,21 @@ public String getHeaderField(String name) {
 	}
 
 	public int getContentLength() {
-		return Integer.parseInt(resp.getFirstHeader("content-length") //$NON-NLS-1$
-				.getValue());
+		Header contentLength = resp.getFirstHeader("content-length"); //$NON-NLS-1$
+		if (contentLength == null) {
+			return -1;
+		}
+
+		try {
+			int l = Integer.parseInt(contentLength.getValue());
+			return l < 0 ? -1 : l;
+		} catch (NumberFormatException e) {
+			return -1;
+		}
 	}
 
 	public void setInstanceFollowRedirects(boolean followRedirects) {
-		this.followRedirects = new Boolean(followRedirects);
+		this.followRedirects = Boolean.valueOf(followRedirects);
 	}
 
 	public void setDoOutput(boolean dooutput) {
diff --git a/org.eclipse.jgit.http.apache/src/org/eclipse/jgit/transport/http/apache/TemporaryBufferEntity.java b/org.eclipse.jgit.http.apache/src/org/eclipse/jgit/transport/http/apache/TemporaryBufferEntity.java
index 377e5ca..93328c9 100644
--- a/org.eclipse.jgit.http.apache/src/org/eclipse/jgit/transport/http/apache/TemporaryBufferEntity.java
+++ b/org.eclipse.jgit.http.apache/src/org/eclipse/jgit/transport/http/apache/TemporaryBufferEntity.java
@@ -105,7 +105,7 @@ public boolean isStreaming() {
 	 * @param contentLength
 	 */
 	public void setContentLength(int contentLength) {
-		this.contentLength = new Integer(contentLength);
+		this.contentLength = Integer.valueOf(contentLength);
 	}
 
 	/**
diff --git a/org.eclipse.jgit.http.server/.classpath b/org.eclipse.jgit.http.server/.classpath
index 04a2be7..cfcf24a 100644
--- a/org.eclipse.jgit.http.server/.classpath
+++ b/org.eclipse.jgit.http.server/.classpath
@@ -2,7 +2,7 @@
 <classpath>
 	<classpathentry kind="src" path="src"/>
 	<classpathentry kind="src" path="resources"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
 	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>
diff --git a/org.eclipse.jgit.http.server/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit.http.server/.settings/org.eclipse.jdt.core.prefs
index cd620c3..80cfbbb 100644
--- a/org.eclipse.jgit.http.server/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit.http.server/.settings/org.eclipse.jdt.core.prefs
@@ -7,9 +7,9 @@
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.compliance=1.8
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -112,7 +112,7 @@
 org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
-org.eclipse.jdt.core.compiler.source=1.7
+org.eclipse.jdt.core.compiler.source=1.8
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
diff --git a/org.eclipse.jgit.http.server/META-INF/MANIFEST.MF b/org.eclipse.jgit.http.server/META-INF/MANIFEST.MF
index 8e2cc59..be3bb33 100644
--- a/org.eclipse.jgit.http.server/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.http.server/META-INF/MANIFEST.MF
@@ -2,27 +2,27 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %plugin_name
 Bundle-SymbolicName: org.eclipse.jgit.http.server
-Bundle-Version: 4.5.7.qualifier
+Bundle-Version: 4.6.2.qualifier
 Bundle-Localization: plugin
 Bundle-Vendor: %provider_name
-Export-Package: org.eclipse.jgit.http.server;version="4.5.7",
- org.eclipse.jgit.http.server.glue;version="4.5.7";
+Export-Package: org.eclipse.jgit.http.server;version="4.6.2",
+ org.eclipse.jgit.http.server.glue;version="4.6.2";
   uses:="javax.servlet,javax.servlet.http",
- org.eclipse.jgit.http.server.resolver;version="4.5.7";
+ org.eclipse.jgit.http.server.resolver;version="4.6.2";
   uses:="org.eclipse.jgit.transport.resolver,
    org.eclipse.jgit.lib,
    org.eclipse.jgit.transport,
    javax.servlet.http"
 Bundle-ActivationPolicy: lazy
-Bundle-RequiredExecutionEnvironment: JavaSE-1.7
+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="[4.5.7,4.6.0)",
- org.eclipse.jgit.internal.storage.dfs;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.internal.storage.file;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.lib;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.nls;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.revwalk;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.transport;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.transport.resolver;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.util;version="[4.5.7,4.6.0)"
+ org.eclipse.jgit.errors;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.internal.storage.dfs;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.internal.storage.file;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.lib;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.nls;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.revwalk;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.transport;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.transport.resolver;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.util;version="[4.6.2,4.7.0)"
diff --git a/org.eclipse.jgit.http.server/pom.xml b/org.eclipse.jgit.http.server/pom.xml
index e40471d..843ec4b 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>4.5.7-SNAPSHOT</version>
+    <version>4.6.2-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.http.server</artifactId>
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/GitSmartHttpTools.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/GitSmartHttpTools.java
index d8cd61d..03c9d8d 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/GitSmartHttpTools.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/GitSmartHttpTools.java
@@ -43,15 +43,15 @@
 
 package org.eclipse.jgit.http.server;
 
-import static org.eclipse.jgit.http.server.ServletUtils.ATTRIBUTE_HANDLER;
-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.CAPABILITY_SIDE_BAND_64K;
-import static org.eclipse.jgit.transport.SideBandOutputStream.CH_ERROR;
-import static org.eclipse.jgit.transport.SideBandOutputStream.SMALL_BUF;
 import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN;
 import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
 import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND;
+import static org.eclipse.jgit.http.server.ServletUtils.ATTRIBUTE_HANDLER;
+import static org.eclipse.jgit.transport.GitProtocolConstants.CAPABILITY_SIDE_BAND_64K;
+import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_SIDE_BAND;
+import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_SIDE_BAND_64K;
+import static org.eclipse.jgit.transport.SideBandOutputStream.CH_ERROR;
+import static org.eclipse.jgit.transport.SideBandOutputStream.SMALL_BUF;
 
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/ServletUtils.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/ServletUtils.java
index 042ccf3..1336d6e 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/ServletUtils.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/ServletUtils.java
@@ -44,6 +44,7 @@
 package org.eclipse.jgit.http.server;
 
 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_ENCODING;
 import static org.eclipse.jgit.util.HttpSupport.HDR_CONTENT_ENCODING;
 import static org.eclipse.jgit.util.HttpSupport.HDR_ETAG;
@@ -111,7 +112,7 @@ public static InputStream getInputStream(final HttpServletRequest req)
 			throws IOException {
 		InputStream in = req.getInputStream();
 		final String enc = req.getHeader(HDR_CONTENT_ENCODING);
-		if (ENCODING_GZIP.equals(enc) || "x-gzip".equals(enc)) //$NON-NLS-1$
+		if (ENCODING_GZIP.equals(enc) || ENCODING_X_GZIP.equals(enc)) //$NON-NLS-1$
 			in = new GZIPInputStream(in);
 		else if (enc != null)
 			throw new IOException(MessageFormat.format(HttpServerText.get().encodingNotSupportedByThisLibrary
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/RegexGroupFilter.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/RegexGroupFilter.java
index 2d466e2..2414660 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/RegexGroupFilter.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/RegexGroupFilter.java
@@ -43,6 +43,8 @@
 
 package org.eclipse.jgit.http.server.glue;
 
+import static java.lang.Integer.valueOf;
+
 import java.io.IOException;
 import java.text.MessageFormat;
 
@@ -53,8 +55,6 @@
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
 
-import static java.lang.Integer.valueOf;
-
 import org.eclipse.jgit.http.server.HttpServerText;
 
 /**
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/WrappedRequest.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/WrappedRequest.java
index 7f8da7c..b702c07 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/WrappedRequest.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/glue/WrappedRequest.java
@@ -72,7 +72,7 @@ public WrappedRequest(final HttpServletRequest originalRequest,
 	@Override
 	public String getPathTranslated() {
 		final String p = getPathInfo();
-		return p != null ? getRealPath(p) : null;
+		return p != null ? getSession().getServletContext().getRealPath(p) : null;
 	}
 
 	@Override
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/resolver/AsIsFileService.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/resolver/AsIsFileService.java
index 43a7e24..4ef2a7c 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/resolver/AsIsFileService.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/resolver/AsIsFileService.java
@@ -47,8 +47,8 @@
 
 import org.eclipse.jgit.http.server.GitServlet;
 import org.eclipse.jgit.lib.Config;
-import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.lib.Config.SectionParser;
+import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.transport.resolver.ServiceNotAuthorizedException;
 import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException;
 
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/resolver/DefaultReceivePackFactory.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/resolver/DefaultReceivePackFactory.java
index df876ba..8c39b79 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/resolver/DefaultReceivePackFactory.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/resolver/DefaultReceivePackFactory.java
@@ -46,9 +46,9 @@
 import javax.servlet.http.HttpServletRequest;
 
 import org.eclipse.jgit.lib.Config;
+import org.eclipse.jgit.lib.Config.SectionParser;
 import org.eclipse.jgit.lib.PersonIdent;
 import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.lib.Config.SectionParser;
 import org.eclipse.jgit.transport.ReceivePack;
 import org.eclipse.jgit.transport.resolver.ReceivePackFactory;
 import org.eclipse.jgit.transport.resolver.ServiceNotAuthorizedException;
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/resolver/DefaultUploadPackFactory.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/resolver/DefaultUploadPackFactory.java
index 76f40c5..34c069e 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/resolver/DefaultUploadPackFactory.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/resolver/DefaultUploadPackFactory.java
@@ -46,8 +46,8 @@
 import javax.servlet.http.HttpServletRequest;
 
 import org.eclipse.jgit.lib.Config;
-import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.lib.Config.SectionParser;
+import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.transport.UploadPack;
 import org.eclipse.jgit.transport.resolver.ServiceNotAuthorizedException;
 import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException;
diff --git a/org.eclipse.jgit.http.test/.classpath b/org.eclipse.jgit.http.test/.classpath
index e1a1a64..e6014c7 100644
--- a/org.eclipse.jgit.http.test/.classpath
+++ b/org.eclipse.jgit.http.test/.classpath
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
 	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
 	<classpathentry kind="src" path="tst"/>
 	<classpathentry kind="src" path="src"/>
diff --git a/org.eclipse.jgit.http.test/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit.http.test/.settings/org.eclipse.jdt.core.prefs
index 87210fb..10c29d5 100644
--- a/org.eclipse.jgit.http.test/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit.http.test/.settings/org.eclipse.jdt.core.prefs
@@ -7,9 +7,9 @@
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.compliance=1.8
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -112,7 +112,7 @@
 org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
-org.eclipse.jdt.core.compiler.source=1.7
+org.eclipse.jdt.core.compiler.source=1.8
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
diff --git a/org.eclipse.jgit.http.test/BUCK b/org.eclipse.jgit.http.test/BUCK
index d65cdad..f5cd10e 100644
--- a/org.eclipse.jgit.http.test/BUCK
+++ b/org.eclipse.jgit.http.test/BUCK
@@ -25,7 +25,7 @@
       '//lib/jetty:util',
       '//lib:commons-logging',
     ],
-    source_under_test = ['//org.eclipse.jgit.http.server:jgit-servlet'],
+    vm_args = ['-Djava.io.tmpdir=buck-out'],
   )
 
 java_library(
diff --git a/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF
index 956ec63..6effed6 100644
--- a/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF
@@ -2,44 +2,44 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %plugin_name
 Bundle-SymbolicName: org.eclipse.jgit.http.test
-Bundle-Version: 4.5.7.qualifier
+Bundle-Version: 4.6.2.qualifier
 Bundle-Vendor: %provider_name
 Bundle-Localization: plugin
-Bundle-RequiredExecutionEnvironment: JavaSE-1.7
+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.jetty.continuation;version="[9.0.0,10.0.0)",
- org.eclipse.jetty.http;version="[9.0.0,10.0.0)",
- org.eclipse.jetty.io;version="[9.0.0,10.0.0)",
- org.eclipse.jetty.security;version="[9.0.0,10.0.0)",
- org.eclipse.jetty.security.authentication;version="[9.0.0,10.0.0)",
- org.eclipse.jetty.server;version="[9.0.0,10.0.0)",
- org.eclipse.jetty.server.handler;version="[9.0.0,10.0.0)",
- org.eclipse.jetty.server.nio;version="[9.0.0,10.0.0)",
- org.eclipse.jetty.servlet;version="[9.0.0,10.0.0)",
- org.eclipse.jetty.util;version="[9.0.0,10.0.0)",
- org.eclipse.jetty.util.component;version="[9.0.0,10.0.0)",
- org.eclipse.jetty.util.log;version="[9.0.0,10.0.0)",
- org.eclipse.jetty.util.security;version="[9.0.0,10.0.0)",
- org.eclipse.jetty.util.thread;version="[9.0.0,10.0.0)",
- org.eclipse.jgit.errors;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.http.server;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.http.server.glue;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.http.server.resolver;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.internal;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.internal.storage.dfs;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.internal.storage.file;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.junit;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.junit.http;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.lib;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.nls;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.revwalk;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.storage.file;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.transport;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.transport.http;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.transport.http.apache;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.transport.resolver;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.util;version="[4.5.7,4.6.0)",
+ org.eclipse.jetty.continuation;version="[9.0.0,9.4.0)",
+ org.eclipse.jetty.http;version="[9.0.0,9.4.0)",
+ org.eclipse.jetty.io;version="[9.0.0,9.4.0)",
+ org.eclipse.jetty.security;version="[9.0.0,9.4.0)",
+ org.eclipse.jetty.security.authentication;version="[9.0.0,9.4.0)",
+ org.eclipse.jetty.server;version="[9.0.0,9.4.0)",
+ org.eclipse.jetty.server.handler;version="[9.0.0,9.4.0)",
+ org.eclipse.jetty.server.nio;version="[9.0.0,9.4.0)",
+ org.eclipse.jetty.servlet;version="[9.0.0,9.4.0)",
+ org.eclipse.jetty.util;version="[9.0.0,9.4.0)",
+ org.eclipse.jetty.util.component;version="[9.0.0,9.4.0)",
+ org.eclipse.jetty.util.log;version="[9.0.0,9.4.0)",
+ org.eclipse.jetty.util.security;version="[9.0.0,9.4.0)",
+ org.eclipse.jetty.util.thread;version="[9.0.0,9.4.0)",
+ org.eclipse.jgit.errors;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.http.server;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.http.server.glue;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.http.server.resolver;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.internal;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.internal.storage.dfs;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.internal.storage.file;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.junit;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.junit.http;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.lib;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.nls;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.revwalk;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.storage.file;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.transport;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.transport.http;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.transport.http.apache;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.transport.resolver;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.util;version="[4.6.2,4.7.0)",
  org.hamcrest.core;version="[1.1.0,2.0.0)",
  org.junit;version="[4.0.0,5.0.0)",
  org.junit.runner;version="[4.0.0,5.0.0)",
diff --git a/org.eclipse.jgit.http.test/pom.xml b/org.eclipse.jgit.http.test/pom.xml
index 9f8a179..0366f75 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>4.5.7-SNAPSHOT</version>
+    <version>4.6.2-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.http.test</artifactId>
@@ -60,7 +60,9 @@
   <description>
     Tests for the HTTP transport.
   </description>
-
+  <properties>
+      <maven.javadoc.skip>true</maven.javadoc.skip>
+  </properties>
   <dependencies>
     <dependency>
       <groupId>junit</groupId>
diff --git a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/server/ClientVersionUtilTest.java b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/server/ClientVersionUtilTest.java
index a8c604c..c7260e3 100644
--- a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/server/ClientVersionUtilTest.java
+++ b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/server/ClientVersionUtilTest.java
@@ -43,11 +43,11 @@
 
 package org.eclipse.jgit.http.server;
 
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
 import static org.eclipse.jgit.http.server.ClientVersionUtil.hasPushStatusBug;
 import static org.eclipse.jgit.http.server.ClientVersionUtil.invalidVersion;
 import static org.eclipse.jgit.http.server.ClientVersionUtil.parseVersion;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 
 import org.junit.Assert;
 import org.junit.Test;
diff --git a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DumbClientSmartServerTest.java b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DumbClientSmartServerTest.java
index da3a098..bce44f9 100644
--- a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DumbClientSmartServerTest.java
+++ b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DumbClientSmartServerTest.java
@@ -199,7 +199,7 @@ public void testListRemote() throws IOException {
 				.startsWith("JGit/"));
 		assertEquals("*/*", info.getRequestHeader(HDR_ACCEPT));
 		assertEquals(200, info.getStatus());
-		assertEquals("text/plain; charset=UTF-8",
+		assertEquals("text/plain;charset=utf-8",
 				info
 				.getResponseHeader(HDR_CONTENT_TYPE));
 
@@ -269,7 +269,7 @@ public void testInitialClone_Packed() throws Exception {
 		assertEquals("GET", req.get(0).getMethod());
 		assertEquals(0, req.get(0).getParameters().size());
 		assertEquals(200, req.get(0).getStatus());
-		assertEquals("text/plain; charset=UTF-8",
+		assertEquals("text/plain;charset=utf-8",
 				req.get(0).getResponseHeader(
 				HDR_CONTENT_TYPE));
 	}
diff --git a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerTest.java b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerTest.java
index 2b9105c..3e88271 100644
--- a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerTest.java
+++ b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerTest.java
@@ -454,7 +454,7 @@ public void testInitialClone_BrokenServer() throws Exception {
 			} catch (TransportException err) {
 				String exp = brokenURI + ": expected"
 						+ " Content-Type application/x-git-upload-pack-result;"
-						+ " received Content-Type text/plain; charset=UTF-8";
+						+ " received Content-Type text/plain;charset=utf-8";
 				assertEquals(exp, err.getMessage());
 			}
 		}
@@ -476,7 +476,7 @@ public void testInitialClone_BrokenServer() throws Exception {
 		assertEquals(join(brokenURI, "git-upload-pack"), service.getPath());
 		assertEquals(0, service.getParameters().size());
 		assertEquals(200, service.getStatus());
-		assertEquals("text/plain; charset=UTF-8",
+		assertEquals("text/plain;charset=utf-8",
 				service.getResponseHeader(HDR_CONTENT_TYPE));
 	}
 
diff --git a/org.eclipse.jgit.junit.http/.classpath b/org.eclipse.jgit.junit.http/.classpath
index b1dabee..b862a29 100644
--- a/org.eclipse.jgit.junit.http/.classpath
+++ b/org.eclipse.jgit.junit.http/.classpath
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>

 <classpath>

-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>

+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>

 	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>

 	<classpathentry kind="src" path="src"/>

 	<classpathentry kind="output" path="bin"/>

diff --git a/org.eclipse.jgit.junit.http/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit.junit.http/.settings/org.eclipse.jdt.core.prefs
index 87210fb..10c29d5 100644
--- a/org.eclipse.jgit.junit.http/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit.junit.http/.settings/org.eclipse.jdt.core.prefs
@@ -7,9 +7,9 @@
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.compliance=1.8
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -112,7 +112,7 @@
 org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
-org.eclipse.jdt.core.compiler.source=1.7
+org.eclipse.jdt.core.compiler.source=1.8
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
diff --git a/org.eclipse.jgit.junit.http/META-INF/MANIFEST.MF b/org.eclipse.jgit.junit.http/META-INF/MANIFEST.MF
index a951d05..cd42e2c 100644
--- a/org.eclipse.jgit.junit.http/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.junit.http/META-INF/MANIFEST.MF
@@ -2,34 +2,34 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %plugin_name
 Bundle-SymbolicName: org.eclipse.jgit.junit.http
-Bundle-Version: 4.5.7.qualifier
+Bundle-Version: 4.6.2.qualifier
 Bundle-Localization: plugin
 Bundle-Vendor: %provider_name
 Bundle-ActivationPolicy: lazy
-Bundle-RequiredExecutionEnvironment: JavaSE-1.7
+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.apache.commons.logging;version="[1.1.1,2.0.0)",
- org.eclipse.jetty.http;version="[9.0.0,10.0.0)",
- org.eclipse.jetty.security;version="[9.0.0,10.0.0)",
- org.eclipse.jetty.security.authentication;version="[9.0.0,10.0.0)",
- org.eclipse.jetty.server;version="[9.0.0,10.0.0)",
- org.eclipse.jetty.server.handler;version="[9.0.0,10.0.0)",
- org.eclipse.jetty.server.nio;version="[9.0.0,10.0.0)",
- org.eclipse.jetty.servlet;version="[9.0.0,10.0.0)",
- org.eclipse.jetty.util.component;version="[9.0.0,10.0.0)",
- org.eclipse.jetty.util.log;version="[9.0.0,10.0.0)",
- org.eclipse.jetty.util.security;version="[9.0.0,10.0.0)",
- org.eclipse.jgit.errors;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.http.server;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.internal.storage.file;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.junit;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.lib;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.revwalk;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.transport;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.transport.resolver;version="[4.5.7,4.6.0)",
+ org.eclipse.jetty.http;version="[9.0.0,9.4.0)",
+ org.eclipse.jetty.security;version="[9.0.0,9.4.0)",
+ org.eclipse.jetty.security.authentication;version="[9.0.0,9.4.0)",
+ org.eclipse.jetty.server;version="[9.0.0,9.4.0)",
+ org.eclipse.jetty.server.handler;version="[9.0.0,9.4.0)",
+ org.eclipse.jetty.server.nio;version="[9.0.0,9.4.0)",
+ org.eclipse.jetty.servlet;version="[9.0.0,9.4.0)",
+ org.eclipse.jetty.util.component;version="[9.0.0,9.4.0)",
+ org.eclipse.jetty.util.log;version="[9.0.0,9.4.0)",
+ org.eclipse.jetty.util.security;version="[9.0.0,9.4.0)",
+ org.eclipse.jgit.errors;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.http.server;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.internal.storage.file;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.junit;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.lib;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.revwalk;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.transport;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.transport.resolver;version="[4.6.2,4.7.0)",
  org.junit;version="[4.0.0,5.0.0)"
-Export-Package: org.eclipse.jgit.junit.http;version="4.5.7";
+Export-Package: org.eclipse.jgit.junit.http;version="4.6.2";
   uses:="org.eclipse.jgit.transport,
    org.eclipse.jgit.junit,
    javax.servlet.http,
diff --git a/org.eclipse.jgit.junit.http/pom.xml b/org.eclipse.jgit.junit.http/pom.xml
index 101d660..ced9c2c 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>4.5.7-SNAPSHOT</version>
+    <version>4.6.2-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.junit.http</artifactId>
diff --git a/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/AppServer.java b/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/AppServer.java
index cca4f43..44c1977 100644
--- a/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/AppServer.java
+++ b/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/AppServer.java
@@ -185,13 +185,11 @@ protected void loadUsers() throws IOException {
 			putUser(username, new Password(password), new String[] { role });
 		}
 
-		protected String[] loadRoleInfo(
-				@SuppressWarnings("unused") KnownUser user) {
+		protected String[] loadRoleInfo(KnownUser user) {
 			return null;
 		}
 
-		protected KnownUser loadUserInfo(
-				@SuppressWarnings("unused") String usrname) {
+		protected KnownUser loadUserInfo(String usrname) {
 			return null;
 		}
 	}
diff --git a/org.eclipse.jgit.junit/.classpath b/org.eclipse.jgit.junit/.classpath
index 098194c..eca7bdb 100644
--- a/org.eclipse.jgit.junit/.classpath
+++ b/org.eclipse.jgit.junit/.classpath
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
 	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
 	<classpathentry kind="src" path="src"/>
 	<classpathentry kind="output" path="bin"/>
diff --git a/org.eclipse.jgit.junit/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit.junit/.settings/org.eclipse.jdt.core.prefs
index 87210fb..10c29d5 100644
--- a/org.eclipse.jgit.junit/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit.junit/.settings/org.eclipse.jdt.core.prefs
@@ -7,9 +7,9 @@
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.compliance=1.8
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -112,7 +112,7 @@
 org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
-org.eclipse.jdt.core.compiler.source=1.7
+org.eclipse.jdt.core.compiler.source=1.8
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
diff --git a/org.eclipse.jgit.junit/META-INF/MANIFEST.MF b/org.eclipse.jgit.junit/META-INF/MANIFEST.MF
index b11cd54..9de6239 100644
--- a/org.eclipse.jgit.junit/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.junit/META-INF/MANIFEST.MF
@@ -2,30 +2,31 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %plugin_name
 Bundle-SymbolicName: org.eclipse.jgit.junit
-Bundle-Version: 4.5.7.qualifier
+Bundle-Version: 4.6.2.qualifier
 Bundle-Localization: plugin
 Bundle-Vendor: %provider_name
 Bundle-ActivationPolicy: lazy
-Bundle-RequiredExecutionEnvironment: JavaSE-1.7
-Import-Package: org.eclipse.jgit.api;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.api.errors;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.dircache;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.errors;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.internal.storage.file;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.internal.storage.pack;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.lib;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.merge;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.revwalk;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.storage.file;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.treewalk;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.treewalk.filter;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.util;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.util.io;version="[4.5.7,4.6.0)",
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Import-Package: org.eclipse.jgit.api;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.api.errors;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.dircache;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.errors;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.internal.storage.file;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.internal.storage.pack;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.lib;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.merge;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.revwalk;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.storage.file;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.treewalk;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.treewalk.filter;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.util;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.util.io;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.util.time;version="[4.6.2,4.7.0)",
  org.junit;version="[4.0.0,5.0.0)",
  org.junit.rules;version="[4.9.0,5.0.0)",
  org.junit.runner;version="[4.0.0,5.0.0)",
  org.junit.runners.model;version="[4.5.0,5.0.0)"
-Export-Package: org.eclipse.jgit.junit;version="4.5.7";
+Export-Package: org.eclipse.jgit.junit;version="4.6.2";
   uses:="org.eclipse.jgit.dircache,
    org.eclipse.jgit.lib,
    org.eclipse.jgit.revwalk,
@@ -33,4 +34,5 @@
    org.eclipse.jgit.treewalk,
    org.eclipse.jgit.util,
    org.eclipse.jgit.storage.file,
-   org.eclipse.jgit.api"
+   org.eclipse.jgit.api",
+ org.eclipse.jgit.junit.time;version="4.6.2"
diff --git a/org.eclipse.jgit.junit/pom.xml b/org.eclipse.jgit.junit/pom.xml
index 9cd6f87..ab757af 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>4.5.7-SNAPSHOT</version>
+    <version>4.6.2-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.junit</artifactId>
diff --git a/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/LocalDiskRepositoryTestCase.java b/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/LocalDiskRepositoryTestCase.java
index 4d713b5..dc2e8bf 100644
--- a/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/LocalDiskRepositoryTestCase.java
+++ b/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/LocalDiskRepositoryTestCase.java
@@ -50,12 +50,21 @@
 
 import java.io.File;
 import java.io.IOException;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeSet;
 
 import org.eclipse.jgit.dircache.DirCache;
 import org.eclipse.jgit.dircache.DirCacheEntry;
 import org.eclipse.jgit.internal.storage.file.FileRepository;
-import org.eclipse.jgit.lib.*;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.PersonIdent;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.RepositoryCache;
 import org.eclipse.jgit.storage.file.FileBasedConfig;
 import org.eclipse.jgit.storage.file.WindowCacheConfig;
 import org.eclipse.jgit.util.FS;
@@ -113,13 +122,8 @@ public void setUp() throws Exception {
 		ceilTestDirectories(getCeilings());
 		SystemReader.setInstance(mockSystemReader);
 
-		final long now = mockSystemReader.getCurrentTime();
-		final int tz = mockSystemReader.getTimezone(now);
 		author = new PersonIdent("J. Author", "jauthor@example.com");
-		author = new PersonIdent(author, now, tz);
-
 		committer = new PersonIdent("J. Committer", "jcommitter@example.com");
-		committer = new PersonIdent(committer, now, tz);
 
 		final WindowCacheConfig c = new WindowCacheConfig();
 		c.setPackedGitLimit(128 * WindowCacheConfig.KB);
diff --git a/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/MockSystemReader.java b/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/MockSystemReader.java
index 28a9556..6faa2ec 100644
--- a/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/MockSystemReader.java
+++ b/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/MockSystemReader.java
@@ -50,10 +50,12 @@
 import java.lang.reflect.Field;
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
+import java.time.Duration;
 import java.util.HashMap;
 import java.util.Locale;
 import java.util.Map;
 import java.util.TimeZone;
+import java.util.concurrent.TimeUnit;
 
 import org.eclipse.jgit.errors.ConfigInvalidException;
 import org.eclipse.jgit.lib.Config;
@@ -61,6 +63,8 @@
 import org.eclipse.jgit.storage.file.FileBasedConfig;
 import org.eclipse.jgit.util.FS;
 import org.eclipse.jgit.util.SystemReader;
+import org.eclipse.jgit.util.time.MonotonicClock;
+import org.eclipse.jgit.util.time.ProposedTimestamp;
 
 /**
  * Mock {@link SystemReader} for tests.
@@ -146,6 +150,27 @@ public long getCurrentTime() {
 		return now;
 	}
 
+	@Override
+	public MonotonicClock getClock() {
+		return new MonotonicClock() {
+			@Override
+			public ProposedTimestamp propose() {
+				long t = getCurrentTime();
+				return new ProposedTimestamp() {
+					@Override
+					public long read(TimeUnit unit) {
+						return unit.convert(t, TimeUnit.MILLISECONDS);
+					}
+
+					@Override
+					public void blockUntil(Duration maxWait) {
+						// Do not wait.
+					}
+				};
+			}
+		};
+	}
+
 	/**
 	 * Adjusts the current time in seconds.
 	 *
diff --git a/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/TestRepository.java b/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/TestRepository.java
index 0a2345f..a44e999 100644
--- a/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/TestRepository.java
+++ b/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/TestRepository.java
@@ -46,6 +46,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.fail;
 
+import java.io.BufferedOutputStream;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
@@ -103,7 +104,6 @@
 import org.eclipse.jgit.treewalk.filter.PathFilterGroup;
 import org.eclipse.jgit.util.ChangeIdUtil;
 import org.eclipse.jgit.util.FileUtils;
-import org.eclipse.jgit.util.io.SafeBufferedOutputStream;
 
 /**
  * Wrapper to make creating test data easier.
@@ -885,14 +885,14 @@ public void packAndPrune() throws Exception {
 
 				pack = nameFor(odb, name, ".pack");
 				try (OutputStream out =
-						new SafeBufferedOutputStream(new FileOutputStream(pack))) {
+						new BufferedOutputStream(new FileOutputStream(pack))) {
 					pw.writePack(m, m, out);
 				}
 				pack.setReadOnly();
 
 				idx = nameFor(odb, name, ".idx");
 				try (OutputStream out =
-						new SafeBufferedOutputStream(new FileOutputStream(idx))) {
+						new BufferedOutputStream(new FileOutputStream(idx))) {
 					pw.writeIndex(out);
 				}
 				idx.setReadOnly();
diff --git a/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/time/MonotonicFakeClock.java b/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/time/MonotonicFakeClock.java
new file mode 100644
index 0000000..f09d303
--- /dev/null
+++ b/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/time/MonotonicFakeClock.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2016, Google Inc.
+ * 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.junit.time;
+
+import java.time.Duration;
+import java.util.concurrent.TimeUnit;
+
+import org.eclipse.jgit.util.time.MonotonicClock;
+import org.eclipse.jgit.util.time.ProposedTimestamp;
+
+/**
+ * Fake {@link MonotonicClock} for testing code that uses Clock.
+ *
+ * @since 4.6
+ */
+public class MonotonicFakeClock implements MonotonicClock {
+	private long now = TimeUnit.SECONDS.toMicros(42);
+
+	/**
+	 * Advance the time returned by future calls to {@link #propose()}.
+	 *
+	 * @param add
+	 *            amount of time to add; must be {@code > 0}.
+	 * @param unit
+	 *            unit of {@code add}.
+	 */
+	public void tick(long add, TimeUnit unit) {
+		if (add <= 0) {
+			throw new IllegalArgumentException();
+		}
+		now += unit.toMillis(add);
+	}
+
+	@Override
+	public ProposedTimestamp propose() {
+		long t = now++;
+		return new ProposedTimestamp() {
+			@Override
+			public long read(TimeUnit unit) {
+				return unit.convert(t, TimeUnit.MILLISECONDS);
+			}
+
+			@Override
+			public void blockUntil(Duration maxWait) {
+				// Nothing to do, since fake time does not go backwards.
+			}
+		};
+	}
+}
diff --git a/org.eclipse.jgit.lfs.server.test/.classpath b/org.eclipse.jgit.lfs.server.test/.classpath
index 2fdcc94..4f9f6bf 100644
--- a/org.eclipse.jgit.lfs.server.test/.classpath
+++ b/org.eclipse.jgit.lfs.server.test/.classpath
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
 	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
 	<classpathentry kind="src" path="tst"/>
 	<classpathentry kind="output" path="bin"/>
diff --git a/org.eclipse.jgit.lfs.server.test/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit.lfs.server.test/.settings/org.eclipse.jdt.core.prefs
index 87210fb..10c29d5 100644
--- a/org.eclipse.jgit.lfs.server.test/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit.lfs.server.test/.settings/org.eclipse.jdt.core.prefs
@@ -7,9 +7,9 @@
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.compliance=1.8
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -112,7 +112,7 @@
 org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
-org.eclipse.jdt.core.compiler.source=1.7
+org.eclipse.jdt.core.compiler.source=1.8
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
diff --git a/org.eclipse.jgit.lfs.server.test/BUCK b/org.eclipse.jgit.lfs.server.test/BUCK
index 9d6e72f..25e9f09 100644
--- a/org.eclipse.jgit.lfs.server.test/BUCK
+++ b/org.eclipse.jgit.lfs.server.test/BUCK
@@ -30,6 +30,5 @@
       '//lib:servlet-api',
       '//lib:commons-logging',
     ],
-    source_under_test = ['//org.eclipse.jgit.lfs.server:jgit-lfs-server'],
     vm_args = ['-Xmx256m', '-Dfile.encoding=UTF-8'],
   )
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 02812da..405e07a 100644
--- a/org.eclipse.jgit.lfs.server.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.lfs.server.test/META-INF/MANIFEST.MF
@@ -2,10 +2,10 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %plugin_name
 Bundle-SymbolicName: org.eclipse.jgit.lfs.server.test
-Bundle-Version: 4.5.7.qualifier
+Bundle-Version: 4.6.2.qualifier
 Bundle-Vendor: %provider_name
 Bundle-Localization: plugin
-Bundle-RequiredExecutionEnvironment: JavaSE-1.7
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
 Import-Package: javax.servlet;version="[3.1.0,4.0.0)",
  javax.servlet.http;version="[3.1.0,4.0.0)",
  org.apache.http;version="[4.3.0,5.0.0)",
@@ -13,25 +13,25 @@
  org.apache.http.client.methods;version="[4.3.0,5.0.0)",
  org.apache.http.entity;version="[4.3.0,5.0.0)",
  org.apache.http.impl.client;version="[4.3.0,5.0.0)",
- org.eclipse.jetty.continuation;version="[9.0.0,10.0.0)",
- org.eclipse.jetty.http;version="[9.0.0,10.0.0)",
- org.eclipse.jetty.io;version="[9.0.0,10.0.0)",
- org.eclipse.jetty.security;version="[9.0.0,10.0.0)",
- org.eclipse.jetty.security.authentication;version="[9.0.0,10.0.0)",
- org.eclipse.jetty.server;version="[9.0.0,10.0.0)",
- org.eclipse.jetty.server.handler;version="[9.0.0,10.0.0)",
- org.eclipse.jetty.server.nio;version="[9.0.0,10.0.0)",
- org.eclipse.jetty.servlet;version="[9.0.0,10.0.0)",
- org.eclipse.jetty.util;version="[9.0.0,10.0.0)",
- org.eclipse.jetty.util.component;version="[9.0.0,10.0.0)",
- org.eclipse.jetty.util.log;version="[9.0.0,10.0.0)",
- org.eclipse.jetty.util.security;version="[9.0.0,10.0.0)",
- org.eclipse.jetty.util.thread;version="[9.0.0,10.0.0)",
- org.eclipse.jgit.junit.http;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.lfs.lib;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.lfs.server.fs;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.lfs.test;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.util;version="[4.5.7,4.6.0)",
+ org.eclipse.jetty.continuation;version="[9.0.0,9.4.0)",
+ org.eclipse.jetty.http;version="[9.0.0,9.4.0)",
+ org.eclipse.jetty.io;version="[9.0.0,9.4.0)",
+ org.eclipse.jetty.security;version="[9.0.0,9.4.0)",
+ org.eclipse.jetty.security.authentication;version="[9.0.0,9.4.0)",
+ org.eclipse.jetty.server;version="[9.0.0,9.4.0)",
+ org.eclipse.jetty.server.handler;version="[9.0.0,9.4.0)",
+ org.eclipse.jetty.server.nio;version="[9.0.0,9.4.0)",
+ org.eclipse.jetty.servlet;version="[9.0.0,9.4.0)",
+ org.eclipse.jetty.util;version="[9.0.0,9.4.0)",
+ org.eclipse.jetty.util.component;version="[9.0.0,9.4.0)",
+ org.eclipse.jetty.util.log;version="[9.0.0,9.4.0)",
+ org.eclipse.jetty.util.security;version="[9.0.0,9.4.0)",
+ org.eclipse.jetty.util.thread;version="[9.0.0,9.4.0)",
+ org.eclipse.jgit.junit.http;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.lfs.lib;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.lfs.server.fs;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.lfs.test;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.util;version="[4.6.2,4.7.0)",
  org.hamcrest.core;version="[1.1.0,2.0.0)",
  org.junit;version="[4.0.0,5.0.0)",
  org.junit.runner;version="[4.0.0,5.0.0)",
diff --git a/org.eclipse.jgit.lfs.server.test/pom.xml b/org.eclipse.jgit.lfs.server.test/pom.xml
index f2ee151..d178fef 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>4.5.7-SNAPSHOT</version>
+    <version>4.6.2-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.lfs.server.test</artifactId>
diff --git a/org.eclipse.jgit.lfs.server.test/tst/org/eclipse/jgit/lfs/server/fs/LfsServerTest.java b/org.eclipse.jgit.lfs.server.test/tst/org/eclipse/jgit/lfs/server/fs/LfsServerTest.java
index 4d948b9..e10660d 100644
--- a/org.eclipse.jgit.lfs.server.test/tst/org/eclipse/jgit/lfs/server/fs/LfsServerTest.java
+++ b/org.eclipse.jgit.lfs.server.test/tst/org/eclipse/jgit/lfs/server/fs/LfsServerTest.java
@@ -84,7 +84,6 @@
 import org.junit.After;
 import org.junit.Before;
 
-@SuppressWarnings("restriction")
 public abstract class LfsServerTest {
 
 	private static final long timeout = /* 10 sec */ 10 * 1000;
diff --git a/org.eclipse.jgit.lfs.server/.classpath b/org.eclipse.jgit.lfs.server/.classpath
index 04a2be7..cfcf24a 100644
--- a/org.eclipse.jgit.lfs.server/.classpath
+++ b/org.eclipse.jgit.lfs.server/.classpath
@@ -2,7 +2,7 @@
 <classpath>
 	<classpathentry kind="src" path="src"/>
 	<classpathentry kind="src" path="resources"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
 	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>
diff --git a/org.eclipse.jgit.lfs.server/.settings/.api_filters b/org.eclipse.jgit.lfs.server/.settings/.api_filters
deleted file mode 100644
index e662937..0000000
--- a/org.eclipse.jgit.lfs.server/.settings/.api_filters
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<component id="org.eclipse.jgit.lfs.server" version="2">
-    <resource path="src/org/eclipse/jgit/lfs/server/LfsProtocolServlet.java" type="org.eclipse.jgit.lfs.server.LfsProtocolServlet">
-        <filter comment="breaking implementors only which is ok under OSGi semver rules" id="336695337">
-            <message_arguments>
-                <message_argument value="org.eclipse.jgit.lfs.server.LfsProtocolServlet"/>
-                <message_argument value="getLargeFileRepository(LfsProtocolServlet.LfsRequest, String)"/>
-            </message_arguments>
-        </filter>
-        <filter comment="breaking implementors only which is ok under OSGi semver rules" id="338792546">
-            <message_arguments>
-                <message_argument value="org.eclipse.jgit.lfs.server.LfsProtocolServlet"/>
-                <message_argument value="getLargeFileRepository()"/>
-            </message_arguments>
-        </filter>
-    </resource>
-</component>
diff --git a/org.eclipse.jgit.lfs.server/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit.lfs.server/.settings/org.eclipse.jdt.core.prefs
index 1ce7cd0..808ec3a 100644
--- a/org.eclipse.jgit.lfs.server/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit.lfs.server/.settings/org.eclipse.jdt.core.prefs
@@ -7,9 +7,9 @@
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.compliance=1.8
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -112,7 +112,7 @@
 org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
-org.eclipse.jdt.core.compiler.source=1.7
+org.eclipse.jdt.core.compiler.source=1.8
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
diff --git a/org.eclipse.jgit.lfs.server/META-INF/MANIFEST.MF b/org.eclipse.jgit.lfs.server/META-INF/MANIFEST.MF
index 3b3a84f..3e8a9d1 100644
--- a/org.eclipse.jgit.lfs.server/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.lfs.server/META-INF/MANIFEST.MF
@@ -2,34 +2,35 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %plugin_name
 Bundle-SymbolicName: org.eclipse.jgit.lfs.server
-Bundle-Version: 4.5.7.qualifier
+Bundle-Version: 4.6.2.qualifier
 Bundle-Localization: plugin
 Bundle-Vendor: %provider_name
-Export-Package: org.eclipse.jgit.lfs.server;version="4.5.7";
+Export-Package: org.eclipse.jgit.lfs.server;version="4.6.2";
   uses:="javax.servlet.http,
    org.eclipse.jgit.lfs.lib",
- org.eclipse.jgit.lfs.server.fs;version="4.5.7";
+ org.eclipse.jgit.lfs.server.fs;version="4.6.2";
   uses:="javax.servlet,
    javax.servlet.http,
    org.eclipse.jgit.lfs.server,
    org.eclipse.jgit.lfs.lib",
- org.eclipse.jgit.lfs.server.internal;version="4.5.7";x-internal:=true,
- org.eclipse.jgit.lfs.server.s3;version="4.5.7";
+ org.eclipse.jgit.lfs.server.internal;version="4.6.2";x-internal:=true,
+ org.eclipse.jgit.lfs.server.s3;version="4.6.2";
   uses:="org.eclipse.jgit.lfs.server,
    org.eclipse.jgit.lfs.lib"
-Bundle-RequiredExecutionEnvironment: JavaSE-1.7
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
 Import-Package: com.google.gson;version="[2.2.4,3.0.0)",
  javax.servlet;version="[3.1.0,4.0.0)",
  javax.servlet.annotation;version="[3.1.0,4.0.0)",
  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="[4.5.7,4.6.0)",
- org.eclipse.jgit.internal;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.internal.storage.file;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.lfs.errors;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.lfs.lib;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.nls;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.transport.http;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.transport.http.apache;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.util;version="[4.5.7,4.6.0)"
+ org.eclipse.jgit.annotations;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.internal;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.internal.storage.file;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.lfs.errors;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.lfs.internal;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.lfs.lib;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.nls;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.transport.http;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.transport.http.apache;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.util;version="[4.6.2,4.7.0)"
diff --git a/org.eclipse.jgit.lfs.server/pom.xml b/org.eclipse.jgit.lfs.server/pom.xml
index 0f55ed0..cc84686 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>4.5.7-SNAPSHOT</version>
+    <version>4.6.2-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.lfs.server</artifactId>
diff --git a/org.eclipse.jgit.lfs.server/resources/org/eclipse/jgit/lfs/server/internal/LfsServerText.properties b/org.eclipse.jgit.lfs.server/resources/org/eclipse/jgit/lfs/server/internal/LfsServerText.properties
index f97acac..b2b487e 100644
--- a/org.eclipse.jgit.lfs.server/resources/org/eclipse/jgit/lfs/server/internal/LfsServerText.properties
+++ b/org.eclipse.jgit.lfs.server/resources/org/eclipse/jgit/lfs/server/internal/LfsServerText.properties
@@ -1,4 +1,3 @@
-corruptLongObject=The content hash ''{0}'' of the long object ''{1}'' doesn''t match its id, the corrupt object will be deleted.
 failedToCalcSignature=Failed to calculate a request signature: {0}
 invalidPathInfo=Invalid pathInfo ''{0}'' does not match ''/'{'SHA-256'}'''
 objectNotFound=Object ''{0}'' not found
diff --git a/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/LfsProtocolServlet.java b/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/LfsProtocolServlet.java
index eb49ff0..841074b 100644
--- a/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/LfsProtocolServlet.java
+++ b/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/LfsProtocolServlet.java
@@ -44,8 +44,8 @@
 
 import static java.nio.charset.StandardCharsets.UTF_8;
 import static org.apache.http.HttpStatus.SC_FORBIDDEN;
-import static org.apache.http.HttpStatus.SC_INTERNAL_SERVER_ERROR;
 import static org.apache.http.HttpStatus.SC_INSUFFICIENT_STORAGE;
+import static org.apache.http.HttpStatus.SC_INTERNAL_SERVER_ERROR;
 import static org.apache.http.HttpStatus.SC_NOT_FOUND;
 import static org.apache.http.HttpStatus.SC_OK;
 import static org.apache.http.HttpStatus.SC_SERVICE_UNAVAILABLE;
diff --git a/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/fs/FileLfsRepository.java b/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/fs/FileLfsRepository.java
index dd70a36..a05fa01 100644
--- a/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/fs/FileLfsRepository.java
+++ b/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/fs/FileLfsRepository.java
@@ -53,6 +53,7 @@
 import java.util.Collections;
 
 import org.eclipse.jgit.annotations.Nullable;
+import org.eclipse.jgit.lfs.internal.AtomicObjectOutputStream;
 import org.eclipse.jgit.lfs.lib.AnyLongObjectId;
 import org.eclipse.jgit.lfs.lib.Constants;
 import org.eclipse.jgit.lfs.server.LargeFileRepository;
diff --git a/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/fs/FileLfsServlet.java b/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/fs/FileLfsServlet.java
index 2ecba6d..a8e3c11 100644
--- a/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/fs/FileLfsServlet.java
+++ b/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/fs/FileLfsServlet.java
@@ -125,7 +125,20 @@ protected void doGet(HttpServletRequest req,
 		}
 	}
 
-	private AnyLongObjectId getObjectToTransfer(HttpServletRequest req,
+	/**
+	 * Retrieve object id from request
+	 *
+	 * @param req
+	 *            servlet request
+	 * @param rsp
+	 *            servlet response
+	 * @return object id, or <code>null</code> if the object id could not be
+	 *         retrieved
+	 * @throws IOException
+	 *             if an I/O error occurs
+         * @since 4.6
+	 */
+	protected AnyLongObjectId getObjectToTransfer(HttpServletRequest req,
 			HttpServletResponse rsp) throws IOException {
 		String info = req.getPathInfo();
 		int length = 1 + Constants.LONG_OBJECT_ID_STRING_LENGTH;
@@ -174,7 +187,20 @@ static class Error {
 		}
 	}
 
-	static void sendError(HttpServletResponse rsp, int status, String message)
+	/**
+	 * Send an error response.
+	 *
+	 * @param rsp
+	 *            the servlet response
+	 * @param status
+	 *            HTTP status code
+	 * @param message
+	 *            error message
+	 * @throws IOException
+	 *             on failure to send the response
+	 * @since 4.6
+	 */
+	protected static void sendError(HttpServletResponse rsp, int status, String message)
 			throws IOException {
 		rsp.setStatus(status);
 		PrintWriter writer = rsp.getWriter();
diff --git a/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/fs/ObjectUploadListener.java b/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/fs/ObjectUploadListener.java
index d44b3db..84e4e6f 100644
--- a/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/fs/ObjectUploadListener.java
+++ b/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/fs/ObjectUploadListener.java
@@ -59,13 +59,16 @@
 
 import org.apache.http.HttpStatus;
 import org.eclipse.jgit.lfs.errors.CorruptLongObjectException;
+import org.eclipse.jgit.lfs.internal.AtomicObjectOutputStream;
 import org.eclipse.jgit.lfs.lib.AnyLongObjectId;
 import org.eclipse.jgit.lfs.lib.Constants;
 
 /**
- * Handle asynchronous object upload
+ * Handle asynchronous object upload.
+ *
+ * @since 4.6
  */
-class ObjectUploadListener implements ReadListener {
+public class ObjectUploadListener implements ReadListener {
 
 	private static Logger LOG = Logger
 			.getLogger(ObjectUploadListener.class.getName());
@@ -138,6 +141,9 @@ public void onAllDataRead() throws IOException {
 		close();
 	}
 
+	/**
+	 * @throws IOException
+	 */
 	protected void close() throws IOException {
 		try {
 			inChannel.close();
@@ -173,4 +179,4 @@ public void onError(Throwable e) {
 			LOG.log(Level.SEVERE, ex.getMessage(), ex);
 		}
 	}
-}
\ No newline at end of file
+}
diff --git a/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/internal/LfsServerText.java b/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/internal/LfsServerText.java
index c5ad53a..2e088fd 100644
--- a/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/internal/LfsServerText.java
+++ b/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/internal/LfsServerText.java
@@ -58,7 +58,6 @@ public static LfsServerText get() {
 	}
 
 	// @formatter:off
-	/***/ public String corruptLongObject;
 	/***/ public String failedToCalcSignature;
 	/***/ public String invalidPathInfo;
 	/***/ public String objectNotFound;
diff --git a/org.eclipse.jgit.lfs.test/.classpath b/org.eclipse.jgit.lfs.test/.classpath
index efc781d..e43ae76 100644
--- a/org.eclipse.jgit.lfs.test/.classpath
+++ b/org.eclipse.jgit.lfs.test/.classpath
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
 	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
 	<classpathentry kind="src" path="src"/>
 	<classpathentry kind="src" path="tst"/>
diff --git a/org.eclipse.jgit.lfs.test/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit.lfs.test/.settings/org.eclipse.jdt.core.prefs
index 87210fb..10c29d5 100644
--- a/org.eclipse.jgit.lfs.test/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit.lfs.test/.settings/org.eclipse.jdt.core.prefs
@@ -7,9 +7,9 @@
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.compliance=1.8
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -112,7 +112,7 @@
 org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
-org.eclipse.jdt.core.compiler.source=1.7
+org.eclipse.jdt.core.compiler.source=1.8
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
diff --git a/org.eclipse.jgit.lfs.test/BUCK b/org.eclipse.jgit.lfs.test/BUCK
index d0fb96f..1298e16 100644
--- a/org.eclipse.jgit.lfs.test/BUCK
+++ b/org.eclipse.jgit.lfs.test/BUCK
@@ -15,7 +15,6 @@
       '//lib:hamcrest-library',
       '//lib:junit',
     ],
-    source_under_test = ['//org.eclipse.jgit.lfs:jgit-lfs'],
   )
 
 java_library(
diff --git a/org.eclipse.jgit.lfs.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.lfs.test/META-INF/MANIFEST.MF
index 5922013..e859f63 100644
--- a/org.eclipse.jgit.lfs.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.lfs.test/META-INF/MANIFEST.MF
@@ -2,18 +2,19 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %plugin_name
 Bundle-SymbolicName: org.eclipse.jgit.lfs.test
-Bundle-Version: 4.5.7.qualifier
+Bundle-Version: 4.6.2.qualifier
 Bundle-Vendor: %provider_name
 Bundle-Localization: plugin
-Bundle-RequiredExecutionEnvironment: JavaSE-1.7
-Import-Package: org.eclipse.jgit.junit;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.lfs.errors;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.lfs.lib;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.lib;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.util;version="[4.5.7,4.6.0)",
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Import-Package: org.eclipse.jgit.junit;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.lfs;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.lfs.errors;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.lfs.lib;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.lib;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.util;version="[4.6.2,4.7.0)",
  org.hamcrest.core;version="[1.1.0,2.0.0)",
  org.junit;version="[4.0.0,5.0.0)",
  org.junit.runner;version="[4.0.0,5.0.0)",
  org.junit.runners;version="[4.0.0,5.0.0)"
-Export-Package: org.eclipse.jgit.lfs.test;version="4.5.7";x-friends:="org.eclipse.jgit.lfs.server.test"
+Export-Package: org.eclipse.jgit.lfs.test;version="4.6.2";x-friends:="org.eclipse.jgit.lfs.server.test"
 
diff --git a/org.eclipse.jgit.lfs.test/pom.xml b/org.eclipse.jgit.lfs.test/pom.xml
index 007440c..a06aefc 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>4.5.7-SNAPSHOT</version>
+    <version>4.6.2-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.lfs.test</artifactId>
diff --git a/org.eclipse.jgit.lfs.test/tst/org/eclipse/jgit/lfs/lib/LFSPointerTest.java b/org.eclipse.jgit.lfs.test/tst/org/eclipse/jgit/lfs/lib/LFSPointerTest.java
new file mode 100644
index 0000000..4827d3d
--- /dev/null
+++ b/org.eclipse.jgit.lfs.test/tst/org/eclipse/jgit/lfs/lib/LFSPointerTest.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2016, Christian Halstrick <christian.halstrick@sap.com>
+ * 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.lfs.lib;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+
+import org.eclipse.jgit.lfs.LfsPointer;
+import org.junit.Test;
+
+/*
+ * Test LfsPointer file abstraction
+ */
+public class LFSPointerTest {
+	@Test
+	public void testEncoding() throws IOException {
+		final String s = "27e15b72937fc8f558da24ac3d50ec20302a4cf21e33b87ae8e4ce90e89c4b10";
+		AnyLongObjectId id = LongObjectId.fromString(s);
+		LfsPointer ptr = new LfsPointer(id, 4);
+		ByteArrayOutputStream baos = new ByteArrayOutputStream();
+		ptr.encode(baos);
+		baos.close();
+		assertEquals("version https://git-lfs.github.com/spec/v1\noid sha256:"
+				+ s + "\nsize 4\n",
+				baos.toString(StandardCharsets.UTF_8.name()));
+	}
+}
diff --git a/org.eclipse.jgit.lfs/.classpath b/org.eclipse.jgit.lfs/.classpath
index 04a2be7..cfcf24a 100644
--- a/org.eclipse.jgit.lfs/.classpath
+++ b/org.eclipse.jgit.lfs/.classpath
@@ -2,7 +2,7 @@
 <classpath>
 	<classpathentry kind="src" path="src"/>
 	<classpathentry kind="src" path="resources"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
 	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>
diff --git a/org.eclipse.jgit.lfs/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit.lfs/.settings/org.eclipse.jdt.core.prefs
index 1ce7cd0..808ec3a 100644
--- a/org.eclipse.jgit.lfs/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit.lfs/.settings/org.eclipse.jdt.core.prefs
@@ -7,9 +7,9 @@
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.compliance=1.8
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -112,7 +112,7 @@
 org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
-org.eclipse.jdt.core.compiler.source=1.7
+org.eclipse.jdt.core.compiler.source=1.8
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
diff --git a/org.eclipse.jgit.lfs/META-INF/MANIFEST.MF b/org.eclipse.jgit.lfs/META-INF/MANIFEST.MF
index ef51330..d5d1f7c 100644
--- a/org.eclipse.jgit.lfs/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.lfs/META-INF/MANIFEST.MF
@@ -2,14 +2,17 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %plugin_name
 Bundle-SymbolicName: org.eclipse.jgit.lfs
-Bundle-Version: 4.5.7.qualifier
+Bundle-Version: 4.6.2.qualifier
 Bundle-Localization: plugin
 Bundle-Vendor: %provider_name
-Export-Package: org.eclipse.jgit.lfs.errors;version="4.5.7",
- org.eclipse.jgit.lfs.internal;version="4.5.7";x-friends:="org.eclipse.jgit.lfs.test",
- org.eclipse.jgit.lfs.lib;version="4.5.7"
-Bundle-RequiredExecutionEnvironment: JavaSE-1.7
-Import-Package: org.eclipse.jgit.internal.storage.file;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.lib;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.nls;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.util;version="[4.5.7,4.6.0)"
+Export-Package: org.eclipse.jgit.lfs;version="4.6.2",
+ org.eclipse.jgit.lfs.errors;version="4.6.2",
+ org.eclipse.jgit.lfs.internal;version="4.6.2";x-friends:="org.eclipse.jgit.lfs.test,org.eclipse.jgit.lfs.server.fs,org.eclipse.jgit.lfs.server",
+ org.eclipse.jgit.lfs.lib;version="4.6.2"
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Import-Package: org.eclipse.jgit.annotations;version="[4.6.2,4.7.0)";resolution:=optional,
+ org.eclipse.jgit.attributes;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.internal.storage.file;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.lib;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.nls;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.util;version="[4.6.2,4.7.0)"
diff --git a/org.eclipse.jgit.lfs/pom.xml b/org.eclipse.jgit.lfs/pom.xml
index c447277..049b360 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>4.5.7-SNAPSHOT</version>
+    <version>4.6.2-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.lfs</artifactId>
diff --git a/org.eclipse.jgit.lfs/resources/org/eclipse/jgit/lfs/internal/LfsText.properties b/org.eclipse.jgit.lfs/resources/org/eclipse/jgit/lfs/internal/LfsText.properties
index 7c3aea2..5e52a78 100644
--- a/org.eclipse.jgit.lfs/resources/org/eclipse/jgit/lfs/internal/LfsText.properties
+++ b/org.eclipse.jgit.lfs/resources/org/eclipse/jgit/lfs/internal/LfsText.properties
@@ -1,7 +1,9 @@
+corruptLongObject=The content hash ''{0}'' of the long object ''{1}'' doesn''t match its id, the corrupt object will be deleted.
 incorrectLONG_OBJECT_ID_LENGTH=Incorrect LONG_OBJECT_ID_LENGTH.
+inconsistentMediafileLength=mediafile {0} has unexpected length; expected {1} but found {2}.
 invalidLongId=Invalid id: {0}
 invalidLongIdLength=Invalid id length {0}; should be {1}
 requiredHashFunctionNotAvailable=Required hash function {0} not available.
 repositoryNotFound=Repository {0} not found
 repositoryReadOnly=Repository {0} is read-only
-lfsUnavailable=LFS is not available for repository {0}
\ No newline at end of file
+lfsUnavailable=LFS is not available for repository {0}
diff --git a/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/CleanFilter.java b/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/CleanFilter.java
new file mode 100644
index 0000000..66feca7
--- /dev/null
+++ b/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/CleanFilter.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2016, Christian Halstrick <christian.halstrick@sap.com>
+ * 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.lfs;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
+
+import org.eclipse.jgit.attributes.FilterCommand;
+import org.eclipse.jgit.attributes.FilterCommandFactory;
+import org.eclipse.jgit.attributes.FilterCommandRegistry;
+import org.eclipse.jgit.lfs.errors.CorruptMediaFile;
+import org.eclipse.jgit.lfs.internal.AtomicObjectOutputStream;
+import org.eclipse.jgit.lfs.lib.AnyLongObjectId;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.util.FileUtils;
+
+/**
+ * Built-in LFS clean filter
+ *
+ * When new content is about to be added to the git repository and this filter
+ * is configured for that content, then this filter will replace the original
+ * content with content of a so-called LFS pointer file. The pointer file
+ * content will then be added to the git repository. Additionally this filter
+ * writes the original content in a so-called 'media file' to '.git/lfs/objects/
+ * <first-two-characters-of-contentid>/<rest-of-contentid>'
+ *
+ * @see <a href="https://github.com/github/git-lfs/blob/master/docs/spec.md">Git
+ *      LFS Specification</a>
+ * @since 4.6
+ */
+public class CleanFilter extends FilterCommand {
+	/**
+	 * The factory is responsible for creating instances of {@link CleanFilter}
+	 */
+	public final static FilterCommandFactory FACTORY = new FilterCommandFactory() {
+
+		@Override
+		public FilterCommand create(Repository db, InputStream in,
+				OutputStream out) throws IOException {
+			return new CleanFilter(db, in, out);
+		}
+	};
+
+	/**
+	 * Registers this filter by calling
+	 * {@link FilterCommandRegistry#register(String, FilterCommandFactory)}
+	 */
+	public final static void register() {
+		FilterCommandRegistry.register(
+				org.eclipse.jgit.lib.Constants.BUILTIN_FILTER_PREFIX
+						+ "lfs/clean", //$NON-NLS-1$
+				FACTORY);
+	}
+
+	// Used to compute the hash for the original content
+	private AtomicObjectOutputStream aOut;
+
+	private Lfs lfsUtil;
+
+	// the size of the original content
+	private long size;
+
+	// a temporary file into which the original content is written. When no
+	// errors occur this file will be renamed to the mediafile
+	private Path tmpFile;
+
+	/**
+	 * @param db
+	 *            the repository
+	 * @param in
+	 *            an {@link InputStream} providing the original content
+	 * @param out
+	 *            the {@link OutputStream} into which the content of the pointer
+	 *            file should be written. That's the content which will be added
+	 *            to the git repository
+	 * @throws IOException
+	 *             when the creation of the temporary file fails or when no
+	 *             {@link OutputStream} for this file can be created
+	 */
+	public CleanFilter(Repository db, InputStream in, OutputStream out)
+			throws IOException {
+		super(in, out);
+		lfsUtil = new Lfs(db.getDirectory().toPath().resolve("lfs")); //$NON-NLS-1$
+		Files.createDirectories(lfsUtil.getLfsTmpDir());
+		tmpFile = lfsUtil.createTmpFile();
+		this.aOut = new AtomicObjectOutputStream(tmpFile.toAbsolutePath());
+	}
+
+	public int run() throws IOException {
+		try {
+			byte[] buf = new byte[8192];
+			int length = in.read(buf);
+			if (length != -1) {
+				aOut.write(buf, 0, length);
+				size += length;
+				return length;
+			} else {
+				aOut.close();
+				AnyLongObjectId loid = aOut.getId();
+				aOut = null;
+				Path mediaFile = lfsUtil.getMediaFile(loid);
+				if (Files.isRegularFile(mediaFile)) {
+					long fsSize = Files.size(mediaFile);
+					if (fsSize != size) {
+						throw new CorruptMediaFile(mediaFile, size, fsSize);
+					} else {
+						FileUtils.delete(tmpFile.toFile());
+					}
+				} else {
+					FileUtils.mkdirs(mediaFile.getParent().toFile(), true);
+					FileUtils.rename(tmpFile.toFile(), mediaFile.toFile(),
+							StandardCopyOption.ATOMIC_MOVE);
+				}
+				LfsPointer lfsPointer = new LfsPointer(loid, size);
+				lfsPointer.encode(out);
+				out.close();
+				return -1;
+			}
+		} catch (IOException e) {
+			if (aOut != null) {
+				aOut.abort();
+			}
+			out.close();
+			throw e;
+		}
+	}
+}
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
new file mode 100644
index 0000000..75e34e0
--- /dev/null
+++ b/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/Lfs.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2016, Christian Halstrick <christian.halstrick@sap.com>
+ * 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.lfs;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import org.eclipse.jgit.lfs.lib.AnyLongObjectId;
+
+/**
+ * Class which represents the lfs folder hierarchy inside a .git folder
+ *
+ * @since 4.6
+ */
+public class Lfs {
+	private Path root;
+
+	private Path objDir;
+
+	private Path tmpDir;
+
+	/**
+	 * @param root
+	 *            the path to the LFS media directory. Will be "<repo>/.git/lfs"
+	 */
+	public Lfs(Path root) {
+		this.root = root;
+	}
+
+	/**
+	 * @return the path to the LFS directory
+	 */
+	public Path getLfsRoot() {
+		return root;
+	}
+
+	/**
+	 * @return the path to the temp directory used by LFS. Will be
+	 *         "<repo>/.git/lfs/tmp"
+	 */
+	public Path getLfsTmpDir() {
+		if (tmpDir == null) {
+			tmpDir = root.resolve("tmp"); //$NON-NLS-1$
+		}
+		return tmpDir;
+	}
+
+	/**
+	 * @return the path to the object directory used by LFS. Will be
+	 *         "<repo>/.git/lfs/objects"
+	 */
+	public Path getLfsObjDir() {
+		if (objDir == null) {
+			objDir = root.resolve("objects"); //$NON-NLS-1$
+		}
+		return objDir;
+	}
+
+	/**
+	 * @param id
+	 *            the id of the mediafile
+	 * @return the file which stores the original content. This will be files
+	 *         underneath
+	 *         "<repo>/.git/lfs/objects/<firstTwoLettersOfID>/<remainingLettersOfID>"
+	 */
+	public Path getMediaFile(AnyLongObjectId id) {
+		String idStr = id.name();
+		return getLfsObjDir().resolve(idStr.substring(0, 2))
+				.resolve(idStr.substring(2));
+	}
+
+	/**
+	 * Create a new temp file in the LFS directory
+	 *
+	 * @return a new temporary file in the LFS directory
+	 * @throws IOException
+	 *             when the temp file could not be created
+	 */
+	public Path createTmpFile() throws IOException {
+		return Files.createTempFile(getLfsTmpDir(), null, null);
+	}
+
+}
diff --git a/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/LfsPointer.java b/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/LfsPointer.java
new file mode 100644
index 0000000..bbea535
--- /dev/null
+++ b/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/LfsPointer.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2016, Christian Halstrick <christian.halstrick@sap.com>
+ * 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.lfs;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.StandardCharsets;
+import java.nio.charset.UnsupportedCharsetException;
+
+import org.eclipse.jgit.annotations.Nullable;
+import org.eclipse.jgit.lfs.lib.AnyLongObjectId;
+import org.eclipse.jgit.lfs.lib.Constants;
+import org.eclipse.jgit.lfs.lib.LongObjectId;
+
+/**
+ * Represents an LFS pointer file
+ *
+ * @since 4.6
+ */
+public class LfsPointer {
+	/**
+	 * The version of the LfsPointer file format
+	 */
+	public static final String VERSION = "https://git-lfs.github.com/spec/v1"; //$NON-NLS-1$
+
+	/**
+	 * The name of the hash function as used in the pointer files. This will
+	 * evaluate to "sha256"
+	 */
+	public static final String HASH_FUNCTION_NAME = Constants.LONG_HASH_FUNCTION
+			.toLowerCase().replace("-", ""); //$NON-NLS-1$ //$NON-NLS-2$
+
+	private AnyLongObjectId oid;
+
+	private long size;
+
+	/**
+	 * @param oid
+	 *            the id of the content
+	 * @param size
+	 *            the size of the content
+	 */
+	public LfsPointer(AnyLongObjectId oid, long size) {
+		this.oid = oid;
+		this.size = size;
+	}
+
+	/**
+	 * @return the id of the content
+	 */
+	public AnyLongObjectId getOid() {
+		return oid;
+	}
+
+	/**
+	 * @return the size of the content
+	 */
+	public long getSize() {
+		return size;
+	}
+
+	/**
+	 * Encode this object into the LFS format defined by {@link #VERSION}
+	 *
+	 * @param out
+	 *            the {@link OutputStream} into which the encoded data should be
+	 *            written
+	 */
+	public void encode(OutputStream out) {
+		try (PrintStream ps = new PrintStream(out, false,
+				StandardCharsets.UTF_8.name())) {
+			ps.print("version "); //$NON-NLS-1$
+			ps.print(VERSION + "\n"); //$NON-NLS-1$
+			ps.print("oid " + HASH_FUNCTION_NAME + ":"); //$NON-NLS-1$ //$NON-NLS-2$
+			ps.print(oid.name() + "\n"); //$NON-NLS-1$
+			ps.print("size "); //$NON-NLS-1$
+			ps.print(size + "\n"); //$NON-NLS-1$
+		} catch (UnsupportedEncodingException e) {
+			// should not happen, we are using a standard charset
+			throw new UnsupportedCharsetException(
+					StandardCharsets.UTF_8.name());
+		}
+	}
+
+	/**
+	 * Try to parse the data provided by an InputStream to the format defined by
+	 * {@link #VERSION}
+	 *
+	 * @param in
+	 *            the {@link InputStream} from where to read the data
+	 * @return an {@link LfsPointer} or <code>null</code> if the stream was not
+	 *         parseable as LfsPointer
+	 * @throws IOException
+	 */
+	@Nullable
+	public static LfsPointer parseLfsPointer(InputStream in)
+			throws IOException {
+		boolean versionLine = false;
+		LongObjectId id = null;
+		long sz = -1;
+
+		try (BufferedReader br = new BufferedReader(
+				new InputStreamReader(in, StandardCharsets.UTF_8.name()))) {
+			for (String s = br.readLine(); s != null; s = br.readLine()) {
+				if (s.startsWith("#") || s.length() == 0) { //$NON-NLS-1$
+					continue;
+				} else if (s.startsWith("version") && s.length() > 8 //$NON-NLS-1$
+						&& s.substring(8).trim().equals(VERSION)) {
+					versionLine = true;
+				} else if (s.startsWith("oid sha256:")) { //$NON-NLS-1$
+					id = LongObjectId.fromString(s.substring(11).trim());
+				} else if (s.startsWith("size") && s.length() > 5) { //$NON-NLS-1$
+					sz = Long.parseLong(s.substring(5).trim());
+				} else {
+					return null;
+				}
+			}
+			if (versionLine && id != null && sz > -1) {
+				return new LfsPointer(id, sz);
+			}
+		}
+		return null;
+	}
+
+	@Override
+	public String toString() {
+		return "LfsPointer: oid=" + oid.name() + ", size=" //$NON-NLS-1$ //$NON-NLS-2$
+				+ size;
+	}
+}
+
diff --git a/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/SmudgeFilter.java b/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/SmudgeFilter.java
new file mode 100644
index 0000000..2332477
--- /dev/null
+++ b/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/SmudgeFilter.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2016, Christian Halstrick <christian.halstrick@sap.com>
+ * 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.lfs;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import org.eclipse.jgit.attributes.FilterCommand;
+import org.eclipse.jgit.attributes.FilterCommandFactory;
+import org.eclipse.jgit.attributes.FilterCommandRegistry;
+import org.eclipse.jgit.lfs.lib.Constants;
+import org.eclipse.jgit.lib.Repository;
+
+/**
+ * Built-in LFS smudge filter
+ *
+ * When content is read from git's object-database and written to the filesystem
+ * and this filter is configured for that content, then this filter will replace
+ * the content of LFS pointer files with the original content. This happens e.g.
+ * when a checkout needs to update a working tree file which is under LFS
+ * control. This implementation expects that the origin content is already
+ * available in the .git/lfs/objects folder. This implementation will not
+ * contact any LFS servers in order to get the missing content.
+ *
+ * @since 4.6
+ */
+public class SmudgeFilter extends FilterCommand {
+	/**
+	 * The factory is responsible for creating instances of {@link SmudgeFilter}
+	 */
+	public final static FilterCommandFactory FACTORY = new FilterCommandFactory() {
+		@Override
+		public FilterCommand create(Repository db, InputStream in,
+				OutputStream out) throws IOException {
+			return new SmudgeFilter(db, in, out);
+		}
+	};
+
+	/**
+	 * Registers this filter in JGit by calling
+	 */
+	public final static void register() {
+		FilterCommandRegistry.register(
+				org.eclipse.jgit.lib.Constants.BUILTIN_FILTER_PREFIX
+						+ "lfs/smudge", //$NON-NLS-1$
+				FACTORY);
+	}
+
+	private Lfs lfs;
+
+	/**
+	 * @param db
+	 * @param in
+	 * @param out
+	 * @throws IOException
+	 */
+	public SmudgeFilter(Repository db, InputStream in, OutputStream out)
+			throws IOException {
+		super(in, out);
+		lfs = new Lfs(db.getDirectory().toPath().resolve(Constants.LFS));
+		LfsPointer res = LfsPointer.parseLfsPointer(in);
+		if (res != null) {
+			Path mediaFile = lfs.getMediaFile(res.getOid());
+			if (Files.exists(mediaFile)) {
+				this.in = Files.newInputStream(mediaFile);
+			}
+		}
+	}
+
+	@Override
+	public int run() throws IOException {
+		int b;
+		if (in != null) {
+			while ((b = in.read()) != -1) {
+				out.write(b);
+			}
+			in.close();
+		}
+		out.close();
+		return -1;
+	}
+}
diff --git a/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/errors/CorruptMediaFile.java b/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/errors/CorruptMediaFile.java
new file mode 100644
index 0000000..f2b51c0
--- /dev/null
+++ b/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/errors/CorruptMediaFile.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2016, Christian Halstrick <christian.halstrick@sap.com>
+ * 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.lfs.errors;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.text.MessageFormat;
+
+import org.eclipse.jgit.lfs.internal.LfsText;
+
+/**
+ * Thrown when a LFS mediafile is found which doesn't have the expected size
+ *
+ * @since 4.6
+ */
+public class CorruptMediaFile extends IOException {
+	private static final long serialVersionUID = 1L;
+
+	private Path mediaFile;
+
+	private long expectedSize;
+
+	private long size;
+
+	/**
+	 * @param mediaFile
+	 * @param expectedSize
+	 * @param size
+	 */
+	@SuppressWarnings("boxing")
+	public CorruptMediaFile(Path mediaFile, long expectedSize,
+			long size) {
+		super(MessageFormat.format(LfsText.get().inconsistentMediafileLength,
+				mediaFile, expectedSize, size));
+		this.mediaFile = mediaFile;
+		this.expectedSize = expectedSize;
+		this.size = size;
+	}
+
+	/**
+	 * @return the media file which seems to be corrupt
+	 */
+	public Path getMediaFile() {
+		return mediaFile;
+	}
+
+	/**
+	 * @return the expected size of the media file
+	 */
+	public long getExpectedSize() {
+		return expectedSize;
+	}
+
+	/**
+	 * @return the actual size of the media file in the file system
+	 */
+	public long getSize() {
+		return size;
+	}
+}
diff --git a/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/fs/AtomicObjectOutputStream.java b/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/internal/AtomicObjectOutputStream.java
similarity index 79%
rename from org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/fs/AtomicObjectOutputStream.java
rename to org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/internal/AtomicObjectOutputStream.java
index ecc7c1f..867cca5 100644
--- a/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/fs/AtomicObjectOutputStream.java
+++ b/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/internal/AtomicObjectOutputStream.java
@@ -40,7 +40,7 @@
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-package org.eclipse.jgit.lfs.server.fs;
+package org.eclipse.jgit.lfs.internal;
 
 import java.io.IOException;
 import java.io.OutputStream;
@@ -48,19 +48,19 @@
 import java.security.DigestOutputStream;
 import java.text.MessageFormat;
 
+import org.eclipse.jgit.annotations.Nullable;
 import org.eclipse.jgit.internal.storage.file.LockFile;
 import org.eclipse.jgit.lfs.errors.CorruptLongObjectException;
 import org.eclipse.jgit.lfs.lib.AnyLongObjectId;
 import org.eclipse.jgit.lfs.lib.Constants;
 import org.eclipse.jgit.lfs.lib.LongObjectId;
-import org.eclipse.jgit.lfs.server.internal.LfsServerText;
 
 /**
  * Output stream writing content to a {@link LockFile} which is committed on
  * close(). The stream checks if the hash of the stream content matches the
  * id.
  */
-class AtomicObjectOutputStream extends OutputStream {
+public class AtomicObjectOutputStream extends OutputStream {
 
 	private LockFile locked;
 
@@ -70,7 +70,12 @@ class AtomicObjectOutputStream extends OutputStream {
 
 	private AnyLongObjectId id;
 
-	AtomicObjectOutputStream(Path path, AnyLongObjectId id)
+	/**
+	 * @param path
+	 * @param id
+	 * @throws IOException
+	 */
+	public AtomicObjectOutputStream(Path path, AnyLongObjectId id)
 			throws IOException {
 		locked = new LockFile(path.toFile());
 		locked.lock();
@@ -79,6 +84,22 @@ class AtomicObjectOutputStream extends OutputStream {
 				Constants.newMessageDigest());
 	}
 
+	/**
+	 * @param path
+	 * @throws IOException
+	 */
+	public AtomicObjectOutputStream(Path path) throws IOException {
+		this(path, null);
+	}
+
+	/**
+	 * @return content hash of the object which was streamed through this
+	 *         stream. May return {@code null} if called before closing this stream.
+	 */
+	public @Nullable AnyLongObjectId getId() {
+		return id;
+	}
+
 	@Override
 	public void write(int b) throws IOException {
 		out.write(b);
@@ -98,7 +119,11 @@ public void write(byte[] b, int off, int len) throws IOException {
 	public void close() throws IOException {
 		out.close();
 		if (!aborted) {
-			verifyHash();
+			if (id != null) {
+				verifyHash();
+			} else {
+				id = LongObjectId.fromRaw(out.getMessageDigest().digest());
+			}
 			locked.commit();
 		}
 	}
@@ -109,12 +134,15 @@ private void verifyHash() {
 		if (!contentHash.equals(id)) {
 			abort();
 			throw new CorruptLongObjectException(id, contentHash,
-					MessageFormat.format(LfsServerText.get().corruptLongObject,
+					MessageFormat.format(LfsText.get().corruptLongObject,
 							contentHash, id));
 		}
 	}
 
-	void abort() {
+	/**
+	 * Aborts the stream. Temporary file will be deleted
+	 */
+	public void abort() {
 		locked.unlock();
 		aborted = true;
 	}
diff --git a/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/internal/LfsText.java b/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/internal/LfsText.java
index 365eaa1..c76df39 100644
--- a/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/internal/LfsText.java
+++ b/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/internal/LfsText.java
@@ -58,6 +58,8 @@ public static LfsText get() {
 	}
 
 	// @formatter:off
+	/***/ public String corruptLongObject;
+	/***/ public String inconsistentMediafileLength;
 	/***/ public String incorrectLONG_OBJECT_ID_LENGTH;
 	/***/ public String invalidLongId;
 	/***/ public String invalidLongIdLength;
diff --git a/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/lib/Constants.java b/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/lib/Constants.java
index d246412..a88057a 100644
--- a/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/lib/Constants.java
+++ b/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/lib/Constants.java
@@ -55,8 +55,19 @@
  **/
 @SuppressWarnings("nls")
 public final class Constants {
-	/** Hash function used natively by Git LFS extension for large objects. */
-	private static final String LONG_HASH_FUNCTION = "SHA-256";
+	/**
+	 * lfs folder
+	 *
+	 * @since 4.6
+	 */
+	public static final String LFS = "lfs";
+
+	/**
+	 * Hash function used natively by Git LFS extension for large objects.
+	 *
+	 * @since 4.6
+	 */
+	public static final String LONG_HASH_FUNCTION = "SHA-256";
 
 	/**
 	 * A Git LFS large object hash is 256 bits, i.e. 32 bytes.
@@ -104,11 +115,11 @@ public static MessageDigest newMessageDigest() {
 	 * Content type used by LFS REST API as defined in
 	 * {@link "https://github.com/github/git-lfs/blob/master/docs/api/v1/http-v1-batch.md"}
 	 */
-	public static String CONTENT_TYPE_GIT_LFS_JSON = "application/vnd.git-lfs+json";
+	public static final String CONTENT_TYPE_GIT_LFS_JSON = "application/vnd.git-lfs+json";
 
 	/**
 	 * "arbitrary binary data" as defined in RFC 2046
 	 * {@link "https://www.ietf.org/rfc/rfc2046.txt"}
 	 */
-	public static String HDR_APPLICATION_OCTET_STREAM = "application/octet-stream";
+	public static final String HDR_APPLICATION_OCTET_STREAM = "application/octet-stream";
 }
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 adc07c8..85ac88b 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="4.5.7.qualifier"
+      version="4.6.2.qualifier"
       provider-name="%providerName">
 
    <description url="http://www.eclipse.org/jgit/">
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.feature/pom.xml
index 004547f..6f75186 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>4.5.7-SNAPSHOT</version>
+    <version>4.6.2-SNAPSHOT</version>
   </parent>
 
   <groupId>org.eclipse.jgit.feature</groupId>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.http.apache.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.http.apache.feature/feature.xml
index c612b0c..e272c0b 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="4.5.7.qualifier"
+      version="4.6.2.qualifier"
       provider-name="%providerName">
 
    <description url="http://www.eclipse.org/jgit/">
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.http.apache.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.http.apache.feature/pom.xml
index b763bbd..679f880 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>4.5.7-SNAPSHOT</version>
+    <version>4.6.2-SNAPSHOT</version>
   </parent>
 
   <groupId>org.eclipse.jgit.feature</groupId>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/feature.properties b/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/feature.properties
index 9ef46ba..4450bbb 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/feature.properties
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/feature.properties
@@ -9,14 +9,13 @@
 #
 ###############################################################################
 
-featureName=JUnit test support for Java implementation of Git
+featureName=Java implementation of Git - JUnit test support
 providerName=Eclipse JGit
 
 updateSiteName=Eclipse JGit Update Site
 
 # description property - text of the "Feature Description"
-description=\
-JUnit test support for JGit.\n
+description=JUnit test support for JGit
 ################ end of description property ##################################
 
 # "copyright" property - text of the "Feature Update Copyright"
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 3c827ed..fe7e3ac 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="4.5.7.qualifier"
+      version="4.6.2.qualifier"
       provider-name="%providerName">
 
    <description url="http://www.eclipse.org/jgit/">
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/pom.xml
index 68b703a..0b0a335 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>4.5.7-SNAPSHOT</version>
+    <version>4.6.2-SNAPSHOT</version>
   </parent>
 
   <groupId>org.eclipse.jgit.feature</groupId>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.lfs.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.lfs.feature/feature.xml
index 82640da..4aefd72 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="4.5.7.qualifier"
+      version="4.6.2.qualifier"
       provider-name="%providerName">
 
    <description url="http://www.eclipse.org/jgit/">
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.lfs.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.lfs.feature/pom.xml
index 1fafcf9..893c492 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>4.5.7-SNAPSHOT</version>
+    <version>4.6.2-SNAPSHOT</version>
   </parent>
 
   <groupId>org.eclipse.jgit.feature</groupId>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/feature.properties b/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/feature.properties
index 1d1130a..8992ad3 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/feature.properties
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/feature.properties
@@ -8,14 +8,14 @@
 #
 ###############################################################################
 
-featureName=Command Line Interface for Java implementation of Git
+featureName=Java implementation of Git - Command Line Interface
 providerName=Eclipse JGit
 
 updateSiteName=Eclipse JGit Update Site
 
 # description property - text of the "Feature Description"
 description=\
-Command line interface for a pure Java implementation of the Git version control system.\n
+Command line interface for a pure Java implementation of the Git version control system
 ################ end of description property ##################################
 
 # "copyright" property - text of the "Feature Update Copyright"
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 c7aca64..2c91754 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="4.5.7.qualifier"
+      version="4.6.2.qualifier"
       provider-name="%providerName">
 
    <description url="http://www.eclipse.org/jgit/">
@@ -31,8 +31,8 @@
          version="0.0.0"/>
 
    <requires>
-      <import feature="org.eclipse.jgit" version="4.5.0" match="equivalent"/>
-      <import feature="org.eclipse.jgit.lfs" version="4.5.0" match="equivalent"/>
+      <import feature="org.eclipse.jgit" version="4.6.2" match="equivalent"/>
+      <import feature="org.eclipse.jgit.lfs" version="4.6.2" match="equivalent"/>
    </requires>
 
    <plugin
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/pom.xml
index 43e75c0..b6c5846 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>4.5.7-SNAPSHOT</version>
+    <version>4.6.2-SNAPSHOT</version>
   </parent>
 
   <groupId>org.eclipse.jgit.feature</groupId>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.source.feature/feature.properties b/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.source.feature/feature.properties
index 20d6641..012c217 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.source.feature/feature.properties
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.source.feature/feature.properties
@@ -8,7 +8,7 @@
 #
 ###############################################################################
 
-featureName=Command Line Interface for Java implementation of Git - Source Code
+featureName=Java implementation of Git - Command Line Interface - Source Code
 providerName=Eclipse JGit
 
 updateSiteName=Eclipse JGit Update Site
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.source.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.source.feature/feature.xml
index 8ea3410..444a872 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.source.feature/feature.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.source.feature/feature.xml
@@ -2,7 +2,7 @@
 <feature
       id="org.eclipse.jgit.pgm.source"
       label="%featureName"
-      version="4.5.7.qualifier"
+      version="4.6.2.qualifier"
       provider-name="%providerName">
 
    <description url="http://www.eclipse.org/jgit/">
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.source.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.source.feature/pom.xml
index 557c868..a35034a 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.source.feature/pom.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.source.feature/pom.xml
@@ -50,7 +50,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>jgit.tycho.parent</artifactId>
-    <version>4.5.7-SNAPSHOT</version>
+    <version>4.6.2-SNAPSHOT</version>
   </parent>
 
   <groupId>org.eclipse.jgit.feature</groupId>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.repository/category.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.repository/category.xml
index 15d10e6..0149029 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.repository/category.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.repository/category.xml
@@ -24,9 +24,9 @@
    <feature url="features/org.eclipse.jgit.lfs_0.0.0.qualifier.jar" id="org.eclipse.jgit.lfs" version="0.0.0">
       <category name="JGit"/>
    </feature>
-   <category-def name="JGit" label="JGit">
+   <category-def name="JGit" label="Java implementation of Git">
       <description>
-         JGit
+         Java implementation of Git
       </description>
    </category-def>
 </site>
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 cbd917b..d611d29 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>4.5.7-SNAPSHOT</version>
+    <version>4.6.2-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.repository</artifactId>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/feature.xml
index 62c46f2..20ab58c 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="4.5.7.qualifier"
+      version="4.6.2.qualifier"
       provider-name="%providerName">
 
    <description url="http://www.eclipse.org/jgit/">
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/pom.xml
index 3b0fd3f..e11e042 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>4.5.7-SNAPSHOT</version>
+    <version>4.6.2-SNAPSHOT</version>
   </parent>
 
   <groupId>org.eclipse.jgit.feature</groupId>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/.classpath b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/.classpath
index 098194c..eca7bdb 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/.classpath
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/.classpath
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
 	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
 	<classpathentry kind="src" path="src"/>
 	<classpathentry kind="output" path="bin"/>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/META-INF/MANIFEST.MF b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/META-INF/MANIFEST.MF
index 069b24e..cd39231 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/META-INF/MANIFEST.MF
@@ -2,4 +2,4 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: JGit Target Platform Bundle
 Bundle-SymbolicName: org.eclipse.jgit.target
-Bundle-Version: 4.5.7.qualifier
+Bundle-Version: 4.6.2.qualifier
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.3.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.3.target
deleted file mode 100644
index 19edf51..0000000
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.3.target
+++ /dev/null
@@ -1,68 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<?pde?>
-<!-- generated with https://github.com/mbarbero/fr.obeo.releng.targetplatform -->
-<target name="jgit-4.3" sequenceNumber="1440024094">
-  <locations>
-    <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
-      <unit id="org.eclipse.jetty.client" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.client.source" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.continuation" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.continuation.source" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.http" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.http.source" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.io" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.io.source" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.security" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.security.source" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.server" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.server.source" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.servlet" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.servlet.source" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.util" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.util.source" version="9.2.13.v20150730"/>
-      <repository id="jetty-9.2.13" location="http://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.2.13.v20150730/"/>
-    </location>
-    <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
-      <unit id="org.apache.ant" version="1.9.2.v201404171502"/>
-      <unit id="org.apache.ant.source" version="1.9.2.v201404171502"/>
-      <unit id="org.apache.commons.compress" version="1.6.0.v201310281400"/>
-      <unit id="org.apache.commons.compress.source" version="1.6.0.v201310281400"/>
-      <unit id="org.apache.commons.logging" version="1.1.1.v201101211721"/>
-      <unit id="org.apache.commons.logging.source" version="1.1.1.v201101211721"/>
-      <unit id="org.apache.httpcomponents.httpcore" version="4.3.3.v201411290715"/>
-      <unit id="org.apache.httpcomponents.httpcore.source" version="4.3.3.v201411290715"/>
-      <unit id="org.apache.httpcomponents.httpclient" version="4.3.6.v201411290715"/>
-      <unit id="org.apache.httpcomponents.httpclient.source" version="4.3.6.v201411290715"/>
-      <unit id="org.apache.log4j" version="1.2.15.v201012070815"/>
-      <unit id="org.apache.log4j.source" version="1.2.15.v201012070815"/>
-      <unit id="org.kohsuke.args4j" version="2.0.21.v201301150030"/>
-      <unit id="org.kohsuke.args4j.source" version="2.0.21.v201301150030"/>
-      <unit id="org.hamcrest.core" version="1.3.0.v201303031735"/>
-      <unit id="org.hamcrest.core.source" version="1.3.0.v201303031735"/>
-      <unit id="javaewah" version="0.7.9.v201401101600"/>
-      <unit id="javaewah.source" version="0.7.9.v201401101600"/>
-      <unit id="org.objenesis" version="1.0.0.v201105211943"/>
-      <unit id="org.objenesis.source" version="1.0.0.v201105211943"/>
-      <unit id="org.mockito" version="1.8.4.v201303031500"/>
-      <unit id="org.mockito.source" version="1.8.4.v201303031500"/>
-      <unit id="com.google.gson" version="2.2.4.v201311231704"/>
-      <unit id="com.jcraft.jsch" version="0.1.51.v201410302000"/>
-      <unit id="com.jcraft.jsch.source" version="0.1.51.v201410302000"/>
-      <unit id="org.junit" version="4.11.0.v201303080030"/>
-      <unit id="org.junit.source" version="4.11.0.v201303080030"/>
-      <unit id="javax.servlet" version="3.1.0.v20140303-1611"/>
-      <unit id="javax.servlet.source" version="3.1.0.v20140303-1611"/>
-      <unit id="org.tukaani.xz" version="1.3.0.v201308270617"/>
-      <unit id="org.tukaani.xz.source" version="1.3.0.v201308270617"/>
-      <unit id="org.slf4j.api" version="1.7.2.v20121108-1250"/>
-      <unit id="org.slf4j.api.source" version="1.7.2.v20121108-1250"/>
-      <unit id="org.slf4j.impl.log4j12" version="1.7.2.v20131105-2200"/>
-      <unit id="org.slf4j.impl.log4j12.source" version="1.7.2.v20131105-2200"/>
-      <repository location="http://download.eclipse.org/tools/orbit/downloads/drops/R20150124073747/repository/"/>
-    </location>
-    <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
-      <unit id="org.eclipse.osgi" version="0.0.0"/>
-      <repository location="http://download.eclipse.org/releases/kepler/"/>
-    </location>
-  </locations>
-</target>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.3.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.3.tpd
deleted file mode 100644
index 062e930..0000000
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.3.tpd
+++ /dev/null
@@ -1,8 +0,0 @@
-target "jgit-4.3" with source configurePhase
-
-include "projects/jetty-9.2.13.tpd"
-include "orbit/R20150124073747-Luna-SR2.tpd"
-
-location "http://download.eclipse.org/releases/kepler/" {
-	org.eclipse.osgi lazy
-}
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.4.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.4.target
deleted file mode 100644
index 3451b42..0000000
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.4.target
+++ /dev/null
@@ -1,68 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<?pde?>
-<!-- generated with https://github.com/mbarbero/fr.obeo.releng.targetplatform -->
-<target name="jgit-4.4" sequenceNumber="1444167820">
-  <locations>
-    <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
-      <unit id="org.eclipse.jetty.client" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.client.source" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.continuation" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.continuation.source" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.http" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.http.source" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.io" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.io.source" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.security" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.security.source" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.server" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.server.source" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.servlet" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.servlet.source" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.util" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.util.source" version="9.2.13.v20150730"/>
-      <repository id="jetty-9.2.13" location="http://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.2.13.v20150730/"/>
-    </location>
-    <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
-      <unit id="org.apache.ant" version="1.9.2.v201404171502"/>
-      <unit id="org.apache.ant.source" version="1.9.2.v201404171502"/>
-      <unit id="org.apache.commons.compress" version="1.6.0.v201310281400"/>
-      <unit id="org.apache.commons.compress.source" version="1.6.0.v201310281400"/>
-      <unit id="org.apache.commons.logging" version="1.1.1.v201101211721"/>
-      <unit id="org.apache.commons.logging.source" version="1.1.1.v201101211721"/>
-      <unit id="org.apache.httpcomponents.httpcore" version="4.3.3.v201411290715"/>
-      <unit id="org.apache.httpcomponents.httpcore.source" version="4.3.3.v201411290715"/>
-      <unit id="org.apache.httpcomponents.httpclient" version="4.3.6.v201411290715"/>
-      <unit id="org.apache.httpcomponents.httpclient.source" version="4.3.6.v201411290715"/>
-      <unit id="org.apache.log4j" version="1.2.15.v201012070815"/>
-      <unit id="org.apache.log4j.source" version="1.2.15.v201012070815"/>
-      <unit id="org.kohsuke.args4j" version="2.0.21.v201301150030"/>
-      <unit id="org.kohsuke.args4j.source" version="2.0.21.v201301150030"/>
-      <unit id="org.hamcrest.core" version="1.3.0.v201303031735"/>
-      <unit id="org.hamcrest.core.source" version="1.3.0.v201303031735"/>
-      <unit id="javaewah" version="0.7.9.v201401101600"/>
-      <unit id="javaewah.source" version="0.7.9.v201401101600"/>
-      <unit id="org.objenesis" version="1.0.0.v201105211943"/>
-      <unit id="org.objenesis.source" version="1.0.0.v201105211943"/>
-      <unit id="org.mockito" version="1.8.4.v201303031500"/>
-      <unit id="org.mockito.source" version="1.8.4.v201303031500"/>
-      <unit id="com.google.gson" version="2.2.4.v201311231704"/>
-      <unit id="com.jcraft.jsch" version="0.1.51.v201410302000"/>
-      <unit id="com.jcraft.jsch.source" version="0.1.51.v201410302000"/>
-      <unit id="org.junit" version="4.11.0.v201303080030"/>
-      <unit id="org.junit.source" version="4.11.0.v201303080030"/>
-      <unit id="javax.servlet" version="3.1.0.v20140303-1611"/>
-      <unit id="javax.servlet.source" version="3.1.0.v20140303-1611"/>
-      <unit id="org.tukaani.xz" version="1.3.0.v201308270617"/>
-      <unit id="org.tukaani.xz.source" version="1.3.0.v201308270617"/>
-      <unit id="org.slf4j.api" version="1.7.2.v20121108-1250"/>
-      <unit id="org.slf4j.api.source" version="1.7.2.v20121108-1250"/>
-      <unit id="org.slf4j.impl.log4j12" version="1.7.2.v20131105-2200"/>
-      <unit id="org.slf4j.impl.log4j12.source" version="1.7.2.v20131105-2200"/>
-      <repository location="http://download.eclipse.org/tools/orbit/downloads/drops/R20150124073747/repository/"/>
-    </location>
-    <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
-      <unit id="org.eclipse.osgi" version="0.0.0"/>
-      <repository location="http://download.eclipse.org/releases/luna/"/>
-    </location>
-  </locations>
-</target>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.4.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.4.tpd
deleted file mode 100644
index 9b9558f..0000000
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.4.tpd
+++ /dev/null
@@ -1,8 +0,0 @@
-target "jgit-4.4" with source configurePhase
-
-include "projects/jetty-9.2.13.tpd"
-include "orbit/R20150124073747-Luna-SR2.tpd"
-
-location "http://download.eclipse.org/releases/luna/" {
-	org.eclipse.osgi lazy
-}
\ No newline at end of file
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.5.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.5.target
index 08116eb..d0da0c4 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.5.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.5.target
@@ -1,26 +1,26 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <?pde?>
 <!-- generated with https://github.com/mbarbero/fr.obeo.releng.targetplatform -->
-<target name="jgit-4.5" sequenceNumber="1456522731">
+<target name="jgit-4.5" sequenceNumber="1502746491">
   <locations>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
-      <unit id="org.eclipse.jetty.client" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.client.source" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.continuation" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.continuation.source" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.http" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.http.source" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.io" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.io.source" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.security" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.security.source" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.server" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.server.source" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.servlet" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.servlet.source" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.util" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.util.source" version="9.2.13.v20150730"/>
-      <repository id="jetty-9.2.13" location="http://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.2.13.v20150730/"/>
+      <unit id="org.eclipse.jetty.client" version="9.3.17.v20170317"/>
+      <unit id="org.eclipse.jetty.client.source" version="9.3.17.v20170317"/>
+      <unit id="org.eclipse.jetty.continuation" version="9.3.17.v20170317"/>
+      <unit id="org.eclipse.jetty.continuation.source" version="9.3.17.v20170317"/>
+      <unit id="org.eclipse.jetty.http" version="9.3.17.v20170317"/>
+      <unit id="org.eclipse.jetty.http.source" version="9.3.17.v20170317"/>
+      <unit id="org.eclipse.jetty.io" version="9.3.17.v20170317"/>
+      <unit id="org.eclipse.jetty.io.source" version="9.3.17.v20170317"/>
+      <unit id="org.eclipse.jetty.security" version="9.3.17.v20170317"/>
+      <unit id="org.eclipse.jetty.security.source" version="9.3.17.v20170317"/>
+      <unit id="org.eclipse.jetty.server" version="9.3.17.v20170317"/>
+      <unit id="org.eclipse.jetty.server.source" version="9.3.17.v20170317"/>
+      <unit id="org.eclipse.jetty.servlet" version="9.3.17.v20170317"/>
+      <unit id="org.eclipse.jetty.servlet.source" version="9.3.17.v20170317"/>
+      <unit id="org.eclipse.jetty.util" version="9.3.17.v20170317"/>
+      <unit id="org.eclipse.jetty.util.source" version="9.3.17.v20170317"/>
+      <repository id="jetty-9.3.17" location="http://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.3.17.v20170317/"/>
     </location>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
       <unit id="org.apache.ant" version="1.9.4.v201504302020"/>
@@ -61,6 +61,46 @@
       <repository location="http://download.eclipse.org/tools/orbit/downloads/drops/R20160221192158/repository/"/>
     </location>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
+      <unit id="org.apache.ant" version="1.9.6.v201510161327"/>
+      <unit id="org.apache.ant.source" version="1.9.6.v201510161327"/>
+      <unit id="org.apache.commons.compress" version="1.6.0.v201310281400"/>
+      <unit id="org.apache.commons.compress.source" version="1.6.0.v201310281400"/>
+      <unit id="org.apache.commons.logging" version="1.1.1.v201101211721"/>
+      <unit id="org.apache.commons.logging.source" version="1.1.1.v201101211721"/>
+      <unit id="org.apache.httpcomponents.httpcore" version="4.3.3.v201411290715"/>
+      <unit id="org.apache.httpcomponents.httpcore.source" version="4.3.3.v201411290715"/>
+      <unit id="org.apache.httpcomponents.httpclient" version="4.3.6.v201511171540"/>
+      <unit id="org.apache.httpcomponents.httpclient.source" version="4.3.6.v201511171540"/>
+      <unit id="org.apache.log4j" version="1.2.15.v201012070815"/>
+      <unit id="org.apache.log4j.source" version="1.2.15.v201012070815"/>
+      <unit id="org.kohsuke.args4j" version="2.0.21.v201301150030"/>
+      <unit id="org.kohsuke.args4j.source" version="2.0.21.v201301150030"/>
+      <unit id="org.hamcrest.core" version="1.3.0.v201303031735"/>
+      <unit id="org.hamcrest.core.source" version="1.3.0.v201303031735"/>
+      <unit id="org.hamcrest.library" version="1.3.0.v201505072020"/>
+      <unit id="org.hamcrest.library.source" version="1.3.0.v201505072020"/>
+      <unit id="javaewah" version="1.1.6.v20160919-1400"/>
+      <unit id="javaewah.source" version="1.1.6.v20160919-1400"/>
+      <unit id="org.objenesis" version="1.0.0.v201505121915"/>
+      <unit id="org.objenesis.source" version="1.0.0.v201505121915"/>
+      <unit id="org.mockito" version="1.8.4.v201303031500"/>
+      <unit id="org.mockito.source" version="1.8.4.v201303031500"/>
+      <unit id="com.google.gson" version="2.2.4.v201311231704"/>
+      <unit id="com.jcraft.jsch" version="0.1.54.v20170116-1932"/>
+      <unit id="com.jcraft.jsch.source" version="0.1.54.v20170116-1932"/>
+      <unit id="org.junit" version="4.12.0.v201504281640"/>
+      <unit id="org.junit.source" version="4.12.0.v201504281640"/>
+      <unit id="javax.servlet" version="3.1.0.v201410161800"/>
+      <unit id="javax.servlet.source" version="3.1.0.v201410161800"/>
+      <unit id="org.tukaani.xz" version="1.3.0.v201308270617"/>
+      <unit id="org.tukaani.xz.source" version="1.3.0.v201308270617"/>
+      <unit id="org.slf4j.api" version="1.7.2.v20121108-1250"/>
+      <unit id="org.slf4j.api.source" version="1.7.2.v20121108-1250"/>
+      <unit id="org.slf4j.impl.log4j12" version="1.7.2.v20131105-2200"/>
+      <unit id="org.slf4j.impl.log4j12.source" version="1.7.2.v20131105-2200"/>
+      <repository location="http://download.eclipse.org/tools/orbit/R-builds/R20170516192513/repository"/>
+    </location>
+    <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
       <unit id="org.eclipse.osgi" version="0.0.0"/>
       <repository location="http://download.eclipse.org/releases/mars/"/>
     </location>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.5.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.5.tpd
index 5cd1037..efc1f44 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.5.tpd
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.5.tpd
@@ -1,7 +1,8 @@
 target "jgit-4.5" with source configurePhase
 
-include "projects/jetty-9.2.13.tpd"
+include "projects/jetty-9.3.17.tpd"
 include "orbit/R20160221192158-Mars.tpd"
+include "orbit/R20170516192513-Oxygen.tpd"
 
 location "http://download.eclipse.org/releases/mars/" {
 	org.eclipse.osgi lazy
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.6.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.6.target
index a1f5abf..065284d 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,26 +1,26 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <?pde?>
 <!-- generated with https://github.com/mbarbero/fr.obeo.releng.targetplatform -->
-<target name="jgit-4.6" sequenceNumber="1465553981">
+<target name="jgit-4.6" sequenceNumber="1502746433">
   <locations>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
-      <unit id="org.eclipse.jetty.client" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.client.source" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.continuation" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.continuation.source" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.http" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.http.source" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.io" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.io.source" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.security" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.security.source" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.server" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.server.source" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.servlet" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.servlet.source" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.util" version="9.2.13.v20150730"/>
-      <unit id="org.eclipse.jetty.util.source" version="9.2.13.v20150730"/>
-      <repository id="jetty-9.2.13" location="http://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.2.13.v20150730/"/>
+      <unit id="org.eclipse.jetty.client" version="9.3.17.v20170317"/>
+      <unit id="org.eclipse.jetty.client.source" version="9.3.17.v20170317"/>
+      <unit id="org.eclipse.jetty.continuation" version="9.3.17.v20170317"/>
+      <unit id="org.eclipse.jetty.continuation.source" version="9.3.17.v20170317"/>
+      <unit id="org.eclipse.jetty.http" version="9.3.17.v20170317"/>
+      <unit id="org.eclipse.jetty.http.source" version="9.3.17.v20170317"/>
+      <unit id="org.eclipse.jetty.io" version="9.3.17.v20170317"/>
+      <unit id="org.eclipse.jetty.io.source" version="9.3.17.v20170317"/>
+      <unit id="org.eclipse.jetty.security" version="9.3.17.v20170317"/>
+      <unit id="org.eclipse.jetty.security.source" version="9.3.17.v20170317"/>
+      <unit id="org.eclipse.jetty.server" version="9.3.17.v20170317"/>
+      <unit id="org.eclipse.jetty.server.source" version="9.3.17.v20170317"/>
+      <unit id="org.eclipse.jetty.servlet" version="9.3.17.v20170317"/>
+      <unit id="org.eclipse.jetty.servlet.source" version="9.3.17.v20170317"/>
+      <unit id="org.eclipse.jetty.util" version="9.3.17.v20170317"/>
+      <unit id="org.eclipse.jetty.util.source" version="9.3.17.v20170317"/>
+      <repository id="jetty-9.3.17" location="http://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.3.17.v20170317/"/>
     </location>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
       <unit id="org.apache.ant" version="1.9.6.v201510161327"/>
@@ -39,15 +39,17 @@
       <unit id="org.kohsuke.args4j.source" version="2.0.21.v201301150030"/>
       <unit id="org.hamcrest.core" version="1.3.0.v201303031735"/>
       <unit id="org.hamcrest.core.source" version="1.3.0.v201303031735"/>
-      <unit id="javaewah" version="0.7.9.v201605172130"/>
-      <unit id="javaewah.source" version="0.7.9.v201605172130"/>
+      <unit id="org.hamcrest.library" version="1.3.0.v201505072020"/>
+      <unit id="org.hamcrest.library.source" version="1.3.0.v201505072020"/>
+      <unit id="javaewah" version="1.1.6.v20160919-1400"/>
+      <unit id="javaewah.source" version="1.1.6.v20160919-1400"/>
       <unit id="org.objenesis" version="1.0.0.v201505121915"/>
       <unit id="org.objenesis.source" version="1.0.0.v201505121915"/>
       <unit id="org.mockito" version="1.8.4.v201303031500"/>
       <unit id="org.mockito.source" version="1.8.4.v201303031500"/>
       <unit id="com.google.gson" version="2.2.4.v201311231704"/>
-      <unit id="com.jcraft.jsch" version="0.1.53.v201508180515"/>
-      <unit id="com.jcraft.jsch.source" version="0.1.53.v201508180515"/>
+      <unit id="com.jcraft.jsch" version="0.1.54.v20170116-1932"/>
+      <unit id="com.jcraft.jsch.source" version="0.1.54.v20170116-1932"/>
       <unit id="org.junit" version="4.12.0.v201504281640"/>
       <unit id="org.junit.source" version="4.12.0.v201504281640"/>
       <unit id="javax.servlet" version="3.1.0.v201410161800"/>
@@ -58,7 +60,7 @@
       <unit id="org.slf4j.api.source" version="1.7.2.v20121108-1250"/>
       <unit id="org.slf4j.impl.log4j12" version="1.7.2.v20131105-2200"/>
       <unit id="org.slf4j.impl.log4j12.source" version="1.7.2.v20131105-2200"/>
-      <repository location="http://download.eclipse.org/tools/orbit/downloads/drops/R20160520211859/repository/"/>
+      <repository location="http://download.eclipse.org/tools/orbit/R-builds/R20170516192513/repository"/>
     </location>
     <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
       <unit id="org.eclipse.osgi" version="0.0.0"/>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.6.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.6.tpd
index c784c1f..90f62ae 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.6.tpd
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.6.tpd
@@ -1,7 +1,7 @@
 target "jgit-4.6" with source configurePhase
 
-include "projects/jetty-9.2.13.tpd"
-include "orbit/R20160520211859-Neon.tpd"
+include "projects/jetty-9.3.17.tpd"
+include "orbit/R20170516192513-Oxygen.tpd"
 
 location "http://download.eclipse.org/releases/neon/" {
 	org.eclipse.osgi lazy
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.7.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.7.target
new file mode 100644
index 0000000..d3a1131
--- /dev/null
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.7.target
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<?pde?>
+<!-- generated with https://github.com/mbarbero/fr.obeo.releng.targetplatform -->
+<target name="jgit-4.7" sequenceNumber="1502746477">
+  <locations>
+    <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
+      <unit id="org.eclipse.jetty.client" version="9.3.17.v20170317"/>
+      <unit id="org.eclipse.jetty.client.source" version="9.3.17.v20170317"/>
+      <unit id="org.eclipse.jetty.continuation" version="9.3.17.v20170317"/>
+      <unit id="org.eclipse.jetty.continuation.source" version="9.3.17.v20170317"/>
+      <unit id="org.eclipse.jetty.http" version="9.3.17.v20170317"/>
+      <unit id="org.eclipse.jetty.http.source" version="9.3.17.v20170317"/>
+      <unit id="org.eclipse.jetty.io" version="9.3.17.v20170317"/>
+      <unit id="org.eclipse.jetty.io.source" version="9.3.17.v20170317"/>
+      <unit id="org.eclipse.jetty.security" version="9.3.17.v20170317"/>
+      <unit id="org.eclipse.jetty.security.source" version="9.3.17.v20170317"/>
+      <unit id="org.eclipse.jetty.server" version="9.3.17.v20170317"/>
+      <unit id="org.eclipse.jetty.server.source" version="9.3.17.v20170317"/>
+      <unit id="org.eclipse.jetty.servlet" version="9.3.17.v20170317"/>
+      <unit id="org.eclipse.jetty.servlet.source" version="9.3.17.v20170317"/>
+      <unit id="org.eclipse.jetty.util" version="9.3.17.v20170317"/>
+      <unit id="org.eclipse.jetty.util.source" version="9.3.17.v20170317"/>
+      <repository id="jetty-9.3.17" location="http://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.3.17.v20170317/"/>
+    </location>
+    <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
+      <unit id="org.apache.ant" version="1.9.6.v201510161327"/>
+      <unit id="org.apache.ant.source" version="1.9.6.v201510161327"/>
+      <unit id="org.apache.commons.compress" version="1.6.0.v201310281400"/>
+      <unit id="org.apache.commons.compress.source" version="1.6.0.v201310281400"/>
+      <unit id="org.apache.commons.logging" version="1.1.1.v201101211721"/>
+      <unit id="org.apache.commons.logging.source" version="1.1.1.v201101211721"/>
+      <unit id="org.apache.httpcomponents.httpcore" version="4.3.3.v201411290715"/>
+      <unit id="org.apache.httpcomponents.httpcore.source" version="4.3.3.v201411290715"/>
+      <unit id="org.apache.httpcomponents.httpclient" version="4.3.6.v201511171540"/>
+      <unit id="org.apache.httpcomponents.httpclient.source" version="4.3.6.v201511171540"/>
+      <unit id="org.apache.log4j" version="1.2.15.v201012070815"/>
+      <unit id="org.apache.log4j.source" version="1.2.15.v201012070815"/>
+      <unit id="org.kohsuke.args4j" version="2.0.21.v201301150030"/>
+      <unit id="org.kohsuke.args4j.source" version="2.0.21.v201301150030"/>
+      <unit id="org.hamcrest.core" version="1.3.0.v201303031735"/>
+      <unit id="org.hamcrest.core.source" version="1.3.0.v201303031735"/>
+      <unit id="org.hamcrest.library" version="1.3.0.v201505072020"/>
+      <unit id="org.hamcrest.library.source" version="1.3.0.v201505072020"/>
+      <unit id="javaewah" version="1.1.6.v20160919-1400"/>
+      <unit id="javaewah.source" version="1.1.6.v20160919-1400"/>
+      <unit id="org.objenesis" version="1.0.0.v201505121915"/>
+      <unit id="org.objenesis.source" version="1.0.0.v201505121915"/>
+      <unit id="org.mockito" version="1.8.4.v201303031500"/>
+      <unit id="org.mockito.source" version="1.8.4.v201303031500"/>
+      <unit id="com.google.gson" version="2.2.4.v201311231704"/>
+      <unit id="com.jcraft.jsch" version="0.1.54.v20170116-1932"/>
+      <unit id="com.jcraft.jsch.source" version="0.1.54.v20170116-1932"/>
+      <unit id="org.junit" version="4.12.0.v201504281640"/>
+      <unit id="org.junit.source" version="4.12.0.v201504281640"/>
+      <unit id="javax.servlet" version="3.1.0.v201410161800"/>
+      <unit id="javax.servlet.source" version="3.1.0.v201410161800"/>
+      <unit id="org.tukaani.xz" version="1.3.0.v201308270617"/>
+      <unit id="org.tukaani.xz.source" version="1.3.0.v201308270617"/>
+      <unit id="org.slf4j.api" version="1.7.2.v20121108-1250"/>
+      <unit id="org.slf4j.api.source" version="1.7.2.v20121108-1250"/>
+      <unit id="org.slf4j.impl.log4j12" version="1.7.2.v20131105-2200"/>
+      <unit id="org.slf4j.impl.log4j12.source" version="1.7.2.v20131105-2200"/>
+      <repository location="http://download.eclipse.org/tools/orbit/R-builds/R20170516192513/repository"/>
+    </location>
+    <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
+      <unit id="org.eclipse.osgi" version="0.0.0"/>
+      <repository location="http://download.eclipse.org/releases/oxygen/"/>
+    </location>
+  </locations>
+</target>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.7.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.7.tpd
new file mode 100644
index 0000000..1d0e693
--- /dev/null
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.7.tpd
@@ -0,0 +1,8 @@
+target "jgit-4.7" with source configurePhase
+
+include "projects/jetty-9.3.17.tpd"
+include "orbit/R20170516192513-Oxygen.tpd"
+
+location "http://download.eclipse.org/releases/oxygen/" {
+	org.eclipse.osgi lazy
+}
\ No newline at end of file
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20170516192513-Oxygen.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20170516192513-Oxygen.tpd
new file mode 100644
index 0000000..3600628
--- /dev/null
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20170516192513-Oxygen.tpd
@@ -0,0 +1,42 @@
+target "R20170516192513-Oxygen" with source configurePhase
+// see http://download.eclipse.org/tools/orbit/downloads/
+
+location "http://download.eclipse.org/tools/orbit/R-builds/R20170516192513/repository" {
+	org.apache.ant [1.9.6.v201510161327,1.9.6.v201510161327]
+	org.apache.ant.source [1.9.6.v201510161327,1.9.6.v201510161327]
+	org.apache.commons.compress [1.6.0.v201310281400,1.6.0.v201310281400]
+	org.apache.commons.compress.source [1.6.0.v201310281400,1.6.0.v201310281400]
+	org.apache.commons.logging [1.1.1.v201101211721,1.1.1.v201101211721]
+	org.apache.commons.logging.source [1.1.1.v201101211721,1.1.1.v201101211721]
+	org.apache.httpcomponents.httpcore [4.3.3.v201411290715,4.3.3.v201411290715]
+	org.apache.httpcomponents.httpcore.source [4.3.3.v201411290715,4.3.3.v201411290715]
+	org.apache.httpcomponents.httpclient [4.3.6.v201511171540,4.3.6.v201511171540]
+	org.apache.httpcomponents.httpclient.source [4.3.6.v201511171540,4.3.6.v201511171540]
+	org.apache.log4j [1.2.15.v201012070815,1.2.15.v201012070815]
+	org.apache.log4j.source [1.2.15.v201012070815,1.2.15.v201012070815]
+	org.kohsuke.args4j [2.0.21.v201301150030,2.0.21.v201301150030]
+	org.kohsuke.args4j.source [2.0.21.v201301150030,2.0.21.v201301150030]
+	org.hamcrest.core [1.3.0.v201303031735,1.3.0.v201303031735]
+	org.hamcrest.core.source [1.3.0.v201303031735,1.3.0.v201303031735]
+	org.hamcrest.library [1.3.0.v201505072020,1.3.0.v201505072020]
+	org.hamcrest.library.source [1.3.0.v201505072020,1.3.0.v201505072020]
+	javaewah [1.1.6.v20160919-1400,1.1.6.v20160919-1400]
+	javaewah.source [1.1.6.v20160919-1400,1.1.6.v20160919-1400]
+	org.objenesis [1.0.0.v201505121915,1.0.0.v201505121915]
+	org.objenesis.source [1.0.0.v201505121915,1.0.0.v201505121915]
+	org.mockito [1.8.4.v201303031500,1.8.4.v201303031500]
+	org.mockito.source [1.8.4.v201303031500,1.8.4.v201303031500]
+	com.google.gson [2.2.4.v201311231704,2.2.4.v201311231704]
+	com.jcraft.jsch [0.1.54.v20170116-1932,0.1.54.v20170116-1932]
+	com.jcraft.jsch.source [0.1.54.v20170116-1932,0.1.54.v20170116-1932]
+	org.junit [4.12.0.v201504281640,4.12.0.v201504281640]
+	org.junit.source [4.12.0.v201504281640,4.12.0.v201504281640]
+	javax.servlet [3.1.0.v201410161800,3.1.0.v201410161800]
+	javax.servlet.source [3.1.0.v201410161800,3.1.0.v201410161800]
+	org.tukaani.xz [1.3.0.v201308270617,1.3.0.v201308270617]
+	org.tukaani.xz.source [1.3.0.v201308270617,1.3.0.v201308270617]
+	org.slf4j.api [1.7.2.v20121108-1250,1.7.2.v20121108-1250]
+	org.slf4j.api.source [1.7.2.v20121108-1250,1.7.2.v20121108-1250]
+	org.slf4j.impl.log4j12 [1.7.2.v20131105-2200,1.7.2.v20131105-2200]
+	org.slf4j.impl.log4j12.source [1.7.2.v20131105-2200,1.7.2.v20131105-2200]
+}
\ No newline at end of file
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/pom.xml
index 09558a5..652b122 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>4.5.7-SNAPSHOT</version>
+    <version>4.6.2-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.target</artifactId>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/projects/jetty-9.2.13.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/projects/jetty-9.2.13.tpd
deleted file mode 100644
index 289a73d..0000000
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/projects/jetty-9.2.13.tpd
+++ /dev/null
@@ -1,20 +0,0 @@
-target "jetty-9.2.13" with source configurePhase
-
-location jetty-9.2.13 "http://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.2.13.v20150730/" {
-	org.eclipse.jetty.client [9.2.13.v20150730,9.2.13.v20150730]
-	org.eclipse.jetty.client.source [9.2.13.v20150730,9.2.13.v20150730]
-	org.eclipse.jetty.continuation [9.2.13.v20150730,9.2.13.v20150730]
-	org.eclipse.jetty.continuation.source [9.2.13.v20150730,9.2.13.v20150730]
-	org.eclipse.jetty.http [9.2.13.v20150730,9.2.13.v20150730]
-	org.eclipse.jetty.http.source [9.2.13.v20150730,9.2.13.v20150730]
-	org.eclipse.jetty.io [9.2.13.v20150730,9.2.13.v20150730]
-	org.eclipse.jetty.io.source [9.2.13.v20150730,9.2.13.v20150730]
-	org.eclipse.jetty.security [9.2.13.v20150730,9.2.13.v20150730]
-	org.eclipse.jetty.security.source [9.2.13.v20150730,9.2.13.v20150730]
-	org.eclipse.jetty.server [9.2.13.v20150730,9.2.13.v20150730]
-	org.eclipse.jetty.server.source [9.2.13.v20150730,9.2.13.v20150730]
-	org.eclipse.jetty.servlet [9.2.13.v20150730,9.2.13.v20150730]
-	org.eclipse.jetty.servlet.source [9.2.13.v20150730,9.2.13.v20150730]
-	org.eclipse.jetty.util [9.2.13.v20150730,9.2.13.v20150730]
-	org.eclipse.jetty.util.source [9.2.13.v20150730,9.2.13.v20150730]
-}
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/projects/jetty-9.3.17.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/projects/jetty-9.3.17.tpd
new file mode 100644
index 0000000..662df09
--- /dev/null
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/projects/jetty-9.3.17.tpd
@@ -0,0 +1,20 @@
+target "jetty-9.3.17" with source configurePhase
+
+location jetty-9.3.17 "http://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.3.17.v20170317/" {
+	org.eclipse.jetty.client [9.3.17.v20170317,9.3.17.v20170317]
+	org.eclipse.jetty.client.source [9.3.17.v20170317,9.3.17.v20170317]
+	org.eclipse.jetty.continuation [9.3.17.v20170317,9.3.17.v20170317]
+	org.eclipse.jetty.continuation.source [9.3.17.v20170317,9.3.17.v20170317]
+	org.eclipse.jetty.http [9.3.17.v20170317,9.3.17.v20170317]
+	org.eclipse.jetty.http.source [9.3.17.v20170317,9.3.17.v20170317]
+	org.eclipse.jetty.io [9.3.17.v20170317,9.3.17.v20170317]
+	org.eclipse.jetty.io.source [9.3.17.v20170317,9.3.17.v20170317]
+	org.eclipse.jetty.security [9.3.17.v20170317,9.3.17.v20170317]
+	org.eclipse.jetty.security.source [9.3.17.v20170317,9.3.17.v20170317]
+	org.eclipse.jetty.server [9.3.17.v20170317,9.3.17.v20170317]
+	org.eclipse.jetty.server.source [9.3.17.v20170317,9.3.17.v20170317]
+	org.eclipse.jetty.servlet [9.3.17.v20170317,9.3.17.v20170317]
+	org.eclipse.jetty.servlet.source [9.3.17.v20170317,9.3.17.v20170317]
+	org.eclipse.jetty.util [9.3.17.v20170317,9.3.17.v20170317]
+	org.eclipse.jetty.util.source [9.3.17.v20170317,9.3.17.v20170317]
+}
diff --git a/org.eclipse.jgit.packaging/pom.xml b/org.eclipse.jgit.packaging/pom.xml
index b6b1c01..583b128 100644
--- a/org.eclipse.jgit.packaging/pom.xml
+++ b/org.eclipse.jgit.packaging/pom.xml
@@ -53,13 +53,13 @@
 
   <groupId>org.eclipse.jgit</groupId>
   <artifactId>jgit.tycho.parent</artifactId>
-  <version>4.5.7-SNAPSHOT</version>
+  <version>4.6.2-SNAPSHOT</version>
   <packaging>pom</packaging>
 
   <name>JGit Tycho Parent</name>
 
   <properties>
-    <tycho-version>0.25.0</tycho-version>
+    <tycho-version>1.0.0</tycho-version>
     <tycho-extras-version>${tycho-version}</tycho-extras-version>
     <target-platform>jgit-4.6</target-platform>
   </properties>
@@ -142,14 +142,14 @@
           <version>${tycho-version}</version>
           <configuration>
             <encoding>UTF-8</encoding>
-            <source>1.7</source>
-            <target>1.7</target>
+            <source>1.8</source>
+            <target>1.8</target>
           </configuration>
         </plugin>
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-resources-plugin</artifactId>
-          <version>2.7</version>
+          <version>3.0.2</version>
           <configuration>
             <encoding>ISO-8859-1</encoding>
           </configuration>
@@ -221,7 +221,7 @@
         <plugin>
           <groupId>org.codehaus.mojo</groupId>
           <artifactId>build-helper-maven-plugin</artifactId>
-          <version>1.10</version>
+          <version>1.12</version>
         </plugin>
       </plugins>
     </pluginManagement>
diff --git a/org.eclipse.jgit.pgm.test/.classpath b/org.eclipse.jgit.pgm.test/.classpath
index 30d83d8..b26f4c4 100644
--- a/org.eclipse.jgit.pgm.test/.classpath
+++ b/org.eclipse.jgit.pgm.test/.classpath
@@ -2,7 +2,7 @@
 <classpath>
 	<classpathentry kind="src" path="tst"/>
 	<classpathentry kind="src" path="src"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
 	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>
diff --git a/org.eclipse.jgit.pgm.test/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit.pgm.test/.settings/org.eclipse.jdt.core.prefs
index 87210fb..10c29d5 100644
--- a/org.eclipse.jgit.pgm.test/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit.pgm.test/.settings/org.eclipse.jdt.core.prefs
@@ -7,9 +7,9 @@
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.compliance=1.8
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -112,7 +112,7 @@
 org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
-org.eclipse.jdt.core.compiler.source=1.7
+org.eclipse.jdt.core.compiler.source=1.8
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
diff --git a/org.eclipse.jgit.pgm.test/BUCK b/org.eclipse.jgit.pgm.test/BUCK
index a3859c9..cd15510 100644
--- a/org.eclipse.jgit.pgm.test/BUCK
+++ b/org.eclipse.jgit.pgm.test/BUCK
@@ -21,7 +21,6 @@
       '//lib:commons-compress',
       '//lib:tukaani-xz',
     ],
-    source_under_test = ['//org.eclipse.jgit.pgm:pgm'],
     vm_args = ['-Xmx256m', '-Dfile.encoding=UTF-8'],
   )
 
diff --git a/org.eclipse.jgit.pgm.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.pgm.test/META-INF/MANIFEST.MF
index 7e8d744..8e7d5ab 100644
--- a/org.eclipse.jgit.pgm.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.pgm.test/META-INF/MANIFEST.MF
@@ -2,28 +2,28 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %plugin_name
 Bundle-SymbolicName: org.eclipse.jgit.pgm.test
-Bundle-Version: 4.5.7.qualifier
+Bundle-Version: 4.6.2.qualifier
 Bundle-Vendor: %provider_name
 Bundle-Localization: plugin
 Bundle-ActivationPolicy: lazy
-Bundle-RequiredExecutionEnvironment: JavaSE-1.7
-Import-Package: org.eclipse.jgit.api;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.api.errors;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.diff;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.dircache;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.internal.storage.file;version="4.5.7",
- org.eclipse.jgit.junit;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.lib;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.merge;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.pgm;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.pgm.internal;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.pgm.opt;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.revwalk;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.storage.file;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.transport;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.treewalk;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.util;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.util.io;version="[4.5.7,4.6.0)",
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Import-Package: org.eclipse.jgit.api;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.api.errors;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.diff;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.dircache;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.internal.storage.file;version="4.6.2",
+ org.eclipse.jgit.junit;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.lib;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.merge;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.pgm;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.pgm.internal;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.pgm.opt;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.revwalk;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.storage.file;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.transport;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.treewalk;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.util;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.util.io;version="[4.6.2,4.7.0)",
  org.hamcrest.core;bundle-version="[1.1.0,2.0.0)",
  org.junit;version="[4.11.0,5.0.0)",
  org.junit.rules;version="[4.11.0,5.0.0)",
diff --git "a/org.eclipse.jgit.pgm.test/org.eclipse.jgit.pgm--All-Tests \050Java7\051.launch" "b/org.eclipse.jgit.pgm.test/org.eclipse.jgit.pgm--All-Tests \050Java7\051.launch"
deleted file mode 100644
index 3df0dcb..0000000
--- "a/org.eclipse.jgit.pgm.test/org.eclipse.jgit.pgm--All-Tests \050Java7\051.launch"
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<launchConfiguration type="org.eclipse.jdt.junit.launchconfig">
-<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
-<listEntry value="/org.eclipse.jgit.pgm.test/tst"/>
-</listAttribute>
-<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
-<listEntry value="2"/>
-</listAttribute>
-<booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="true"/>
-<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
-<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
-<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
-</listAttribute>
-<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value="=org.eclipse.jgit.pgm.test/tst"/>
-<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/>
-<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/>
-<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit4"/>
-<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
-<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value=""/>
-<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.jgit.pgm.test"/>
-</launchConfiguration>
diff --git "a/org.eclipse.jgit.pgm.test/org.eclipse.jgit.pgm--All-Tests \050Java8\051 \050de\051.launch" "b/org.eclipse.jgit.pgm.test/org.eclipse.jgit.pgm--All-Tests \050Java8\051 \050de\051.launch"
index 5c137f2..e11b72f 100644
--- "a/org.eclipse.jgit.pgm.test/org.eclipse.jgit.pgm--All-Tests \050Java8\051 \050de\051.launch"
+++ "b/org.eclipse.jgit.pgm.test/org.eclipse.jgit.pgm--All-Tests \050Java8\051 \050de\051.launch"
@@ -20,7 +20,7 @@
 <stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit4"/>
 <booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_START_ON_FIRST_THREAD" value="true"/>
 <listAttribute key="org.eclipse.jdt.launching.CLASSPATH">
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry containerPath=&quot;org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7&quot; path=&quot;1&quot; type=&quot;4&quot;/&gt;&#10;"/>
+<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry containerPath=&quot;org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8&quot; path=&quot;1&quot; type=&quot;4&quot;/&gt;&#10;"/>
 <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry id=&quot;org.eclipse.jdt.launching.classpathentry.defaultClasspath&quot;&gt;&#10;&lt;memento exportedEntriesOnly=&quot;false&quot; project=&quot;org.eclipse.jgit.pgm.test&quot;/&gt;&#10;&lt;/runtimeClasspathEntry&gt;&#10;"/>
 </listAttribute>
 <booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/>
diff --git "a/org.eclipse.jgit.pgm.test/org.eclipse.jgit.pgm--All-Tests \050Java8\051.launch" "b/org.eclipse.jgit.pgm.test/org.eclipse.jgit.pgm--All-Tests \050Java8\051.launch"
index ce473ed..8b0452a 100644
--- "a/org.eclipse.jgit.pgm.test/org.eclipse.jgit.pgm--All-Tests \050Java8\051.launch"
+++ "b/org.eclipse.jgit.pgm.test/org.eclipse.jgit.pgm--All-Tests \050Java8\051.launch"
@@ -17,7 +17,7 @@
 <stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit4"/>
 <booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_START_ON_FIRST_THREAD" value="true"/>
 <listAttribute key="org.eclipse.jdt.launching.CLASSPATH">
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry containerPath=&quot;org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7&quot; path=&quot;1&quot; type=&quot;4&quot;/&gt;&#10;"/>
+<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry containerPath=&quot;org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8&quot; path=&quot;1&quot; type=&quot;4&quot;/&gt;&#10;"/>
 <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry id=&quot;org.eclipse.jdt.launching.classpathentry.defaultClasspath&quot;&gt;&#10;&lt;memento exportedEntriesOnly=&quot;false&quot; project=&quot;org.eclipse.jgit.pgm.test&quot;/&gt;&#10;&lt;/runtimeClasspathEntry&gt;&#10;"/>
 </listAttribute>
 <booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/>
diff --git a/org.eclipse.jgit.pgm.test/pom.xml b/org.eclipse.jgit.pgm.test/pom.xml
index cd9b135..c8188cb 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>4.5.7-SNAPSHOT</version>
+    <version>4.6.2-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 a6af077..b675d3c 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
@@ -62,15 +62,11 @@ public class CLIRepositoryTestCase extends LocalDiskRepositoryTestCase {
 	/** Test repository, initialized for this test case. */
 	protected Repository db;
 
-	/** Working directory of {@link #db}. */
-	protected File trash;
-
 	@Override
 	@Before
 	public void setUp() throws Exception {
 		super.setUp();
 		db = createWorkRepository();
-		trash = db.getWorkTree();
 	}
 
 	/**
diff --git a/org.eclipse.jgit.pgm.test/src/org/eclipse/jgit/pgm/CLIGitCommand.java b/org.eclipse.jgit.pgm.test/src/org/eclipse/jgit/pgm/CLIGitCommand.java
index 3f39656..b08bc8a 100644
--- a/org.eclipse.jgit.pgm.test/src/org/eclipse/jgit/pgm/CLIGitCommand.java
+++ b/org.eclipse.jgit.pgm.test/src/org/eclipse/jgit/pgm/CLIGitCommand.java
@@ -46,7 +46,6 @@
 
 import java.io.ByteArrayOutputStream;
 import java.io.File;
-
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -218,7 +217,7 @@ else if (r.length() > 0) {
 					inquote = !inquote;
 				continue;
 			case '\\':
-				if (inquote || ip == commandLine.length())
+				if (inDblQuote || inquote || ip == commandLine.length())
 					r.append(b); // literal within a quote
 				else
 					r.append(commandLine.charAt(ip++));
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 a503ffd..35467c6 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
@@ -528,15 +528,15 @@ public void testTarPreservesMode() throws Exception {
 
 	@Test
 	public void testArchiveWithLongFilename() throws Exception {
-		String filename = "";
+		StringBuilder filename = new StringBuilder();
 		List<String> l = new ArrayList<String>();
 		for (int i = 0; i < 20; i++) {
-			filename = filename + "1234567890/";
-			l.add(filename);
+			filename.append("1234567890/");
+			l.add(filename.toString());
 		}
-		filename = filename + "1234567890";
-		l.add(filename);
-		writeTrashFile(filename, "file with long path");
+		filename.append("1234567890");
+		l.add(filename.toString());
+		writeTrashFile(filename.toString(), "file with long path");
 		git.add().addFilepattern("1234567890").call();
 		git.commit().setMessage("file with long name").call();
 
@@ -548,15 +548,15 @@ public void testArchiveWithLongFilename() throws Exception {
 
 	@Test
 	public void testTarWithLongFilename() throws Exception {
-		String filename = "";
+		StringBuilder filename = new StringBuilder();
 		List<String> l = new ArrayList<String>();
 		for (int i = 0; i < 20; i++) {
-			filename = filename + "1234567890/";
-			l.add(filename);
+			filename.append("1234567890/");
+			l.add(filename.toString());
 		}
-		filename = filename + "1234567890";
-		l.add(filename);
-		writeTrashFile(filename, "file with long path");
+		filename.append("1234567890");
+		l.add(filename.toString());
+		writeTrashFile(filename.toString(), "file with long path");
 		git.add().addFilepattern("1234567890").call();
 		git.commit().setMessage("file with long name").call();
 
diff --git a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/CLIGitCommandTest.java b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/CLIGitCommandTest.java
index 24788a4..58d8e03 100644
--- a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/CLIGitCommandTest.java
+++ b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/CLIGitCommandTest.java
@@ -51,9 +51,11 @@ public class CLIGitCommandTest {
 
 	@Test
 	public void testSplit() throws Exception {
+		assertArrayEquals(new String[0], split(""));
 		assertArrayEquals(new String[] { "a" }, split("a"));
 		assertArrayEquals(new String[] { "a", "b" }, split("a b"));
 		assertArrayEquals(new String[] { "a", "b c" }, split("a 'b c'"));
 		assertArrayEquals(new String[] { "a", "b c" }, split("a \"b c\""));
+		assertArrayEquals(new String[] { "a", "b\\c" }, split("a \"b\\c\""));
 	}
 }
diff --git a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/CheckoutTest.java b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/CheckoutTest.java
index 3651542..4b86b60 100644
--- a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/CheckoutTest.java
+++ b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/CheckoutTest.java
@@ -613,7 +613,30 @@ public void testCheckoutPath() throws Exception {
 	}
 
 	@Test
-	public void testCheckouSingleFile() throws Exception {
+	public void testCheckoutAllPaths() throws Exception {
+		try (Git git = new Git(db)) {
+			writeTrashFile("a", "Hello world a");
+			git.add().addFilepattern(".").call();
+			git.commit().setMessage("commit file a").call();
+			git.branchCreate().setName("branch_1").call();
+			git.checkout().setName("branch_1").call();
+			File b = writeTrashFile("b", "Hello world b");
+			git.add().addFilepattern("b").call();
+			git.commit().setMessage("commit file b").call();
+			File a = writeTrashFile("a", "New Hello world a");
+			git.add().addFilepattern(".").call();
+			git.commit().setMessage("modified a").call();
+			assertArrayEquals(new String[] { "" },
+					execute("git checkout HEAD~2 -- ."));
+			assertEquals("Hello world a", read(a));
+			assertArrayEquals(new String[] { "* branch_1", "  master", "" },
+					execute("git branch"));
+			assertEquals("Hello world b", read(b));
+		}
+	}
+
+	@Test
+	public void testCheckoutSingleFile() throws Exception {
 		try (Git git = new Git(db)) {
 			File a = writeTrashFile("a", "file a");
 			git.add().addFilepattern(".").call();
diff --git a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/CleanTest.java b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/CleanTest.java
index bbac296..82c0d98 100644
--- a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/CleanTest.java
+++ b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/CleanTest.java
@@ -42,13 +42,14 @@
  */
 package org.eclipse.jgit.pgm;
 
+import static org.eclipse.jgit.junit.JGitTestUtil.check;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
 import org.eclipse.jgit.api.Git;
 import org.eclipse.jgit.lib.CLIRepositoryTestCase;
 import org.junit.Test;
-import static org.eclipse.jgit.junit.JGitTestUtil.check;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.assertFalse;
 
 public class CleanTest extends CLIRepositoryTestCase {
 	@Test
diff --git a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/ProxyConfigTest.java b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/ProxyConfigTest.java
new file mode 100644
index 0000000..06e7a1d
--- /dev/null
+++ b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/ProxyConfigTest.java
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2016, Chrisian Halstrick <christian.halstrick@sap.com> 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.pgm;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Test how the content of the environment variables http[s]_proxy (upper- and
+ * lowercase) influence the setting of the system properties
+ * http[s].proxy[Host|Port]
+ */
+public class ProxyConfigTest {
+	private ProcessBuilder processBuilder;
+
+	private Map<String, String> environment;
+
+	@Before
+	public void setUp() {
+		String separator = System.getProperty("file.separator");
+		String classpath = System.getProperty("java.class.path");
+		String path = System.getProperty("java.home") + separator + "bin"
+				+ separator + "java";
+		processBuilder = new ProcessBuilder(path, "-cp", classpath,
+				ProxyPropertiesDumper.class.getName());
+		environment = processBuilder.environment();
+		environment.remove("http_proxy");
+		environment.remove("https_proxy");
+		environment.remove("HTTP_PROXY");
+		environment.remove("HTTPS_PROXY");
+	}
+
+	@Test
+	public void testNoSetting() throws Exception {
+		Process start = processBuilder.start();
+		start.waitFor();
+		assertEquals(
+				"http.proxyHost: null, http.proxyPort: null, https.proxyHost: null, https.proxyPort: null",
+				getOutput(start));
+	}
+
+	@Test
+	public void testHttpProxy_lowerCase() throws Exception {
+		environment.put("http_proxy", "http://xx:1234");
+		Process start = processBuilder.start();
+		start.waitFor();
+		assertEquals(
+				"http.proxyHost: xx, http.proxyPort: 1234, https.proxyHost: null, https.proxyPort: null",
+				getOutput(start));
+	}
+
+	@Test
+	public void testHttpProxy_upperCase() throws Exception {
+		environment.put("HTTP_PROXY", "http://XX:1234");
+		Process start = processBuilder.start();
+		start.waitFor();
+		assertEquals(
+				"http.proxyHost: null, http.proxyPort: null, https.proxyHost: null, https.proxyPort: null",
+				getOutput(start));
+	}
+
+	@Test
+	public void testHttpProxy_bothCases() throws Exception {
+		environment.put("http_proxy", "http://xx:1234");
+		environment.put("HTTP_PROXY", "http://XX:1234");
+		Process start = processBuilder.start();
+		start.waitFor();
+		assertEquals(
+				"http.proxyHost: xx, http.proxyPort: 1234, https.proxyHost: null, https.proxyPort: null",
+				getOutput(start));
+	}
+
+	@Test
+	public void testHttpsProxy_lowerCase() throws Exception {
+		environment.put("https_proxy", "http://xx:1234");
+		Process start = processBuilder.start();
+		start.waitFor();
+		assertEquals(
+				"http.proxyHost: null, http.proxyPort: null, https.proxyHost: xx, https.proxyPort: 1234",
+				getOutput(start));
+	}
+
+	@Test
+	public void testHttpsProxy_upperCase() throws Exception {
+		environment.put("HTTPS_PROXY", "http://XX:1234");
+		Process start = processBuilder.start();
+		start.waitFor();
+		assertEquals(
+				"http.proxyHost: null, http.proxyPort: null, https.proxyHost: XX, https.proxyPort: 1234",
+				getOutput(start));
+	}
+
+	@Test
+	public void testHttpsProxy_bothCases() throws Exception {
+		environment.put("https_proxy", "http://xx:1234");
+		environment.put("HTTPS_PROXY", "http://XX:1234");
+		Process start = processBuilder.start();
+		start.waitFor();
+		assertEquals(
+				"http.proxyHost: null, http.proxyPort: null, https.proxyHost: xx, https.proxyPort: 1234",
+				getOutput(start));
+	}
+
+	@Test
+	public void testAll() throws Exception {
+		environment.put("http_proxy", "http://xx:1234");
+		environment.put("HTTP_PROXY", "http://XX:1234");
+		environment.put("https_proxy", "http://yy:1234");
+		environment.put("HTTPS_PROXY", "http://YY:1234");
+		Process start = processBuilder.start();
+		start.waitFor();
+		assertEquals(
+				"http.proxyHost: xx, http.proxyPort: 1234, https.proxyHost: yy, https.proxyPort: 1234",
+				getOutput(start));
+	}
+
+	@Test
+	public void testDontOverwriteHttp()
+			throws IOException, InterruptedException {
+		environment.put("http_proxy", "http://xx:1234");
+		environment.put("HTTP_PROXY", "http://XX:1234");
+		environment.put("https_proxy", "http://yy:1234");
+		environment.put("HTTPS_PROXY", "http://YY:1234");
+		List<String> command = processBuilder.command();
+		command.add(1, "-Dhttp.proxyHost=gondola");
+		command.add(2, "-Dhttp.proxyPort=5678");
+		command.add("dontClearProperties");
+		Process start = processBuilder.start();
+		start.waitFor();
+		assertEquals(
+				"http.proxyHost: gondola, http.proxyPort: 5678, https.proxyHost: yy, https.proxyPort: 1234",
+				getOutput(start));
+	}
+
+	@Test
+	public void testOverwriteHttpPort()
+			throws IOException, InterruptedException {
+		environment.put("http_proxy", "http://xx:1234");
+		environment.put("HTTP_PROXY", "http://XX:1234");
+		environment.put("https_proxy", "http://yy:1234");
+		environment.put("HTTPS_PROXY", "http://YY:1234");
+		List<String> command = processBuilder.command();
+		command.add(1, "-Dhttp.proxyPort=5678");
+		command.add("dontClearProperties");
+		Process start = processBuilder.start();
+		start.waitFor();
+		assertEquals(
+				"http.proxyHost: xx, http.proxyPort: 1234, https.proxyHost: yy, https.proxyPort: 1234",
+				getOutput(start));
+	}
+
+	private static String getOutput(Process p)
+			throws IOException, UnsupportedEncodingException {
+		try (InputStream inputStream = p.getInputStream()) {
+			ByteArrayOutputStream result = new ByteArrayOutputStream();
+			byte[] buffer = new byte[1024];
+			int length;
+			while ((length = inputStream.read(buffer)) != -1) {
+				result.write(buffer, 0, length);
+			}
+			return result.toString("UTF-8");
+		}
+	}
+}
+
+class ProxyPropertiesDumper {
+	public static void main(String args[]) {
+		try {
+			if (args.length == 0 || !args[0].equals("dontClearProperties")) {
+				System.clearProperty("http.proxyHost");
+				System.clearProperty("http.proxyPort");
+				System.clearProperty("https.proxyHost");
+				System.clearProperty("https.proxyPort");
+			}
+			Main.configureHttpProxy();
+			System.out.printf(
+					"http.proxyHost: %s, http.proxyPort: %s, https.proxyHost: %s, https.proxyPort: %s",
+					System.getProperty("http.proxyHost"),
+					System.getProperty("http.proxyPort"),
+					System.getProperty("https.proxyHost"),
+					System.getProperty("https.proxyPort"));
+			System.out.flush();
+		} catch (MalformedURLException e) {
+			System.out.println("exception: " + e);
+		}
+	}
+}
diff --git a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/ResetTest.java b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/ResetTest.java
index 16c5889..44a7630 100644
--- a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/ResetTest.java
+++ b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/ResetTest.java
@@ -42,7 +42,10 @@
  */
 package org.eclipse.jgit.pgm;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 
 import org.eclipse.jgit.api.Git;
 import org.eclipse.jgit.lib.CLIRepositoryTestCase;
diff --git a/org.eclipse.jgit.pgm/.classpath b/org.eclipse.jgit.pgm/.classpath
index c5d5a57..e8bc977 100644
--- a/org.eclipse.jgit.pgm/.classpath
+++ b/org.eclipse.jgit.pgm/.classpath
@@ -3,7 +3,7 @@
 	<classpathentry kind="src" path="src"/>
 	<classpathentry excluding="*|resources/|resources/" including="META-INF/" kind="src" path=""/>
 	<classpathentry kind="src" path="resources"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
 	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>
diff --git a/org.eclipse.jgit.pgm/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit.pgm/.settings/org.eclipse.jdt.core.prefs
index bfaf736..4f1759f 100644
--- a/org.eclipse.jgit.pgm/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit.pgm/.settings/org.eclipse.jdt.core.prefs
@@ -7,9 +7,9 @@
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.compliance=1.8
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -112,7 +112,7 @@
 org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
-org.eclipse.jdt.core.compiler.source=1.7
+org.eclipse.jdt.core.compiler.source=1.8
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
diff --git a/org.eclipse.jgit.pgm/BUCK b/org.eclipse.jgit.pgm/BUCK
index 47711b5..5d5e6f7 100644
--- a/org.eclipse.jgit.pgm/BUCK
+++ b/org.eclipse.jgit.pgm/BUCK
@@ -9,6 +9,7 @@
     '//org.eclipse.jgit:jgit',
     '//org.eclipse.jgit.archive:jgit-archive',
     '//org.eclipse.jgit.http.apache:http-apache',
+    '//org.eclipse.jgit.lfs:jgit-lfs',
     '//org.eclipse.jgit.lfs.server:jgit-lfs-server',
     '//org.eclipse.jgit.ui:ui',
     '//lib:args4j',
diff --git a/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF b/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF
index 59d9e49..5c30da7 100644
--- a/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF
@@ -2,69 +2,71 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %plugin_name
 Bundle-SymbolicName: org.eclipse.jgit.pgm
-Bundle-Version: 4.5.7.qualifier
+Bundle-Version: 4.6.2.qualifier
 Bundle-Vendor: %provider_name
 Bundle-ActivationPolicy: lazy
 Bundle-Localization: plugin
-Bundle-RequiredExecutionEnvironment: JavaSE-1.7
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
 Import-Package: javax.servlet;version="[3.1.0,4.0.0)",
  javax.servlet.http;version="[3.1.0,4.0.0)",
  org.apache.commons.compress.archivers;version="[1.3,2.0)",
  org.apache.commons.compress.archivers.tar;version="[1.3,2.0)",
  org.apache.commons.compress.archivers.zip;version="[1.3,2.0)",
- org.eclipse.jetty.continuation;version="[9.0.0,10.0.0)",
- org.eclipse.jetty.http;version="[9.0.0,10.0.0)",
- org.eclipse.jetty.io;version="[9.0.0,10.0.0)",
- org.eclipse.jetty.security;version="[9.0.0,10.0.0)",
- org.eclipse.jetty.security.authentication;version="[9.0.0,10.0.0)",
- org.eclipse.jetty.server;version="[9.0.0,10.0.0)",
- org.eclipse.jetty.server.handler;version="[9.0.0,10.0.0)",
- org.eclipse.jetty.server.nio;version="[9.0.0,10.0.0)",
- org.eclipse.jetty.servlet;version="[9.0.0,10.0.0)",
- org.eclipse.jetty.util;version="[9.0.0,10.0.0)",
- org.eclipse.jetty.util.component;version="[9.0.0,10.0.0)",
- org.eclipse.jetty.util.log;version="[9.0.0,10.0.0)",
- org.eclipse.jetty.util.security;version="[9.0.0,10.0.0)",
- org.eclipse.jetty.util.thread;version="[9.0.0,10.0.0)",
- org.eclipse.jgit.api;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.api.errors;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.archive;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.awtui;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.blame;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.diff;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.dircache;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.errors;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.gitrepo;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.internal.ketch;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.internal.storage.file;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.internal.storage.pack;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.internal.storage.reftree;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.lfs.lib;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.lfs.server;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.lfs.server.fs;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.lfs.server.s3;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.lib;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.merge;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.nls;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.notes;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.revplot;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.revwalk;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.revwalk.filter;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.storage.file;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.storage.pack;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.transport;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.transport.http.apache;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.transport.resolver;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.treewalk;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.treewalk.filter;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.util;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.util.io;version="[4.5.7,4.6.0)",
+ org.apache.commons.logging;version="1.1.1",
+ org.eclipse.jetty.continuation;version="[9.0.0,9.4.0)",
+ org.eclipse.jetty.http;version="[9.0.0,9.4.0)",
+ org.eclipse.jetty.io;version="[9.0.0,9.4.0)",
+ org.eclipse.jetty.security;version="[9.0.0,9.4.0)",
+ org.eclipse.jetty.security.authentication;version="[9.0.0,9.4.0)",
+ org.eclipse.jetty.server;version="[9.0.0,9.4.0)",
+ org.eclipse.jetty.server.handler;version="[9.0.0,9.4.0)",
+ org.eclipse.jetty.server.nio;version="[9.0.0,9.4.0)",
+ org.eclipse.jetty.servlet;version="[9.0.0,9.4.0)",
+ org.eclipse.jetty.util;version="[9.0.0,9.4.0)",
+ org.eclipse.jetty.util.component;version="[9.0.0,9.4.0)",
+ org.eclipse.jetty.util.log;version="[9.0.0,9.4.0)",
+ org.eclipse.jetty.util.security;version="[9.0.0,9.4.0)",
+ org.eclipse.jetty.util.thread;version="[9.0.0,9.4.0)",
+ org.eclipse.jgit.api;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.api.errors;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.archive;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.awtui;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.blame;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.diff;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.dircache;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.errors;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.gitrepo;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.internal.ketch;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.internal.storage.file;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.internal.storage.pack;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.internal.storage.reftree;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.lfs;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.lfs.lib;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.lfs.server;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.lfs.server.fs;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.lfs.server.s3;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.lib;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.merge;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.nls;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.notes;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.revplot;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.revwalk;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.revwalk.filter;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.storage.file;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.storage.pack;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.transport;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.transport.http.apache;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.transport.resolver;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.treewalk;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.treewalk.filter;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.util;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.util.io;version="[4.6.2,4.7.0)",
  org.kohsuke.args4j;version="[2.0.12,2.1.0)",
  org.kohsuke.args4j.spi;version="[2.0.15,2.1.0)"
-Export-Package: org.eclipse.jgit.console;version="4.5.7";
+Export-Package: org.eclipse.jgit.console;version="4.6.2";
   uses:="org.eclipse.jgit.transport,
    org.eclipse.jgit.util",
- org.eclipse.jgit.pgm;version="4.5.7";
+ org.eclipse.jgit.pgm;version="4.6.2";
   uses:="org.eclipse.jgit.revwalk,
    org.eclipse.jgit.treewalk.filter,
    org.eclipse.jgit.pgm.opt,
@@ -75,11 +77,11 @@
    org.eclipse.jgit.treewalk,
    javax.swing,
    org.eclipse.jgit.transport",
- org.eclipse.jgit.pgm.debug;version="4.5.7";
+ org.eclipse.jgit.pgm.debug;version="4.6.2";
   uses:="org.eclipse.jgit.util.io,
    org.eclipse.jgit.pgm",
- org.eclipse.jgit.pgm.internal;version="4.5.7";x-friends:="org.eclipse.jgit.pgm.test,org.eclipse.jgit.test",
- org.eclipse.jgit.pgm.opt;version="4.5.7";
+ org.eclipse.jgit.pgm.internal;version="4.6.2";x-friends:="org.eclipse.jgit.pgm.test,org.eclipse.jgit.test",
+ org.eclipse.jgit.pgm.opt;version="4.6.2";
   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 fb822fa..443ccc8 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: 4.5.7.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit.pgm;version="4.5.7.qualifier";roots="."
+Bundle-Version: 4.6.2.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit.pgm;version="4.6.2.qualifier";roots="."
diff --git a/org.eclipse.jgit.pgm/pom.xml b/org.eclipse.jgit.pgm/pom.xml
index adaeb40..c6f4aca 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>4.5.7-SNAPSHOT</version>
+    <version>4.6.2-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.pgm</artifactId>
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/console/ConsoleAuthenticator.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/console/ConsoleAuthenticator.java
index bdaccb0..8bf451c 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/console/ConsoleAuthenticator.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/console/ConsoleAuthenticator.java
@@ -49,9 +49,8 @@
 import java.net.PasswordAuthentication;
 import java.text.MessageFormat;
 
-import org.eclipse.jgit.util.CachedAuthenticator;
-
 import org.eclipse.jgit.pgm.internal.CLIText;
+import org.eclipse.jgit.util.CachedAuthenticator;
 
 /**
  * Basic network prompt for username/password when using the console.
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/console/ConsoleCredentialsProvider.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/console/ConsoleCredentialsProvider.java
index e805add..0aa0cf4 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/console/ConsoleCredentialsProvider.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/console/ConsoleCredentialsProvider.java
@@ -48,14 +48,13 @@
 import java.io.Console;
 
 import org.eclipse.jgit.errors.UnsupportedCredentialItem;
+import org.eclipse.jgit.pgm.internal.CLIText;
 import org.eclipse.jgit.transport.ChainingCredentialsProvider;
 import org.eclipse.jgit.transport.CredentialItem;
 import org.eclipse.jgit.transport.CredentialsProvider;
 import org.eclipse.jgit.transport.NetRCCredentialsProvider;
 import org.eclipse.jgit.transport.URIish;
 
-import org.eclipse.jgit.pgm.internal.CLIText;
-
 /**
  * Interacts with the user during authentication by using the text console.
  *
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Archive.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Archive.java
index fe2ba83..cff0bf6 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Archive.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Archive.java
@@ -52,7 +52,6 @@
 import org.eclipse.jgit.api.errors.GitAPIException;
 import org.eclipse.jgit.archive.ArchiveFormats;
 import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.pgm.TextBuiltin;
 import org.eclipse.jgit.pgm.internal.CLIText;
 import org.kohsuke.args4j.Argument;
 import org.kohsuke.args4j.Option;
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Checkout.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Checkout.java
index 94517db..0c3b720 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Checkout.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Checkout.java
@@ -92,8 +92,11 @@ protected void run() throws Exception {
 			CheckoutCommand command = git.checkout();
 			if (paths.size() > 0) {
 				command.setStartPoint(name);
-				for (String path : paths)
-					command.addPath(path);
+				if (paths.size() == 1 && paths.get(0).equals(".")) { //$NON-NLS-1$
+					command.setAllPaths(true);
+				} else {
+					command.addPaths(paths);
+				}
 			} else {
 				command.setCreateBranch(createBranch);
 				command.setName(name);
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/DiffTree.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/DiffTree.java
index 32adf6d..95c2132 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/DiffTree.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/DiffTree.java
@@ -47,14 +47,14 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import org.kohsuke.args4j.Argument;
-import org.kohsuke.args4j.Option;
 import org.eclipse.jgit.lib.FileMode;
 import org.eclipse.jgit.pgm.opt.PathTreeFilterHandler;
 import org.eclipse.jgit.treewalk.AbstractTreeIterator;
 import org.eclipse.jgit.treewalk.TreeWalk;
 import org.eclipse.jgit.treewalk.filter.AndTreeFilter;
 import org.eclipse.jgit.treewalk.filter.TreeFilter;
+import org.kohsuke.args4j.Argument;
+import org.kohsuke.args4j.Option;
 
 @Command(usage = "usage_ShowDiffTree")
 class DiffTree extends TextBuiltin {
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Main.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Main.java
index d701f22..a0f4d06 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Main.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Main.java
@@ -57,6 +57,8 @@
 import org.eclipse.jgit.awtui.AwtAuthenticator;
 import org.eclipse.jgit.awtui.AwtCredentialsProvider;
 import org.eclipse.jgit.errors.TransportException;
+import org.eclipse.jgit.lfs.CleanFilter;
+import org.eclipse.jgit.lfs.SmudgeFilter;
 import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.lib.RepositoryBuilder;
 import org.eclipse.jgit.pgm.internal.CLIText;
@@ -97,6 +99,8 @@ public class Main {
 	 */
 	public Main() {
 		HttpTransport.setConnectionFactory(new HttpClientConnectionFactory());
+		CleanFilter.register();
+		SmudgeFilter.register();
 	}
 
 	/**
@@ -339,17 +343,28 @@ private static void install(final String name)
 	 * <code>https_proxy</code> environment variables as a means of specifying
 	 * an HTTP/S proxy for requests made behind a firewall. This is not natively
 	 * recognized by the JRE, so this method can be used by command line
-	 * utilities to configure the JRE before the first request is sent.
+	 * utilities to configure the JRE before the first request is sent. The
+	 * information found in the environment variables is copied to the
+	 * associated system properties. This is not done when the system properties
+	 * are already set. The default way of telling java programs about proxies
+	 * (the system properties) takes precedence over environment variables.
 	 *
 	 * @throws MalformedURLException
 	 *             the value in <code>http_proxy</code> or
 	 *             <code>https_proxy</code> is unsupportable.
 	 */
-	private static void configureHttpProxy() throws MalformedURLException {
+	static void configureHttpProxy() throws MalformedURLException {
 		for (String protocol : new String[] { "http", "https" }) { //$NON-NLS-1$ //$NON-NLS-2$
-			final String s = System.getenv(protocol + "_proxy"); //$NON-NLS-1$
-			if (s == null || s.equals("")) //$NON-NLS-1$
-				return;
+			if (System.getProperty(protocol + ".proxyHost") != null) { //$NON-NLS-1$
+				continue;
+			}
+			String s = System.getenv(protocol + "_proxy"); //$NON-NLS-1$
+			if (s == null && protocol.equals("https")) { //$NON-NLS-1$
+				s = System.getenv("HTTPS_PROXY"); //$NON-NLS-1$
+			}
+			if (s == null || s.equals("")) { //$NON-NLS-1$
+				continue;
+			}
 
 			final URL u = new URL(
 					(s.indexOf("://") == -1) ? protocol + "://" + s : s); //$NON-NLS-1$ //$NON-NLS-2$
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Merge.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Merge.java
index 485efc5..1aab748 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Merge.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Merge.java
@@ -49,8 +49,8 @@
 
 import org.eclipse.jgit.api.Git;
 import org.eclipse.jgit.api.MergeCommand;
-import org.eclipse.jgit.api.MergeResult;
 import org.eclipse.jgit.api.MergeCommand.FastForwardMode;
+import org.eclipse.jgit.api.MergeResult;
 import org.eclipse.jgit.api.errors.CheckoutConflictException;
 import org.eclipse.jgit.lib.AnyObjectId;
 import org.eclipse.jgit.lib.Constants;
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/MergeBase.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/MergeBase.java
index 29cbb53..9dcd512 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/MergeBase.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/MergeBase.java
@@ -47,10 +47,10 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import org.kohsuke.args4j.Argument;
-import org.kohsuke.args4j.Option;
 import org.eclipse.jgit.revwalk.RevCommit;
 import org.eclipse.jgit.revwalk.filter.RevFilter;
+import org.kohsuke.args4j.Argument;
+import org.kohsuke.args4j.Option;
 
 @Command(usage = "usage_MergeBase")
 class MergeBase extends TextBuiltin {
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/RevParse.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/RevParse.java
index c5ecb84..6833ad3 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/RevParse.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/RevParse.java
@@ -51,13 +51,13 @@
 import java.util.List;
 import java.util.Map;
 
-import org.kohsuke.args4j.Argument;
-import org.kohsuke.args4j.CmdLineException;
-import org.kohsuke.args4j.Option;
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.Ref;
 import org.eclipse.jgit.pgm.internal.CLIText;
 import org.eclipse.jgit.pgm.opt.CmdLineParser;
+import org.kohsuke.args4j.Argument;
+import org.kohsuke.args4j.CmdLineException;
+import org.kohsuke.args4j.Option;
 
 @Command(usage = "usage_RevParse")
 class RevParse extends TextBuiltin {
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/RevWalkTextBuiltin.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/RevWalkTextBuiltin.java
index d6063c3..1543586 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/RevWalkTextBuiltin.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/RevWalkTextBuiltin.java
@@ -49,8 +49,6 @@
 import java.util.List;
 import java.util.Map;
 
-import org.kohsuke.args4j.Argument;
-import org.kohsuke.args4j.Option;
 import org.eclipse.jgit.diff.DiffConfig;
 import org.eclipse.jgit.errors.IncorrectObjectTypeException;
 import org.eclipse.jgit.lib.Constants;
@@ -73,6 +71,8 @@
 import org.eclipse.jgit.revwalk.filter.RevFilter;
 import org.eclipse.jgit.treewalk.filter.AndTreeFilter;
 import org.eclipse.jgit.treewalk.filter.TreeFilter;
+import org.kohsuke.args4j.Argument;
+import org.kohsuke.args4j.Option;
 
 abstract class RevWalkTextBuiltin extends TextBuiltin {
 	RevWalk walk;
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Status.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Status.java
index de3df80..43b292e 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Status.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Status.java
@@ -59,10 +59,10 @@
 import org.eclipse.jgit.lib.Ref;
 import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.pgm.internal.CLIText;
+import org.eclipse.jgit.pgm.opt.UntrackedFilesHandler;
 import org.kohsuke.args4j.Argument;
 import org.kohsuke.args4j.Option;
 import org.kohsuke.args4j.spi.RestOfArgumentsHandler;
-import org.eclipse.jgit.pgm.opt.UntrackedFilesHandler;
 
 /**
  * Status command
@@ -70,8 +70,6 @@
 @Command(usage = "usage_Status", common = true)
 class Status extends TextBuiltin {
 
-	protected final String lineFormat = CLIText.get().lineFormat;
-
 	protected final String statusFileListFormat = CLIText.get().statusFileListFormat;
 
 	protected final String statusFileListFormatWithPrefix = CLIText.get().statusFileListFormatWithPrefix;
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/LfsStore.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/LfsStore.java
index c4d9548..52b6d19 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/LfsStore.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/LfsStore.java
@@ -64,8 +64,8 @@
 import org.eclipse.jgit.errors.ConfigInvalidException;
 import org.eclipse.jgit.lfs.server.LargeFileRepository;
 import org.eclipse.jgit.lfs.server.LfsProtocolServlet;
-import org.eclipse.jgit.lfs.server.fs.FileLfsServlet;
 import org.eclipse.jgit.lfs.server.fs.FileLfsRepository;
+import org.eclipse.jgit.lfs.server.fs.FileLfsServlet;
 import org.eclipse.jgit.lfs.server.s3.S3Config;
 import org.eclipse.jgit.lfs.server.s3.S3Repository;
 import org.eclipse.jgit.pgm.Command;
@@ -238,7 +238,7 @@ protected void run() throws Exception {
 		case S3:
 			readAWSKeys();
 			checkOptions();
-			S3Config config = new S3Config(region.toString(), bucket,
+			S3Config config = new S3Config(region, bucket,
 					storageClass.toString(), accessKey, secretKey,
 					expirationSeconds, disableSslVerify);
 			repository = new S3Repository(config);
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/AbstractTreeIteratorHandler.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/AbstractTreeIteratorHandler.java
index 6b8a61d..8f56bda 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/AbstractTreeIteratorHandler.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/AbstractTreeIteratorHandler.java
@@ -48,12 +48,6 @@
 import java.io.IOException;
 import java.text.MessageFormat;
 
-import org.kohsuke.args4j.CmdLineException;
-import org.kohsuke.args4j.CmdLineParser;
-import org.kohsuke.args4j.OptionDef;
-import org.kohsuke.args4j.spi.OptionHandler;
-import org.kohsuke.args4j.spi.Parameters;
-import org.kohsuke.args4j.spi.Setter;
 import org.eclipse.jgit.dircache.DirCache;
 import org.eclipse.jgit.dircache.DirCacheIterator;
 import org.eclipse.jgit.errors.IncorrectObjectTypeException;
@@ -66,6 +60,12 @@
 import org.eclipse.jgit.treewalk.FileTreeIterator;
 import org.eclipse.jgit.treewalk.WorkingTreeOptions;
 import org.eclipse.jgit.util.FS;
+import org.kohsuke.args4j.CmdLineException;
+import org.kohsuke.args4j.CmdLineParser;
+import org.kohsuke.args4j.OptionDef;
+import org.kohsuke.args4j.spi.OptionHandler;
+import org.kohsuke.args4j.spi.Parameters;
+import org.kohsuke.args4j.spi.Setter;
 
 /**
  * Custom argument handler {@link AbstractTreeIterator} from string values.
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/ObjectIdHandler.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/ObjectIdHandler.java
index 364809d..75ca554 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/ObjectIdHandler.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/ObjectIdHandler.java
@@ -47,14 +47,14 @@
 import java.io.IOException;
 import java.text.MessageFormat;
 
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.pgm.internal.CLIText;
 import org.kohsuke.args4j.CmdLineException;
 import org.kohsuke.args4j.CmdLineParser;
 import org.kohsuke.args4j.OptionDef;
 import org.kohsuke.args4j.spi.OptionHandler;
 import org.kohsuke.args4j.spi.Parameters;
 import org.kohsuke.args4j.spi.Setter;
-import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.pgm.internal.CLIText;
 
 /**
  * Custom argument handler {@link ObjectId} from string values.
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/PathTreeFilterHandler.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/PathTreeFilterHandler.java
index 122cce7..e468023 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/PathTreeFilterHandler.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/PathTreeFilterHandler.java
@@ -46,6 +46,10 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import org.eclipse.jgit.pgm.internal.CLIText;
+import org.eclipse.jgit.treewalk.filter.PathFilter;
+import org.eclipse.jgit.treewalk.filter.PathFilterGroup;
+import org.eclipse.jgit.treewalk.filter.TreeFilter;
 import org.kohsuke.args4j.CmdLineException;
 import org.kohsuke.args4j.CmdLineParser;
 import org.kohsuke.args4j.Option;
@@ -53,10 +57,6 @@
 import org.kohsuke.args4j.spi.OptionHandler;
 import org.kohsuke.args4j.spi.Parameters;
 import org.kohsuke.args4j.spi.Setter;
-import org.eclipse.jgit.pgm.internal.CLIText;
-import org.eclipse.jgit.treewalk.filter.PathFilter;
-import org.eclipse.jgit.treewalk.filter.PathFilterGroup;
-import org.eclipse.jgit.treewalk.filter.TreeFilter;
 
 /**
  * Create a {@link TreeFilter} to patch math names.
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/RefSpecHandler.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/RefSpecHandler.java
index dae0c47..f50c7ad 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/RefSpecHandler.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/RefSpecHandler.java
@@ -43,14 +43,14 @@
 
 package org.eclipse.jgit.pgm.opt;
 
+import org.eclipse.jgit.pgm.internal.CLIText;
+import org.eclipse.jgit.transport.RefSpec;
 import org.kohsuke.args4j.CmdLineException;
 import org.kohsuke.args4j.CmdLineParser;
 import org.kohsuke.args4j.OptionDef;
 import org.kohsuke.args4j.spi.OptionHandler;
 import org.kohsuke.args4j.spi.Parameters;
 import org.kohsuke.args4j.spi.Setter;
-import org.eclipse.jgit.pgm.internal.CLIText;
-import org.eclipse.jgit.transport.RefSpec;
 
 /**
  * Custom argument handler {@link RefSpec} from string values.
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/RevCommitHandler.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/RevCommitHandler.java
index 9ae56e4..7661774 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/RevCommitHandler.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/RevCommitHandler.java
@@ -47,18 +47,18 @@
 import java.io.IOException;
 import java.text.MessageFormat;
 
-import org.kohsuke.args4j.CmdLineException;
-import org.kohsuke.args4j.CmdLineParser;
-import org.kohsuke.args4j.OptionDef;
-import org.kohsuke.args4j.spi.OptionHandler;
-import org.kohsuke.args4j.spi.Parameters;
-import org.kohsuke.args4j.spi.Setter;
 import org.eclipse.jgit.errors.IncorrectObjectTypeException;
 import org.eclipse.jgit.errors.MissingObjectException;
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.pgm.internal.CLIText;
 import org.eclipse.jgit.revwalk.RevCommit;
 import org.eclipse.jgit.revwalk.RevFlag;
+import org.kohsuke.args4j.CmdLineException;
+import org.kohsuke.args4j.CmdLineParser;
+import org.kohsuke.args4j.OptionDef;
+import org.kohsuke.args4j.spi.OptionHandler;
+import org.kohsuke.args4j.spi.Parameters;
+import org.kohsuke.args4j.spi.Setter;
 
 /**
  * Custom argument handler {@link RevCommit} from string values.
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/RevTreeHandler.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/RevTreeHandler.java
index e2879e0..9f1d21e 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/RevTreeHandler.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/RevTreeHandler.java
@@ -47,17 +47,17 @@
 import java.io.IOException;
 import java.text.MessageFormat;
 
+import org.eclipse.jgit.errors.IncorrectObjectTypeException;
+import org.eclipse.jgit.errors.MissingObjectException;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.pgm.internal.CLIText;
+import org.eclipse.jgit.revwalk.RevTree;
 import org.kohsuke.args4j.CmdLineException;
 import org.kohsuke.args4j.CmdLineParser;
 import org.kohsuke.args4j.OptionDef;
 import org.kohsuke.args4j.spi.OptionHandler;
 import org.kohsuke.args4j.spi.Parameters;
 import org.kohsuke.args4j.spi.Setter;
-import org.eclipse.jgit.errors.IncorrectObjectTypeException;
-import org.eclipse.jgit.errors.MissingObjectException;
-import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.pgm.internal.CLIText;
-import org.eclipse.jgit.revwalk.RevTree;
 
 /**
  * Custom argument handler {@link RevTree} from string values.
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/SubcommandHandler.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/SubcommandHandler.java
index 96f3ed0..311597e 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/SubcommandHandler.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/SubcommandHandler.java
@@ -45,16 +45,16 @@
 
 import java.text.MessageFormat;
 
+import org.eclipse.jgit.pgm.CommandCatalog;
+import org.eclipse.jgit.pgm.CommandRef;
+import org.eclipse.jgit.pgm.TextBuiltin;
+import org.eclipse.jgit.pgm.internal.CLIText;
 import org.kohsuke.args4j.CmdLineException;
 import org.kohsuke.args4j.CmdLineParser;
 import org.kohsuke.args4j.OptionDef;
 import org.kohsuke.args4j.spi.OptionHandler;
 import org.kohsuke.args4j.spi.Parameters;
 import org.kohsuke.args4j.spi.Setter;
-import org.eclipse.jgit.pgm.CommandCatalog;
-import org.eclipse.jgit.pgm.CommandRef;
-import org.eclipse.jgit.pgm.TextBuiltin;
-import org.eclipse.jgit.pgm.internal.CLIText;
 
 /**
  * Custom Argument handler for jgit command selection.
diff --git a/org.eclipse.jgit.test/.classpath b/org.eclipse.jgit.test/.classpath
index 8b81bf5..84b5052 100644
--- a/org.eclipse.jgit.test/.classpath
+++ b/org.eclipse.jgit.test/.classpath
@@ -4,7 +4,7 @@
 	<classpathentry kind="src" path="src"/>
 	<classpathentry kind="src" path="tst-rsrc"/>
 	<classpathentry kind="src" path="exttst"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
 	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>
diff --git a/org.eclipse.jgit.test/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit.test/.settings/org.eclipse.jdt.core.prefs
index 87210fb..10c29d5 100644
--- a/org.eclipse.jgit.test/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit.test/.settings/org.eclipse.jdt.core.prefs
@@ -7,9 +7,9 @@
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.compliance=1.8
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -112,7 +112,7 @@
 org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
-org.eclipse.jdt.core.compiler.source=1.7
+org.eclipse.jdt.core.compiler.source=1.8
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
diff --git a/org.eclipse.jgit.test/BUCK b/org.eclipse.jgit.test/BUCK
index 3df3336..5b7be89 100644
--- a/org.eclipse.jgit.test/BUCK
+++ b/org.eclipse.jgit.test/BUCK
@@ -60,6 +60,7 @@
       ':tst_rsrc',
       '//org.eclipse.jgit:jgit',
       '//org.eclipse.jgit.junit:junit',
+      '//org.eclipse.jgit.lfs:jgit-lfs',
       '//lib:hamcrest-core',
       '//lib:hamcrest-library',
       '//lib:javaewah',
@@ -67,7 +68,6 @@
       '//lib:slf4j-api',
       '//lib:slf4j-simple',
     ] + DEPS.get(src, []),
-    source_under_test = ['//org.eclipse.jgit:jgit'],
     vm_args = ['-Xmx256m', '-Dfile.encoding=UTF-8'],
   )
 
diff --git a/org.eclipse.jgit.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.test/META-INF/MANIFEST.MF
index b4afe5e..f48cae0 100644
--- a/org.eclipse.jgit.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.test/META-INF/MANIFEST.MF
@@ -2,57 +2,58 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %plugin_name
 Bundle-SymbolicName: org.eclipse.jgit.test
-Bundle-Version: 4.5.7.qualifier
+Bundle-Version: 4.6.2.qualifier
 Bundle-Localization: plugin
 Bundle-Vendor: %provider_name
 Bundle-ActivationPolicy: lazy
-Bundle-RequiredExecutionEnvironment: JavaSE-1.7
-Import-Package: com.googlecode.javaewah;version="[0.7.9,0.8.0)",
- org.eclipse.jgit.api;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.api.errors;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.attributes;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.awtui;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.blame;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.diff;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.dircache;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.errors;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.events;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.fnmatch;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.gitrepo;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.hooks;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.ignore;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.ignore.internal;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.internal;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.internal.storage.dfs;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.internal.storage.file;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.internal.storage.pack;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.internal.storage.reftree;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.junit;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.lib;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.merge;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.nls;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.notes;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.patch;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.pgm;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.pgm.internal;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.revplot;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.revwalk;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.revwalk.filter;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.storage.file;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.storage.pack;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.submodule;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.transport;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.transport.http;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.transport.resolver;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.treewalk;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.treewalk.filter;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.util;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.util.io;version="[4.5.7,4.6.0)",
- org.hamcrest;version="[1.1.0,2.0.0)",
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Import-Package: com.googlecode.javaewah;version="[1.1.6,2.0.0)",
+ org.eclipse.jgit.api;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.api.errors;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.attributes;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.awtui;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.blame;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.diff;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.dircache;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.errors;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.events;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.fnmatch;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.gitrepo;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.hooks;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.ignore;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.ignore.internal;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.internal;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.internal.storage.dfs;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.internal.storage.file;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.internal.storage.pack;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.internal.storage.reftree;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.junit;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.lfs;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.lib;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.merge;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.nls;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.notes;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.patch;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.pgm;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.pgm.internal;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.revplot;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.revwalk;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.revwalk.filter;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.storage.file;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.storage.pack;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.submodule;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.transport;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.transport.http;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.transport.resolver;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.treewalk;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.treewalk.filter;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.util;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.util.io;version="[4.6.2,4.7.0)",
  org.junit;version="[4.4.0,5.0.0)",
  org.junit.experimental.theories;version="[4.4.0,5.0.0)",
  org.junit.rules;version="[4.11.0,5.0.0)",
  org.junit.runner;version="[4.4.0,5.0.0)",
  org.junit.runners;version="[4.11.0,5.0.0)",
  org.slf4j;version="[1.7.2,2.0.0)"
-Require-Bundle: org.hamcrest.core;bundle-version="[1.1.0,2.0.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)"
diff --git "a/org.eclipse.jgit.test/org.eclipse.jgit.core--All-External-Tests \050Java 6\051.launch" "b/org.eclipse.jgit.test/org.eclipse.jgit.core--All-External-Tests \050Java 6\051.launch"
deleted file mode 100644
index db13a84..0000000
--- "a/org.eclipse.jgit.test/org.eclipse.jgit.core--All-External-Tests \050Java 6\051.launch"
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<launchConfiguration type="org.eclipse.jdt.junit.launchconfig">
-<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
-<listEntry value="/org.eclipse.jgit.test/exttst"/>
-</listAttribute>
-<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
-<listEntry value="2"/>
-</listAttribute>
-<booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="true"/>
-<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
-<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
-<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
-</listAttribute>
-<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value="=org.eclipse.jgit.test/exttst"/>
-<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/>
-<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/>
-<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit4"/>
-<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
-<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value=""/>
-<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.jgit.test"/>
-</launchConfiguration>
diff --git a/org.eclipse.jgit.test/org.eclipse.jgit.core--All-External-Tests.launch b/org.eclipse.jgit.test/org.eclipse.jgit.core--All-External-Tests.launch
deleted file mode 100644
index 2adb02c..0000000
--- a/org.eclipse.jgit.test/org.eclipse.jgit.core--All-External-Tests.launch
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<launchConfiguration type="org.eclipse.jdt.junit.launchconfig">
-<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
-<listEntry value="/org.eclipse.jgit.test/exttst"/>
-</listAttribute>
-<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
-<listEntry value="2"/>
-</listAttribute>
-<booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="true"/>
-<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
-<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
-<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
-</listAttribute>
-<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value="=org.eclipse.jgit.test/exttst"/>
-<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/>
-<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/>
-<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit4"/>
-<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value=""/>
-<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.jgit.test"/>
-</launchConfiguration>
diff --git "a/org.eclipse.jgit.test/org.eclipse.jgit.core--All-Tests \050Java 6\051.launch" "b/org.eclipse.jgit.test/org.eclipse.jgit.core--All-Tests \050Java 6\051.launch"
deleted file mode 100644
index f253d59..0000000
--- "a/org.eclipse.jgit.test/org.eclipse.jgit.core--All-Tests \050Java 6\051.launch"
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<launchConfiguration type="org.eclipse.jdt.junit.launchconfig">
-<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
-<listEntry value="/org.eclipse.jgit.test/tst"/>
-</listAttribute>
-<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
-<listEntry value="2"/>
-</listAttribute>
-<booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="true"/>
-<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
-<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
-<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
-</listAttribute>
-<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value="=org.eclipse.jgit.test/tst"/>
-<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/>
-<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/>
-<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit4"/>
-<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
-<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value=""/>
-<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.jgit.test"/>
-<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xmx256m"/>
-</launchConfiguration>
diff --git "a/org.eclipse.jgit.test/org.eclipse.jgit.core--All-Tests \050Java 7\051 \050de\051.launch" "b/org.eclipse.jgit.test/org.eclipse.jgit.core--All-Tests \050Java 7\051 \050de\051.launch"
deleted file mode 100644
index 86446f9..0000000
--- "a/org.eclipse.jgit.test/org.eclipse.jgit.core--All-Tests \050Java 7\051 \050de\051.launch"
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<launchConfiguration type="org.eclipse.jdt.junit.launchconfig">
-<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
-<listEntry value="/org.eclipse.jgit.test/tst"/>
-</listAttribute>
-<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
-<listEntry value="2"/>
-</listAttribute>
-<booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="true"/>
-<mapAttribute key="org.eclipse.debug.core.environmentVariables">
-<mapEntry key="LANG" value="de_DE.UTF-8"/>
-</mapAttribute>
-<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
-<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
-<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
-</listAttribute>
-<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value="=org.eclipse.jgit.test/tst"/>
-<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/>
-<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/>
-<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit4"/>
-<listAttribute key="org.eclipse.jdt.launching.CLASSPATH">
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry containerPath=&quot;org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6&quot; path=&quot;1&quot; type=&quot;4&quot;/&gt;&#10;"/>
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry id=&quot;org.eclipse.jdt.launching.classpathentry.defaultClasspath&quot;&gt;&#10;&lt;memento exportedEntriesOnly=&quot;false&quot; project=&quot;org.eclipse.jgit.test&quot;/&gt;&#10;&lt;/runtimeClasspathEntry&gt;&#10;"/>
-</listAttribute>
-<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/>
-<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
-<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value=""/>
-<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.jgit.test"/>
-<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xmx256m"/>
-</launchConfiguration>
diff --git "a/org.eclipse.jgit.test/org.eclipse.jgit.core--All-Tests \050Java 7\051.launch" "b/org.eclipse.jgit.test/org.eclipse.jgit.core--All-Tests \050Java 7\051.launch"
deleted file mode 100644
index a83fabb..0000000
--- "a/org.eclipse.jgit.test/org.eclipse.jgit.core--All-Tests \050Java 7\051.launch"
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<launchConfiguration type="org.eclipse.jdt.junit.launchconfig">
-<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
-<listEntry value="/org.eclipse.jgit.test/tst"/>
-</listAttribute>
-<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
-<listEntry value="2"/>
-</listAttribute>
-<booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="true"/>
-<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
-<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
-<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
-</listAttribute>
-<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value="=org.eclipse.jgit.test/tst"/>
-<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/>
-<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/>
-<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit4"/>
-<listAttribute key="org.eclipse.jdt.launching.CLASSPATH">
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry containerPath=&quot;org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6&quot; path=&quot;1&quot; type=&quot;4&quot;/&gt;&#10;"/>
-<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry id=&quot;org.eclipse.jdt.launching.classpathentry.defaultClasspath&quot;&gt;&#10;&lt;memento exportedEntriesOnly=&quot;false&quot; project=&quot;org.eclipse.jgit.test&quot;/&gt;&#10;&lt;/runtimeClasspathEntry&gt;&#10;"/>
-</listAttribute>
-<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/>
-<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
-<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value=""/>
-<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.jgit.test"/>
-<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xmx256m"/>
-</launchConfiguration>
diff --git a/org.eclipse.jgit.test/pom.xml b/org.eclipse.jgit.test/pom.xml
index 1088021..1aff289 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>4.5.7-SNAPSHOT</version>
+    <version>4.6.2-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.test</artifactId>
diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/indexdiff/filerepo.txt b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/indexdiff/filerepo.txt
new file mode 100644
index 0000000..3255efb
--- /dev/null
+++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/indexdiff/filerepo.txt
@@ -0,0 +1,30 @@
+blob
+mark :1
+data 10
+äéü.txt
+blob
+mark :2
+data 8
+test.txt
+blob
+mark :3
+data 5
+Test
+
+blob
+mark :4
+data 7
+äéü
+
+reset refs/heads/master
+commit refs/heads/master
+mark :5
+author A U Thor <author@example.com> 1450727513 +0100
+committer A U Thor <author@example.com> 1450727513 +0100
+data 26
+Initial commit with links
+M 120000 :1 testfolder/aeu.txt
+M 120000 :2 testfolder/link.txt
+M 100644 :3 testfolder/test.txt
+M 100644 :4 testfolder/äéü.txt
+
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/AddCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/AddCommandTest.java
index 42601aa..5ad73f1 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/AddCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/AddCommandTest.java
@@ -57,12 +57,21 @@
 import org.eclipse.jgit.api.errors.FilterFailedException;
 import org.eclipse.jgit.api.errors.GitAPIException;
 import org.eclipse.jgit.api.errors.NoFilepatternException;
+import org.eclipse.jgit.attributes.FilterCommandRegistry;
 import org.eclipse.jgit.dircache.DirCache;
 import org.eclipse.jgit.dircache.DirCacheBuilder;
 import org.eclipse.jgit.dircache.DirCacheEntry;
 import org.eclipse.jgit.junit.JGitTestUtil;
 import org.eclipse.jgit.junit.RepositoryTestCase;
-import org.eclipse.jgit.lib.*;
+import org.eclipse.jgit.lfs.CleanFilter;
+import org.eclipse.jgit.lfs.SmudgeFilter;
+import org.eclipse.jgit.lib.ConfigConstants;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.FileMode;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectInserter;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.StoredConfig;
 import org.eclipse.jgit.revwalk.RevCommit;
 import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
 import org.eclipse.jgit.treewalk.TreeWalk;
@@ -70,8 +79,23 @@
 import org.eclipse.jgit.util.FS;
 import org.eclipse.jgit.util.FileUtils;
 import org.junit.Test;
+import org.junit.experimental.theories.DataPoints;
+import org.junit.experimental.theories.Theories;
+import org.junit.experimental.theories.Theory;
+import org.junit.runner.RunWith;
 
+@RunWith(Theories.class)
 public class AddCommandTest extends RepositoryTestCase {
+	@DataPoints
+	public static boolean[] sleepBeforeAddOptions = { true, false };
+
+
+	@Override
+	public void setUp() throws Exception {
+		CleanFilter.register();
+		SmudgeFilter.register();
+		super.setUp();
+	}
 
 	@Test
 	public void testAddNothing() throws GitAPIException {
@@ -110,8 +134,7 @@ public void testAddExistingSingleFile() throws IOException, GitAPIException {
 	}
 
 	@Test
-	public void testCleanFilter() throws IOException,
-			GitAPIException {
+	public void testCleanFilter() throws IOException, GitAPIException {
 		writeTrashFile(".gitattributes", "*.txt filter=tstFilter");
 		writeTrashFile("src/a.tmp", "foo");
 		// Caution: we need a trailing '\n' since sed on mac always appends
@@ -134,6 +157,128 @@ public void testCleanFilter() throws IOException,
 		}
 	}
 
+	@Theory
+	public void testBuiltinFilters(boolean sleepBeforeAdd)
+			throws IOException,
+			GitAPIException, InterruptedException {
+		writeTrashFile(".gitattributes", "*.txt filter=lfs");
+		writeTrashFile("src/a.tmp", "foo");
+		// Caution: we need a trailing '\n' since sed on mac always appends
+		// linefeeds if missing
+		File script = writeTempFile("sed s/o/e/g");
+		File f = writeTrashFile("src/a.txt", "foo\n");
+
+		try (Git git = new Git(db)) {
+			if (!sleepBeforeAdd) {
+				fsTick(f);
+			}
+			git.add().addFilepattern(".gitattributes").call();
+			StoredConfig config = git.getRepository().getConfig();
+			config.setString("filter", "lfs", "clean",
+					"sh " + slashify(script.getPath()));
+			config.setString("filter", "lfs", "smudge",
+					"sh " + slashify(script.getPath()));
+			config.setBoolean("filter", "lfs", "useJGitBuiltin", true);
+			config.save();
+
+			if (!sleepBeforeAdd) {
+				fsTick(f);
+			}
+			git.add().addFilepattern("src/a.txt").addFilepattern("src/a.tmp")
+					.addFilepattern(".gitattributes").call();
+
+			assertEquals(
+					"[.gitattributes, mode:100644, content:*.txt filter=lfs][src/a.tmp, mode:100644, content:foo][src/a.txt, mode:100644, content:version https://git-lfs.github.com/spec/v1\noid sha256:b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c\nsize 4\n]",
+					indexState(CONTENT));
+
+			RevCommit c1 = git.commit().setMessage("c1").call();
+			assertTrue(git.status().call().isClean());
+			f = writeTrashFile("src/a.txt", "foobar\n");
+			if (!sleepBeforeAdd) {
+				fsTick(f);
+			}
+			git.add().addFilepattern("src/a.txt").call();
+			git.commit().setMessage("c2").call();
+			assertTrue(git.status().call().isClean());
+			assertEquals(
+					"[.gitattributes, mode:100644, content:*.txt filter=lfs][src/a.tmp, mode:100644, content:foo][src/a.txt, mode:100644, content:version https://git-lfs.github.com/spec/v1\noid sha256:aec070645fe53ee3b3763059376134f058cc337247c978add178b6ccdfb0019f\nsize 7\n]",
+					indexState(CONTENT));
+			assertEquals("foobar\n", read("src/a.txt"));
+			git.checkout().setName(c1.getName()).call();
+			assertEquals(
+					"[.gitattributes, mode:100644, content:*.txt filter=lfs][src/a.tmp, mode:100644, content:foo][src/a.txt, mode:100644, content:version https://git-lfs.github.com/spec/v1\noid sha256:b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c\nsize 4\n]",
+					indexState(CONTENT));
+			assertEquals(
+					"foo\n", read("src/a.txt"));
+		}
+	}
+
+	@Theory
+	public void testBuiltinCleanFilter(boolean sleepBeforeAdd)
+			throws IOException, GitAPIException, InterruptedException {
+		writeTrashFile(".gitattributes", "*.txt filter=lfs");
+		writeTrashFile("src/a.tmp", "foo");
+		// Caution: we need a trailing '\n' since sed on mac always appends
+		// linefeeds if missing
+		File script = writeTempFile("sed s/o/e/g");
+		File f = writeTrashFile("src/a.txt", "foo\n");
+
+		// unregister the smudge filter. Only clean filter should be builtin
+		FilterCommandRegistry.unregister(
+				org.eclipse.jgit.lib.Constants.BUILTIN_FILTER_PREFIX
+						+ "lfs/smudge");
+
+		try (Git git = new Git(db)) {
+			if (!sleepBeforeAdd) {
+				fsTick(f);
+			}
+			git.add().addFilepattern(".gitattributes").call();
+			StoredConfig config = git.getRepository().getConfig();
+			config.setString("filter", "lfs", "clean",
+					"sh " + slashify(script.getPath()));
+			config.setString("filter", "lfs", "smudge",
+					"sh " + slashify(script.getPath()));
+			config.setBoolean("filter", "lfs", "useJGitBuiltin", true);
+			config.save();
+
+			if (!sleepBeforeAdd) {
+				fsTick(f);
+			}
+			git.add().addFilepattern("src/a.txt").addFilepattern("src/a.tmp")
+					.addFilepattern(".gitattributes").call();
+
+			assertEquals(
+					"[.gitattributes, mode:100644, content:*.txt filter=lfs][src/a.tmp, mode:100644, content:foo][src/a.txt, mode:100644, content:version https://git-lfs.github.com/spec/v1\noid sha256:b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c\nsize 4\n]",
+					indexState(CONTENT));
+
+			RevCommit c1 = git.commit().setMessage("c1").call();
+			assertTrue(git.status().call().isClean());
+			f = writeTrashFile("src/a.txt", "foobar\n");
+			if (!sleepBeforeAdd) {
+				fsTick(f);
+			}
+			git.add().addFilepattern("src/a.txt").call();
+			git.commit().setMessage("c2").call();
+			assertTrue(git.status().call().isClean());
+			assertEquals(
+					"[.gitattributes, mode:100644, content:*.txt filter=lfs][src/a.tmp, mode:100644, content:foo][src/a.txt, mode:100644, content:version https://git-lfs.github.com/spec/v1\noid sha256:aec070645fe53ee3b3763059376134f058cc337247c978add178b6ccdfb0019f\nsize 7\n]",
+					indexState(CONTENT));
+			assertEquals("foobar\n", read("src/a.txt"));
+			git.checkout().setName(c1.getName()).call();
+			assertEquals(
+					"[.gitattributes, mode:100644, content:*.txt filter=lfs][src/a.tmp, mode:100644, content:foo][src/a.txt, mode:100644, content:version https://git-lfs.github.com/spec/v1\noid sha256:b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c\nsize 4\n]",
+					indexState(CONTENT));
+			// due to lfs clean filter but dummy smudge filter we expect strange
+			// content. The smudge filter converts from real content to pointer
+			// file content (starting with "version ") but the smudge filter
+			// replaces 'o' by 'e' which results in a text starting with
+			// "versien "
+			assertEquals(
+					"versien https://git-lfs.github.cem/spec/v1\neid sha256:b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c\nsize 4\n",
+					read("src/a.txt"));
+		}
+	}
+
 	@Test
 	public void testAttributesWithTreeWalkFilter()
 			throws IOException, GitAPIException {
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CheckoutCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CheckoutCommandTest.java
index 0bb6610..3c19672 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CheckoutCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CheckoutCommandTest.java
@@ -74,6 +74,8 @@
 import org.eclipse.jgit.dircache.DirCacheEntry;
 import org.eclipse.jgit.junit.JGitTestUtil;
 import org.eclipse.jgit.junit.RepositoryTestCase;
+import org.eclipse.jgit.lfs.CleanFilter;
+import org.eclipse.jgit.lfs.SmudgeFilter;
 import org.eclipse.jgit.lib.ConfigConstants;
 import org.eclipse.jgit.lib.Constants;
 import org.eclipse.jgit.lib.Ref;
@@ -87,6 +89,7 @@
 import org.eclipse.jgit.transport.RemoteConfig;
 import org.eclipse.jgit.transport.URIish;
 import org.eclipse.jgit.util.FileUtils;
+import org.eclipse.jgit.util.SystemReader;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -100,6 +103,8 @@ public class CheckoutCommandTest extends RepositoryTestCase {
 	@Override
 	@Before
 	public void setUp() throws Exception {
+		CleanFilter.register();
+		SmudgeFilter.register();
 		super.setUp();
 		git = new Git(db);
 		// commit something
@@ -563,11 +568,11 @@ public void testCheckoutAutoCrlfTrue() throws Exception {
 	public void testSmudgeFilter_modifyExisting() throws IOException, GitAPIException {
 		File script = writeTempFile("sed s/o/e/g");
 		StoredConfig config = git.getRepository().getConfig();
-		config.setString("filter", "tstFilter", "smudge",
+		config.setString("filter", "lfs", "smudge",
 				"sh " + slashify(script.getPath()));
 		config.save();
 
-		writeTrashFile(".gitattributes", "*.txt filter=tstFilter");
+		writeTrashFile(".gitattributes", "*.txt filter=lfs");
 		git.add().addFilepattern(".gitattributes").call();
 		git.commit().setMessage("add filter").call();
 
@@ -589,7 +594,7 @@ public void testSmudgeFilter_modifyExisting() throws IOException, GitAPIExceptio
 		git.checkout().setName(content2.getName()).call();
 
 		assertEquals(
-				"[.gitattributes, mode:100644, content:*.txt filter=tstFilter][Test.txt, mode:100644, content:Some change][src/a.tmp, mode:100644, content:foo][src/a.txt, mode:100644, content:foo\n]",
+				"[.gitattributes, mode:100644, content:*.txt filter=lfs][Test.txt, mode:100644, content:Some change][src/a.tmp, mode:100644, content:foo][src/a.txt, mode:100644, content:foo\n]",
 				indexState(CONTENT));
 		assertEquals(Sets.of("src/a.txt"), git.status().call().getModified());
 		assertEquals("foo", read("src/a.tmp"));
@@ -601,7 +606,7 @@ public void testSmudgeFilter_createNew()
 			throws IOException, GitAPIException {
 		File script = writeTempFile("sed s/o/e/g");
 		StoredConfig config = git.getRepository().getConfig();
-		config.setString("filter", "tstFilter", "smudge",
+		config.setString("filter", "lfs", "smudge",
 				"sh " + slashify(script.getPath()));
 		config.save();
 
@@ -609,7 +614,7 @@ public void testSmudgeFilter_createNew()
 		git.add().addFilepattern("foo").call();
 		RevCommit initial = git.commit().setMessage("initial").call();
 
-		writeTrashFile(".gitattributes", "*.txt filter=tstFilter");
+		writeTrashFile(".gitattributes", "*.txt filter=lfs");
 		git.add().addFilepattern(".gitattributes").call();
 		git.commit().setMessage("add filter").call();
 
@@ -625,7 +630,7 @@ public void testSmudgeFilter_createNew()
 		git.checkout().setName(content.getName()).call();
 
 		assertEquals(
-				"[.gitattributes, mode:100644, content:*.txt filter=tstFilter][Test.txt, mode:100644, content:Some change][foo, mode:100644, content:foo][src/a.tmp, mode:100644, content:foo][src/a.txt, mode:100644, content:foo\n]",
+				"[.gitattributes, mode:100644, content:*.txt filter=lfs][Test.txt, mode:100644, content:Some change][foo, mode:100644, content:foo][src/a.tmp, mode:100644, content:foo][src/a.txt, mode:100644, content:foo\n]",
 				indexState(CONTENT));
 		assertEquals("foo", read("src/a.tmp"));
 		assertEquals("fee\n", read("src/a.txt"));
@@ -636,7 +641,7 @@ public void testSmudgeFilter_deleteFileAndRestoreFromCommit()
 			throws IOException, GitAPIException {
 		File script = writeTempFile("sed s/o/e/g");
 		StoredConfig config = git.getRepository().getConfig();
-		config.setString("filter", "tstFilter", "smudge",
+		config.setString("filter", "lfs", "smudge",
 				"sh " + slashify(script.getPath()));
 		config.save();
 
@@ -644,7 +649,7 @@ public void testSmudgeFilter_deleteFileAndRestoreFromCommit()
 		git.add().addFilepattern("foo").call();
 		git.commit().setMessage("initial").call();
 
-		writeTrashFile(".gitattributes", "*.txt filter=tstFilter");
+		writeTrashFile(".gitattributes", "*.txt filter=lfs");
 		git.add().addFilepattern(".gitattributes").call();
 		git.commit().setMessage("add filter").call();
 
@@ -661,7 +666,7 @@ public void testSmudgeFilter_deleteFileAndRestoreFromCommit()
 				.call();
 
 		assertEquals(
-				"[.gitattributes, mode:100644, content:*.txt filter=tstFilter][Test.txt, mode:100644, content:Some change][foo, mode:100644, content:foo][src/a.tmp, mode:100644, content:foo][src/a.txt, mode:100644, content:foo\n]",
+				"[.gitattributes, mode:100644, content:*.txt filter=lfs][Test.txt, mode:100644, content:Some change][foo, mode:100644, content:foo][src/a.tmp, mode:100644, content:foo][src/a.txt, mode:100644, content:foo\n]",
 				indexState(CONTENT));
 		assertEquals("foo", read("src/a.tmp"));
 		assertEquals("fee\n", read("src/a.txt"));
@@ -672,7 +677,7 @@ public void testSmudgeFilter_deleteFileAndRestoreFromIndex()
 			throws IOException, GitAPIException {
 		File script = writeTempFile("sed s/o/e/g");
 		StoredConfig config = git.getRepository().getConfig();
-		config.setString("filter", "tstFilter", "smudge",
+		config.setString("filter", "lfs", "smudge",
 				"sh " + slashify(script.getPath()));
 		config.save();
 
@@ -680,7 +685,7 @@ public void testSmudgeFilter_deleteFileAndRestoreFromIndex()
 		git.add().addFilepattern("foo").call();
 		git.commit().setMessage("initial").call();
 
-		writeTrashFile(".gitattributes", "*.txt filter=tstFilter");
+		writeTrashFile(".gitattributes", "*.txt filter=lfs");
 		git.add().addFilepattern(".gitattributes").call();
 		git.commit().setMessage("add filter").call();
 
@@ -696,7 +701,7 @@ public void testSmudgeFilter_deleteFileAndRestoreFromIndex()
 		git.checkout().addPath("src/a.txt").call();
 
 		assertEquals(
-				"[.gitattributes, mode:100644, content:*.txt filter=tstFilter][Test.txt, mode:100644, content:Some change][foo, mode:100644, content:foo][src/a.tmp, mode:100644, content:foo][src/a.txt, mode:100644, content:foo\n]",
+				"[.gitattributes, mode:100644, content:*.txt filter=lfs][Test.txt, mode:100644, content:Some change][foo, mode:100644, content:foo][src/a.tmp, mode:100644, content:foo][src/a.txt, mode:100644, content:foo\n]",
 				indexState(CONTENT));
 		assertEquals("foo", read("src/a.tmp"));
 		assertEquals("fee\n", read("src/a.txt"));
@@ -707,7 +712,7 @@ public void testSmudgeFilter_deleteFileAndCreateBranchAndRestoreFromCommit()
 			throws IOException, GitAPIException {
 		File script = writeTempFile("sed s/o/e/g");
 		StoredConfig config = git.getRepository().getConfig();
-		config.setString("filter", "tstFilter", "smudge",
+		config.setString("filter", "lfs", "smudge",
 				"sh " + slashify(script.getPath()));
 		config.save();
 
@@ -715,7 +720,7 @@ public void testSmudgeFilter_deleteFileAndCreateBranchAndRestoreFromCommit()
 		git.add().addFilepattern("foo").call();
 		git.commit().setMessage("initial").call();
 
-		writeTrashFile(".gitattributes", "*.txt filter=tstFilter");
+		writeTrashFile(".gitattributes", "*.txt filter=lfs");
 		git.add().addFilepattern(".gitattributes").call();
 		git.commit().setMessage("add filter").call();
 
@@ -732,7 +737,7 @@ public void testSmudgeFilter_deleteFileAndCreateBranchAndRestoreFromCommit()
 				.setStartPoint(content).addPath("src/a.txt").call();
 
 		assertEquals(
-				"[.gitattributes, mode:100644, content:*.txt filter=tstFilter][Test.txt, mode:100644, content:Some change][foo, mode:100644, content:foo][src/a.tmp, mode:100644, content:foo][src/a.txt, mode:100644, content:foo\n]",
+				"[.gitattributes, mode:100644, content:*.txt filter=lfs][Test.txt, mode:100644, content:Some change][foo, mode:100644, content:foo][src/a.tmp, mode:100644, content:foo][src/a.txt, mode:100644, content:foo\n]",
 				indexState(CONTENT));
 		assertEquals("foo", read("src/a.tmp"));
 		assertEquals("fee\n", read("src/a.txt"));
@@ -745,12 +750,13 @@ public void testSmudgeAndClean() throws Exception {
 
 		try (Git git2 = new Git(db)) {
 			StoredConfig config = git.getRepository().getConfig();
-			config.setString("filter", "tstFilter", "smudge",
+			config.setString("filter", "lfs", "smudge",
 					"sh " + slashify(smudge_filter.getPath()));
-			config.setString("filter", "tstFilter", "clean",
+			config.setString("filter", "lfs", "clean",
 					"sh " + slashify(clean_filter.getPath()));
+			config.setBoolean("filter", "lfs", "useJGitBuiltin", true);
 			config.save();
-			writeTrashFile(".gitattributes", "filterTest.txt filter=tstFilter");
+			writeTrashFile(".gitattributes", "filterTest.txt filter=lfs");
 			git2.add().addFilepattern(".gitattributes").call();
 			git2.commit().setMessage("add attributes").call();
 
@@ -758,7 +764,7 @@ public void testSmudgeAndClean() throws Exception {
 			git2.add().addFilepattern("filterTest.txt").call();
 			RevCommit one = git2.commit().setMessage("add filterText.txt").call();
 			assertEquals(
-					"[.gitattributes, mode:100644, content:filterTest.txt filter=tstFilter][Test.txt, mode:100644, content:Some change][filterTest.txt, mode:100644, content:hello world, @version\n]",
+					"[.gitattributes, mode:100644, content:filterTest.txt filter=lfs][Test.txt, mode:100644, content:Some change][filterTest.txt, mode:100644, content:version https://git-lfs.github.com/spec/v1\noid sha256:7bd5d32e5c494354aa4c2473a1306d0ce7b52cc3bffeb342c03cd517ef8cf8da\nsize 16\n]",
 					indexState(CONTENT));
 
 			fsTick(writeTrashFile("filterTest.txt", "bon giorno world, V1\n"));
@@ -767,25 +773,57 @@ public void testSmudgeAndClean() throws Exception {
 
 			assertTrue(git2.status().call().isClean());
 			assertEquals(
-					"[.gitattributes, mode:100644, content:filterTest.txt filter=tstFilter][Test.txt, mode:100644, content:Some change][filterTest.txt, mode:100644, content:bon giorno world, @version\n]",
+					"[.gitattributes, mode:100644, content:filterTest.txt filter=lfs][Test.txt, mode:100644, content:Some change][filterTest.txt, mode:100644, content:version https://git-lfs.github.com/spec/v1\noid sha256:087148cccf53b0049c56475c1595113c9da4b638997c3489af8ac7108d51ef13\nsize 21\n]",
 					indexState(CONTENT));
 
 			git2.checkout().setName(one.getName()).call();
 			assertTrue(git2.status().call().isClean());
 			assertEquals(
-					"[.gitattributes, mode:100644, content:filterTest.txt filter=tstFilter][Test.txt, mode:100644, content:Some change][filterTest.txt, mode:100644, content:hello world, @version\n]",
+					"[.gitattributes, mode:100644, content:filterTest.txt filter=lfs][Test.txt, mode:100644, content:Some change][filterTest.txt, mode:100644, content:version https://git-lfs.github.com/spec/v1\noid sha256:7bd5d32e5c494354aa4c2473a1306d0ce7b52cc3bffeb342c03cd517ef8cf8da\nsize 16\n]",
 					indexState(CONTENT));
 			assertEquals("hello world, V1\n", read("filterTest.txt"));
 
 			git2.checkout().setName(two.getName()).call();
 			assertTrue(git2.status().call().isClean());
 			assertEquals(
-					"[.gitattributes, mode:100644, content:filterTest.txt filter=tstFilter][Test.txt, mode:100644, content:Some change][filterTest.txt, mode:100644, content:bon giorno world, @version\n]",
+					"[.gitattributes, mode:100644, content:filterTest.txt filter=lfs][Test.txt, mode:100644, content:Some change][filterTest.txt, mode:100644, content:version https://git-lfs.github.com/spec/v1\noid sha256:087148cccf53b0049c56475c1595113c9da4b638997c3489af8ac7108d51ef13\nsize 21\n]",
 					indexState(CONTENT));
 			assertEquals("bon giorno world, V1\n", read("filterTest.txt"));
 		}
 	}
 
+	@Test
+	public void testNonDeletableFilesOnWindows()
+			throws GitAPIException, IOException {
+		// Only on windows a FileInputStream blocks us from deleting a file
+		org.junit.Assume.assumeTrue(SystemReader.getInstance().isWindows());
+		writeTrashFile("toBeModified.txt", "a");
+		writeTrashFile("toBeDeleted.txt", "a");
+		git.add().addFilepattern(".").call();
+		RevCommit addFiles = git.commit().setMessage("add more files").call();
+
+		git.rm().setCached(false).addFilepattern("Test.txt")
+				.addFilepattern("toBeDeleted.txt").call();
+		writeTrashFile("toBeModified.txt", "b");
+		writeTrashFile("toBeCreated.txt", "a");
+		git.add().addFilepattern(".").call();
+		RevCommit crudCommit = git.commit().setMessage("delete, modify, add")
+				.call();
+		git.checkout().setName(addFiles.getName()).call();
+		try ( FileInputStream fis=new FileInputStream(new File(db.getWorkTree(), "Test.txt")) ) {
+			CheckoutCommand coCommand = git.checkout();
+			coCommand.setName(crudCommit.getName()).call();
+			CheckoutResult result = coCommand.getResult();
+			assertEquals(Status.NONDELETED, result.getStatus());
+			assertEquals("[Test.txt, toBeDeleted.txt]",
+					result.getRemovedList().toString());
+			assertEquals("[toBeCreated.txt, toBeModified.txt]",
+					result.getModifiedList().toString());
+			assertEquals("[Test.txt]", result.getUndeletedList().toString());
+			assertTrue(result.getConflictList().isEmpty());
+		}
+	}
+
 	private File writeTempFile(String body) throws IOException {
 		File f = File.createTempFile("AddCommandTest_", "");
 		JGitTestUtil.write(f, body);
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CleanCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CleanCommandTest.java
index 68f5dd1..0e1cf02 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CleanCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CleanCommandTest.java
@@ -42,10 +42,10 @@
  */
 package org.eclipse.jgit.api;
 
+import static org.eclipse.jgit.lib.Constants.DOT_GIT_MODULES;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
-import static org.eclipse.jgit.lib.Constants.DOT_GIT_MODULES;
 
 import java.io.File;
 import java.util.Set;
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitCommandTest.java
index ba84081..021c245 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitCommandTest.java
@@ -43,10 +43,10 @@
 package org.eclipse.jgit.api;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.fail;
 
 import java.io.File;
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/DiffCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/DiffCommandTest.java
index 4f5b50d..43c3a8c 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/DiffCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/DiffCommandTest.java
@@ -95,7 +95,7 @@ public void testDiffModified() throws Exception {
 					+ "\\ No newline at end of file\n"
 					+ "+folder change\n"
 					+ "\\ No newline at end of file\n";
-			assertEquals(expected.toString(), actual);
+			assertEquals(expected, actual);
 		}
 	}
 
@@ -130,7 +130,7 @@ public void testDiffCached() throws Exception {
 					+ "@@ -0,0 +1 @@\n"
 					+ "+folder\n"
 					+ "\\ No newline at end of file\n";
-			assertEquals(expected.toString(), actual);
+			assertEquals(expected, actual);
 		}
 	}
 
@@ -179,7 +179,7 @@ public void testDiffTwoCommits() throws Exception {
 					+ "\\ No newline at end of file\n"
 					+ "+folder change\n"
 					+ "\\ No newline at end of file\n";
-			assertEquals(expected.toString(), actual);
+			assertEquals(expected, actual);
 		}
 	}
 
@@ -201,7 +201,7 @@ public void testDiffWithPrefixes() throws Exception {
 					+ "+++ new/test.txt\n" + "@@ -1 +1 @@\n" + "-test\n"
 					+ "\\ No newline at end of file\n" + "+test change\n"
 					+ "\\ No newline at end of file\n";
-			assertEquals(expected.toString(), actual);
+			assertEquals(expected, actual);
 		}
 	}
 
@@ -223,7 +223,7 @@ public void testDiffWithNegativeLineCount() throws Exception {
 					+ "index f55b5c9..c5ec8fd 100644\n" + "--- a/test.txt\n"
 					+ "+++ b/test.txt\n" + "@@ -4,3 +4,3 @@\n" + " 3\n" + "-4\n"
 					+ "+4a\n" + " 5\n";
-			assertEquals(expected.toString(), actual);
+			assertEquals(expected, actual);
 		}
 	}
 
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/EolStreamTypeUtilTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/EolStreamTypeUtilTest.java
index 8ca1b31..2ee77a0 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/EolStreamTypeUtilTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/EolStreamTypeUtilTest.java
@@ -42,8 +42,12 @@
 
 package org.eclipse.jgit.api;
 
+import static org.eclipse.jgit.lib.CoreConfig.EolStreamType.AUTO_CRLF;
+import static org.eclipse.jgit.lib.CoreConfig.EolStreamType.AUTO_LF;
+import static org.eclipse.jgit.lib.CoreConfig.EolStreamType.DIRECT;
+import static org.eclipse.jgit.lib.CoreConfig.EolStreamType.TEXT_CRLF;
+import static org.eclipse.jgit.lib.CoreConfig.EolStreamType.TEXT_LF;
 import static org.junit.Assert.assertArrayEquals;
-import static org.eclipse.jgit.lib.CoreConfig.EolStreamType.*;
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/NotesCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/NotesCommandTest.java
index 6ddf89c..9d15699 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/NotesCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/NotesCommandTest.java
@@ -43,6 +43,7 @@
 package org.eclipse.jgit.api;
 
 import static org.junit.Assert.assertEquals;
+
 import java.util.List;
 
 import org.eclipse.jgit.junit.RepositoryTestCase;
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/DiffFormatterTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/DiffFormatterTest.java
index 638a163..b4234dc 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/DiffFormatterTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/DiffFormatterTest.java
@@ -45,6 +45,7 @@
 
 import static org.junit.Assert.assertEquals;
 
+import java.io.BufferedOutputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 
@@ -65,7 +66,6 @@
 import org.eclipse.jgit.util.FileUtils;
 import org.eclipse.jgit.util.RawParseUtils;
 import org.eclipse.jgit.util.io.DisabledOutputStream;
-import org.eclipse.jgit.util.io.SafeBufferedOutputStream;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -381,7 +381,7 @@ public void testDiff() throws Exception {
 		write(new File(folder, "folder.txt"), "folder");
 		try (Git git = new Git(db);
 				ByteArrayOutputStream os = new ByteArrayOutputStream();
-				DiffFormatter dfmt = new DiffFormatter(new SafeBufferedOutputStream(os))) {
+				DiffFormatter dfmt = new DiffFormatter(new BufferedOutputStream(os))) {
 			git.add().addFilepattern(".").call();
 			git.commit().setMessage("Initial commit").call();
 			write(new File(folder, "folder.txt"), "folder change");
@@ -414,7 +414,7 @@ public void testDiffRootNullToTree() throws Exception {
 		write(new File(folder, "folder.txt"), "folder");
 		try (Git git = new Git(db);
 				ByteArrayOutputStream os = new ByteArrayOutputStream();
-				DiffFormatter dfmt = new DiffFormatter(new SafeBufferedOutputStream(os))) {
+				DiffFormatter dfmt = new DiffFormatter(new BufferedOutputStream(os))) {
 			git.add().addFilepattern(".").call();
 			RevCommit commit = git.commit().setMessage("Initial commit").call();
 			write(new File(folder, "folder.txt"), "folder change");
@@ -446,7 +446,7 @@ public void testDiffRootTreeToNull() throws Exception {
 		write(new File(folder, "folder.txt"), "folder");
 		try (Git git = new Git(db);
 				ByteArrayOutputStream os = new ByteArrayOutputStream();
-				DiffFormatter dfmt = new DiffFormatter(new SafeBufferedOutputStream(os));) {
+				DiffFormatter dfmt = new DiffFormatter(new BufferedOutputStream(os));) {
 			git.add().addFilepattern(".").call();
 			RevCommit commit = git.commit().setMessage("Initial commit").call();
 			write(new File(folder, "folder.txt"), "folder change");
@@ -473,7 +473,7 @@ public void testDiffRootTreeToNull() throws Exception {
 	@Test
 	public void testDiffNullToNull() throws Exception {
 		try (ByteArrayOutputStream os = new ByteArrayOutputStream();
-				DiffFormatter dfmt = new DiffFormatter(new SafeBufferedOutputStream(os))) {
+				DiffFormatter dfmt = new DiffFormatter(new BufferedOutputStream(os))) {
 			dfmt.setRepository(db);
 			dfmt.format((AnyObjectId) null, null);
 			dfmt.flush();
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/fnmatch/FileNameMatcherTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/fnmatch/FileNameMatcherTest.java
index 1db6c80..ba78591 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/fnmatch/FileNameMatcherTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/fnmatch/FileNameMatcherTest.java
@@ -69,7 +69,7 @@ private static void assertFileNameMatch(final String pattern,
 			final boolean appendCanMatchExpected)
 			throws InvalidPatternException {
 		final FileNameMatcher matcher = new FileNameMatcher(pattern,
-				new Character(excludedCharacter));
+				Character.valueOf(excludedCharacter));
 		matcher.append(input);
 		assertEquals(matchExpected, matcher.isMatch());
 		assertEquals(appendCanMatchExpected, matcher.canAppendMatch());
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/gitrepo/ManifestParserTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/gitrepo/ManifestParserTest.java
index 30b3df1..b1138f0 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/gitrepo/ManifestParserTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/gitrepo/ManifestParserTest.java
@@ -42,8 +42,8 @@
  */
 package org.eclipse.jgit.gitrepo;
 
-import static org.junit.Assert.assertTrue;
 import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.junit.Assert.assertTrue;
 
 import java.io.ByteArrayInputStream;
 import java.util.HashSet;
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/indexdiff/IndexDiffWithSymlinkTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/indexdiff/IndexDiffWithSymlinkTest.java
new file mode 100644
index 0000000..4f3b601
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/indexdiff/IndexDiffWithSymlinkTest.java
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2015 Thomas Wolf <thomas.wolf@paranor.ch>
+ *
+ * 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.indexdiff;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeTrue;
+
+import java.io.BufferedOutputStream;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Collections;
+
+import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.IndexDiff;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
+import org.eclipse.jgit.treewalk.FileTreeIterator;
+import org.eclipse.jgit.treewalk.WorkingTreeIterator;
+import org.eclipse.jgit.treewalk.filter.PathFilterGroup;
+import org.eclipse.jgit.util.FS;
+import org.eclipse.jgit.util.SystemReader;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * MacOS-only test for dealing with symlinks in IndexDiff. Recreates using cgit
+ * a test repository prepared with git 2.2.1 on MacOS 10.7.5 containing some
+ * symlinks. Examines a symlink pointing to a file named "äéü.txt" (should be
+ * encoded as UTF-8 NFC), changes it through Java, examines it again to verify
+ * it's been changed to UTF-8 NFD, and finally calculates an IndexDiff.
+ */
+public class IndexDiffWithSymlinkTest extends LocalDiskRepositoryTestCase {
+
+	private static final String FILEREPO = "filerepo";
+
+	private static final String TESTFOLDER = "testfolder";
+
+	private static final String TESTTARGET = "äéü.txt";
+
+	private static final String TESTLINK = "aeu.txt";
+
+	private static final byte[] NFC = // "äéü.txt" in NFC
+	{ -61, -92, -61, -87, -61, -68, 46, 116, 120, 116 };
+
+	private static final byte[] NFD = // "äéü.txt" in NFD
+	{ 97, -52, -120, 101, -52, -127, 117, -52, -120, 46, 116, 120, 116 };
+
+	private File testRepoDir;
+
+	@Override
+	@Before
+	public void setUp() throws Exception {
+		assumeTrue(SystemReader.getInstance().isMacOS()
+				&& FS.DETECTED.supportsSymlinks());
+		super.setUp();
+		File testDir = createTempDirectory(this.getClass().getSimpleName());
+		InputStream in = this.getClass().getClassLoader().getResourceAsStream(
+				this.getClass().getPackage().getName().replace('.', '/') + '/'
+						+ FILEREPO + ".txt");
+		assertNotNull("Test repo file not found", in);
+		try {
+			testRepoDir = restoreGitRepo(in, testDir, FILEREPO);
+		} finally {
+			in.close();
+		}
+	}
+
+	private File restoreGitRepo(InputStream in, File testDir, String name)
+			throws Exception {
+		File exportedTestRepo = new File(testDir, name + ".txt");
+		copy(in, exportedTestRepo);
+		// Use CGit to restore
+		File restoreScript = new File(testDir, name + ".sh");
+		try (OutputStream out = new BufferedOutputStream(
+				new FileOutputStream(restoreScript));
+				Writer writer = new OutputStreamWriter(out,
+						StandardCharsets.UTF_8)) {
+			writer.write("echo `which git` 1>&2\n");
+			writer.write("echo `git --version` 1>&2\n");
+			writer.write("git init " + name + " && \\\n");
+			writer.write("cd ./" + name + " && \\\n");
+			writer.write("git fast-import < ../" + name + ".txt && \\\n");
+			writer.write("git checkout -f\n");
+		}
+		String[] cmd = { "/bin/sh", "./" + name + ".sh" };
+		int exitCode;
+		String stdErr;
+		Process process = Runtime.getRuntime().exec(cmd, null, testDir);
+		try (InputStream stdOutStream = process.getInputStream();
+				InputStream stdErrStream = process.getErrorStream();
+				OutputStream stdInStream = process.getOutputStream()) {
+			readStream(stdOutStream);
+			stdErr = readStream(stdErrStream);
+			process.waitFor();
+			exitCode = process.exitValue();
+		}
+		if (exitCode != 0) {
+			fail("cgit repo restore returned " + exitCode + '\n' + stdErr);
+		}
+		return new File(new File(testDir, name), Constants.DOT_GIT);
+	}
+
+	private void copy(InputStream from, File to) throws IOException {
+		try (OutputStream out = new FileOutputStream(to)) {
+			byte[] buffer = new byte[4096];
+			int n;
+			while ((n = from.read(buffer)) > 0) {
+				out.write(buffer, 0, n);
+			}
+		}
+	}
+
+	private String readStream(InputStream stream) throws IOException {
+		try (BufferedReader in = new BufferedReader(
+				new InputStreamReader(stream))) {
+			StringBuilder out = new StringBuilder();
+			String line;
+			while ((line = in.readLine()) != null) {
+				out.append(line).append('\n');
+			}
+			return out.toString();
+		}
+	}
+
+	@Test
+	public void testSymlinkWithEncodingDifference() throws Exception {
+		try (Repository testRepo = FileRepositoryBuilder.create(testRepoDir)) {
+			File workingTree = testRepo.getWorkTree();
+			File symLink = new File(new File(workingTree, TESTFOLDER),
+					TESTLINK);
+			// Read the symlink as it was created by cgit
+			Path linkTarget = Files.readSymbolicLink(symLink.toPath());
+			assertEquals("Unexpected link target", TESTTARGET,
+					linkTarget.toString());
+			byte[] raw = rawPath(linkTarget);
+			if (raw != null) {
+				assertArrayEquals("Expected an NFC link target", NFC, raw);
+			}
+			// Now re-create that symlink through Java
+			assertTrue("Could not delete symlink", symLink.delete());
+			Files.createSymbolicLink(symLink.toPath(), Paths.get(TESTTARGET));
+			// Read it again
+			linkTarget = Files.readSymbolicLink(symLink.toPath());
+			assertEquals("Unexpected link target", TESTTARGET,
+					linkTarget.toString());
+			raw = rawPath(linkTarget);
+			if (raw != null) {
+				assertArrayEquals("Expected an NFD link target", NFD, raw);
+			}
+			// Do the indexdiff
+			WorkingTreeIterator iterator = new FileTreeIterator(testRepo);
+			IndexDiff diff = new IndexDiff(testRepo, Constants.HEAD, iterator);
+			diff.setFilter(PathFilterGroup.createFromStrings(
+					Collections.singleton(TESTFOLDER + '/' + TESTLINK)));
+			diff.diff();
+			// We're testing that this does NOT throw "EOFException: Short read
+			// of block." The diff will not report any modified files -- the
+			// link modification is not visible to JGit, which always works with
+			// the Java internal NFC encoding. CGit does report the link as an
+			// unstaged modification here, though.
+		}
+	}
+
+	private byte[] rawPath(Path p) {
+		try {
+			Method method = p.getClass().getDeclaredMethod("asByteArray");
+			if (method != null) {
+				method.setAccessible(true);
+				return (byte[]) method.invoke(p);
+			}
+		} catch (NoSuchMethodException | IllegalAccessException
+				| IllegalArgumentException | InvocationTargetException e) {
+			// Ignore and fall through.
+		}
+		return null;
+	}
+}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsBlockCacheConfigTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsBlockCacheConfigTest.java
new file mode 100644
index 0000000..e612061
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsBlockCacheConfigTest.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2016, Philipp Marx <philippmarx@gmx.de> and
+ * other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v1.0 which accompanies this
+ * distribution, is reproduced below, and is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.eclipse.jgit.internal.storage.dfs;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+
+import org.eclipse.jgit.internal.JGitText;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+public class DfsBlockCacheConfigTest {
+
+	@Rule
+	public ExpectedException thrown = ExpectedException.none();
+
+	@Test
+	public void blockSizeNotPowerOfTwoExpectsException() {
+		thrown.expect(IllegalArgumentException.class);
+		thrown.expectMessage(is(JGitText.get().blockSizeNotPowerOf2));
+
+		new DfsBlockCacheConfig().setBlockSize(1000);
+	}
+
+	@Test
+	@SuppressWarnings("boxing")
+	public void negativeBlockSizeIsConvertedToDefault() {
+		DfsBlockCacheConfig config = new DfsBlockCacheConfig();
+		config.setBlockSize(-1);
+
+		assertThat(config.getBlockSize(), is(512));
+	}
+
+	@Test
+	@SuppressWarnings("boxing")
+	public void tooSmallBlockSizeIsConvertedToDefault() {
+		DfsBlockCacheConfig config = new DfsBlockCacheConfig();
+		config.setBlockSize(10);
+
+		assertThat(config.getBlockSize(), is(512));
+	}
+
+	@Test
+	@SuppressWarnings("boxing")
+	public void validBlockSize() {
+		DfsBlockCacheConfig config = new DfsBlockCacheConfig();
+		config.setBlockSize(65536);
+
+		assertThat(config.getBlockSize(), is(65536));
+	}
+}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/AbbreviationTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/AbbreviationTest.java
index 9875403..ece8f67 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/AbbreviationTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/AbbreviationTest.java
@@ -50,6 +50,7 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
+import java.io.BufferedOutputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileOutputStream;
@@ -60,9 +61,6 @@
 import java.util.List;
 
 import org.eclipse.jgit.errors.AmbiguousObjectException;
-import org.eclipse.jgit.internal.storage.file.FileRepository;
-import org.eclipse.jgit.internal.storage.file.PackIndexWriter;
-import org.eclipse.jgit.internal.storage.file.PackIndexWriterV2;
 import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase;
 import org.eclipse.jgit.junit.TestRepository;
 import org.eclipse.jgit.lib.AbbreviatedObjectId;
@@ -72,7 +70,6 @@
 import org.eclipse.jgit.revwalk.RevBlob;
 import org.eclipse.jgit.transport.PackedObjectInfo;
 import org.eclipse.jgit.util.FileUtils;
-import org.eclipse.jgit.util.io.SafeBufferedOutputStream;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -183,13 +180,10 @@ public void testAbbreviateIsActuallyUnique() throws Exception {
 		File idxFile = new File(packDir, packName + ".idx");
 		File packFile = new File(packDir, packName + ".pack");
 		FileUtils.mkdir(packDir, true);
-		OutputStream dst = new SafeBufferedOutputStream(new FileOutputStream(
-				idxFile));
-		try {
+		try (OutputStream dst = new BufferedOutputStream(
+				new FileOutputStream(idxFile))) {
 			PackIndexWriter writer = new PackIndexWriterV2(dst);
 			writer.write(objects, new byte[OBJECT_ID_LENGTH]);
-		} finally {
-			dst.close();
 		}
 		new FileOutputStream(packFile).close();
 
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/AutoGcTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/AutoGcTest.java
new file mode 100644
index 0000000..56994a6
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/AutoGcTest.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2016, Matthias Sohn <matthias.sohn@sap.com>
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ *   copyright notice, this list of conditions and the following
+ *   disclaimer in the documentation and/or other materials provided
+ *   with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ *   names of its contributors may be used to endorse or promote
+ *   products derived from this software without specific prior
+ *   written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.eclipse.jgit.internal.storage.file;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.eclipse.jgit.lib.ConfigConstants;
+import org.eclipse.jgit.storage.file.FileBasedConfig;
+import org.eclipse.jgit.test.resources.SampleDataRepositoryTestCase;
+import org.junit.Test;
+
+public class AutoGcTest extends GcTestCase {
+
+	@Test
+	public void testNotTooManyLooseObjects() {
+		assertFalse("should not find too many loose objects",
+				gc.tooManyLooseObjects());
+	}
+
+	@Test
+	public void testTooManyLooseObjects() throws Exception {
+		FileBasedConfig c = repo.getConfig();
+		c.setInt(ConfigConstants.CONFIG_GC_SECTION, null,
+				ConfigConstants.CONFIG_KEY_AUTO, 255);
+		c.save();
+		commitChain(10, 50);
+		assertTrue("should find too many loose objects",
+				gc.tooManyLooseObjects());
+	}
+
+	@Test
+	public void testNotTooManyPacks() {
+		assertFalse("should not find too many packs", gc.tooManyPacks());
+	}
+
+	@Test
+	public void testTooManyPacks() throws Exception {
+		FileBasedConfig c = repo.getConfig();
+		c.setInt(ConfigConstants.CONFIG_GC_SECTION, null,
+				ConfigConstants.CONFIG_KEY_AUTOPACKLIMIT, 1);
+		c.save();
+		SampleDataRepositoryTestCase.copyCGitTestPacks(repo);
+
+		assertTrue("should find too many packs", gc.tooManyPacks());
+	}
+}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ConcurrentRepackTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ConcurrentRepackTest.java
index 9d7a482..1d71cb3 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ConcurrentRepackTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ConcurrentRepackTest.java
@@ -51,6 +51,7 @@
 import static org.junit.Assert.assertNotSame;
 import static org.junit.Assert.fail;
 
+import java.io.BufferedOutputStream;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
@@ -71,7 +72,6 @@
 import org.eclipse.jgit.revwalk.RevWalk;
 import org.eclipse.jgit.storage.file.WindowCacheConfig;
 import org.eclipse.jgit.util.FileUtils;
-import org.eclipse.jgit.util.io.SafeBufferedOutputStream;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -235,20 +235,15 @@ private static void write(final File[] files, final PackWriter pw)
 			throws IOException {
 		final long begin = files[0].getParentFile().lastModified();
 		NullProgressMonitor m = NullProgressMonitor.INSTANCE;
-		OutputStream out;
 
-		out = new SafeBufferedOutputStream(new FileOutputStream(files[0]));
-		try {
+		try (OutputStream out = new BufferedOutputStream(
+				new FileOutputStream(files[0]))) {
 			pw.writePack(m, m, out);
-		} finally {
-			out.close();
 		}
 
-		out = new SafeBufferedOutputStream(new FileOutputStream(files[1]));
-		try {
+		try (OutputStream out = new BufferedOutputStream(
+				new FileOutputStream(files[1]))) {
 			pw.writeIndex(out);
-		} finally {
-			out.close();
 		}
 
 		touch(begin, files[0].getParentFile());
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/DescriptionTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/DescriptionTest.java
new file mode 100644
index 0000000..73bd35b
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/DescriptionTest.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2016, Google Inc.
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ *   copyright notice, this list of conditions and the following
+ *   disclaimer in the documentation and/or other materials provided
+ *   with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ *   names of its contributors may be used to endorse or promote
+ *   products derived from this software without specific prior
+ *   written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.eclipse.jgit.internal.storage.file;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase;
+import org.eclipse.jgit.lib.Repository;
+import org.junit.Test;
+
+/** Test managing the gitweb description file. */
+public class DescriptionTest extends LocalDiskRepositoryTestCase {
+	private static final String UNCONFIGURED = "Unnamed repository; edit this file to name it for gitweb.";
+
+	@Test
+	public void description() throws IOException {
+		Repository git = createBareRepository();
+		File path = new File(git.getDirectory(), "description");
+		assertNull("description", git.getGitwebDescription());
+
+		String desc = "a test repo\nfor jgit";
+		git.setGitwebDescription(desc);
+		assertEquals(desc + '\n', read(path));
+		assertEquals(desc, git.getGitwebDescription());
+
+		git.setGitwebDescription(null);
+		assertEquals("", read(path));
+
+		desc = "foo";
+		git.setGitwebDescription(desc);
+		assertEquals(desc + '\n', read(path));
+		assertEquals(desc, git.getGitwebDescription());
+
+		git.setGitwebDescription("");
+		assertEquals("", read(path));
+
+		git.setGitwebDescription(UNCONFIGURED);
+		assertEquals(UNCONFIGURED + '\n', read(path));
+		assertNull("description", git.getGitwebDescription());
+	}
+}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/FileSnapshotTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/FileSnapshotTest.java
index 07b1bc7..98a9501 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/FileSnapshotTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/FileSnapshotTest.java
@@ -42,8 +42,6 @@
  */
 package org.eclipse.jgit.internal.storage.file;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
 import java.io.File;
@@ -52,7 +50,6 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import org.eclipse.jgit.internal.storage.file.FileSnapshot;
 import org.eclipse.jgit.util.FileUtils;
 import org.junit.After;
 import org.junit.Before;
@@ -100,43 +97,6 @@ public void testActuallyIsModifiedTrivial() throws Exception {
 	}
 
 	/**
-	 * Check that file is modified by looking at its size.
-	 *
-	 * @throws Exception
-	 */
-	@Test
-	public void tesIsModifiedBySameLastModifiedAndDifferentSize() throws Exception {
-		File f1 = createFile("foo", "lorem".getBytes());
-		File f2 = createFile("bar", "lorem ipsum".getBytes());
-
-		f1.setLastModified(f2.lastModified()); // Make sure f1 and f2 have the same lastModified
-		FileSnapshot save = FileSnapshot.save(f1);
-
-		// Make sure that the modified and read timestamps are far enough, so that
-		// check is done by size
-		Thread.sleep(3000L);
-
-		assertEquals(save.lastModified(), f2.lastModified());
-		assertTrue(save.isModified(f2));
-	}
-
-	/**
-	 * Create a file, wait long enough and verify that it has not been modified.
-	 * 3.5 seconds mean any difference between file system timestamp and system
-	 * clock should be significant.
-	 *
-	 * @throws Exception
-	 */
-	@Test
-	public void testOldFile() throws Exception {
-		File f1 = createFile("oldfile");
-		waitNextSec(f1);
-		FileSnapshot save = FileSnapshot.save(f1);
-		Thread.sleep(3500);
-		assertFalse(save.isModified(f1));
-	}
-
-	/**
 	 * Create a file, but don't wait long enough for the difference between file
 	 * system clock and system clock to be significant. Assume the file may have
 	 * been modified. It may have been, but the clock alone cannot determine
@@ -174,22 +134,10 @@ private File createFile(String string) throws IOException {
 		return f;
 	}
 
-	private File createFile(String string, byte[] content) throws IOException {
-		File f = createFile(string);
-		append(f, content);
-		return f;
-	}
-
 	private static void append(File f, byte b) throws IOException {
-		append(f, new byte[] { b });
-	}
-
-	private static void append(File f, byte[] content) throws IOException {
 		FileOutputStream os = new FileOutputStream(f, true);
 		try {
-			for (byte b : content) {
-				os.write(b);
-			}
+			os.write(b);
 		} finally {
 			os.close();
 		}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcOrphanFilesTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcOrphanFilesTest.java
new file mode 100644
index 0000000..d9317b8
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcOrphanFilesTest.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2017 Ericsson
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ *   copyright notice, this list of conditions and the following
+ *   disclaimer in the documentation and/or other materials provided
+ *   with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ *   names of its contributors may be used to endorse or promote
+ *   products derived from this software without specific prior
+ *   written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.eclipse.jgit.internal.storage.file;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class GcOrphanFilesTest extends GcTestCase {
+	private final static String PACK = "pack";
+
+	private final static String BITMAP_File_1 = PACK + "-1.bitmap";
+
+	private final static String IDX_File_2 = PACK + "-2.idx";
+
+	private final static String IDX_File_malformed = PACK + "-1234idx";
+
+	private final static String PACK_File_2 = PACK + "-2.pack";
+
+	private final static String PACK_File_3 = PACK + "-3.pack";
+
+	private File packDir;
+
+	@Before
+	public void setUp() throws Exception {
+		super.setUp();
+		packDir = new File(repo.getObjectsDirectory(), PACK);
+	}
+
+	@Test
+	public void bitmapAndIdxDeletedButPackNot() throws Exception {
+		createFileInPackFolder(BITMAP_File_1);
+		createFileInPackFolder(IDX_File_2);
+		createFileInPackFolder(PACK_File_3);
+		gc.gc();
+		assertFalse(new File(packDir, BITMAP_File_1).exists());
+		assertFalse(new File(packDir, IDX_File_2).exists());
+		assertTrue(new File(packDir, PACK_File_3).exists());
+	}
+
+	@Test
+	public void bitmapDeletedButIdxAndPackNot() throws Exception {
+		createFileInPackFolder(BITMAP_File_1);
+		createFileInPackFolder(IDX_File_2);
+		createFileInPackFolder(PACK_File_2);
+		createFileInPackFolder(PACK_File_3);
+		gc.gc();
+		assertFalse(new File(packDir, BITMAP_File_1).exists());
+		assertTrue(new File(packDir, IDX_File_2).exists());
+		assertTrue(new File(packDir, PACK_File_2).exists());
+		assertTrue(new File(packDir, PACK_File_3).exists());
+	}
+
+	@Test
+	public void malformedIdxNotDeleted() throws Exception {
+		createFileInPackFolder(IDX_File_malformed);
+		gc.gc();
+		assertTrue(new File(packDir, IDX_File_malformed).exists());
+	}
+
+	private void createFileInPackFolder(String fileName) throws IOException {
+		if (!packDir.exists() || !packDir.isDirectory()) {
+			assertTrue(packDir.mkdirs());
+		}
+		assertTrue(new File(packDir, fileName).createNewFile());
+	}
+
+	@Test
+	public void noSuchPackFolder() throws Exception {
+		assertTrue(packDir.delete());
+		gc.gc();
+	}
+}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcTestCase.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcTestCase.java
index e463285..90c1152 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcTestCase.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcTestCase.java
@@ -105,6 +105,46 @@ protected RevCommit commitChain(int depth) throws Exception {
 		return tip;
 	}
 
+	/**
+	 * Create a chain of commits of given depth with given number of added files
+	 * per commit.
+	 * <p>
+	 * Each commit contains {@code files} files as its content. The created
+	 * commit chain is referenced from any ref.
+	 * <p>
+	 * A chain will create {@code (2 + files) * depth} objects in Gits object
+	 * database. For each depth level the following objects are created: the
+	 * commit object, the top-level tree object and @code files} blobs for the
+	 * content of the file "a".
+	 *
+	 * @param depth
+	 *            the depth of the commit chain.
+	 * @param width
+	 *            number of files added per commit
+	 * @return the commit that is the tip of the commit chain
+	 * @throws Exception
+	 */
+	protected RevCommit commitChain(int depth, int width) throws Exception {
+		if (depth <= 0) {
+			throw new IllegalArgumentException("Chain depth must be > 0");
+		}
+		if (width <= 0) {
+			throw new IllegalArgumentException("Number of files per commit must be > 0");
+		}
+		CommitBuilder cb = tr.commit();
+		RevCommit tip = null;
+		do {
+			--depth;
+			for (int i=0; i < width; i++) {
+				String id = depth + "-" + i;
+				cb.add("a" + id, id).message(id);
+			}
+			tip = cb.create();
+			cb = cb.child();
+		} while (depth > 0);
+		return tip;
+	}
+
 	protected long lastModified(AnyObjectId objectId) throws IOException {
 		return repo.getFS().lastModified(
 				repo.getObjectDatabase().fileFor(objectId));
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/InflatingBitSetTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/InflatingBitSetTest.java
index 465c61b..2124b80 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/InflatingBitSetTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/InflatingBitSetTest.java
@@ -46,11 +46,10 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
-import com.googlecode.javaewah.EWAHCompressedBitmap;
-
-import org.eclipse.jgit.internal.storage.file.InflatingBitSet;
 import org.junit.Test;
 
+import com.googlecode.javaewah.EWAHCompressedBitmap;
+
 public class InflatingBitSetTest {
 
 	@Test
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/LockFileTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/LockFileTest.java
index f1bc7c8..3bfd047 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/LockFileTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/LockFileTest.java
@@ -49,7 +49,6 @@
 import org.eclipse.jgit.api.Git;
 import org.eclipse.jgit.api.errors.JGitInternalException;
 import org.eclipse.jgit.errors.LockFailedException;
-import org.eclipse.jgit.internal.storage.file.LockFile;
 import org.eclipse.jgit.junit.RepositoryTestCase;
 import org.eclipse.jgit.revwalk.RevCommit;
 import org.junit.Test;
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ObjectDirectoryTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ObjectDirectoryTest.java
index 923f283..87554ae 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ObjectDirectoryTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ObjectDirectoryTest.java
@@ -42,6 +42,11 @@
 
 package org.eclipse.jgit.internal.storage.file;
 
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.FilenameFilter;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.concurrent.Callable;
@@ -49,10 +54,13 @@
 import java.util.concurrent.Executors;
 import java.util.concurrent.Future;
 
-import org.eclipse.jgit.internal.storage.file.ObjectDirectory;
 import org.eclipse.jgit.junit.RepositoryTestCase;
+import org.eclipse.jgit.lib.ConfigConstants;
 import org.eclipse.jgit.lib.Constants;
 import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.storage.file.FileBasedConfig;
+import org.junit.Assume;
 import org.junit.Test;
 
 public class ObjectDirectoryTest extends RepositoryTestCase {
@@ -69,6 +77,100 @@ public void testConcurrentInsertionOfBlobsToTheSameNewFanOutDirectory()
 		}
 	}
 
+	/**
+	 * Test packfile scanning while a gc is done from the outside (different
+	 * process or different Repository instance). This situation occurs e.g. if
+	 * a gerrit server is serving fetch requests while native git is doing a
+	 * garbage collection. The test shows that when core.trustfolderstat==true
+	 * jgit may miss to detect that a new packfile was created. This situation
+	 * is persistent until a new full rescan of the pack directory is triggered.
+	 *
+	 * The test works with two Repository instances working on the same disk
+	 * location. One (db) for all write operations (creating commits, doing gc)
+	 * and another one (receivingDB) which just reads and which in the end shows
+	 * the bug
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void testScanningForPackfiles() throws Exception {
+		ObjectId unknownID = ObjectId
+				.fromString("c0ffee09d0b63d694bf49bc1e6847473f42d4a8c");
+		GC gc = new GC(db);
+		gc.setExpireAgeMillis(0);
+		gc.setPackExpireAgeMillis(0);
+
+		// the default repo db is used to create the objects. The receivingDB
+		// repo is used to trigger gc's
+		try (FileRepository receivingDB = new FileRepository(
+				db.getDirectory())) {
+			// set trustfolderstat to true. If set to false the test always
+			// succeeds.
+			FileBasedConfig cfg = receivingDB.getConfig();
+			cfg.setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null,
+					ConfigConstants.CONFIG_KEY_TRUSTFOLDERSTAT, true);
+			cfg.save();
+
+			// setup a repo which has at least one pack file and trigger
+			// scanning of the packs directory
+			ObjectId id = commitFile("file.txt", "test", "master").getId();
+			gc.gc();
+			assertFalse(receivingDB.hasObject(unknownID));
+			assertTrue(receivingDB.getObjectDatabase().hasPackedObject(id));
+
+			// preparations
+			File packsFolder = new File(receivingDB.getObjectsDirectory(),
+					"pack");
+			// prepare creation of a temporary file in the pack folder. This
+			// simulates that a native git gc is happening starting to write
+			// temporary files but has not yet finished
+			File tmpFile = new File(packsFolder, "1.tmp");
+			RevCommit id2 = commitFile("file.txt", "test2", "master");
+			// wait until filesystem timer ticks. This raises probability that
+			// the next statements are executed in the same tick as the
+			// filesystem timer
+			fsTick(null);
+
+			// create a Temp file in the packs folder and trigger a rescan of
+			// the packs folder. This lets receivingDB think it has scanned the
+			// packs folder at the current fs timestamp t1. The following gc
+			// will create new files which have the same timestamp t1 but this
+			// will not update the mtime of the packs folder. Because of that
+			// JGit will not rescan the packs folder later on and fails to see
+			// the pack file created during gc.
+			assertTrue(tmpFile.createNewFile());
+			assertFalse(receivingDB.hasObject(unknownID));
+
+			// trigger a gc. This will create packfiles which have likely the
+			// same mtime than the packfolder
+			gc.gc();
+
+			// To deal with racy-git situations JGit's Filesnapshot class will
+			// report a file/folder potentially dirty if
+			// cachedLastReadTime-cachedLastModificationTime < 2500ms. This
+			// causes JGit to always rescan a file after modification. But:
+			// this was true only if the difference between current system time
+			// and cachedLastModification time was less than 2500ms. If the
+			// modification is more than 2500ms ago we may have reported a
+			// file/folder to be clean although it has not been rescanned. A
+			// Bug. To show the bug we sleep for more than 2500ms
+			Thread.sleep(2600);
+
+			File[] ret = packsFolder.listFiles(new FilenameFilter() {
+				@Override
+				public boolean accept(File dir, String name) {
+					return name.endsWith(".pack");
+				}
+			});
+			assertTrue(ret.length == 1);
+			Assume.assumeTrue(tmpFile.lastModified() == ret[0].lastModified());
+
+			// all objects are in a new packfile but we will not detect it
+			assertFalse(receivingDB.hasObject(unknownID));
+			assertTrue(receivingDB.hasObject(id2));
+		}
+	}
+
 	private Collection<Callable<ObjectId>> blobInsertersForTheSameFanOutDir(
 			final ObjectDirectory dir) {
 		Callable<ObjectId> callable = new Callable<ObjectId>() {
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackFileTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackFileTest.java
index ba07d68..1c10bb3 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackFileTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackFileTest.java
@@ -310,6 +310,27 @@ public void testDelta_FailsOver2GiB() throws Exception {
 		}
 	}
 
+	@Test
+	public void testConfigurableStreamFileThreshold() throws Exception {
+		byte[] data = getRng().nextBytes(300);
+		RevBlob id = tr.blob(data);
+		tr.branch("master").commit().add("A", id).create();
+		tr.packAndPrune();
+		assertTrue("has blob", wc.has(id));
+
+		ObjectLoader ol = wc.open(id);
+		ObjectStream in = ol.openStream();
+		assertTrue(in instanceof ObjectStream.SmallStream);
+		assertEquals(300, in.available());
+		in.close();
+
+		wc.setStreamFileThreshold(299);
+		ol = wc.open(id);
+		in = ol.openStream();
+		assertTrue(in instanceof ObjectStream.Filter);
+		assertEquals(1, in.available());
+	}
+
 	private static byte[] clone(int first, byte[] base) {
 		byte[] r = new byte[base.length];
 		System.arraycopy(base, 1, r, 1, r.length - 1);
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackIndexTestCase.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackIndexTestCase.java
index 7eeb0c0..b6aa4bc 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackIndexTestCase.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackIndexTestCase.java
@@ -52,7 +52,6 @@
 import java.util.NoSuchElementException;
 
 import org.eclipse.jgit.errors.MissingObjectException;
-import org.eclipse.jgit.internal.storage.file.PackIndex;
 import org.eclipse.jgit.internal.storage.file.PackIndex.MutableEntry;
 import org.eclipse.jgit.junit.RepositoryTestCase;
 import org.junit.Test;
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackReverseIndexTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackReverseIndexTest.java
index 2126cac..a4aa8bc 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackReverseIndexTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackReverseIndexTest.java
@@ -50,8 +50,6 @@
 import static org.junit.Assert.fail;
 
 import org.eclipse.jgit.errors.CorruptObjectException;
-import org.eclipse.jgit.internal.storage.file.PackIndex;
-import org.eclipse.jgit.internal.storage.file.PackReverseIndex;
 import org.eclipse.jgit.internal.storage.file.PackIndex.MutableEntry;
 import org.eclipse.jgit.junit.JGitTestUtil;
 import org.eclipse.jgit.junit.RepositoryTestCase;
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 3cb4c39..2e57952 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
@@ -43,13 +43,13 @@
 
 package org.eclipse.jgit.internal.storage.file;
 
+import static org.eclipse.jgit.internal.storage.pack.PackWriter.NONE;
 import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
-import static org.eclipse.jgit.internal.storage.pack.PackWriter.NONE;
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
@@ -75,8 +75,8 @@
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.ObjectIdSet;
 import org.eclipse.jgit.lib.ObjectInserter;
-import org.eclipse.jgit.lib.Sets;
 import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.Sets;
 import org.eclipse.jgit.revwalk.DepthWalk;
 import org.eclipse.jgit.revwalk.ObjectWalk;
 import org.eclipse.jgit.revwalk.RevBlob;
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/RefDirectoryTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/RefDirectoryTest.java
index ef5dfcd..5999acf 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/RefDirectoryTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/RefDirectoryTest.java
@@ -73,8 +73,8 @@
 import org.eclipse.jgit.junit.TestRepository;
 import org.eclipse.jgit.lib.AnyObjectId;
 import org.eclipse.jgit.lib.BatchRefUpdate;
-import org.eclipse.jgit.lib.ProgressMonitor;
 import org.eclipse.jgit.lib.NullProgressMonitor;
+import org.eclipse.jgit.lib.ProgressMonitor;
 import org.eclipse.jgit.lib.Ref;
 import org.eclipse.jgit.lib.Ref.Storage;
 import org.eclipse.jgit.lib.RefDatabase;
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 b6ad22b..ae1e531 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
@@ -82,9 +82,13 @@
 import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
 import org.eclipse.jgit.test.resources.SampleDataRepositoryTestCase;
 import org.eclipse.jgit.util.FileUtils;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
 public class T0003_BasicTest extends SampleDataRepositoryTestCase {
+	@Rule
+	public ExpectedException expectedException = ExpectedException.none();
 
 	@Test
 	public void test001_Initalize() {
@@ -326,6 +330,17 @@ public void test002_WriteEmptyTree2() throws IOException {
 	}
 
 	@Test
+	public void test002_CreateBadTree() throws Exception {
+		// We won't create a tree entry with an empty filename
+		//
+		expectedException.expect(IllegalArgumentException.class);
+		expectedException.expectMessage(JGitText.get().invalidTreeZeroLengthName);
+		final TreeFormatter formatter = new TreeFormatter();
+		formatter.append("", FileMode.TREE,
+				ObjectId.fromString("4b825dc642cb6eb9a060e54bf8d69288fbee4904"));
+	}
+
+	@Test
 	public void test006_ReadUglyConfig() throws IOException,
 			ConfigInvalidException {
 		final File cfg = new File(db.getDirectory(), Constants.CONFIG);
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/pack/DeltaIndexTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/pack/DeltaIndexTest.java
index bb94a37..640203d 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/pack/DeltaIndexTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/pack/DeltaIndexTest.java
@@ -51,9 +51,6 @@
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 
-import org.eclipse.jgit.internal.storage.pack.BinaryDelta;
-import org.eclipse.jgit.internal.storage.pack.DeltaEncoder;
-import org.eclipse.jgit.internal.storage.pack.DeltaIndex;
 import org.eclipse.jgit.junit.JGitTestUtil;
 import org.eclipse.jgit.junit.TestRng;
 import org.eclipse.jgit.lib.Constants;
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/pack/GcCommitSelectionTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/pack/GcCommitSelectionTest.java
index 49e1f6f..20b8c51 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/pack/GcCommitSelectionTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/pack/GcCommitSelectionTest.java
@@ -55,8 +55,6 @@
 
 import org.eclipse.jgit.internal.storage.file.GcTestCase;
 import org.eclipse.jgit.internal.storage.file.PackBitmapIndexBuilder;
-import org.eclipse.jgit.internal.storage.pack.ObjectToPack;
-import org.eclipse.jgit.internal.storage.pack.PackWriterBitmapPreparer;
 import org.eclipse.jgit.internal.storage.pack.PackWriterBitmapPreparer.BitmapCommit;
 import org.eclipse.jgit.junit.TestRepository.BranchBuilder;
 import org.eclipse.jgit.junit.TestRepository.CommitBuilder;
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConstantsEncodingTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConstantsEncodingTest.java
index 4db6f6d..5c2fddd 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConstantsEncodingTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConstantsEncodingTest.java
@@ -48,6 +48,7 @@
 import static org.junit.Assert.fail;
 
 import java.io.UnsupportedEncodingException;
+
 import org.junit.Test;
 
 public class ConstantsEncodingTest {
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/DirCacheCheckoutMaliciousPathTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/DirCacheCheckoutMaliciousPathTest.java
index 59a4699..32a1ec9 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/DirCacheCheckoutMaliciousPathTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/DirCacheCheckoutMaliciousPathTest.java
@@ -366,7 +366,9 @@ private void testMaliciousPath(boolean good, boolean secondCheckout,
 			insertId = blobId;
 			for (int i = path.length - 1; i >= 0; --i) {
 				TreeFormatter treeFormatter = new TreeFormatter();
-				treeFormatter.append(path[i], mode, insertId);
+				treeFormatter.append(path[i].getBytes(), 0,
+							path[i].getBytes().length,
+							mode, insertId, true);
 				insertId = newObjectInserter.insert(treeFormatter);
 				mode = FileMode.TREE;
 			}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ObjectIdTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ObjectIdTest.java
index 2198b87..80ece1c 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ObjectIdTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ObjectIdTest.java
@@ -50,7 +50,6 @@
 import static org.junit.Assert.assertTrue;
 
 import org.eclipse.jgit.errors.InvalidObjectIdException;
-
 import org.junit.Test;
 
 public class ObjectIdTest {
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/MergeMessageFormatterTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/MergeMessageFormatterTest.java
index 6c90f7d..f271544 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/MergeMessageFormatterTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/MergeMessageFormatterTest.java
@@ -50,9 +50,9 @@
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.ObjectIdRef;
 import org.eclipse.jgit.lib.Ref;
-import org.eclipse.jgit.lib.SymbolicRef;
 import org.eclipse.jgit.lib.Ref.Storage;
 import org.eclipse.jgit.lib.RefUpdate;
+import org.eclipse.jgit.lib.SymbolicRef;
 import org.eclipse.jgit.test.resources.SampleDataRepositoryTestCase;
 import org.junit.Before;
 import org.junit.Test;
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/patch/PatchCcErrorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/patch/PatchCcErrorTest.java
index 962e818..e4b4317 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/patch/PatchCcErrorTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/patch/PatchCcErrorTest.java
@@ -44,7 +44,6 @@
 package org.eclipse.jgit.patch;
 
 import static java.lang.Integer.valueOf;
-import static java.lang.Long.valueOf;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/FooterLineTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/FooterLineTest.java
index fbd5127..87c8547 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/FooterLineTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/FooterLineTest.java
@@ -48,6 +48,7 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+
 import java.io.IOException;
 import java.util.List;
 
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/ObjectWalkFilterTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/ObjectWalkFilterTest.java
index 55117b7..75ac561 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/ObjectWalkFilterTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/ObjectWalkFilterTest.java
@@ -46,22 +46,20 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
+import java.io.IOException;
+import java.util.Set;
 
 import org.eclipse.jgit.internal.storage.dfs.DfsRepositoryDescription;
 import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
 import org.eclipse.jgit.junit.TestRepository;
 import org.eclipse.jgit.lib.AnyObjectId;
 import org.eclipse.jgit.lib.Sets;
-import org.eclipse.jgit.revwalk.ObjectWalk;
 import org.eclipse.jgit.revwalk.filter.MessageRevFilter;
 import org.eclipse.jgit.revwalk.filter.NotRevFilter;
 import org.eclipse.jgit.revwalk.filter.ObjectFilter;
-
-import java.io.IOException;
-import java.util.Set;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
 
 public class ObjectWalkFilterTest {
 	private TestRepository<InMemoryRepository> tr;
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkMergeBaseTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkMergeBaseTest.java
index b5d4909..2451c50 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkMergeBaseTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkMergeBaseTest.java
@@ -146,4 +146,29 @@ public void testCrissCross() throws Exception {
 		assertCommit(b, rw.next());
 		assertNull(rw.next());
 	}
-}
+
+	@Test
+	public void testInconsistentCommitTimes() throws Exception {
+		// When commit times are inconsistent (a parent is younger than a child)
+		// make sure that not both, parent and child, are reported as merge
+		// base. In the following repo the merge base between C,D should be B.
+		// But when A is younger than B the MergeBaseGenerator used to generate
+		// A before it detected that B is also a merge base.
+		//
+		//   +---C
+		//  /   /
+		// A---B---D
+
+		final RevCommit a = commit(2);
+		final RevCommit b = commit(-1, a);
+		final RevCommit c = commit(2, b, a);
+		final RevCommit d = commit(1, b);
+
+		rw.setRevFilter(RevFilter.MERGE_BASE);
+		markStart(d);
+		markStart(c);
+		assertCommit(b, rw.next());
+		assertNull(rw.next());
+	}
+
+}
\ No newline at end of file
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/test/resources/SampleDataRepositoryTestCase.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/test/resources/SampleDataRepositoryTestCase.java
index 3a3b3d8..a57ef40 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/test/resources/SampleDataRepositoryTestCase.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/test/resources/SampleDataRepositoryTestCase.java
@@ -47,7 +47,9 @@
 package org.eclipse.jgit.test.resources;
 
 import java.io.File;
+import java.io.IOException;
 
+import org.eclipse.jgit.internal.storage.file.FileRepository;
 import org.eclipse.jgit.junit.JGitTestUtil;
 import org.eclipse.jgit.junit.RepositoryTestCase;
 
@@ -57,7 +59,17 @@ public abstract class SampleDataRepositoryTestCase extends RepositoryTestCase {
 	@Override
 	public void setUp() throws Exception {
 		super.setUp();
+		copyCGitTestPacks(db);
+	}
 
+	/**
+	 * Copy C Git generated pack files into given repository for testing
+	 *
+	 * @param repo
+	 *            test repository to receive packfile copies
+	 * @throws IOException
+	 */
+	public static void copyCGitTestPacks(FileRepository repo) throws IOException {
 		final String[] packs = {
 				"pack-34be9032ac282b11fa9babdc2b2a93ca996c9c2f",
 				"pack-df2982f284bbabb6bdb59ee3fcc6eb0983e20371",
@@ -67,13 +79,14 @@ public void setUp() throws Exception {
 				"pack-e6d07037cbcf13376308a0a995d1fa48f8f76aaa",
 				"pack-3280af9c07ee18a87705ef50b0cc4cd20266cf12"
 		};
-		final File packDir = new File(db.getObjectDatabase().getDirectory(), "pack");
+		final File packDir = new File(repo.getObjectDatabase().getDirectory(),
+				"pack");
 		for (String n : packs) {
 			JGitTestUtil.copyTestResource(n + ".pack", new File(packDir, n + ".pack"));
 			JGitTestUtil.copyTestResource(n + ".idx", new File(packDir, n + ".idx"));
 		}
 
 		JGitTestUtil.copyTestResource("packed-refs",
-				new File(db.getDirectory(), "packed-refs"));
+				new File(repo.getDirectory(), "packed-refs"));
 	}
 }
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/SideBandOutputStreamTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/SideBandOutputStreamTest.java
index d2c3a0b..4571619 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/SideBandOutputStreamTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/SideBandOutputStreamTest.java
@@ -44,7 +44,6 @@
 package org.eclipse.jgit.transport;
 
 import static java.lang.Integer.valueOf;
-import static java.lang.Long.valueOf;
 import static org.eclipse.jgit.transport.SideBandOutputStream.CH_DATA;
 import static org.eclipse.jgit.transport.SideBandOutputStream.CH_ERROR;
 import static org.eclipse.jgit.transport.SideBandOutputStream.CH_PROGRESS;
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/WalkEncryptionTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/WalkEncryptionTest.java
index ac2bfd1..cc5870e 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/WalkEncryptionTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/WalkEncryptionTest.java
@@ -576,7 +576,7 @@ static void policySetup(boolean restrictedOn) {
 						.forName("javax.crypto.JceSecurity")
 						.getDeclaredField("isRestricted");
 				isRestricted.setAccessible(true);
-				isRestricted.set(null, new Boolean(restrictedOn));
+				isRestricted.set(null, Boolean.valueOf(restrictedOn));
 			} catch (Throwable e) {
 				logger.info(
 						"Could not setup JCE security policy restrictions.");
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FilterCommandsTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FilterCommandsTest.java
new file mode 100644
index 0000000..0d31811
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FilterCommandsTest.java
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2016, Christian Halstrick <christian.halstrick@sap.com>
+ * 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.util;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.errors.GitAPIException;
+import org.eclipse.jgit.attributes.FilterCommand;
+import org.eclipse.jgit.attributes.FilterCommandFactory;
+import org.eclipse.jgit.attributes.FilterCommandRegistry;
+import org.eclipse.jgit.junit.RepositoryTestCase;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.RefUpdate;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.StoredConfig;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.junit.Before;
+import org.junit.Test;
+
+public class FilterCommandsTest extends RepositoryTestCase {
+	private Git git;
+
+	RevCommit initialCommit;
+
+	RevCommit secondCommit;
+
+	class TestCommandFactory implements FilterCommandFactory {
+		private int prefix;
+
+		public TestCommandFactory(int prefix) {
+			this.prefix = prefix;
+		}
+
+		@Override
+		public FilterCommand create(Repository repo, InputStream in,
+				final OutputStream out) {
+			FilterCommand cmd = new FilterCommand(in, out) {
+
+				@Override
+				public int run() throws IOException {
+					int b = in.read();
+					if (b == -1) {
+						return b;
+					}
+					out.write(prefix);
+					out.write(b);
+					return 1;
+				}
+			};
+			return cmd;
+		}
+	}
+
+	@Override
+	@Before
+	public void setUp() throws Exception {
+		super.setUp();
+		git = new Git(db);
+		// commit something
+		writeTrashFile("Test.txt", "Hello world");
+		git.add().addFilepattern("Test.txt").call();
+		initialCommit = git.commit().setMessage("Initial commit").call();
+
+		// create a master branch and switch to it
+		git.branchCreate().setName("test").call();
+		RefUpdate rup = db.updateRef(Constants.HEAD);
+		rup.link("refs/heads/test");
+
+		// commit something on the test branch
+		writeTrashFile("Test.txt", "Some change");
+		git.add().addFilepattern("Test.txt").call();
+		secondCommit = git.commit().setMessage("Second commit").call();
+	}
+
+	@Test
+	public void testBuiltinCleanFilter()
+			throws IOException, GitAPIException {
+		String builtinCommandName = "jgit://builtin/test/clean";
+		FilterCommandRegistry.register(builtinCommandName,
+				new TestCommandFactory('c'));
+		StoredConfig config = git.getRepository().getConfig();
+		config.setString("filter", "test", "clean", builtinCommandName);
+		config.save();
+
+		writeTrashFile(".gitattributes", "*.txt filter=test");
+		git.add().addFilepattern(".gitattributes").call();
+		git.commit().setMessage("add filter").call();
+
+		writeTrashFile("Test.txt", "Hello again");
+		git.add().addFilepattern("Test.txt").call();
+		assertEquals(
+				"[.gitattributes, mode:100644, content:*.txt filter=test][Test.txt, mode:100644, content:cHceclclcoc cacgcacicn]",
+				indexState(CONTENT));
+
+		writeTrashFile("Test.bin", "Hello again");
+		git.add().addFilepattern("Test.bin").call();
+		assertEquals(
+				"[.gitattributes, mode:100644, content:*.txt filter=test][Test.bin, mode:100644, content:Hello again][Test.txt, mode:100644, content:cHceclclcoc cacgcacicn]",
+				indexState(CONTENT));
+
+		config.setString("filter", "test", "clean", null);
+		config.save();
+
+		git.add().addFilepattern("Test.txt").call();
+		assertEquals(
+				"[.gitattributes, mode:100644, content:*.txt filter=test][Test.bin, mode:100644, content:Hello again][Test.txt, mode:100644, content:Hello again]",
+				indexState(CONTENT));
+
+		config.setString("filter", "test", "clean", null);
+		config.save();
+	}
+
+	@Test
+	public void testBuiltinSmudgeFilter() throws IOException, GitAPIException {
+		String builtinCommandName = "jgit://builtin/test/smudge";
+		FilterCommandRegistry.register(builtinCommandName,
+				new TestCommandFactory('s'));
+		StoredConfig config = git.getRepository().getConfig();
+		config.setString("filter", "test", "smudge", builtinCommandName);
+		config.save();
+
+		writeTrashFile(".gitattributes", "*.txt filter=test");
+		git.add().addFilepattern(".gitattributes").call();
+		git.commit().setMessage("add filter").call();
+
+		writeTrashFile("Test.txt", "Hello again");
+		git.add().addFilepattern("Test.txt").call();
+		assertEquals(
+				"[.gitattributes, mode:100644, content:*.txt filter=test][Test.txt, mode:100644, content:Hello again]",
+				indexState(CONTENT));
+		assertEquals("Hello again", read("Test.txt"));
+		deleteTrashFile("Test.txt");
+		git.checkout().addPath("Test.txt").call();
+		assertEquals("sHseslslsos sasgsasisn", read("Test.txt"));
+
+		writeTrashFile("Test.bin", "Hello again");
+		git.add().addFilepattern("Test.bin").call();
+		assertEquals(
+				"[.gitattributes, mode:100644, content:*.txt filter=test][Test.bin, mode:100644, content:Hello again][Test.txt, mode:100644, content:Hello again]",
+				indexState(CONTENT));
+		deleteTrashFile("Test.bin");
+		git.checkout().addPath("Test.bin").call();
+		assertEquals("Hello again", read("Test.bin"));
+
+		config.setString("filter", "test", "clean", null);
+		config.save();
+
+		git.add().addFilepattern("Test.txt").call();
+		assertEquals(
+				"[.gitattributes, mode:100644, content:*.txt filter=test][Test.bin, mode:100644, content:Hello again][Test.txt, mode:100644, content:sHseslslsos sasgsasisn]",
+				indexState(CONTENT));
+
+		config.setString("filter", "test", "clean", null);
+		config.save();
+	}
+
+	@Test
+	public void testBuiltinCleanAndSmudgeFilter() throws IOException, GitAPIException {
+		String builtinCommandPrefix = "jgit://builtin/test/";
+		FilterCommandRegistry.register(builtinCommandPrefix + "smudge",
+				new TestCommandFactory('s'));
+		FilterCommandRegistry.register(builtinCommandPrefix + "clean",
+				new TestCommandFactory('c'));
+		StoredConfig config = git.getRepository().getConfig();
+		config.setString("filter", "test", "smudge", builtinCommandPrefix+"smudge");
+		config.setString("filter", "test", "clean",
+				builtinCommandPrefix + "clean");
+		config.save();
+
+		writeTrashFile(".gitattributes", "*.txt filter=test");
+		git.add().addFilepattern(".gitattributes").call();
+		git.commit().setMessage("add filter").call();
+
+		writeTrashFile("Test.txt", "Hello again");
+		git.add().addFilepattern("Test.txt").call();
+		assertEquals(
+				"[.gitattributes, mode:100644, content:*.txt filter=test][Test.txt, mode:100644, content:cHceclclcoc cacgcacicn]",
+				indexState(CONTENT));
+		assertEquals("Hello again", read("Test.txt"));
+		deleteTrashFile("Test.txt");
+		git.checkout().addPath("Test.txt").call();
+		assertEquals("scsHscsescslscslscsoscs scsascsgscsascsiscsn",
+				read("Test.txt"));
+
+		writeTrashFile("Test.bin", "Hello again");
+		git.add().addFilepattern("Test.bin").call();
+		assertEquals(
+				"[.gitattributes, mode:100644, content:*.txt filter=test][Test.bin, mode:100644, content:Hello again][Test.txt, mode:100644, content:cHceclclcoc cacgcacicn]",
+				indexState(CONTENT));
+		deleteTrashFile("Test.bin");
+		git.checkout().addPath("Test.bin").call();
+		assertEquals("Hello again", read("Test.bin"));
+
+		config.setString("filter", "test", "clean", null);
+		config.save();
+
+		git.add().addFilepattern("Test.txt").call();
+		assertEquals(
+				"[.gitattributes, mode:100644, content:*.txt filter=test][Test.bin, mode:100644, content:Hello again][Test.txt, mode:100644, content:scsHscsescslscslscsoscs scsascsgscsascsiscsn]",
+				indexState(CONTENT));
+
+		config.setString("filter", "test", "clean", null);
+		config.save();
+	}
+
+}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/RelativeDateFormatterTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/RelativeDateFormatterTest.java
index 2901c93..76687d1 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/RelativeDateFormatterTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/RelativeDateFormatterTest.java
@@ -42,17 +42,16 @@
  */
 package org.eclipse.jgit.util;
 
-import static org.junit.Assert.assertEquals;
-import static org.eclipse.jgit.util.RelativeDateFormatter.YEAR_IN_MILLIS;
-import static org.eclipse.jgit.util.RelativeDateFormatter.SECOND_IN_MILLIS;
-import static org.eclipse.jgit.util.RelativeDateFormatter.MINUTE_IN_MILLIS;
-import static org.eclipse.jgit.util.RelativeDateFormatter.HOUR_IN_MILLIS;
 import static org.eclipse.jgit.util.RelativeDateFormatter.DAY_IN_MILLIS;
+import static org.eclipse.jgit.util.RelativeDateFormatter.HOUR_IN_MILLIS;
+import static org.eclipse.jgit.util.RelativeDateFormatter.MINUTE_IN_MILLIS;
+import static org.eclipse.jgit.util.RelativeDateFormatter.SECOND_IN_MILLIS;
+import static org.eclipse.jgit.util.RelativeDateFormatter.YEAR_IN_MILLIS;
+import static org.junit.Assert.assertEquals;
 
 import java.util.Date;
 
 import org.eclipse.jgit.junit.MockSystemReader;
-import org.eclipse.jgit.util.RelativeDateFormatter;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
diff --git a/org.eclipse.jgit.ui/.classpath b/org.eclipse.jgit.ui/.classpath
index a14ade4..110168f 100644
--- a/org.eclipse.jgit.ui/.classpath
+++ b/org.eclipse.jgit.ui/.classpath
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
 	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
 	<classpathentry kind="src" path="src"/>
 	<classpathentry kind="src" path="resources"/>
diff --git a/org.eclipse.jgit.ui/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit.ui/.settings/org.eclipse.jdt.core.prefs
index 1ce7cd0..808ec3a 100644
--- a/org.eclipse.jgit.ui/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit.ui/.settings/org.eclipse.jdt.core.prefs
@@ -7,9 +7,9 @@
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.compliance=1.8
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -112,7 +112,7 @@
 org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
-org.eclipse.jdt.core.compiler.source=1.7
+org.eclipse.jdt.core.compiler.source=1.8
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
diff --git a/org.eclipse.jgit.ui/META-INF/MANIFEST.MF b/org.eclipse.jgit.ui/META-INF/MANIFEST.MF
index c89f37d..667e3b2 100644
--- a/org.eclipse.jgit.ui/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.ui/META-INF/MANIFEST.MF
@@ -3,14 +3,14 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %plugin_name
 Bundle-SymbolicName: org.eclipse.jgit.ui
-Bundle-Version: 4.5.7.qualifier
+Bundle-Version: 4.6.2.qualifier
 Bundle-Vendor: %provider_name
-Bundle-RequiredExecutionEnvironment: JavaSE-1.7
-Export-Package: org.eclipse.jgit.awtui;version="4.5.7"
-Import-Package: org.eclipse.jgit.errors;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.lib;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.nls;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.revplot;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.revwalk;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.transport;version="[4.5.7,4.6.0)",
- org.eclipse.jgit.util;version="[4.5.7,4.6.0)"
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Export-Package: org.eclipse.jgit.awtui;version="4.6.2"
+Import-Package: org.eclipse.jgit.errors;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.lib;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.nls;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.revplot;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.revwalk;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.transport;version="[4.6.2,4.7.0)",
+ org.eclipse.jgit.util;version="[4.6.2,4.7.0)"
diff --git a/org.eclipse.jgit.ui/pom.xml b/org.eclipse.jgit.ui/pom.xml
index c7e8a9d..280399b 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>4.5.7-SNAPSHOT</version>
+    <version>4.6.2-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.ui</artifactId>
diff --git a/org.eclipse.jgit/.classpath b/org.eclipse.jgit/.classpath
index 04a2be7..cfcf24a 100644
--- a/org.eclipse.jgit/.classpath
+++ b/org.eclipse.jgit/.classpath
@@ -2,7 +2,7 @@
 <classpath>
 	<classpathentry kind="src" path="src"/>
 	<classpathentry kind="src" path="resources"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
 	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>
diff --git a/org.eclipse.jgit/.settings/.api_filters b/org.eclipse.jgit/.settings/.api_filters
index fe83211..c74a500 100644
--- a/org.eclipse.jgit/.settings/.api_filters
+++ b/org.eclipse.jgit/.settings/.api_filters
@@ -3,8 +3,66 @@
     <resource path="META-INF/MANIFEST.MF">
         <filter id="924844039">
             <message_arguments>
-                <message_argument value="4.5.4"/>
-                <message_argument value="4.5.0"/>
+                <message_argument value="4.6.2"/>
+                <message_argument value="4.6.0"/>
+            </message_arguments>
+        </filter>
+    </resource>
+    <resource path="src/org/eclipse/jgit/errors/NoPackSignatureException.java" type="org.eclipse.jgit.errors.NoPackSignatureException">
+        <filter id="1108344834">
+            <message_arguments>
+                <message_argument value="4.5"/>
+                <message_argument value="4.6"/>
+                <message_argument value="org.eclipse.jgit.errors.NoPackSignatureException"/>
+            </message_arguments>
+        </filter>
+    </resource>
+    <resource path="src/org/eclipse/jgit/errors/UnsupportedPackIndexVersionException.java" type="org.eclipse.jgit.errors.UnsupportedPackIndexVersionException">
+        <filter id="1108344834">
+            <message_arguments>
+                <message_argument value="4.5"/>
+                <message_argument value="4.6"/>
+                <message_argument value="org.eclipse.jgit.errors.UnsupportedPackIndexVersionException"/>
+            </message_arguments>
+        </filter>
+    </resource>
+    <resource path="src/org/eclipse/jgit/errors/UnsupportedPackVersionException.java" type="org.eclipse.jgit.errors.UnsupportedPackVersionException">
+        <filter id="1108344834">
+            <message_arguments>
+                <message_argument value="4.5"/>
+                <message_argument value="4.6"/>
+                <message_argument value="org.eclipse.jgit.errors.UnsupportedPackVersionException"/>
+            </message_arguments>
+        </filter>
+    </resource>
+    <resource path="src/org/eclipse/jgit/lib/ConfigConstants.java" type="org.eclipse.jgit.lib.ConfigConstants">
+        <filter id="336658481">
+            <message_arguments>
+                <message_argument value="org.eclipse.jgit.lib.ConfigConstants"/>
+                <message_argument value="CONFIG_KEY_SUPPORTSATOMICFILECREATION"/>
+            </message_arguments>
+        </filter>
+        <filter id="1141899266">
+            <message_arguments>
+                <message_argument value="4.5"/>
+                <message_argument value="4.6"/>
+                <message_argument value="CONFIG_KEY_SUPPORTSATOMICFILECREATION"/>
+            </message_arguments>
+        </filter>
+    </resource>
+    <resource path="src/org/eclipse/jgit/util/FS.java" type="org.eclipse.jgit.util.FS">
+        <filter id="1141899266">
+            <message_arguments>
+                <message_argument value="4.5"/>
+                <message_argument value="4.6"/>
+                <message_argument value="createNewFile(File)"/>
+            </message_arguments>
+        </filter>
+        <filter id="1141899266">
+            <message_arguments>
+                <message_argument value="4.5"/>
+                <message_argument value="4.6"/>
+                <message_argument value="supportsAtomicCreateNewFile()"/>
             </message_arguments>
         </filter>
         <filter id="924844039">
diff --git a/org.eclipse.jgit/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit/.settings/org.eclipse.jdt.core.prefs
index bfaf736..4f1759f 100644
--- a/org.eclipse.jgit/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit/.settings/org.eclipse.jdt.core.prefs
@@ -7,9 +7,9 @@
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.compliance=1.8
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -112,7 +112,7 @@
 org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
-org.eclipse.jdt.core.compiler.source=1.7
+org.eclipse.jdt.core.compiler.source=1.8
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
diff --git a/org.eclipse.jgit/META-INF/MANIFEST.MF b/org.eclipse.jgit/META-INF/MANIFEST.MF
index ea2ef79..701efcf 100644
--- a/org.eclipse.jgit/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit/META-INF/MANIFEST.MF
@@ -2,12 +2,12 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %plugin_name
 Bundle-SymbolicName: org.eclipse.jgit
-Bundle-Version: 4.5.7.qualifier
+Bundle-Version: 4.6.2.qualifier
 Bundle-Localization: plugin
 Bundle-Vendor: %provider_name
 Bundle-ActivationPolicy: lazy
-Export-Package: org.eclipse.jgit.annotations;version="4.5.7",
- org.eclipse.jgit.api;version="4.5.7";
+Export-Package: org.eclipse.jgit.annotations;version="4.6.2",
+ org.eclipse.jgit.api;version="4.6.2";
   uses:="org.eclipse.jgit.revwalk,
    org.eclipse.jgit.treewalk.filter,
    org.eclipse.jgit.diff,
@@ -21,60 +21,57 @@
    org.eclipse.jgit.submodule,
    org.eclipse.jgit.transport,
    org.eclipse.jgit.merge",
- org.eclipse.jgit.api.errors;version="4.5.7";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.errors",
- org.eclipse.jgit.attributes;version="4.5.7",
- org.eclipse.jgit.blame;version="4.5.7";
+ org.eclipse.jgit.api.errors;version="4.6.2";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.errors",
+ org.eclipse.jgit.attributes;version="4.6.2",
+ org.eclipse.jgit.blame;version="4.6.2";
   uses:="org.eclipse.jgit.lib,
    org.eclipse.jgit.revwalk,
    org.eclipse.jgit.treewalk.filter,
    org.eclipse.jgit.diff",
- org.eclipse.jgit.diff;version="4.5.7";
+ org.eclipse.jgit.diff;version="4.6.2";
   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="4.5.7";
+ org.eclipse.jgit.dircache;version="4.6.2";
   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="4.5.7";
+ org.eclipse.jgit.errors;version="4.6.2";
   uses:="org.eclipse.jgit.lib,
    org.eclipse.jgit.internal.storage.pack,
    org.eclipse.jgit.transport,
    org.eclipse.jgit.dircache",
- org.eclipse.jgit.events;version="4.5.7";uses:="org.eclipse.jgit.lib",
- org.eclipse.jgit.fnmatch;version="4.5.7",
- org.eclipse.jgit.gitrepo;version="4.5.7";
+ org.eclipse.jgit.events;version="4.6.2";uses:="org.eclipse.jgit.lib",
+ org.eclipse.jgit.fnmatch;version="4.6.2",
+ org.eclipse.jgit.gitrepo;version="4.6.2";
   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="4.5.7";x-internal:=true,
- org.eclipse.jgit.hooks;version="4.5.7";uses:="org.eclipse.jgit.lib",
- org.eclipse.jgit.ignore;version="4.5.7",
- org.eclipse.jgit.ignore.internal;version="4.5.7";x-friends:="org.eclipse.jgit.test",
- org.eclipse.jgit.internal;version="4.5.7";x-friends:="org.eclipse.jgit.test,org.eclipse.jgit.http.test",
- org.eclipse.jgit.internal.ketch;version="4.5.7";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm",
- org.eclipse.jgit.internal.storage.dfs;version="4.5.7";
-  x-friends:="org.eclipse.jgit.test,
-   org.eclipse.jgit.http.server,
-   org.eclipse.jgit.http.test",
- org.eclipse.jgit.internal.storage.file;version="4.5.7";
+ org.eclipse.jgit.gitrepo.internal;version="4.6.2";x-internal:=true,
+ org.eclipse.jgit.hooks;version="4.6.2";uses:="org.eclipse.jgit.lib",
+ org.eclipse.jgit.ignore;version="4.6.2",
+ org.eclipse.jgit.ignore.internal;version="4.6.2";x-friends:="org.eclipse.jgit.test",
+ org.eclipse.jgit.internal;version="4.6.2";x-friends:="org.eclipse.jgit.test,org.eclipse.jgit.http.test",
+ org.eclipse.jgit.internal.ketch;version="4.6.2";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm",
+ org.eclipse.jgit.internal.storage.dfs;version="4.6.2";x-friends:="org.eclipse.jgit.test,org.eclipse.jgit.http.server,org.eclipse.jgit.http.test",
+ org.eclipse.jgit.internal.storage.file;version="4.6.2";
   x-friends:="org.eclipse.jgit.test,
    org.eclipse.jgit.junit,
    org.eclipse.jgit.junit.http,
    org.eclipse.jgit.http.server,
-   org.eclipse.jgit.lfs.server,
+   org.eclipse.jgit.lfs,
    org.eclipse.jgit.pgm,
    org.eclipse.jgit.pgm.test",
- org.eclipse.jgit.internal.storage.pack;version="4.5.7";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm",
- org.eclipse.jgit.internal.storage.reftree;version="4.5.7";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm",
- org.eclipse.jgit.lib;version="4.5.7";
+ org.eclipse.jgit.internal.storage.pack;version="4.6.2";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm",
+ org.eclipse.jgit.internal.storage.reftree;version="4.6.2";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm",
+ org.eclipse.jgit.lib;version="4.6.2";
   uses:="org.eclipse.jgit.revwalk,
    org.eclipse.jgit.treewalk.filter,
    org.eclipse.jgit.util,
@@ -84,32 +81,32 @@
    org.eclipse.jgit.treewalk,
    org.eclipse.jgit.transport,
    org.eclipse.jgit.submodule",
- org.eclipse.jgit.merge;version="4.5.7";
+ org.eclipse.jgit.merge;version="4.6.2";
   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="4.5.7",
- org.eclipse.jgit.notes;version="4.5.7";
+ org.eclipse.jgit.nls;version="4.6.2",
+ org.eclipse.jgit.notes;version="4.6.2";
   uses:="org.eclipse.jgit.lib,
    org.eclipse.jgit.treewalk,
    org.eclipse.jgit.revwalk,
    org.eclipse.jgit.merge",
- org.eclipse.jgit.patch;version="4.5.7";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.diff",
- org.eclipse.jgit.revplot;version="4.5.7";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.revwalk",
- org.eclipse.jgit.revwalk;version="4.5.7";
+ org.eclipse.jgit.patch;version="4.6.2";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.diff",
+ org.eclipse.jgit.revplot;version="4.6.2";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.revwalk",
+ org.eclipse.jgit.revwalk;version="4.6.2";
   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="4.5.7";uses:="org.eclipse.jgit.revwalk,org.eclipse.jgit.lib,org.eclipse.jgit.util",
- org.eclipse.jgit.storage.file;version="4.5.7";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.util",
- org.eclipse.jgit.storage.pack;version="4.5.7";uses:="org.eclipse.jgit.lib",
- org.eclipse.jgit.submodule;version="4.5.7";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.treewalk.filter,org.eclipse.jgit.treewalk",
- org.eclipse.jgit.transport;version="4.5.7";
+ org.eclipse.jgit.revwalk.filter;version="4.6.2";uses:="org.eclipse.jgit.revwalk,org.eclipse.jgit.lib,org.eclipse.jgit.util",
+ org.eclipse.jgit.storage.file;version="4.6.2";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.util",
+ org.eclipse.jgit.storage.pack;version="4.6.2";uses:="org.eclipse.jgit.lib",
+ org.eclipse.jgit.submodule;version="4.6.2";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.treewalk.filter,org.eclipse.jgit.treewalk",
+ org.eclipse.jgit.transport;version="4.6.2";
   uses:="org.eclipse.jgit.transport.resolver,
    org.eclipse.jgit.revwalk,
    org.eclipse.jgit.internal.storage.pack,
@@ -121,24 +118,25 @@
    org.eclipse.jgit.transport.http,
    org.eclipse.jgit.errors,
    org.eclipse.jgit.storage.pack",
- org.eclipse.jgit.transport.http;version="4.5.7";uses:="javax.net.ssl",
- org.eclipse.jgit.transport.resolver;version="4.5.7";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.transport",
- org.eclipse.jgit.treewalk;version="4.5.7";
+ org.eclipse.jgit.transport.http;version="4.6.2";uses:="javax.net.ssl",
+ org.eclipse.jgit.transport.resolver;version="4.6.2";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.transport",
+ org.eclipse.jgit.treewalk;version="4.6.2";
   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="4.5.7";uses:="org.eclipse.jgit.treewalk",
- org.eclipse.jgit.util;version="4.5.7";
+ org.eclipse.jgit.treewalk.filter;version="4.6.2";uses:="org.eclipse.jgit.treewalk",
+ org.eclipse.jgit.util;version="4.6.2";
   uses:="org.eclipse.jgit.lib,
    org.eclipse.jgit.transport.http,
    org.eclipse.jgit.storage.file,
    org.ietf.jgss",
- org.eclipse.jgit.util.io;version="4.5.7"
-Bundle-RequiredExecutionEnvironment: JavaSE-1.7
-Import-Package: com.googlecode.javaewah;version="[0.7.9,0.8.0)",
+ org.eclipse.jgit.util.io;version="4.6.2",
+ org.eclipse.jgit.util.time;version="4.6.2"
+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)",
  javax.crypto,
  javax.net.ssl,
diff --git a/org.eclipse.jgit/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit/META-INF/SOURCE-MANIFEST.MF
index b88125f..c863b04 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: 4.5.7.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit;version="4.5.7.qualifier";roots="."
+Bundle-Version: 4.6.2.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit;version="4.6.2.qualifier";roots="."
diff --git a/org.eclipse.jgit/pom.xml b/org.eclipse.jgit/pom.xml
index 61646ce..4e31e0b 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>4.5.7-SNAPSHOT</version>
+    <version>4.6.2-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit</artifactId>
diff --git a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
index c949c0a..cde45cf 100644
--- a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
+++ b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
@@ -39,6 +39,7 @@
 blameNotCommittedYet=Not Committed Yet
 blobNotFound=Blob not found: {0}
 blobNotFoundForPath=Blob not found: {0} for path: {1}
+blockSizeNotPowerOf2=blockSize must be a power of 2
 branchNameInvalid=Branch name {0} is not allowed
 buildingBitmaps=Building bitmaps
 cachedPacksPreventsIndexCreation=Using cached packs prevents index creation
@@ -115,6 +116,7 @@
 checkoutUnexpectedResult=Checkout returned unexpected result {0}
 classCastNotA=Not a {0}
 cloneNonEmptyDirectory=Destination path "{0}" already exists and is not an empty directory
+closed=closed
 collisionOn=Collision on {0}
 commandRejectedByHook=Rejected by "{0}" hook.\n{1}
 commandWasCalledInTheWrongState=Command {0} was called in the wrong state
@@ -280,6 +282,7 @@
 expectedPktLineWithService=expected pkt-line with ''# service=-'', got ''{0}''
 expectedReceivedContentType=expected Content-Type {0}; received Content-Type {1}
 expectedReportForRefNotReceived={0}: expected report for ref {1} not received
+failedToDetermineFilterDefinition=An exception occured while determining filter definitions
 failedUpdatingRefs=failed updating refs
 failureDueToOneOfTheFollowing=Failure due to one of the following:
 failureUpdatingFETCH_HEAD=Failure updating FETCH_HEAD: {0}
@@ -367,6 +370,7 @@
 invalidTimeout=Invalid timeout: {0}
 invalidTimeUnitValue2=Invalid time unit value: {0}.{1}={2}
 invalidTimeUnitValue3=Invalid time unit value: {0}.{1}.{2}={3}
+invalidTreeZeroLengthName=Cannot append a tree entry with zero-length name
 invalidURL=Invalid URL {0}
 invalidWildcards=Invalid wildcards {0}
 invalidRefSpec=Invalid refspec {0}
@@ -464,6 +468,7 @@
 packedRefsHandleIsStale=packed-refs handle is stale, {0}. retry
 packetSizeMustBeAtLeast=packet size {0} must be >= {1}
 packetSizeMustBeAtMost=packet size {0} must be <= {1}
+packedRefsCorruptionDetected=packed-refs corruption detected: {0}
 packfileCorruptionDetected=Packfile corruption detected: {0}
 packFileInvalid=Pack file invalid: {0}
 packfileIsTruncated=Packfile {0} is truncated.
@@ -602,6 +607,7 @@
 tagNameInvalid=tag name {0} is invalid
 tagOnRepoWithoutHEADCurrentlyNotSupported=Tag on repository without HEAD currently not supported
 theFactoryMustNotBeNull=The factory must not be null
+timeIsUncertain=Time is uncertain
 timerAlreadyTerminated=Timer already terminated
 tooManyIncludeRecursions=Too many recursions; circular includes in config file(s)?
 topologicalSortRequired=Topological sort required.
@@ -671,6 +677,7 @@
 unsupportedOperationNotAddAtEnd=Not add-at-end: {0}
 unsupportedPackIndexVersion=Unsupported pack index version {0}
 unsupportedPackVersion=Unsupported pack version {0}.
+unsupportedRepositoryDescription=Repository description not supported
 updatingHeadFailed=Updating HEAD failed
 updatingReferences=Updating references
 updatingRefFailed=Updating the ref {0} to {1} failed. ReturnCode from RefUpdate.update() was {2}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/AddCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/AddCommand.java
index 1f37833..16ec146 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/AddCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/AddCommand.java
@@ -224,6 +224,11 @@ public DirCache call() throws GitAPIException, NoFilepatternException {
 					entry.setLength(f.getEntryLength());
 					entry.setLastModified(f.getEntryLastModified());
 					long len = f.getEntryContentLength();
+					// We read and filter the content multiple times.
+					// f.getEntryContentLength() reads and filters the input and
+					// inserter.insert(...) does it again. That's because an
+					// ObjectInserter needs to know the length before it starts
+					// inserting. TODO: Fix this by using Buffers.
 					try (InputStream in = f.openEntryStream()) {
 						ObjectId id = inserter.insert(OBJ_BLOB, len, in);
 						entry.setObjectId(id);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/BlameCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/BlameCommand.java
index d803efd..2a2e07d 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/BlameCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/BlameCommand.java
@@ -61,9 +61,9 @@
 import org.eclipse.jgit.dircache.DirCache;
 import org.eclipse.jgit.lib.AnyObjectId;
 import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.CoreConfig.AutoCRLF;
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.lib.CoreConfig.AutoCRLF;
 import org.eclipse.jgit.treewalk.WorkingTreeOptions;
 import org.eclipse.jgit.util.IO;
 import org.eclipse.jgit.util.io.AutoLFInputStream;
@@ -248,11 +248,12 @@ private RawText getRawText(File inTree) throws IOException,
 			rawText = new RawText(inTree);
 			break;
 		case TRUE:
-			AutoLFInputStream in = new AutoLFInputStream(
-					new FileInputStream(inTree), true);
-			// Canonicalization should lead to same or shorter length
-			// (CRLF to LF), so the file size on disk is an upper size bound
-			rawText = new RawText(toByteArray(in, (int) inTree.length()));
+			try (AutoLFInputStream in = new AutoLFInputStream(
+					new FileInputStream(inTree), true)) {
+				// Canonicalization should lead to same or shorter length
+				// (CRLF to LF), so the file size on disk is an upper size bound
+				rawText = new RawText(toByteArray(in, (int) inTree.length()));
+			}
 			break;
 		default:
 			throw new IllegalArgumentException(
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java
index 65508ef..c17ae5c 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java
@@ -318,7 +318,9 @@ else if (orphan) {
 
 			if (!dco.getToBeDeleted().isEmpty()) {
 				status = new CheckoutResult(Status.NONDELETED,
-						dco.getToBeDeleted());
+						dco.getToBeDeleted(),
+						new ArrayList<String>(dco.getUpdated().keySet()),
+						dco.getRemoved());
 			} else
 				status = new CheckoutResult(new ArrayList<String>(dco
 						.getUpdated().keySet()), dco.getRemoved());
@@ -365,6 +367,26 @@ public CheckoutCommand addPath(String path) {
 	}
 
 	/**
+	 * Add multiple slash-separated paths to the list of paths to check out. To
+	 * check out all paths, use {@link #setAllPaths(boolean)}.
+	 * <p>
+	 * If this option is set, neither the {@link #setCreateBranch(boolean)} nor
+	 * {@link #setName(String)} option is considered. In other words, these
+	 * options are exclusive.
+	 *
+	 * @param p
+	 *            paths to update in the working tree and index (with
+	 *            <code>/</code> as separator)
+	 * @return {@code this}
+	 * @since 4.6
+	 */
+	public CheckoutCommand addPaths(List<String> p) {
+		checkCallable();
+		this.paths.addAll(p);
+		return this;
+	}
+
+	/**
 	 * Set whether to checkout all paths.
 	 * <p>
 	 * This options should be used when you want to do a path checkout on the
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutResult.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutResult.java
index 6a1bfb8..92a67f4 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutResult.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutResult.java
@@ -113,6 +113,28 @@ public enum Status {
 	 *            {@link Status#CONFLICTS} or {@link Status#NONDELETED}.
 	 */
 	CheckoutResult(Status status, List<String> fileList) {
+		this(status, fileList, null, null);
+	}
+
+	/**
+	 * Create a new fail result. If status is {@link Status#CONFLICTS},
+	 * <code>fileList</code> is a list of conflicting files, if status is
+	 * {@link Status#NONDELETED}, <code>fileList</code> is a list of not deleted
+	 * files. All other values ignore <code>fileList</code>. To create a result
+	 * for {@link Status#OK}, see {@link #CheckoutResult(List, List)}.
+	 *
+	 * @param status
+	 *            the failure status
+	 * @param fileList
+	 *            the list of files to store, status has to be either
+	 *            {@link Status#CONFLICTS} or {@link Status#NONDELETED}.
+	 * @param modified
+	 *            the modified files
+	 * @param removed
+	 *            the removed files.
+	 */
+	CheckoutResult(Status status, List<String> fileList, List<String> modified,
+			List<String> removed) {
 		myStatus = status;
 		if (status == Status.CONFLICTS)
 			this.conflictList = fileList;
@@ -123,8 +145,8 @@ public enum Status {
 		else
 			this.undeletedList = new ArrayList<String>(0);
 
-		this.modifiedList = new ArrayList<String>(0);
-		this.removedList = new ArrayList<String>(0);
+		this.modifiedList = modified;
+		this.removedList = removed;
 	}
 
 	/**
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/CherryPickCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/CherryPickCommand.java
index e82a697..276bf96 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/CherryPickCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/CherryPickCommand.java
@@ -330,4 +330,15 @@ private String calculateOurName(Ref headRef) {
 		String headName = Repository.shortenRefName(targetRefName);
 		return headName;
 	}
+
+	@SuppressWarnings("nls")
+	@Override
+	public String toString() {
+		return "CherryPickCommand [repo=" + repo + ",\ncommits=" + commits
+				+ ",\nmainlineParentNumber=" + mainlineParentNumber
+				+ ", noCommit=" + noCommit + ", ourCommitName=" + ourCommitName
+				+ ", reflogPrefix=" + reflogPrefix + ", strategy=" + strategy
+				+ "]";
+	}
+
 }
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 38b1097..ced1863 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeCommand.java
@@ -381,6 +381,7 @@ public MergeResult call() throws GitAPIException, NoHeadException,
 									.call().getId();
 						}
 						mergeStatus = MergeStatus.MERGED;
+						getRepository().autoGC(monitor);
 					}
 					if (commit && squash) {
 						msg = JGitText.get().squashCommitNotUpdatingHEAD;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java
index 2d6a76b..d10cc3d 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java
@@ -400,8 +400,8 @@ private boolean autoStashApply() throws IOException, GitAPIException {
 		boolean conflicts = false;
 		if (rebaseState.getFile(AUTOSTASH).exists()) {
 			String stash = rebaseState.readFile(AUTOSTASH);
-			try {
-				Git.wrap(repo).stashApply().setStashRef(stash)
+			try (Git git = Git.wrap(repo)) {
+				git.stashApply().setStashRef(stash)
 						.ignoreRepositoryState(true).setStrategy(strategy)
 						.call();
 			} catch (StashApplyFailureException e) {
@@ -463,8 +463,10 @@ private RebaseResult processStep(RebaseTodoLine step, boolean shouldPick)
 			String oldMessage = commitToPick.getFullMessage();
 			String newMessage = interactiveHandler
 					.modifyCommitMessage(oldMessage);
-			newHead = new Git(repo).commit().setMessage(newMessage)
-					.setAmend(true).setNoVerify(true).call();
+			try (Git git = new Git(repo)) {
+				newHead = git.commit().setMessage(newMessage).setAmend(true)
+						.setNoVerify(true).call();
+			}
 			return null;
 		case EDIT:
 			rebaseState.createFile(AMEND, commitToPick.name());
@@ -693,6 +695,7 @@ private RebaseResult finishRebase(RevCommit finalHead,
 		String headName = rebaseState.readFile(HEAD_NAME);
 		updateHead(headName, finalHead, upstreamCommit);
 		boolean stashConflicts = autoStashApply();
+		getRepository().autoGC(monitor);
 		FileUtils.delete(rebaseState.getDir(), FileUtils.RECURSIVE);
 		if (stashConflicts)
 			return RebaseResult.STASH_APPLY_CONFLICTS_RESULT;
@@ -752,12 +755,12 @@ private void resetSoftToParent() throws IOException,
 			GitAPIException, CheckoutConflictException {
 		Ref ref = repo.exactRef(Constants.ORIG_HEAD);
 		ObjectId orig_head = ref == null ? null : ref.getObjectId();
-		try {
-			// we have already commited the cherry-picked commit.
+		try (Git git = Git.wrap(repo)) {
+			// we have already committed the cherry-picked commit.
 			// what we need is to have changes introduced by this
 			// commit to be on the index
 			// resetting is a workaround
-			Git.wrap(repo).reset().setMode(ResetType.SOFT)
+			git.reset().setMode(ResetType.SOFT)
 					.setRef("HEAD~1").call(); //$NON-NLS-1$
 		} finally {
 			// set ORIG_HEAD back to where we started because soft
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/ResetCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/ResetCommand.java
index 3ceff84..106988d 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/ResetCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/ResetCommand.java
@@ -432,4 +432,12 @@ private void resetRevert() throws IOException {
 		repo.writeMergeCommitMsg(null);
 	}
 
+	@SuppressWarnings("nls")
+	@Override
+	public String toString() {
+		return "ResetCommand [repo=" + repo + ", ref=" + ref + ", mode=" + mode
+				+ ", isReflogDisabled=" + isReflogDisabled + ", filepaths="
+				+ filepaths + "]";
+	}
+
 }
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleAddCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleAddCommand.java
index fbb24c1..b0f772e 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleAddCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleAddCommand.java
@@ -133,7 +133,9 @@ public SubmoduleAddCommand setProgressMonitor(final ProgressMonitor monitor) {
 	 */
 	protected boolean submoduleExists() throws IOException {
 		TreeFilter filter = PathFilter.create(path);
-		return SubmoduleWalk.forIndex(repo).setFilter(filter).next();
+		try (SubmoduleWalk w = SubmoduleWalk.forIndex(repo)) {
+			return w.setFilter(filter).next();
+		}
 	}
 
 	/**
@@ -178,7 +180,11 @@ public Repository call() throws GitAPIException {
 		clone.setURI(resolvedUri);
 		if (monitor != null)
 			clone.setProgressMonitor(monitor);
-		Repository subRepo = clone.call().getRepository();
+		Repository subRepo = null;
+		try (Git git = clone.call()) {
+			subRepo = git.getRepository();
+			subRepo.incrementOpen();
+		}
 
 		// Save submodule URL to parent repository's config
 		StoredConfig config = repo.getConfig();
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleInitCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleInitCommand.java
index 0ed02ac..1dbe368 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleInitCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleInitCommand.java
@@ -94,8 +94,7 @@ public SubmoduleInitCommand addPath(final String path) {
 	public Collection<String> call() throws GitAPIException {
 		checkCallable();
 
-		try {
-			SubmoduleWalk generator = SubmoduleWalk.forIndex(repo);
+		try (SubmoduleWalk generator = SubmoduleWalk.forIndex(repo)) {
 			if (!paths.isEmpty())
 				generator.setFilter(PathFilterGroup.createFromStrings(paths));
 			StoredConfig config = repo.getConfig();
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleStatusCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleStatusCommand.java
index 6e89f98..a1ea790 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleStatusCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleStatusCommand.java
@@ -54,9 +54,9 @@
 import org.eclipse.jgit.lib.Constants;
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.submodule.SubmoduleWalk;
 import org.eclipse.jgit.submodule.SubmoduleStatus;
 import org.eclipse.jgit.submodule.SubmoduleStatusType;
+import org.eclipse.jgit.submodule.SubmoduleWalk;
 import org.eclipse.jgit.treewalk.filter.PathFilterGroup;
 
 /**
@@ -94,8 +94,7 @@ public SubmoduleStatusCommand addPath(final String path) {
 	public Map<String, SubmoduleStatus> call() throws GitAPIException {
 		checkCallable();
 
-		try {
-			SubmoduleWalk generator = SubmoduleWalk.forIndex(repo);
+		try (SubmoduleWalk generator = SubmoduleWalk.forIndex(repo)) {
 			if (!paths.isEmpty())
 				generator.setFilter(PathFilterGroup.createFromStrings(paths));
 			Map<String, SubmoduleStatus> statuses = new HashMap<String, SubmoduleStatus>();
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleSyncCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleSyncCommand.java
index 024f0be..088eedc 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleSyncCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleSyncCommand.java
@@ -111,8 +111,7 @@ protected String getHeadBranch(final Repository subRepo) throws IOException {
 	public Map<String, String> call() throws GitAPIException {
 		checkCallable();
 
-		try {
-			SubmoduleWalk generator = SubmoduleWalk.forIndex(repo);
+		try (SubmoduleWalk generator = SubmoduleWalk.forIndex(repo)) {
 			if (!paths.isEmpty())
 				generator.setFilter(PathFilterGroup.createFromStrings(paths));
 			Map<String, String> synced = new HashMap<String, String>();
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/errors/StashApplyFailureException.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/errors/StashApplyFailureException.java
index 1d54f77..222c1db 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/errors/StashApplyFailureException.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/errors/StashApplyFailureException.java
@@ -1,7 +1,5 @@
 package org.eclipse.jgit.api.errors;
 
-import org.eclipse.jgit.api.errors.GitAPIException;
-
 /**
  * Thrown from StashApplyCommand when stash apply fails
  */
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/attributes/AttributesHandler.java b/org.eclipse.jgit/src/org/eclipse/jgit/attributes/AttributesHandler.java
index 19e4afd..3bf4179 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/attributes/AttributesHandler.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/attributes/AttributesHandler.java
@@ -54,8 +54,8 @@
 import org.eclipse.jgit.treewalk.AbstractTreeIterator;
 import org.eclipse.jgit.treewalk.CanonicalTreeParser;
 import org.eclipse.jgit.treewalk.TreeWalk;
-import org.eclipse.jgit.treewalk.WorkingTreeIterator;
 import org.eclipse.jgit.treewalk.TreeWalk.OperationType;
+import org.eclipse.jgit.treewalk.WorkingTreeIterator;
 
 /**
  * The attributes handler knows how to retrieve, parse and merge attributes from
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/attributes/FilterCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/attributes/FilterCommand.java
new file mode 100644
index 0000000..10be588
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/attributes/FilterCommand.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2016, Christian Halstrick <christian.halstrick@sap.com>
+ * 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.attributes;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * An abstraction for JGit's builtin implementations for hooks and filters.
+ * Instead of spawning an external processes to start a filter/hook and to pump
+ * data from/to stdin/stdout these builtin commmands may be used. They are
+ * constructed by {@link FilterCommandFactory}.
+ *
+ * @since 4.6
+ */
+public abstract class FilterCommand {
+	/**
+	 * The {@link InputStream} this command should read from
+	 */
+	protected InputStream in;
+
+	/**
+	 * The {@link OutputStream} this command should write to
+	 */
+	protected OutputStream out;
+
+	/**
+	 * @param in
+	 *            The {@link InputStream} this command should read from
+	 * @param out
+	 *            The {@link OutputStream} this command should write to
+	 */
+	public FilterCommand(InputStream in, OutputStream out) {
+		this.in = in;
+		this.out = out;
+	}
+
+	/**
+	 * Execute the command. The command is supposed to read data from
+	 * {@link #in} and to write the result to {@link #out}. It returns the
+	 * number of bytes it read from {@link #in}. It should be called in a loop
+	 * until it returns -1 signaling that the {@link InputStream} is completely
+	 * processed.
+	 *
+	 * @return the number of bytes read from the {@link InputStream} or -1. -1
+	 *         means that the {@link InputStream} is completely processed.
+	 * @throws IOException
+	 *             when {@link IOException} occured while reading from
+	 *             {@link #in} or writing to {@link #out}
+	 *
+	 */
+	public abstract int run() throws IOException;
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/attributes/FilterCommandFactory.java b/org.eclipse.jgit/src/org/eclipse/jgit/attributes/FilterCommandFactory.java
new file mode 100644
index 0000000..6b973da
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/attributes/FilterCommandFactory.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2016, Christian Halstrick <christian.halstrick@sap.com>
+ * 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.attributes;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.eclipse.jgit.lib.Repository;
+
+/**
+ * The factory responsible for creating instances of {@link FilterCommand}.
+ *
+ * @since 4.6
+ */
+public interface FilterCommandFactory {
+	/**
+	 * Create a new {@link FilterCommand}.
+	 *
+	 * @param db
+	 *            the repository this command should work on
+	 * @param in
+	 *            the {@link InputStream} this command should read from
+	 * @param out
+	 *            the {@link OutputStream} this command should write to
+	 * @return the created {@link FilterCommand}
+	 * @throws IOException
+	 *             thrown when the command constructor throws an IOException
+	 */
+	public FilterCommand create(Repository db, InputStream in,
+			OutputStream out) throws IOException;
+
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/attributes/FilterCommandRegistry.java b/org.eclipse.jgit/src/org/eclipse/jgit/attributes/FilterCommandRegistry.java
new file mode 100644
index 0000000..3fbaedb
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/attributes/FilterCommandRegistry.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2016, Matthias Sohn <matthias.sohn@sap.com>
+ * 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.attributes;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.eclipse.jgit.lib.Repository;
+
+/**
+ * Registry for built-in filters
+ *
+ * @since 4.6
+ */
+public class FilterCommandRegistry {
+	private static ConcurrentHashMap<String, FilterCommandFactory> filterCommandRegistry = new ConcurrentHashMap<>();
+
+	/**
+	 * Registers a {@link FilterCommandFactory} responsible for creating
+	 * {@link FilterCommand}s for a certain command name. If the factory f1 is
+	 * registered for the name "jgit://builtin/x" then a call to
+	 * <code>getCommand("jgit://builtin/x", ...)</code> will call
+	 * <code>f1(...)</code> to create a new instance of {@link FilterCommand}
+	 *
+	 * @param filterCommandName
+	 *            the command name for which this factory is registered
+	 * @param factory
+	 *            the factory responsible for creating {@link FilterCommand}s
+	 *            for the specified name
+	 * @return the previous factory associated with <tt>commandName</tt>, or
+	 *         <tt>null</tt> if there was no mapping for <tt>commandName</tt>
+	 */
+	public static FilterCommandFactory register(String filterCommandName,
+			FilterCommandFactory factory) {
+		return filterCommandRegistry.put(filterCommandName, factory);
+	}
+
+	/**
+	 * Unregisters the {@link FilterCommandFactory} registered for the given
+	 * command name
+	 *
+	 * @param filterCommandName
+	 *            the FilterCommandFactory's filter command name
+	 * @return the previous factory associated with <tt>filterCommandName</tt>,
+	 *         or <tt>null</tt> if there was no mapping for <tt>commandName</tt>
+	 */
+	public static FilterCommandFactory unregister(String filterCommandName) {
+		return filterCommandRegistry.remove(filterCommandName);
+	}
+
+	/**
+	 * Checks whether any {@link FilterCommandFactory} is registered for a given
+	 * command name
+	 *
+	 * @param filterCommandName
+	 *            the name for which the registry should be checked
+	 * @return <code>true</code> if any factory was registered for the name
+	 */
+	public static boolean isRegistered(String filterCommandName) {
+		return filterCommandRegistry.containsKey(filterCommandName);
+	}
+
+	/**
+	 * @return Set of commandNames for which a {@link FilterCommandFactory} is
+	 *         registered
+	 */
+	public static Set<String> getRegisteredFilterCommands() {
+		return filterCommandRegistry.keySet();
+	}
+
+	/**
+	 * Creates a new {@link FilterCommand} for the given name. A factory must be
+	 * registered for the name in advance.
+	 *
+	 * @param filterCommandName
+	 *            The name for which a new {@link FilterCommand} should be
+	 *            created
+	 * @param db
+	 *            the repository this command should work on
+	 * @param in
+	 *            the {@link InputStream} this {@link FilterCommand} should read
+	 *            from
+	 * @param out
+	 *            the {@link OutputStream} this {@link FilterCommand} should
+	 *            write to
+	 * @return the command if a command could be created or <code>null</code> if
+	 *         there was no factory registered for that name
+	 * @throws IOException
+	 */
+	public static FilterCommand createFilterCommand(String filterCommandName,
+			Repository db, InputStream in, OutputStream out)
+			throws IOException {
+		FilterCommandFactory cf = filterCommandRegistry.get(filterCommandName);
+		return (cf == null) ? null : cf.create(db, in, out);
+	}
+
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCache.java b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCache.java
index b9101c0..b0cf8be 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCache.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCache.java
@@ -46,6 +46,7 @@
 package org.eclipse.jgit.dircache;
 
 import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
 import java.io.EOFException;
 import java.io.File;
 import java.io.FileInputStream;
@@ -86,7 +87,6 @@
 import org.eclipse.jgit.util.MutableInteger;
 import org.eclipse.jgit.util.NB;
 import org.eclipse.jgit.util.TemporaryBuffer;
-import org.eclipse.jgit.util.io.SafeBufferedOutputStream;
 
 /**
  * Support for the Git dircache (aka index file).
@@ -634,9 +634,9 @@ public boolean lock() throws IOException {
 	public void write() throws IOException {
 		final LockFile tmp = myLock;
 		requireLocked(tmp);
-		try {
-			writeTo(liveFile.getParentFile(),
-					new SafeBufferedOutputStream(tmp.getOutputStream()));
+		try (OutputStream o = tmp.getOutputStream();
+				OutputStream bo = new BufferedOutputStream(o)) {
+			writeTo(liveFile.getParentFile(), bo);
 		} catch (IOException err) {
 			tmp.unlock();
 			throw err;
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 8af7e46..c318443 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java
@@ -54,6 +54,8 @@
 import java.util.Map;
 
 import org.eclipse.jgit.api.errors.FilterFailedException;
+import org.eclipse.jgit.attributes.FilterCommand;
+import org.eclipse.jgit.attributes.FilterCommandRegistry;
 import org.eclipse.jgit.errors.CheckoutConflictException;
 import org.eclipse.jgit.errors.CorruptObjectException;
 import org.eclipse.jgit.errors.IncorrectObjectTypeException;
@@ -86,11 +88,15 @@
 import org.eclipse.jgit.util.RawParseUtils;
 import org.eclipse.jgit.util.SystemReader;
 import org.eclipse.jgit.util.io.EolStreamTypeUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * This class handles checking out one or two trees merging with the index.
  */
 public class DirCacheCheckout {
+	private static Logger LOG = LoggerFactory.getLogger(DirCacheCheckout.class);
+
 	private static final int MAX_EXCEPTION_TEXT_SIZE = 10 * 1024;
 
 	/**
@@ -1303,45 +1309,19 @@ public static void checkoutEntry(Repository repo, DirCacheEntry entry,
 		} else {
 			nonNullEolStreamType = EolStreamType.DIRECT;
 		}
-		OutputStream channel = EolStreamTypeUtil.wrapOutputStream(
-				new FileOutputStream(tmpFile), nonNullEolStreamType);
-		if (checkoutMetadata.smudgeFilterCommand != null) {
-			ProcessBuilder filterProcessBuilder = fs.runInShell(
-					checkoutMetadata.smudgeFilterCommand, new String[0]);
-			filterProcessBuilder.directory(repo.getWorkTree());
-			filterProcessBuilder.environment().put(Constants.GIT_DIR_KEY,
-					repo.getDirectory().getAbsolutePath());
-			ExecutionResult result;
-			int rc;
-			try {
-				// TODO: wire correctly with AUTOCRLF
-				result = fs.execute(filterProcessBuilder, ol.openStream());
-				rc = result.getRc();
-				if (rc == 0) {
-					result.getStdout().writeTo(channel,
-							NullProgressMonitor.INSTANCE);
+		try (OutputStream channel = EolStreamTypeUtil.wrapOutputStream(
+				new FileOutputStream(tmpFile), nonNullEolStreamType)) {
+			if (checkoutMetadata.smudgeFilterCommand != null) {
+				if (FilterCommandRegistry
+						.isRegistered(checkoutMetadata.smudgeFilterCommand)) {
+					runBuiltinFilterCommand(repo, checkoutMetadata, ol,
+							channel);
+				} else {
+					runExternalFilterCommand(repo, entry, checkoutMetadata, ol,
+							fs, channel);
 				}
-			} catch (IOException | InterruptedException e) {
-				throw new IOException(new FilterFailedException(e,
-						checkoutMetadata.smudgeFilterCommand,
-						entry.getPathString()));
-
-			} finally {
-				channel.close();
-			}
-			if (rc != 0) {
-				throw new IOException(new FilterFailedException(rc,
-						checkoutMetadata.smudgeFilterCommand,
-						entry.getPathString(),
-						result.getStdout().toByteArray(MAX_EXCEPTION_TEXT_SIZE),
-						RawParseUtils.decode(result.getStderr()
-								.toByteArray(MAX_EXCEPTION_TEXT_SIZE))));
-			}
-		} else {
-			try {
+			} else {
 				ol.copyTo(channel);
-			} finally {
-				channel.close();
 			}
 		}
 		// The entry needs to correspond to the on-disk filesize. If the content
@@ -1382,6 +1362,63 @@ public static void checkoutEntry(Repository repo, DirCacheEntry entry,
 		entry.setLastModified(fs.lastModified(f));
 	}
 
+	// Run an external filter command
+	private static void runExternalFilterCommand(Repository repo,
+			DirCacheEntry entry,
+			CheckoutMetadata checkoutMetadata, ObjectLoader ol, FS fs,
+			OutputStream channel) throws IOException {
+		ProcessBuilder filterProcessBuilder = fs.runInShell(
+				checkoutMetadata.smudgeFilterCommand, new String[0]);
+		filterProcessBuilder.directory(repo.getWorkTree());
+		filterProcessBuilder.environment().put(Constants.GIT_DIR_KEY,
+				repo.getDirectory().getAbsolutePath());
+		ExecutionResult result;
+		int rc;
+		try {
+			// TODO: wire correctly with AUTOCRLF
+			result = fs.execute(filterProcessBuilder, ol.openStream());
+			rc = result.getRc();
+			if (rc == 0) {
+				result.getStdout().writeTo(channel,
+						NullProgressMonitor.INSTANCE);
+			}
+		} catch (IOException | InterruptedException e) {
+			throw new IOException(new FilterFailedException(e,
+					checkoutMetadata.smudgeFilterCommand,
+					entry.getPathString()));
+		}
+		if (rc != 0) {
+			throw new IOException(new FilterFailedException(rc,
+					checkoutMetadata.smudgeFilterCommand,
+					entry.getPathString(),
+					result.getStdout().toByteArray(MAX_EXCEPTION_TEXT_SIZE),
+					RawParseUtils.decode(result.getStderr()
+							.toByteArray(MAX_EXCEPTION_TEXT_SIZE))));
+		}
+	}
+
+	// Run a builtin filter command
+	private static void runBuiltinFilterCommand(Repository repo,
+			CheckoutMetadata checkoutMetadata, ObjectLoader ol,
+			OutputStream channel) throws MissingObjectException, IOException {
+		FilterCommand command = null;
+		try {
+			command = FilterCommandRegistry.createFilterCommand(
+					checkoutMetadata.smudgeFilterCommand, repo, ol.openStream(),
+					channel);
+		} catch (IOException e) {
+			LOG.error(JGitText.get().failedToDetermineFilterDefinition, e);
+			// In case an IOException occurred during creating of the command
+			// then proceed as if there would not have been a builtin filter.
+			ol.copyTo(channel);
+		}
+		if (command != null) {
+			while (command.run() != -1) {
+				// loop as long as command.run() tells there is work to do
+			}
+		}
+	}
+
 	@SuppressWarnings("deprecation")
 	private static void checkValidPath(CanonicalTreeParser t)
 			throws InvalidPathException {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/ManifestParser.java b/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/ManifestParser.java
index 2370ae1..8a35d35 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/ManifestParser.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/ManifestParser.java
@@ -215,10 +215,13 @@ public void startElement(
 						attributes.getValue("dest"))); //$NON-NLS-1$
 		} else if ("include".equals(qName)) { //$NON-NLS-1$
 			String name = attributes.getValue("name"); //$NON-NLS-1$
-			InputStream is = null;
 			if (includedReader != null) {
-				try {
-					is = includedReader.readIncludeFile(name);
+				try (InputStream is = includedReader.readIncludeFile(name)) {
+					if (is == null) {
+						throw new SAXException(
+								RepoText.get().errorIncludeNotImplemented);
+					}
+					read(is);
 				} catch (Exception e) {
 					throw new SAXException(MessageFormat.format(
 							RepoText.get().errorIncludeFile, name), e);
@@ -226,22 +229,13 @@ public void startElement(
 			} else if (filename != null) {
 				int index = filename.lastIndexOf('/');
 				String path = filename.substring(0, index + 1) + name;
-				try {
-					is = new FileInputStream(path);
+				try (InputStream is = new FileInputStream(path)) {
+					read(is);
 				} catch (IOException e) {
 					throw new SAXException(MessageFormat.format(
 							RepoText.get().errorIncludeFile, path), e);
 				}
 			}
-			if (is == null) {
-				throw new SAXException(
-						RepoText.get().errorIncludeNotImplemented);
-			}
-			try {
-				read(is);
-			} catch (IOException e) {
-				throw new SAXException(e);
-			}
 		}
 	}
 
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoCommand.java
index 9b7f094..86dbabc 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoCommand.java
@@ -180,17 +180,11 @@ public ObjectId sha1(String uri, String ref) throws GitAPIException {
 		public byte[] readFile(String uri, String ref, String path)
 				throws GitAPIException, IOException {
 			File dir = FileUtils.createTempDir("jgit_", ".git", null); //$NON-NLS-1$ //$NON-NLS-2$
-			Repository repo = Git
-					.cloneRepository()
-					.setBare(true)
-					.setDirectory(dir)
-					.setURI(uri)
-					.call()
-					.getRepository();
-			try {
+			try (Git git = Git.cloneRepository().setBare(true).setDirectory(dir)
+					.setURI(uri).call();
+					Repository repo = git.getRepository()) {
 				return readFileFromRepo(repo, ref, path);
 			} finally {
-				repo.close();
 				FileUtils.delete(dir, FileUtils.RECURSIVE);
 			}
 		}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/ignore/FastIgnoreRule.java b/org.eclipse.jgit/src/org/eclipse/jgit/ignore/FastIgnoreRule.java
index eb081ad..ef67d49 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/ignore/FastIgnoreRule.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/ignore/FastIgnoreRule.java
@@ -42,10 +42,11 @@
  */
 package org.eclipse.jgit.ignore;
 
+import static org.eclipse.jgit.ignore.internal.IMatcher.NO_MATCH;
+import static org.eclipse.jgit.ignore.internal.Strings.isDirectoryPattern;
 import static org.eclipse.jgit.ignore.internal.Strings.stripTrailing;
 import static org.eclipse.jgit.ignore.internal.Strings.stripTrailingWhitespace;
-import static org.eclipse.jgit.ignore.internal.Strings.isDirectoryPattern;
-import static org.eclipse.jgit.ignore.internal.IMatcher.NO_MATCH;
+
 import org.eclipse.jgit.errors.InvalidPatternException;
 import org.eclipse.jgit.ignore.internal.IMatcher;
 import org.eclipse.jgit.ignore.internal.PathMatcher;
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 d32e873..df2cc50 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
@@ -98,6 +98,7 @@ public static JGitText get() {
 	/***/ public String blameNotCommittedYet;
 	/***/ public String blobNotFound;
 	/***/ public String blobNotFoundForPath;
+	/***/ public String blockSizeNotPowerOf2;
 	/***/ public String branchNameInvalid;
 	/***/ public String buildingBitmaps;
 	/***/ public String cachedPacksPreventsIndexCreation;
@@ -174,6 +175,7 @@ public static JGitText get() {
 	/***/ public String checkoutUnexpectedResult;
 	/***/ public String classCastNotA;
 	/***/ public String cloneNonEmptyDirectory;
+	/***/ public String closed;
 	/***/ public String collisionOn;
 	/***/ public String commandRejectedByHook;
 	/***/ public String commandWasCalledInTheWrongState;
@@ -339,6 +341,7 @@ public static JGitText get() {
 	/***/ public String expectedPktLineWithService;
 	/***/ public String expectedReceivedContentType;
 	/***/ public String expectedReportForRefNotReceived;
+	/***/ public String failedToDetermineFilterDefinition;
 	/***/ public String failedUpdatingRefs;
 	/***/ public String failureDueToOneOfTheFollowing;
 	/***/ public String failureUpdatingFETCH_HEAD;
@@ -425,6 +428,7 @@ public static JGitText get() {
 	/***/ public String invalidTimeout;
 	/***/ public String invalidTimeUnitValue2;
 	/***/ public String invalidTimeUnitValue3;
+	/***/ public String invalidTreeZeroLengthName;
 	/***/ public String invalidURL;
 	/***/ public String invalidWildcards;
 	/***/ public String invalidRefSpec;
@@ -523,6 +527,7 @@ public static JGitText get() {
 	/***/ public String packedRefsHandleIsStale;
 	/***/ public String packetSizeMustBeAtLeast;
 	/***/ public String packetSizeMustBeAtMost;
+	/***/ public String packedRefsCorruptionDetected;
 	/***/ public String packfileCorruptionDetected;
 	/***/ public String packFileInvalid;
 	/***/ public String packfileIsTruncated;
@@ -662,6 +667,7 @@ public static JGitText get() {
 	/***/ public String tagOnRepoWithoutHEADCurrentlyNotSupported;
 	/***/ public String transactionAborted;
 	/***/ public String theFactoryMustNotBeNull;
+	/***/ public String timeIsUncertain;
 	/***/ public String timerAlreadyTerminated;
 	/***/ public String tooManyIncludeRecursions;
 	/***/ public String topologicalSortRequired;
@@ -730,6 +736,7 @@ public static JGitText get() {
 	/***/ public String unsupportedOperationNotAddAtEnd;
 	/***/ public String unsupportedPackIndexVersion;
 	/***/ public String unsupportedPackVersion;
+	/***/ public String unsupportedRepositoryDescription;
 	/***/ public String updatingHeadFailed;
 	/***/ public String updatingReferences;
 	/***/ public String updatingRefFailed;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/ElectionRound.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/ElectionRound.java
index 014eab2..1221ddd 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/ElectionRound.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/ElectionRound.java
@@ -43,10 +43,12 @@
 
 package org.eclipse.jgit.internal.ketch;
 
+import static java.util.concurrent.TimeUnit.SECONDS;
 import static org.eclipse.jgit.internal.ketch.KetchConstants.TERM;
 
 import java.io.IOException;
 import java.util.List;
+import java.util.concurrent.TimeoutException;
 
 import org.eclipse.jgit.lib.CommitBuilder;
 import org.eclipse.jgit.lib.ObjectId;
@@ -55,6 +57,7 @@
 import org.eclipse.jgit.lib.TreeFormatter;
 import org.eclipse.jgit.revwalk.RevCommit;
 import org.eclipse.jgit.revwalk.RevWalk;
+import org.eclipse.jgit.util.time.ProposedTimestamp;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -75,9 +78,11 @@ class ElectionRound extends Round {
 	void start() throws IOException {
 		ObjectId id;
 		try (Repository git = leader.openRepository();
+				ProposedTimestamp ts = getSystem().getClock().propose();
 				ObjectInserter inserter = git.newObjectInserter()) {
-			id = bumpTerm(git, inserter);
+			id = bumpTerm(git, ts, inserter);
 			inserter.flush();
+			blockUntil(ts);
 		}
 		runAsync(id);
 	}
@@ -91,12 +96,17 @@ long getTerm() {
 		return term;
 	}
 
-	private ObjectId bumpTerm(Repository git, ObjectInserter inserter)
-			throws IOException {
+	private ObjectId bumpTerm(Repository git, ProposedTimestamp ts,
+			ObjectInserter inserter) throws IOException {
 		CommitBuilder b = new CommitBuilder();
 		if (!ObjectId.zeroId().equals(acceptedOldIndex)) {
 			try (RevWalk rw = new RevWalk(git)) {
 				RevCommit c = rw.parseCommit(acceptedOldIndex);
+				if (getSystem().requireMonotonicLeaderElections()) {
+					if (ts.read(SECONDS) < c.getCommitTime()) {
+						throw new TimeIsUncertainException();
+					}
+				}
 				b.setTreeId(c.getTree());
 				b.setParentId(acceptedOldIndex);
 				term = parseTerm(c.getFooterLines(TERM)) + 1;
@@ -116,7 +126,7 @@ private ObjectId bumpTerm(Repository git, ObjectInserter inserter)
 			msg.append(' ').append(tag);
 		}
 
-		b.setAuthor(leader.getSystem().newCommitter());
+		b.setAuthor(leader.getSystem().newCommitter(ts));
 		b.setCommitter(b.getAuthor());
 		b.setMessage(msg.toString());
 
@@ -138,4 +148,12 @@ private static long parseTerm(List<String> footer) {
 		}
 		return Long.parseLong(s, 10);
 	}
+
+	private void blockUntil(ProposedTimestamp ts) throws IOException {
+		try {
+			ts.blockUntil(getSystem().getMaxWaitForMonotonicClock());
+		} catch (InterruptedException | TimeoutException e) {
+			throw new TimeIsUncertainException(e);
+		}
+	}
 }
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/KetchSystem.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/KetchSystem.java
index 71e872e..33f526e 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/KetchSystem.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/KetchSystem.java
@@ -53,6 +53,7 @@
 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_REMOTE;
 
 import java.net.URISyntaxException;
+import java.time.Duration;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Random;
@@ -67,6 +68,9 @@
 import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.transport.RemoteConfig;
 import org.eclipse.jgit.transport.URIish;
+import org.eclipse.jgit.util.time.MonotonicClock;
+import org.eclipse.jgit.util.time.MonotonicSystemClock;
+import org.eclipse.jgit.util.time.ProposedTimestamp;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -88,6 +92,7 @@ public static ScheduledExecutorService defaultExecutor() {
 	}
 
 	private final ScheduledExecutorService executor;
+	private final MonotonicClock clock;
 	private final String txnNamespace;
 	private final String txnAccepted;
 	private final String txnCommitted;
@@ -95,7 +100,7 @@ public static ScheduledExecutorService defaultExecutor() {
 
 	/** Create a default system with a thread pool of 1 thread per CPU. */
 	public KetchSystem() {
-		this(defaultExecutor(), DEFAULT_TXN_NAMESPACE);
+		this(defaultExecutor(), new MonotonicSystemClock(), DEFAULT_TXN_NAMESPACE);
 	}
 
 	/**
@@ -103,13 +108,17 @@ public KetchSystem() {
 	 *
 	 * @param executor
 	 *            thread pool to run background operations.
+	 * @param clock
+	 *            clock to create timestamps.
 	 * @param txnNamespace
 	 *            reference namespace for the RefTree graph and associated
 	 *            transaction state. Must begin with {@code "refs/"} and end
 	 *            with {@code '/'}, for example {@code "refs/txn/"}.
 	 */
-	public KetchSystem(ScheduledExecutorService executor, String txnNamespace) {
+	public KetchSystem(ScheduledExecutorService executor, MonotonicClock clock,
+			String txnNamespace) {
 		this.executor = executor;
+		this.clock = clock;
 		this.txnNamespace = txnNamespace;
 		this.txnAccepted = txnNamespace + ACCEPTED;
 		this.txnCommitted = txnNamespace + COMMITTED;
@@ -121,6 +130,28 @@ public ScheduledExecutorService getExecutor() {
 		return executor;
 	}
 
+	/** @return clock to obtain timestamps from. */
+	public MonotonicClock getClock() {
+		return clock;
+	}
+
+	/**
+	 * @return how long the leader will wait for the {@link #getClock()}'s
+	 *         {@code ProposedTimestamp} used in commits proposed to the RefTree
+	 *         graph ({@link #getTxnAccepted()}). Defaults to 5 seconds.
+	 */
+	public Duration getMaxWaitForMonotonicClock() {
+		return Duration.ofSeconds(5);
+	}
+
+	/**
+	 * @return true if elections should require monotonically increasing commit
+	 *         timestamps. This requires a very good {@link MonotonicClock}.
+	 */
+	public boolean requireMonotonicLeaderElections() {
+		return false;
+	}
+
 	/**
 	 * Get the namespace used for the RefTree graph and transaction management.
 	 *
@@ -145,27 +176,32 @@ public String getTxnStage() {
 		return txnStage;
 	}
 
-	/** @return identity line for the committer header of a RefTreeGraph. */
-	public PersonIdent newCommitter() {
+	/**
+	 * @param time
+	 *            timestamp for the committer.
+	 * @return identity line for the committer header of a RefTreeGraph.
+	 */
+	public PersonIdent newCommitter(ProposedTimestamp time) {
 		String name = "ketch"; //$NON-NLS-1$
 		String email = "ketch@system"; //$NON-NLS-1$
-		return new PersonIdent(name, email);
+		return new PersonIdent(name, email, time);
 	}
 
 	/**
 	 * Construct a random tag to identify a candidate during leader election.
 	 * <p>
 	 * Multiple processes trying to elect themselves leaders at exactly the same
-	 * time (rounded to seconds) using the same {@link #newCommitter()} identity
-	 * strings, for the same term, may generate the same ObjectId for the
-	 * election commit and falsely assume they have both won.
+	 * time (rounded to seconds) using the same
+	 * {@link #newCommitter(ProposedTimestamp)} identity strings, for the same
+	 * term, may generate the same ObjectId for the election commit and falsely
+	 * assume they have both won.
 	 * <p>
 	 * Candidates add this tag to their election ballot commit to disambiguate
 	 * the election. The tag only needs to be unique for a given triplet of
-	 * {@link #newCommitter()}, system time (rounded to seconds), and term. If
-	 * every replica in the system uses a unique {@code newCommitter} (such as
-	 * including the host name after the {@code "@"} in the email address) the
-	 * tag could be the empty string.
+	 * {@link #newCommitter(ProposedTimestamp)}, system time (rounded to
+	 * seconds), and term. If every replica in the system uses a unique
+	 * {@code newCommitter} (such as including the host name after the
+	 * {@code "@"} in the email address) the tag could be the empty string.
 	 * <p>
 	 * The default implementation generates a few bytes of random data.
 	 *
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/LocalReplica.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/LocalReplica.java
index e297bca..907eecb 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/LocalReplica.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/LocalReplica.java
@@ -64,6 +64,8 @@
 import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.revwalk.RevWalk;
 import org.eclipse.jgit.transport.ReceiveCommand;
+import org.eclipse.jgit.util.time.MonotonicClock;
+import org.eclipse.jgit.util.time.ProposedTimestamp;
 
 /** Ketch replica running on the same system as the {@link KetchLeader}. */
 public class LocalReplica extends KetchReplica {
@@ -119,9 +121,11 @@ protected void startPush(final ReplicaPushRequest req) {
 		getSystem().getExecutor().execute(new Runnable() {
 			@Override
 			public void run() {
-				try (Repository git = getLeader().openRepository()) {
+				MonotonicClock clk = getSystem().getClock();
+				try (Repository git = getLeader().openRepository();
+						ProposedTimestamp ts = clk.propose()) {
 					try {
-						update(git, req);
+						update(git, req, ts);
 						req.done(git);
 					} catch (Throwable err) {
 						req.setException(git, err);
@@ -139,8 +143,8 @@ protected void blockingFetch(Repository repo, ReplicaFetchRequest req)
 		throw new IOException(KetchText.get().cannotFetchFromLocalReplica);
 	}
 
-	private void update(Repository git, ReplicaPushRequest req)
-			throws IOException {
+	private void update(Repository git, ReplicaPushRequest req,
+			ProposedTimestamp ts) throws IOException {
 		RefDatabase refdb = git.getRefDatabase();
 		CommitMethod method = getCommitMethod();
 
@@ -156,7 +160,8 @@ private void update(Repository git, ReplicaPushRequest req)
 		}
 
 		BatchRefUpdate batch = refdb.newBatchUpdate();
-		batch.setRefLogIdent(getSystem().newCommitter());
+		batch.addProposedTimestamp(ts);
+		batch.setRefLogIdent(getSystem().newCommitter(ts));
 		batch.setRefLogMessage("ketch", false); //$NON-NLS-1$
 		batch.setAllowNonFastForwards(true);
 
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/Proposal.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/Proposal.java
index 0876eb5..12d3f4c 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/Proposal.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/Proposal.java
@@ -67,6 +67,7 @@
 import org.eclipse.jgit.revwalk.RevWalk;
 import org.eclipse.jgit.transport.PushCertificate;
 import org.eclipse.jgit.transport.ReceiveCommand;
+import org.eclipse.jgit.util.time.ProposedTimestamp;
 
 /**
  * A proposal to be applied in a Ketch system.
@@ -123,6 +124,8 @@ public boolean isDone() {
 	private PersonIdent author;
 	private String message;
 	private PushCertificate pushCert;
+
+	private List<ProposedTimestamp> timestamps;
 	private final List<Runnable> listeners = new CopyOnWriteArrayList<>();
 	private final AtomicReference<State> state = new AtomicReference<>(NEW);
 
@@ -223,6 +226,31 @@ public Proposal setPushCertificate(@Nullable PushCertificate cert) {
 	}
 
 	/**
+	 * @return timestamps that Ketch must block for. These may have been used as
+	 *         commit times inside the objects involved in the proposal.
+	 */
+	public List<ProposedTimestamp> getProposedTimestamps() {
+		if (timestamps != null) {
+			return timestamps;
+		}
+		return Collections.emptyList();
+	}
+
+	/**
+	 * Request the proposal to wait for the affected timestamps to resolve.
+	 *
+	 * @param ts
+	 * @return {@code this}.
+	 */
+	public Proposal addProposedTimestamp(ProposedTimestamp ts) {
+		if (timestamps == null) {
+			timestamps = new ArrayList<>(4);
+		}
+		timestamps.add(ts);
+		return this;
+	}
+
+	/**
 	 * Add a callback to be invoked when the proposal is done.
 	 * <p>
 	 * A proposal is done when it has entered either {@link State#EXECUTED} or
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/ProposalRound.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/ProposalRound.java
index d34477a..ddd7059 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/ProposalRound.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/ProposalRound.java
@@ -46,12 +46,16 @@
 import static org.eclipse.jgit.internal.ketch.Proposal.State.RUNNING;
 
 import java.io.IOException;
+import java.time.Duration;
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.TimeoutException;
+import java.util.stream.Collectors;
 
 import org.eclipse.jgit.annotations.Nullable;
 import org.eclipse.jgit.internal.storage.reftree.Command;
@@ -65,6 +69,7 @@
 import org.eclipse.jgit.revwalk.RevCommit;
 import org.eclipse.jgit.revwalk.RevWalk;
 import org.eclipse.jgit.transport.ReceiveCommand;
+import org.eclipse.jgit.util.time.ProposedTimestamp;
 
 /** A {@link Round} that aggregates and sends user {@link Proposal}s. */
 class ProposalRound extends Round {
@@ -123,8 +128,10 @@ void start() throws IOException {
 		}
 		try {
 			ObjectId id;
-			try (Repository git = leader.openRepository()) {
-				id = insertProposals(git);
+			try (Repository git = leader.openRepository();
+					ProposedTimestamp ts = getSystem().getClock().propose()) {
+				id = insertProposals(git, ts);
+				blockUntil(ts);
 			}
 			runAsync(id);
 		} catch (NoOp e) {
@@ -143,16 +150,16 @@ void start() throws IOException {
 		}
 	}
 
-	private ObjectId insertProposals(Repository git)
+	private ObjectId insertProposals(Repository git, ProposedTimestamp ts)
 			throws IOException, NoOp {
 		ObjectId id;
 		try (ObjectInserter inserter = git.newObjectInserter()) {
 			// TODO(sop) Process signed push certificates.
 
 			if (queuedTree != null) {
-				id = insertSingleProposal(git, inserter);
+				id = insertSingleProposal(git, ts, inserter);
 			} else {
-				id = insertMultiProposal(git, inserter);
+				id = insertMultiProposal(git, ts, inserter);
 			}
 
 			stageCommands = makeStageList(git, inserter);
@@ -161,7 +168,7 @@ private ObjectId insertProposals(Repository git)
 		return id;
 	}
 
-	private ObjectId insertSingleProposal(Repository git,
+	private ObjectId insertSingleProposal(Repository git, ProposedTimestamp ts,
 			ObjectInserter inserter) throws IOException, NoOp {
 		// Fast path: tree is passed in with all proposals applied.
 		ObjectId treeId = queuedTree.writeTree(inserter);
@@ -183,13 +190,13 @@ private ObjectId insertSingleProposal(Repository git,
 		if (!ObjectId.zeroId().equals(acceptedOldIndex)) {
 			b.setParentId(acceptedOldIndex);
 		}
-		b.setCommitter(leader.getSystem().newCommitter());
+		b.setCommitter(leader.getSystem().newCommitter(ts));
 		b.setAuthor(p.getAuthor() != null ? p.getAuthor() : b.getCommitter());
 		b.setMessage(message(p));
 		return inserter.insert(b);
 	}
 
-	private ObjectId insertMultiProposal(Repository git,
+	private ObjectId insertMultiProposal(Repository git, ProposedTimestamp ts,
 			ObjectInserter inserter) throws IOException, NoOp {
 		// The tree was not passed in, or there are multiple proposals
 		// each needing their own commit. Reset the tree and replay each
@@ -208,7 +215,7 @@ private ObjectId insertMultiProposal(Repository git,
 			}
 		}
 
-		PersonIdent committer = leader.getSystem().newCommitter();
+		PersonIdent committer = leader.getSystem().newCommitter(ts);
 		for (Proposal p : todo) {
 			if (!tree.apply(p.getCommands())) {
 				// This should not occur, previously during queuing the
@@ -292,6 +299,20 @@ private List<ReceiveCommand> makeStageList(Repository git,
 		return b.makeStageList(newObjs, git, inserter);
 	}
 
+	private void blockUntil(ProposedTimestamp ts)
+			throws TimeIsUncertainException {
+		List<ProposedTimestamp> times = todo.stream()
+				.flatMap(p -> p.getProposedTimestamps().stream())
+				.collect(Collectors.toCollection(ArrayList::new));
+		times.add(ts);
+
+		try {
+			Duration maxWait = getSystem().getMaxWaitForMonotonicClock();
+			ProposedTimestamp.blockUntil(times, maxWait);
+		} catch (InterruptedException | TimeoutException e) {
+			throw new TimeIsUncertainException(e);
+		}
+	}
 
 	private static class NoOp extends Exception {
 		private static final long serialVersionUID = 1L;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/RemoteGitReplica.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/RemoteGitReplica.java
index 6f4a178..396fbdd 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/RemoteGitReplica.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/RemoteGitReplica.java
@@ -44,13 +44,13 @@
 package org.eclipse.jgit.internal.ketch;
 
 import static org.eclipse.jgit.internal.ketch.KetchReplica.CommitMethod.ALL_REFS;
+import static org.eclipse.jgit.lib.Ref.Storage.NETWORK;
 import static org.eclipse.jgit.transport.ReceiveCommand.Result.LOCK_FAILURE;
 import static org.eclipse.jgit.transport.ReceiveCommand.Result.NOT_ATTEMPTED;
 import static org.eclipse.jgit.transport.ReceiveCommand.Result.OK;
 import static org.eclipse.jgit.transport.ReceiveCommand.Result.REJECTED_NODELETE;
 import static org.eclipse.jgit.transport.ReceiveCommand.Result.REJECTED_NONFASTFORWARD;
 import static org.eclipse.jgit.transport.ReceiveCommand.Result.REJECTED_OTHER_REASON;
-import static org.eclipse.jgit.lib.Ref.Storage.NETWORK;
 
 import java.io.IOException;
 import java.util.ArrayList;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/Round.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/Round.java
index 1335b85..dd8e568 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/Round.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/Round.java
@@ -75,6 +75,10 @@ abstract class Round {
 		this.acceptedOldIndex = head;
 	}
 
+	KetchSystem getSystem() {
+		return leader.getSystem();
+	}
+
 	/**
 	 * Creates a commit for {@code refs/txn/accepted} and calls
 	 * {@link #runAsync(AnyObjectId)} to begin execution of the round across
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/TimeIsUncertainException.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/TimeIsUncertainException.java
new file mode 100644
index 0000000..7223f55
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/TimeIsUncertainException.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2016, Google Inc.
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ *   copyright notice, this list of conditions and the following
+ *   disclaimer in the documentation and/or other materials provided
+ *   with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ *   names of its contributors may be used to endorse or promote
+ *   products derived from this software without specific prior
+ *   written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.eclipse.jgit.internal.ketch;
+
+import java.io.IOException;
+
+import org.eclipse.jgit.internal.JGitText;
+
+class TimeIsUncertainException extends IOException {
+	private static final long serialVersionUID = 1L;
+
+	TimeIsUncertainException() {
+		super(JGitText.get().timeIsUncertain);
+	}
+
+	TimeIsUncertainException(Exception e) {
+		super(JGitText.get().timeIsUncertain, e);
+	}
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlockCache.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlockCache.java
index ecd4b23..f7decf1 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlockCache.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlockCache.java
@@ -145,6 +145,8 @@ public static DfsBlockCache getInstance() {
 	 * <p>
 	 * If a pack file has a native size, a whole multiple of the native size
 	 * will be used until it matches this size.
+	 * <p>
+	 * The value for blockSize must be a power of 2.
 	 */
 	private final int blockSize;
 
@@ -175,13 +177,14 @@ public static DfsBlockCache getInstance() {
 	/** Number of bytes currently loaded in the cache. */
 	private volatile long liveBytes;
 
+	@SuppressWarnings("unchecked")
 	private DfsBlockCache(final DfsBlockCacheConfig cfg) {
 		tableSize = tableSize(cfg);
 		if (tableSize < 1)
 			throw new IllegalArgumentException(JGitText.get().tSizeMustBeGreaterOrEqual1);
 
 		table = new AtomicReferenceArray<HashEntry>(tableSize);
-		loadLocks = new ReentrantLock[32];
+		loadLocks = new ReentrantLock[cfg.getConcurrencyLevel()];
 		for (int i = 0; i < loadLocks.length; i++)
 			loadLocks[i] = new ReentrantLock(true /* fair */);
 
@@ -260,20 +263,22 @@ DfsPackFile getOrCreate(DfsPackDescription dsc, DfsPackKey key) {
 		// TODO This table grows without bound. It needs to clean up
 		// entries that aren't in cache anymore, and aren't being used
 		// by a live DfsObjDatabase reference.
-		synchronized (packCache) {
-			DfsPackFile pack = packCache.get(dsc);
-			if (pack != null && pack.invalid()) {
-				packCache.remove(dsc);
-				pack = null;
-			}
-			if (pack == null) {
-				if (key == null)
-					key = new DfsPackKey();
-				pack = new DfsPackFile(this, dsc, key);
-				packCache.put(dsc, pack);
-			}
+
+		DfsPackFile pack = packCache.get(dsc);
+		if (pack != null && !pack.invalid()) {
 			return pack;
 		}
+
+		// 'pack' either didn't exist or was invalid. Compute a new
+		// entry atomically (guaranteed by ConcurrentHashMap).
+		return packCache.compute(dsc, (k, v) -> {
+			if (v != null && !v.invalid()) { // valid value added by
+				return v;                    // another thread
+			} else {
+				return new DfsPackFile(
+						this, dsc, key != null ? key : new DfsPackKey());
+			}
+		});
 	}
 
 	private int hash(int packHash, long off) {
@@ -416,6 +421,7 @@ private void creditSpace(int credit) {
 		clockLock.unlock();
 	}
 
+	@SuppressWarnings("unchecked")
 	private void addToClock(Ref ref, int credit) {
 		clockLock.lock();
 		try {
@@ -500,9 +506,7 @@ private <T> Ref<T> scanRef(HashEntry n, DfsPackKey pack, long position) {
 	}
 
 	void remove(DfsPackFile pack) {
-		synchronized (packCache) {
-			packCache.remove(pack.getPackDescription());
-		}
+		packCache.remove(pack.getPackDescription());
 	}
 
 	private int slot(DfsPackKey pack, long position) {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlockCacheConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlockCacheConfig.java
index a7d13de..089bfa4 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlockCacheConfig.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlockCacheConfig.java
@@ -47,6 +47,7 @@
 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_DFS_SECTION;
 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_BLOCK_LIMIT;
 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_BLOCK_SIZE;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_CONCURRENCY_LEVEL;
 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_STREAM_RATIO;
 
 import java.text.MessageFormat;
@@ -65,12 +66,14 @@ public class DfsBlockCacheConfig {
 	private long blockLimit;
 	private int blockSize;
 	private double streamRatio;
+	private int concurrencyLevel;
 
 	/** Create a default configuration. */
 	public DfsBlockCacheConfig() {
 		setBlockLimit(32 * MB);
 		setBlockSize(64 * KB);
 		setStreamRatio(0.30);
+		setConcurrencyLevel(32);
 	}
 
 	/**
@@ -103,10 +106,38 @@ public int getBlockSize() {
 	/**
 	 * @param newSize
 	 *            size in bytes of a single window read in from the pack file.
+	 *            The value must be a power of 2.
 	 * @return {@code this}
 	 */
 	public DfsBlockCacheConfig setBlockSize(final int newSize) {
-		blockSize = Math.max(512, newSize);
+		int size = Math.max(512, newSize);
+		if ((size & (size - 1)) != 0) {
+			throw new IllegalArgumentException(
+					JGitText.get().blockSizeNotPowerOf2);
+		}
+		blockSize = size;
+		return this;
+	}
+
+	/**
+	 * @return the estimated number of threads concurrently accessing the cache.
+	 *         <b>Default is 32.</b>
+	 * @since 4.6
+	 */
+	public int getConcurrencyLevel() {
+		return concurrencyLevel;
+	}
+
+	/**
+	 * @param newConcurrencyLevel
+	 *            the estimated number of threads concurrently accessing the
+	 *            cache.
+	 * @return {@code this}
+	 * @since 4.6
+	 */
+	public DfsBlockCacheConfig setConcurrencyLevel(
+			final int newConcurrencyLevel) {
+		concurrencyLevel = newConcurrencyLevel;
 		return this;
 	}
 
@@ -154,6 +185,12 @@ public DfsBlockCacheConfig fromConfig(final Config rc) {
 				CONFIG_KEY_BLOCK_SIZE,
 				getBlockSize()));
 
+		setConcurrencyLevel(rc.getInt(
+				CONFIG_CORE_SECTION,
+				CONFIG_DFS_SECTION,
+				CONFIG_KEY_CONCURRENCY_LEVEL,
+				getConcurrencyLevel()));
+
 		String v = rc.getString(
 				CONFIG_CORE_SECTION,
 				CONFIG_DFS_SECTION,
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsInserter.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsInserter.java
index a5e920a..c179e77 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsInserter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsInserter.java
@@ -312,8 +312,7 @@ PackIndex writePackIndex(DfsPackDescription pack, byte[] packHash,
 		}
 
 		DfsOutputStream os = db.writeFile(pack, INDEX);
-		try {
-			CountingOutputStream cnt = new CountingOutputStream(os);
+		try (CountingOutputStream cnt = new CountingOutputStream(os)) {
 			if (buf != null)
 				buf.writeTo(cnt, null);
 			else
@@ -321,7 +320,9 @@ PackIndex writePackIndex(DfsPackDescription pack, byte[] packHash,
 			pack.addFileExt(INDEX);
 			pack.setFileSize(INDEX, cnt.getCount());
 		} finally {
-			os.close();
+			if (buf != null) {
+				buf.close();
+			}
 		}
 		return packIndex;
 	}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReader.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReader.java
index 2f61dea..8c93295 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReader.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReader.java
@@ -113,6 +113,7 @@ public final class DfsReader extends ObjectReader implements ObjectReuseAsIs {
 
 	DfsReader(DfsObjDatabase db) {
 		this.db = db;
+		this.streamFileThreshold = db.getReaderOptions().getStreamFileThreshold();
 	}
 
 	DfsReaderOptions getOptions() {
@@ -125,10 +126,6 @@ DeltaBaseCache getDeltaBaseCache() {
 		return baseCache;
 	}
 
-	int getStreamFileThreshold() {
-		return getOptions().getStreamFileThreshold();
-	}
-
 	@Override
 	public ObjectReader newReader() {
 		return new DfsReader(db);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsRefUpdate.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsRefUpdate.java
index d872f97..1f26fe3 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsRefUpdate.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsRefUpdate.java
@@ -47,9 +47,9 @@
 
 import org.eclipse.jgit.lib.ObjectIdRef;
 import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.lib.Ref.Storage;
 import org.eclipse.jgit.lib.RefUpdate;
 import org.eclipse.jgit.lib.SymbolicRef;
-import org.eclipse.jgit.lib.Ref.Storage;
 import org.eclipse.jgit.revwalk.RevObject;
 import org.eclipse.jgit.revwalk.RevTag;
 import org.eclipse.jgit.revwalk.RevWalk;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/InMemoryRepository.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/InMemoryRepository.java
index 6f390a4..fd21397 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/InMemoryRepository.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/InMemoryRepository.java
@@ -16,6 +16,7 @@
 import java.util.concurrent.locks.ReadWriteLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 
+import org.eclipse.jgit.annotations.Nullable;
 import org.eclipse.jgit.internal.storage.pack.PackExt;
 import org.eclipse.jgit.lib.BatchRefUpdate;
 import org.eclipse.jgit.lib.ObjectId;
@@ -54,6 +55,7 @@ public InMemoryRepository build() throws IOException {
 
 	private final DfsObjDatabase objdb;
 	private final RefDatabase refdb;
+	private String gitwebDescription;
 	private boolean performsAtomicTransactions = true;
 
 	/**
@@ -94,6 +96,17 @@ public void setPerformsAtomicTransactions(boolean atomic) {
 		performsAtomicTransactions = atomic;
 	}
 
+	@Override
+	@Nullable
+	public String getGitwebDescription() {
+		return gitwebDescription;
+	}
+
+	@Override
+	public void setGitwebDescription(@Nullable String d) {
+		gitwebDescription = d;
+	}
+
 	private class MemObjDatabase extends DfsObjDatabase {
 		private List<DfsPackDescription> packs = new ArrayList<DfsPackDescription>();
 
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/BasePackBitmapIndex.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/BasePackBitmapIndex.java
index 3c101e6..30e973e 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/BasePackBitmapIndex.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/BasePackBitmapIndex.java
@@ -43,11 +43,11 @@
 
 package org.eclipse.jgit.internal.storage.file;
 
-import com.googlecode.javaewah.EWAHCompressedBitmap;
-
 import org.eclipse.jgit.lib.AnyObjectId;
 import org.eclipse.jgit.lib.ObjectIdOwnerMap;
 
+import com.googlecode.javaewah.EWAHCompressedBitmap;
+
 /**
  * Base implementation of the PackBitmapIndex.
  */
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/BitSet.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/BitSet.java
index ddb5ff0..bafae87 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/BitSet.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/BitSet.java
@@ -96,7 +96,7 @@ final EWAHCompressedBitmap toEWAHCompressedBitmap() {
 			}
 
 			if (lastNonEmptyWord != 0)
-				compressed.add(lastNonEmptyWord);
+				compressed.addWord(lastNonEmptyWord);
 
 			if (runningEmptyWords > 0) {
 				compressed.addStreamOfEmptyWords(false, runningEmptyWords);
@@ -107,7 +107,7 @@ final EWAHCompressedBitmap toEWAHCompressedBitmap() {
 		}
 		int bitsThatMatter = 64 - Long.numberOfLeadingZeros(lastNonEmptyWord);
 		if (bitsThatMatter > 0)
-			compressed.add(lastNonEmptyWord, bitsThatMatter);
+			compressed.addWord(lastNonEmptyWord, bitsThatMatter);
 		return compressed;
 	}
 
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/BitmapIndexImpl.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/BitmapIndexImpl.java
index b27bcc4..b18a06f 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/BitmapIndexImpl.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/BitmapIndexImpl.java
@@ -47,9 +47,6 @@
 import java.util.Iterator;
 import java.util.NoSuchElementException;
 
-import com.googlecode.javaewah.EWAHCompressedBitmap;
-import com.googlecode.javaewah.IntIterator;
-
 import org.eclipse.jgit.internal.JGitText;
 import org.eclipse.jgit.lib.AnyObjectId;
 import org.eclipse.jgit.lib.BitmapIndex;
@@ -59,6 +56,9 @@
 import org.eclipse.jgit.lib.ObjectIdOwnerMap;
 import org.eclipse.jgit.util.BlockList;
 
+import com.googlecode.javaewah.EWAHCompressedBitmap;
+import com.googlecode.javaewah.IntIterator;
+
 /** A compressed bitmap representation of the entire object graph. */
 public class BitmapIndexImpl implements BitmapIndex {
 	private static final int EXTRA_BITS = 10 * 1024;
@@ -504,10 +504,10 @@ public int getType() {
 	static final EWAHCompressedBitmap ones(int sizeInBits) {
 		EWAHCompressedBitmap mask = new EWAHCompressedBitmap();
 		mask.addStreamOfEmptyWords(
-				true, sizeInBits / EWAHCompressedBitmap.wordinbits);
-		int remaining = sizeInBits % EWAHCompressedBitmap.wordinbits;
+				true, sizeInBits / EWAHCompressedBitmap.WORD_IN_BITS);
+		int remaining = sizeInBits % EWAHCompressedBitmap.WORD_IN_BITS;
 		if (remaining > 0)
-			mask.add((1L << remaining) - 1, remaining);
+			mask.addWord((1L << remaining) - 1, remaining);
 		return mask;
 	}
 }
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileRepository.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileRepository.java
index 53fd37e..0388acb 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileRepository.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileRepository.java
@@ -53,9 +53,13 @@
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.text.MessageFormat;
+import java.text.ParseException;
 import java.util.HashSet;
+import java.util.Objects;
 import java.util.Set;
 
+import org.eclipse.jgit.annotations.Nullable;
+import org.eclipse.jgit.api.errors.JGitInternalException;
 import org.eclipse.jgit.attributes.AttributesNode;
 import org.eclipse.jgit.attributes.AttributesNodeProvider;
 import org.eclipse.jgit.errors.ConfigInvalidException;
@@ -63,15 +67,16 @@
 import org.eclipse.jgit.events.ConfigChangedListener;
 import org.eclipse.jgit.events.IndexChangedEvent;
 import org.eclipse.jgit.internal.JGitText;
-import org.eclipse.jgit.internal.storage.reftree.RefTreeDatabase;
 import org.eclipse.jgit.internal.storage.file.ObjectDirectory.AlternateHandle;
 import org.eclipse.jgit.internal.storage.file.ObjectDirectory.AlternateRepository;
+import org.eclipse.jgit.internal.storage.reftree.RefTreeDatabase;
 import org.eclipse.jgit.lib.BaseRepositoryBuilder;
 import org.eclipse.jgit.lib.ConfigConstants;
 import org.eclipse.jgit.lib.Constants;
 import org.eclipse.jgit.lib.CoreConfig.HideDotFiles;
 import org.eclipse.jgit.lib.CoreConfig.SymLinks;
 import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ProgressMonitor;
 import org.eclipse.jgit.lib.Ref;
 import org.eclipse.jgit.lib.RefDatabase;
 import org.eclipse.jgit.lib.RefUpdate;
@@ -79,8 +84,11 @@
 import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.storage.file.FileBasedConfig;
 import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
+import org.eclipse.jgit.storage.pack.PackConfig;
 import org.eclipse.jgit.util.FS;
 import org.eclipse.jgit.util.FileUtils;
+import org.eclipse.jgit.util.IO;
+import org.eclipse.jgit.util.RawParseUtils;
 import org.eclipse.jgit.util.StringUtils;
 import org.eclipse.jgit.util.SystemReader;
 
@@ -110,16 +118,13 @@
  *
  */
 public class FileRepository extends Repository {
+	private static final String UNNAMED = "Unnamed repository; edit this file to name it for gitweb."; //$NON-NLS-1$
+
 	private final FileBasedConfig systemConfig;
-
 	private final FileBasedConfig userConfig;
-
 	private final FileBasedConfig repoConfig;
-
 	private final RefDatabase refs;
-
 	private final ObjectDirectory objectDatabase;
-
 	private FileSnapshot snapshot;
 
 	/**
@@ -177,10 +182,12 @@ public FileRepository(final BaseRepositoryBuilder options) throws IOException {
 					getFS());
 		else
 			systemConfig = new FileBasedConfig(null, FS.DETECTED) {
+				@Override
 				public void load() {
 					// empty, do not load
 				}
 
+				@Override
 				public boolean isOutdated() {
 					// regular class would bomb here
 					return false;
@@ -197,6 +204,7 @@ public boolean isOutdated() {
 		loadRepoConfig();
 
 		repoConfig.addChangeListener(new ConfigChangedListener() {
+			@Override
 			public void onConfigChanged(ConfigChangedEvent event) {
 				fireEvent(event);
 			}
@@ -279,6 +287,7 @@ private void loadRepoConfig() throws IOException {
 	 * @throws IOException
 	 *             in case of IO problem
 	 */
+	@Override
 	public void create(boolean bare) throws IOException {
 		final FileBasedConfig cfg = getConfig();
 		if (cfg.getFile().exists()) {
@@ -376,21 +385,20 @@ public File getObjectsDirectory() {
 		return objectDatabase.getDirectory();
 	}
 
-	/**
-	 * @return the object database which stores this repository's data.
-	 */
+	/** @return the object database storing this repository's data. */
+	@Override
 	public ObjectDirectory getObjectDatabase() {
 		return objectDatabase;
 	}
 
 	/** @return the reference database which stores the reference namespace. */
+	@Override
 	public RefDatabase getRefDatabase() {
 		return refs;
 	}
 
-	/**
-	 * @return the configuration of this repository
-	 */
+	/** @return the configuration of this repository. */
+	@Override
 	public FileBasedConfig getConfig() {
 		if (systemConfig.isOutdated()) {
 			try {
@@ -416,6 +424,59 @@ public FileBasedConfig getConfig() {
 		return repoConfig;
 	}
 
+	@Override
+	@Nullable
+	public String getGitwebDescription() throws IOException {
+		String d;
+		try {
+			d = RawParseUtils.decode(IO.readFully(descriptionFile()));
+		} catch (FileNotFoundException err) {
+			return null;
+		}
+		if (d != null) {
+			d = d.trim();
+			if (d.isEmpty() || UNNAMED.equals(d)) {
+				return null;
+			}
+		}
+		return d;
+	}
+
+	@Override
+	public void setGitwebDescription(@Nullable String description)
+			throws IOException {
+		String old = getGitwebDescription();
+		if (Objects.equals(old, description)) {
+			return;
+		}
+
+		File path = descriptionFile();
+		LockFile lock = new LockFile(path);
+		if (!lock.lock()) {
+			throw new IOException(MessageFormat.format(JGitText.get().lockError,
+					path.getAbsolutePath()));
+		}
+		try {
+			String d = description;
+			if (d != null) {
+				d = d.trim();
+				if (!d.isEmpty()) {
+					d += '\n';
+				}
+			} else {
+				d = ""; //$NON-NLS-1$
+			}
+			lock.write(Constants.encode(d));
+			lock.commit();
+		} finally {
+			lock.unlock();
+		}
+	}
+
+	private File descriptionFile() {
+		return new File(getDirectory(), "description"); //$NON-NLS-1$
+	}
+
 	/**
 	 * Objects known to exist but not expressed by {@link #getAllRefs()}.
 	 * <p>
@@ -426,6 +487,7 @@ public FileBasedConfig getConfig() {
 	 *
 	 * @return unmodifiable collection of other known objects.
 	 */
+	@Override
 	public Set<ObjectId> getAdditionalHaves() {
 		HashSet<ObjectId> r = new HashSet<ObjectId>();
 		for (AlternateHandle d : objectDatabase.myAlternates()) {
@@ -464,9 +526,7 @@ public void scanForRepoChanges() throws IOException {
 		detectIndexChanges();
 	}
 
-	/**
-	 * Detect index changes.
-	 */
+	/** Detect index changes. */
 	private void detectIndexChanges() {
 		if (isBare())
 			return;
@@ -490,6 +550,7 @@ public void notifyIndexChanged() {
 	 *         named ref does not exist.
 	 * @throws IOException the ref could not be accessed.
 	 */
+	@Override
 	public ReflogReader getReflogReader(String refName) throws IOException {
 		Ref ref = findRef(refName);
 		if (ref != null)
@@ -527,6 +588,7 @@ protected AttributesNodeProviderImpl(Repository repo) {
 			globalAttributesNode = new GlobalAttributesNode(repo);
 		}
 
+		@Override
 		public AttributesNode getInfoAttributesNode() throws IOException {
 			if (infoAttributesNode instanceof InfoAttributesNode)
 				infoAttributesNode = ((InfoAttributesNode) infoAttributesNode)
@@ -534,6 +596,7 @@ public AttributesNode getInfoAttributesNode() throws IOException {
 			return infoAttributesNode;
 		}
 
+		@Override
 		public AttributesNode getGlobalAttributesNode() throws IOException {
 			if (globalAttributesNode instanceof GlobalAttributesNode)
 				globalAttributesNode = ((GlobalAttributesNode) globalAttributesNode)
@@ -555,4 +618,16 @@ static void loadRulesFromFile(AttributesNode r, File attrs)
 
 	}
 
+	@Override
+	public void autoGC(ProgressMonitor monitor) {
+		GC gc = new GC(this);
+		gc.setPackConfig(new PackConfig(this));
+		gc.setProgressMonitor(monitor);
+		gc.setAuto(true);
+		try {
+			gc.gc();
+		} catch (ParseException | IOException e) {
+			throw new JGitInternalException(JGitText.get().gcFailed, e);
+		}
+	}
 }
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileSnapshot.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileSnapshot.java
index fbd1dbf..be49f78 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileSnapshot.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileSnapshot.java
@@ -293,12 +293,6 @@ private boolean isModified(final long currLastModified) {
 			return false;
 		}
 
-		// Our lastRead flag may be old, refresh and retry
-		lastRead = System.currentTimeMillis();
-		if (notRacyClean(lastRead)) {
-			return false;
-		}
-
 		// We last read this path too close to its last observed
 		// modification time. We may have missed a modification.
 		// Scan again, to ensure we still see the same state.
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java
index a3e9430..b608416 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java
@@ -52,6 +52,10 @@
 import java.io.OutputStream;
 import java.nio.channels.Channels;
 import java.nio.channels.FileChannel;
+import java.nio.file.DirectoryStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.nio.file.StandardCopyOption;
 import java.text.MessageFormat;
 import java.text.ParseException;
@@ -62,12 +66,16 @@
 import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
 import java.util.TreeMap;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import org.eclipse.jgit.annotations.NonNull;
 import org.eclipse.jgit.dircache.DirCacheIterator;
@@ -100,6 +108,8 @@
 import org.eclipse.jgit.util.FileUtils;
 import org.eclipse.jgit.util.GitDateParser;
 import org.eclipse.jgit.util.SystemReader;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * A garbage collector for git {@link FileRepository}. Instances of this class
@@ -109,10 +119,27 @@
  * adapted to FileRepositories.
  */
 public class GC {
+	private final static Logger LOG = LoggerFactory
+			.getLogger(GC.class);
+
 	private static final String PRUNE_EXPIRE_DEFAULT = "2.weeks.ago"; //$NON-NLS-1$
 
 	private static final String PRUNE_PACK_EXPIRE_DEFAULT = "1.hour.ago"; //$NON-NLS-1$
 
+	private static final Pattern PATTERN_LOOSE_OBJECT = Pattern
+			.compile("[0-9a-fA-F]{38}"); //$NON-NLS-1$
+
+	private static final String PACK_EXT = "." + PackExt.PACK.getExtension();//$NON-NLS-1$
+
+	private static final String BITMAP_EXT = "." //$NON-NLS-1$
+			+ PackExt.BITMAP_INDEX.getExtension();
+
+	private static final String INDEX_EXT = "." + PackExt.INDEX.getExtension(); //$NON-NLS-1$
+
+	private static final int DEFAULT_AUTOPACKLIMIT = 50;
+
+	private static final int DEFAULT_AUTOLIMIT = 6700;
+
 	private final FileRepository repo;
 
 	private ProgressMonitor pm;
@@ -143,6 +170,11 @@ public class GC {
 	private long lastRepackTime;
 
 	/**
+	 * Whether gc should do automatic housekeeping
+	 */
+	private boolean automatic;
+
+	/**
 	 * Creates a new garbage collector with default values. An expirationTime of
 	 * two weeks and <code>null</code> as progress monitor will be used.
 	 *
@@ -163,6 +195,10 @@ public GC(FileRepository repo) {
 	 * <li>prune all loose objects which are now reachable by packs</li>
 	 * </ul>
 	 *
+	 * If {@link #setAuto(boolean)} was set to {@code true} {@code gc} will
+	 * first check whether any housekeeping is required; if not, it exits
+	 * without performing any work.
+	 *
 	 * @return the collection of {@link PackFile}'s which are newly created
 	 * @throws IOException
 	 * @throws ParseException
@@ -170,6 +206,9 @@ public GC(FileRepository repo) {
 	 *             parsed
 	 */
 	public Collection<PackFile> gc() throws IOException, ParseException {
+		if (automatic && !needGc()) {
+			return Collections.emptyList();
+		}
 		pm.start(6 /* tasks */);
 		packRefs();
 		// TODO: implement reflog_expire(pm, repo);
@@ -325,45 +364,48 @@ public void prune(Set<ObjectId> objectsToKeep) throws IOException,
 		Set<ObjectId> indexObjects = null;
 		File objects = repo.getObjectsDirectory();
 		String[] fanout = objects.list();
-		if (fanout != null && fanout.length > 0) {
-			pm.beginTask(JGitText.get().pruneLooseUnreferencedObjects,
-					fanout.length);
-			try {
-				for (String d : fanout) {
-					pm.update(1);
-					if (d.length() != 2)
+		if (fanout == null || fanout.length == 0) {
+			return;
+		}
+		pm.beginTask(JGitText.get().pruneLooseUnreferencedObjects,
+				fanout.length);
+		try {
+			for (String d : fanout) {
+				pm.update(1);
+				if (d.length() != 2)
+					continue;
+				File[] entries = new File(objects, d).listFiles();
+				if (entries == null)
+					continue;
+				for (File f : entries) {
+					String fName = f.getName();
+					if (fName.length() != Constants.OBJECT_ID_STRING_LENGTH - 2)
 						continue;
-					File[] entries = new File(objects, d).listFiles();
-					if (entries == null)
+					if (repo.getFS().lastModified(f) >= expireDate)
 						continue;
-					for (File f : entries) {
-						String fName = f.getName();
-						if (fName.length() != Constants.OBJECT_ID_STRING_LENGTH - 2)
+					try {
+						ObjectId id = ObjectId.fromString(d + fName);
+						if (objectsToKeep.contains(id))
 							continue;
-						if (repo.getFS().lastModified(f) >= expireDate)
+						if (indexObjects == null)
+							indexObjects = listNonHEADIndexObjects();
+						if (indexObjects.contains(id))
 							continue;
-						try {
-							ObjectId id = ObjectId.fromString(d + fName);
-							if (objectsToKeep.contains(id))
-								continue;
-							if (indexObjects == null)
-								indexObjects = listNonHEADIndexObjects();
-							if (indexObjects.contains(id))
-								continue;
-							deletionCandidates.put(id, f);
-						} catch (IllegalArgumentException notAnObject) {
-							// ignoring the file that does not represent loose
-							// object
-							continue;
-						}
+						deletionCandidates.put(id, f);
+					} catch (IllegalArgumentException notAnObject) {
+						// ignoring the file that does not represent loose
+						// object
+						continue;
 					}
 				}
-			} finally {
-				pm.endTask();
 			}
+		} finally {
+			pm.endTask();
 		}
-		if (deletionCandidates.isEmpty())
+
+		if (deletionCandidates.isEmpty()) {
 			return;
+		}
 
 		// From the set of current refs remove all those which have been handled
 		// during last repack(). Only those refs will survive which have been
@@ -433,12 +475,19 @@ public void prune(Set<ObjectId> objectsToKeep) throws IOException,
 		// loose objects. Make a last check, though, to avoid deleting objects
 		// that could have been referenced while the candidates list was being
 		// built (by an incoming push, for example).
+		Set<File> touchedFanout = new HashSet<>();
 		for (File f : deletionCandidates.values()) {
 			if (f.lastModified() < expireDate) {
 				f.delete();
+				touchedFanout.add(f.getParentFile());
 			}
 		}
 
+		for (File f : touchedFanout) {
+			FileUtils.delete(f,
+					FileUtils.EMPTY_DIRECTORIES_ONLY | FileUtils.IGNORE_ERRORS);
+		}
+
 		repo.getObjectDatabase().close();
 	}
 
@@ -625,6 +674,7 @@ else if (RefTreeNames.isRefTree(refdb, ref.getName()))
 			throw new IOException(e);
 		}
 		prunePacked();
+		deleteOrphans();
 
 		lastPackedRefs = refsBefore;
 		lastRepackTime = time;
@@ -632,6 +682,48 @@ else if (RefTreeNames.isRefTree(refdb, ref.getName()))
 	}
 
 	/**
+	 * Deletes orphans
+	 * <p>
+	 * A file is considered an orphan if it is either a "bitmap" or an index
+	 * file, and its corresponding pack file is missing in the list.
+	 * </p>
+	 */
+	private void deleteOrphans() {
+		Path packDir = Paths.get(repo.getObjectsDirectory().getAbsolutePath(),
+				"pack"); //$NON-NLS-1$
+		List<String> fileNames = null;
+		try (Stream<Path> files = Files.list(packDir)) {
+			fileNames = files.map(path -> path.getFileName().toString())
+					.filter(name -> {
+						return (name.endsWith(PACK_EXT)
+								|| name.endsWith(BITMAP_EXT)
+								|| name.endsWith(INDEX_EXT));
+					}).sorted(Collections.reverseOrder())
+					.collect(Collectors.toList());
+		} catch (IOException e1) {
+			// ignore
+		}
+		if (fileNames == null) {
+			return;
+		}
+
+		String base = null;
+		for (String n : fileNames) {
+			if (n.endsWith(PACK_EXT)) {
+				base = n.substring(0, n.lastIndexOf('.'));
+			} else {
+				if (base == null || !n.startsWith(base)) {
+					try {
+						Files.delete(new File(packDir.toFile(), n).toPath());
+					} catch (IOException e) {
+						LOG.error(e.getMessage(), e);
+					}
+				}
+			}
+		}
+	}
+
+	/**
 	 * @param ref
 	 *            the ref which log should be inspected
 	 * @param minTime only reflog entries not older then this time are processed
@@ -1081,4 +1173,114 @@ public void setPackExpire(Date packExpire) {
 		this.packExpire = packExpire;
 		packExpireAgeMillis = -1;
 	}
+
+	/**
+	 * Set the {@code gc --auto} option.
+	 *
+	 * With this option, gc checks whether any housekeeping is required; if not,
+	 * it exits without performing any work. Some JGit commands run
+	 * {@code gc --auto} after performing operations that could create many
+	 * loose objects.
+	 * <p/>
+	 * Housekeeping is required if there are too many loose objects or too many
+	 * packs in the repository. If the number of loose objects exceeds the value
+	 * of the gc.auto option JGit GC consolidates all existing packs into a
+	 * single pack (equivalent to {@code -A} option), whereas git-core would
+	 * combine all loose objects into a single pack using {@code repack -d -l}.
+	 * Setting the value of {@code gc.auto} to 0 disables automatic packing of
+	 * loose objects.
+	 * <p/>
+	 * If the number of packs exceeds the value of {@code gc.autoPackLimit},
+	 * then existing packs (except those marked with a .keep file) are
+	 * consolidated into a single pack by using the {@code -A} option of repack.
+	 * Setting {@code gc.autoPackLimit} to 0 disables automatic consolidation of
+	 * packs.
+	 * <p/>
+	 * Like git the following jgit commands run auto gc:
+	 * <ul>
+	 * <li>fetch</li>
+	 * <li>merge</li>
+	 * <li>rebase</li>
+	 * <li>receive-pack</li>
+	 * </ul>
+	 * The auto gc for receive-pack can be suppressed by setting the config
+	 * option {@code receive.autogc = false}
+	 *
+	 * @param auto
+	 *            defines whether gc should do automatic housekeeping
+	 * @since 4.5
+	 */
+	public void setAuto(boolean auto) {
+		this.automatic = auto;
+	}
+
+	private boolean needGc() {
+		if (tooManyPacks()) {
+			addRepackAllOption();
+		} else if (!tooManyLooseObjects()) {
+			return false;
+		}
+		// TODO run pre-auto-gc hook, if it fails return false
+		return true;
+	}
+
+	private void addRepackAllOption() {
+		// TODO: if JGit GC is enhanced to support repack's option -l this
+		// method needs to be implemented
+	}
+
+	/**
+	 * @return {@code true} if number of packs > gc.autopacklimit (default 50)
+	 */
+	boolean tooManyPacks() {
+		int autopacklimit = repo.getConfig().getInt(
+				ConfigConstants.CONFIG_GC_SECTION,
+				ConfigConstants.CONFIG_KEY_AUTOPACKLIMIT,
+				DEFAULT_AUTOPACKLIMIT);
+		if (autopacklimit <= 0) {
+			return false;
+		}
+		// JGit always creates two packfiles, one for the objects reachable from
+		// branches, and another one for the rest
+		return repo.getObjectDatabase().getPacks().size() > (autopacklimit + 1);
+	}
+
+	/**
+	 * Quickly estimate number of loose objects, SHA1 is distributed evenly so
+	 * counting objects in one directory (bucket 17) is sufficient
+	 *
+	 * @return {@code true} if number of loose objects > gc.auto (default 6700)
+	 */
+	boolean tooManyLooseObjects() {
+		int auto = repo.getConfig().getInt(ConfigConstants.CONFIG_GC_SECTION,
+				ConfigConstants.CONFIG_KEY_AUTO, DEFAULT_AUTOLIMIT);
+		if (auto <= 0) {
+			return false;
+		}
+		int n = 0;
+		int threshold = (auto + 255) / 256;
+		Path dir = repo.getObjectsDirectory().toPath().resolve("17"); //$NON-NLS-1$
+		if (!Files.exists(dir)) {
+			return false;
+		}
+		try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir,
+				new DirectoryStream.Filter<Path>() {
+
+					public boolean accept(Path file) throws IOException {
+						return Files.isRegularFile(file) && PATTERN_LOOSE_OBJECT
+								.matcher(file.getFileName().toString())
+								.matches();
+					}
+				})) {
+			for (Iterator<Path> iter = stream.iterator(); iter.hasNext();
+					iter.next()) {
+				if (++n > threshold) {
+					return true;
+				}
+			}
+		} catch (IOException e) {
+			LOG.error(e.getMessage(), e);
+		}
+		return false;
+	}
 }
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackBitmapIndex.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackBitmapIndex.java
index e743cb4..7fb8e6d 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackBitmapIndex.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackBitmapIndex.java
@@ -49,13 +49,13 @@
 import java.io.InputStream;
 import java.text.MessageFormat;
 
-import com.googlecode.javaewah.EWAHCompressedBitmap;
-
 import org.eclipse.jgit.errors.CorruptObjectException;
 import org.eclipse.jgit.internal.JGitText;
 import org.eclipse.jgit.lib.AnyObjectId;
 import org.eclipse.jgit.lib.ObjectId;
 
+import com.googlecode.javaewah.EWAHCompressedBitmap;
+
 /**
  * Logical representation of the bitmap data stored in the pack index.
  * {@link ObjectId}s are encoded as a single integer in the range [0,
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackBitmapIndexBuilder.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackBitmapIndexBuilder.java
index 4ff09a1..956e8de 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackBitmapIndexBuilder.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackBitmapIndexBuilder.java
@@ -50,8 +50,6 @@
 import java.util.List;
 import java.util.NoSuchElementException;
 
-import com.googlecode.javaewah.EWAHCompressedBitmap;
-
 import org.eclipse.jgit.internal.JGitText;
 import org.eclipse.jgit.internal.storage.file.BitmapIndexImpl.CompressedBitmap;
 import org.eclipse.jgit.internal.storage.pack.ObjectToPack;
@@ -63,6 +61,8 @@
 import org.eclipse.jgit.lib.ObjectIdOwnerMap;
 import org.eclipse.jgit.util.BlockList;
 
+import com.googlecode.javaewah.EWAHCompressedBitmap;
+
 /**
  * Helper for constructing {@link PackBitmapIndex}es.
  */
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackBitmapIndexRemapper.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackBitmapIndexRemapper.java
index 7cd68b6..2c462a7 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackBitmapIndexRemapper.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackBitmapIndexRemapper.java
@@ -47,15 +47,15 @@
 import java.util.Iterator;
 import java.util.NoSuchElementException;
 
-import com.googlecode.javaewah.EWAHCompressedBitmap;
-import com.googlecode.javaewah.IntIterator;
-
 import org.eclipse.jgit.internal.storage.file.BasePackBitmapIndex.StoredBitmap;
 import org.eclipse.jgit.lib.AnyObjectId;
 import org.eclipse.jgit.lib.BitmapIndex;
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.ObjectIdOwnerMap;
 
+import com.googlecode.javaewah.EWAHCompressedBitmap;
+import com.googlecode.javaewah.IntIterator;
+
 /**
  * A PackBitmapIndex that remaps the bitmaps in the previous index to the
  * positions in the new pack index. Note, unlike typical PackBitmapIndex
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackBitmapIndexV1.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackBitmapIndexV1.java
index a7ab00d..9d2c70b 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackBitmapIndexV1.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackBitmapIndexV1.java
@@ -49,8 +49,6 @@
 import java.text.MessageFormat;
 import java.util.Arrays;
 
-import com.googlecode.javaewah.EWAHCompressedBitmap;
-
 import org.eclipse.jgit.internal.JGitText;
 import org.eclipse.jgit.lib.AnyObjectId;
 import org.eclipse.jgit.lib.Constants;
@@ -59,6 +57,8 @@
 import org.eclipse.jgit.util.IO;
 import org.eclipse.jgit.util.NB;
 
+import com.googlecode.javaewah.EWAHCompressedBitmap;
+
 /**
  * Support for the pack bitmap index v1 format.
  *
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackBitmapIndexWriterV1.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackBitmapIndexWriterV1.java
index 8325e2e..f8f02e9 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackBitmapIndexWriterV1.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackBitmapIndexWriterV1.java
@@ -50,12 +50,11 @@
 import java.security.DigestOutputStream;
 import java.text.MessageFormat;
 
-import com.googlecode.javaewah.EWAHCompressedBitmap;
-
 import org.eclipse.jgit.internal.JGitText;
 import org.eclipse.jgit.internal.storage.file.PackBitmapIndexBuilder.StoredEntry;
 import org.eclipse.jgit.lib.Constants;
-import org.eclipse.jgit.util.io.SafeBufferedOutputStream;
+
+import com.googlecode.javaewah.EWAHCompressedBitmap;
 
 /**
  * Creates the version 1 pack bitmap index files.
@@ -74,7 +73,7 @@ public class PackBitmapIndexWriterV1 {
 	 */
 	public PackBitmapIndexWriterV1(final OutputStream dst) {
 		out = new DigestOutputStream(dst instanceof BufferedOutputStream ? dst
-				: new SafeBufferedOutputStream(dst),
+				: new BufferedOutputStream(dst),
 				Constants.newMessageDigest());
 		dataOutput = new SimpleDataOutput(out);
 	}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackIndexWriter.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackIndexWriter.java
index 6dfe74b..5153911 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackIndexWriter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackIndexWriter.java
@@ -56,7 +56,6 @@
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.transport.PackedObjectInfo;
 import org.eclipse.jgit.util.NB;
-import org.eclipse.jgit.util.io.SafeBufferedOutputStream;
 
 /**
  * Creates a table of contents to support random access by {@link PackFile}.
@@ -183,7 +182,7 @@ public static PackIndexWriter createVersion(final OutputStream dst,
 	 */
 	protected PackIndexWriter(final OutputStream dst) {
 		out = new DigestOutputStream(dst instanceof BufferedOutputStream ? dst
-				: new SafeBufferedOutputStream(dst),
+				: new BufferedOutputStream(dst),
 				Constants.newMessageDigest());
 		tmp = new byte[4 + Constants.OBJECT_ID_LENGTH];
 	}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java
index cd98539..a5d380d 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java
@@ -850,6 +850,11 @@ private RefList<Ref> parsePackedRefs(final BufferedReader br)
 			}
 
 			int sp = p.indexOf(' ');
+			if (sp < 0) {
+				throw new IOException(MessageFormat.format(
+						JGitText.get().packedRefsCorruptionDetected,
+						packedRefsFile.getAbsolutePath()));
+			}
 			ObjectId id = ObjectId.fromString(p.substring(0, sp));
 			String name = copy(p, sp + 1, p.length());
 			ObjectIdRef cur;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/WindowCursor.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/WindowCursor.java
index a2c0561..a742d17 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/WindowCursor.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/WindowCursor.java
@@ -94,12 +94,14 @@ final class WindowCursor extends ObjectReader implements ObjectReuseAsIs {
 	WindowCursor(FileObjectDatabase db) {
 		this.db = db;
 		this.createdFromInserter = null;
+		this.streamFileThreshold = WindowCache.getStreamFileThreshold();
 	}
 
 	WindowCursor(FileObjectDatabase db,
 			@Nullable ObjectDirectoryInserter createdFromInserter) {
 		this.db = db;
 		this.createdFromInserter = createdFromInserter;
+		this.streamFileThreshold = WindowCache.getStreamFileThreshold();
 	}
 
 	DeltaBaseCache getDeltaBaseCache() {
@@ -337,10 +339,6 @@ void pin(final PackFile pack, final long position)
 		}
 	}
 
-	int getStreamFileThreshold() {
-		return WindowCache.getStreamFileThreshold();
-	}
-
 	@Override
 	@Nullable
 	public ObjectInserter getCreatedFromInserter() {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackOutputStream.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackOutputStream.java
index be1e3d4..59166e6 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackOutputStream.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackOutputStream.java
@@ -183,7 +183,7 @@ public final void writeObject(ObjectToPack otp) throws IOException {
 	public final void writeHeader(ObjectToPack otp, long rawLength)
 			throws IOException {
 		ObjectToPack b = otp.getDeltaBase();
-		if (b != null && (b.isWritten() & ofsDelta)) {
+		if (b != null && (b.isWritten() & ofsDelta)) { // Non-short-circuit logic is intentional
 			int n = objectHeader(rawLength, OBJ_OFS_DELTA, headerBuffer);
 			n = ofsDelta(count - b.getOffset(), headerBuffer, n);
 			write(headerBuffer, 0, n);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java
index 691867a..8b4d2e6 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java
@@ -1597,14 +1597,15 @@ private void writeDeltaObjectDeflate(PackOutputStream out,
 			}
 		}
 
-		TemporaryBuffer.Heap delta = delta(otp);
-		out.writeHeader(otp, delta.length());
+		try (TemporaryBuffer.Heap delta = delta(otp)) {
+			out.writeHeader(otp, delta.length());
 
-		Deflater deflater = deflater();
-		deflater.reset();
-		DeflaterOutputStream dst = new DeflaterOutputStream(out, deflater);
-		delta.writeTo(dst, null);
-		dst.finish();
+			Deflater deflater = deflater();
+			deflater.reset();
+			DeflaterOutputStream dst = new DeflaterOutputStream(out, deflater);
+			delta.writeTo(dst, null);
+			dst.finish();
+		}
 		typeStats.cntDeltas++;
 		typeStats.deltaBytes += out.length() - otp.getOffset();
 	}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriterBitmapWalker.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriterBitmapWalker.java
index d9ac9ef..2ec4d56 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriterBitmapWalker.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriterBitmapWalker.java
@@ -49,11 +49,11 @@
 import org.eclipse.jgit.errors.IncorrectObjectTypeException;
 import org.eclipse.jgit.errors.MissingObjectException;
 import org.eclipse.jgit.lib.BitmapIndex;
+import org.eclipse.jgit.lib.BitmapIndex.Bitmap;
+import org.eclipse.jgit.lib.BitmapIndex.BitmapBuilder;
 import org.eclipse.jgit.lib.Constants;
 import org.eclipse.jgit.lib.NullProgressMonitor;
 import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.BitmapIndex.Bitmap;
-import org.eclipse.jgit.lib.BitmapIndex.BitmapBuilder;
 import org.eclipse.jgit.lib.ProgressMonitor;
 import org.eclipse.jgit.revwalk.ObjectWalk;
 import org.eclipse.jgit.revwalk.RevCommit;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftree/Scanner.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftree/Scanner.java
index d383abf..2ef0f20 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftree/Scanner.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftree/Scanner.java
@@ -43,7 +43,6 @@
 
 package org.eclipse.jgit.internal.storage.reftree;
 
-import static org.eclipse.jgit.lib.RefDatabase.MAX_SYMBOLIC_REF_DEPTH;
 import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;
 import static org.eclipse.jgit.lib.Constants.R_REFS;
 import static org.eclipse.jgit.lib.Constants.encode;
@@ -52,6 +51,7 @@
 import static org.eclipse.jgit.lib.FileMode.TYPE_TREE;
 import static org.eclipse.jgit.lib.Ref.Storage.NEW;
 import static org.eclipse.jgit.lib.Ref.Storage.PACKED;
+import static org.eclipse.jgit.lib.RefDatabase.MAX_SYMBOLIC_REF_DEPTH;
 
 import java.io.IOException;
 
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/BatchRefUpdate.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/BatchRefUpdate.java
index 8550ec3..653c9f6 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/BatchRefUpdate.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/BatchRefUpdate.java
@@ -49,18 +49,21 @@
 
 import java.io.IOException;
 import java.text.MessageFormat;
+import java.time.Duration;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
+import java.util.concurrent.TimeoutException;
 
 import org.eclipse.jgit.internal.JGitText;
 import org.eclipse.jgit.lib.RefUpdate.Result;
 import org.eclipse.jgit.revwalk.RevWalk;
 import org.eclipse.jgit.transport.PushCertificate;
 import org.eclipse.jgit.transport.ReceiveCommand;
+import org.eclipse.jgit.util.time.ProposedTimestamp;
 
 /**
  * Batch of reference updates to be applied to a repository.
@@ -69,6 +72,17 @@
  * server is making changes to more than one reference at a time.
  */
 public class BatchRefUpdate {
+	/**
+	 * Maximum delay the calling thread will tolerate while waiting for a
+	 * {@code MonotonicClock} to resolve associated {@link ProposedTimestamp}s.
+	 * <p>
+	 * A default of 5 seconds was chosen by guessing. A common assumption is
+	 * clock skew between machines on the same LAN using an NTP server also on
+	 * the same LAN should be under 5 seconds. 5 seconds is also not that long
+	 * for a large `git push` operation to complete.
+	 */
+	private static final Duration MAX_WAIT = Duration.ofSeconds(5);
+
 	private final RefDatabase refdb;
 
 	/** Commands to apply during this batch. */
@@ -95,6 +109,9 @@ public class BatchRefUpdate {
 	/** Push options associated with this update. */
 	private List<String> pushOptions;
 
+	/** Associated timestamps that should be blocked on before update. */
+	private List<ProposedTimestamp> timestamps;
+
 	/**
 	 * Initialize a new batch update.
 	 *
@@ -314,6 +331,32 @@ public List<String> getPushOptions() {
 	}
 
 	/**
+	 * @return list of timestamps the batch must wait for.
+	 * @since 4.6
+	 */
+	public List<ProposedTimestamp> getProposedTimestamps() {
+		if (timestamps != null) {
+			return Collections.unmodifiableList(timestamps);
+		}
+		return Collections.emptyList();
+	}
+
+	/**
+	 * Request the batch to wait for the affected timestamps to resolve.
+	 *
+	 * @param ts
+	 * @return {@code this}.
+	 * @since 4.6
+	 */
+	public BatchRefUpdate addProposedTimestamp(ProposedTimestamp ts) {
+		if (timestamps == null) {
+			timestamps = new ArrayList<>(4);
+		}
+		timestamps.add(ts);
+		return this;
+	}
+
+	/**
 	 * Execute this batch update.
 	 * <p>
 	 * The default implementation of this method performs a sequential reference
@@ -348,6 +391,9 @@ public void execute(RevWalk walk, ProgressMonitor monitor,
 			}
 			return;
 		}
+		if (!blockUntilTimestamps(MAX_WAIT)) {
+			return;
+		}
 
 		if (options != null) {
 			pushOptions = options;
@@ -433,6 +479,33 @@ public void execute(RevWalk walk, ProgressMonitor monitor,
 	}
 
 	/**
+	 * Wait for timestamps to be in the past, aborting commands on timeout.
+	 *
+	 * @param maxWait
+	 *            maximum amount of time to wait for timestamps to resolve.
+	 * @return true if timestamps were successfully waited for; false if
+	 *         commands were aborted.
+	 * @since 4.6
+	 */
+	protected boolean blockUntilTimestamps(Duration maxWait) {
+		if (timestamps == null) {
+			return true;
+		}
+		try {
+			ProposedTimestamp.blockUntil(timestamps, maxWait);
+			return true;
+		} catch (TimeoutException | InterruptedException e) {
+			String msg = JGitText.get().timeIsUncertain;
+			for (ReceiveCommand c : commands) {
+				if (c.getResult() == NOT_ATTEMPTED) {
+					c.setResult(REJECTED_OTHER_REASON, msg);
+				}
+			}
+			return false;
+		}
+	}
+
+	/**
 	 * Execute this batch update without option strings.
 	 *
 	 * @param walk
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java
index e3f8ba5..87a95b9 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java
@@ -65,6 +65,12 @@ public class ConfigConstants {
 	/** The "dfs" section */
 	public static final String CONFIG_DFS_SECTION = "dfs";
 
+	/**
+	 * The "receive" section
+	 * @since 4.6
+	 */
+	public static final String CONFIG_RECEIVE_SECTION = "receive";
+
 	/** The "user" section */
 	public static final String CONFIG_USER_SECTION = "user";
 
@@ -101,6 +107,12 @@ public class ConfigConstants {
 	 */
 	public static final String CONFIG_PULL_SECTION = "pull";
 
+	/**
+	 * The "filter" section
+	 * @since 4.6
+	 */
+	public static final String CONFIG_FILTER_SECTION = "filter";
+
 	/** The "algorithm" key */
 	public static final String CONFIG_KEY_ALGORITHM = "algorithm";
 
@@ -108,6 +120,24 @@ public class ConfigConstants {
 	public static final String CONFIG_KEY_AUTOCRLF = "autocrlf";
 
 	/**
+	 * The "auto" key
+	 * @since 4.6
+	 */
+	public static final String CONFIG_KEY_AUTO = "auto";
+
+	/**
+	 * The "autogc" key
+	 * @since 4.6
+	 */
+	public static final String CONFIG_KEY_AUTOGC = "autogc";
+
+	/**
+	 * The "autopacklimit" key
+	 * @since 4.6
+	 */
+	public static final String CONFIG_KEY_AUTOPACKLIMIT = "autopacklimit";
+
+	/**
 	 * The "eol" key
 	 *
 	 * @since 4.3
@@ -145,6 +175,13 @@ public class ConfigConstants {
 	/** The "blockSize" key */
 	public static final String CONFIG_KEY_BLOCK_SIZE = "blockSize";
 
+	/**
+	 * The "concurrencyLevel" key
+	 *
+	 * @since 4.6
+	 */
+	public static final String CONFIG_KEY_CONCURRENCY_LEVEL = "concurrencyLevel";
+
 	/** The "deltaBaseCacheLimit" key */
 	public static final String CONFIG_KEY_DELTA_BASE_CACHE_LIMIT = "deltaBaseCacheLimit";
 
@@ -337,4 +374,11 @@ public class ConfigConstants {
 	 * @since 4.0
 	 */
 	public static final String CONFIG_KEY_STREAM_RATIO = "streamRatio";
+
+	/**
+	 * Flag in the filter section whether to use JGit's implementations of
+	 * filters and hooks
+	 * @since 4.6
+	 */
+	public static final String CONFIG_KEY_USEJGITBUILTIN = "useJGitBuiltin";
 }
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 d30edaf..ff80672 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Constants.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Constants.java
@@ -391,6 +391,13 @@ public final class Constants {
 	 */
 	public static final String ATTR_FILTER_TYPE_SMUDGE = "smudge";
 
+	/**
+	 * Builtin filter commands start with this prefix
+	 *
+	 * @since 4.6
+	 */
+	public static final String BUILTIN_FILTER_PREFIX = "jgit://builtin/";
+
 	/** Name of the ignore file */
 	public static final String DOT_GIT_IGNORE = ".gitignore";
 
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/IndexDiff.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/IndexDiff.java
index 9e474f8..af6a4fb 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/IndexDiff.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/IndexDiff.java
@@ -65,7 +65,6 @@
 import org.eclipse.jgit.errors.MissingObjectException;
 import org.eclipse.jgit.errors.StopWalkException;
 import org.eclipse.jgit.internal.JGitText;
-import org.eclipse.jgit.revwalk.RevTree;
 import org.eclipse.jgit.revwalk.RevWalk;
 import org.eclipse.jgit.submodule.SubmoduleWalk;
 import org.eclipse.jgit.submodule.SubmoduleWalk.IgnoreSubmoduleMode;
@@ -73,8 +72,8 @@
 import org.eclipse.jgit.treewalk.EmptyTreeIterator;
 import org.eclipse.jgit.treewalk.FileTreeIterator;
 import org.eclipse.jgit.treewalk.TreeWalk;
-import org.eclipse.jgit.treewalk.WorkingTreeIterator;
 import org.eclipse.jgit.treewalk.TreeWalk.OperationType;
+import org.eclipse.jgit.treewalk.WorkingTreeIterator;
 import org.eclipse.jgit.treewalk.filter.AndTreeFilter;
 import org.eclipse.jgit.treewalk.filter.IndexDiffFilter;
 import org.eclipse.jgit.treewalk.filter.SkipWorkTreeFilter;
@@ -248,7 +247,7 @@ public TreeFilter clone() {
 
 	private final Repository repository;
 
-	private final RevTree tree;
+	private final AnyObjectId tree;
 
 	private TreeFilter filter = null;
 
@@ -311,10 +310,13 @@ public IndexDiff(Repository repository, String revstr,
 	public IndexDiff(Repository repository, ObjectId objectId,
 			WorkingTreeIterator workingTreeIterator) throws IOException {
 		this.repository = repository;
-		if (objectId != null)
-			tree = new RevWalk(repository).parseTree(objectId);
-		else
+		if (objectId != null) {
+			try (RevWalk rw = new RevWalk(repository)) {
+				tree = rw.parseTree(objectId);
+			}
+		} else {
 			tree = null;
+		}
 		this.initialWorkingTreeIterator = workingTreeIterator;
 	}
 
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectChecker.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectChecker.java
index 0b5efd7..feecbd8 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectChecker.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectChecker.java
@@ -709,11 +709,12 @@ private int scanPathSegment(byte[] raw, int ptr, int end,
 		return ptr;
 	}
 
-	@SuppressWarnings("resource")
 	@Nullable
 	private ObjectId idFor(int objType, byte[] raw) {
 		if (skipList != null) {
-			return new ObjectInserter.Formatter().idFor(objType, raw);
+			try (ObjectInserter.Formatter fmt = new ObjectInserter.Formatter()) {
+				return fmt.idFor(objType, raw);
+			}
 		}
 		return null;
 	}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectId.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectId.java
index 4edb38c..2a2d67d 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectId.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectId.java
@@ -44,15 +44,15 @@
 
 package org.eclipse.jgit.lib;
 
-import org.eclipse.jgit.errors.InvalidObjectIdException;
-import org.eclipse.jgit.util.NB;
-import org.eclipse.jgit.util.RawParseUtils;
-
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
 import java.io.Serializable;
 
+import org.eclipse.jgit.errors.InvalidObjectIdException;
+import org.eclipse.jgit.util.NB;
+import org.eclipse.jgit.util.RawParseUtils;
+
 /**
  * A SHA-1 abstraction.
  */
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectIdOwnerMap.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectIdOwnerMap.java
index 442261c..95cb976 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectIdOwnerMap.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectIdOwnerMap.java
@@ -143,6 +143,7 @@ public V get(final AnyObjectId toFind) {
 	 *            object to find.
 	 * @return true if the mapping exists for this object; false otherwise.
 	 */
+	@Override
 	public boolean contains(final AnyObjectId toFind) {
 		return get(toFind) != null;
 	}
@@ -219,20 +220,20 @@ public boolean isEmpty() {
 		return size == 0;
 	}
 
+	@Override
 	public Iterator<V> iterator() {
 		return new Iterator<V>() {
 			private int found;
-
 			private int dirIdx;
-
 			private int tblIdx;
-
 			private V next;
 
+			@Override
 			public boolean hasNext() {
 				return found < size;
 			}
 
+			@Override
 			public V next() {
 				if (next != null)
 					return found(next);
@@ -261,6 +262,7 @@ private V found(V v) {
 				return v;
 			}
 
+			@Override
 			public void remove() {
 				throw new UnsupportedOperationException();
 			}
@@ -341,7 +343,7 @@ private static final boolean equals(AnyObjectId firstObjectId,
 
 	/** Type of entry stored in the {@link ObjectIdOwnerMap}. */
 	public static abstract class Entry extends ObjectId {
-		Entry next;
+		transient Entry next;
 
 		/**
 		 * Initialize this entry with a specific ObjectId.
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectReader.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectReader.java
index b23145d..372da98 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectReader.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectReader.java
@@ -66,6 +66,13 @@ public abstract class ObjectReader implements AutoCloseable {
 	public static final int OBJ_ANY = -1;
 
 	/**
+	 * The threshold at which a file will be streamed rather than loaded
+	 * entirely into memory.
+	 * @since 4.6
+	 */
+	protected int streamFileThreshold;
+
+	/**
 	 * Construct a new reader from the same data.
 	 * <p>
 	 * Applications can use this method to build a new reader from the same data
@@ -445,6 +452,29 @@ public ObjectInserter getCreatedFromInserter() {
 	public abstract void close();
 
 	/**
+	 * Sets the threshold at which a file will be streamed rather than loaded
+	 * entirely into memory
+	 *
+	 * @param threshold
+	 *            the new threshold
+	 * @since 4.6
+	 */
+	public void setStreamFileThreshold(int threshold) {
+		streamFileThreshold = threshold;
+	}
+
+	/**
+	 * Returns the threshold at which a file will be streamed rather than loaded
+	 * entirely into memory
+	 *
+	 * @return the threshold in bytes
+	 * @since 4.6
+	 */
+	public int getStreamFileThreshold() {
+		return streamFileThreshold;
+	}
+
+	/**
 	 * Wraps a delegate ObjectReader.
 	 *
 	 * @since 4.4
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/PersonIdent.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/PersonIdent.java
index e08a985..627ccaa 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/PersonIdent.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/PersonIdent.java
@@ -53,6 +53,7 @@
 
 import org.eclipse.jgit.internal.JGitText;
 import org.eclipse.jgit.util.SystemReader;
+import org.eclipse.jgit.util.time.ProposedTimestamp;
 
 /**
  * A combination of a person identity and time in Git.
@@ -189,6 +190,19 @@ public PersonIdent(final String aName, final String aEmailAddress) {
 	}
 
 	/**
+	 * Construct a new {@link PersonIdent} with current time.
+	 *
+	 * @param aName
+	 * @param aEmailAddress
+	 * @param when
+	 * @since 4.6
+	 */
+	public PersonIdent(String aName, String aEmailAddress,
+			ProposedTimestamp when) {
+		this(aName, aEmailAddress, when.millis());
+	}
+
+	/**
 	 * Copy a PersonIdent, but alter the clone's time stamp
 	 *
 	 * @param pi
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RebaseTodoFile.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RebaseTodoFile.java
index 4ebe5fe..75a3592 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RebaseTodoFile.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RebaseTodoFile.java
@@ -43,6 +43,7 @@
 
 package org.eclipse.jgit.lib;
 
+import java.io.BufferedOutputStream;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
@@ -53,7 +54,6 @@
 import org.eclipse.jgit.lib.RebaseTodoLine.Action;
 import org.eclipse.jgit.util.IO;
 import org.eclipse.jgit.util.RawParseUtils;
-import org.eclipse.jgit.util.io.SafeBufferedOutputStream;
 
 /**
  * Offers methods to read and write files formatted like the git-rebase-todo
@@ -216,9 +216,8 @@ private static RebaseTodoLine parseLine(byte[] buf, int tokenBegin,
 	 */
 	public void writeRebaseTodoFile(String path, List<RebaseTodoLine> steps,
 			boolean append) throws IOException {
-		OutputStream fw = new SafeBufferedOutputStream(new FileOutputStream(
-				new File(repo.getDirectory(), path), append));
-		try {
+		try (OutputStream fw = new BufferedOutputStream(new FileOutputStream(
+				new File(repo.getDirectory(), path), append))) {
 			StringBuilder sb = new StringBuilder();
 			for (RebaseTodoLine step : steps) {
 				sb.setLength(0);
@@ -234,8 +233,6 @@ public void writeRebaseTodoFile(String path, List<RebaseTodoLine> steps,
 				sb.append('\n');
 				fw.write(Constants.encode(sb.toString()));
 			}
-		} finally {
-			fw.close();
 		}
 	}
 }
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ReflogEntry.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ReflogEntry.java
index e2102e5..0504646 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ReflogEntry.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ReflogEntry.java
@@ -42,9 +42,6 @@
  */
 package org.eclipse.jgit.lib;
 
-import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.PersonIdent;
-
 /**
  * Parsed reflog entry
  *
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java
index aba5242..c5b2ef8 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java
@@ -52,6 +52,7 @@
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.OutputStream;
 import java.net.URISyntaxException;
 import java.text.MessageFormat;
 import java.util.Collection;
@@ -80,6 +81,7 @@
 import org.eclipse.jgit.events.ListenerList;
 import org.eclipse.jgit.events.RepositoryEvent;
 import org.eclipse.jgit.internal.JGitText;
+import org.eclipse.jgit.internal.storage.file.GC;
 import org.eclipse.jgit.revwalk.RevBlob;
 import org.eclipse.jgit.revwalk.RevCommit;
 import org.eclipse.jgit.revwalk.RevObject;
@@ -93,7 +95,6 @@
 import org.eclipse.jgit.util.IO;
 import org.eclipse.jgit.util.RawParseUtils;
 import org.eclipse.jgit.util.SystemReader;
-import org.eclipse.jgit.util.io.SafeBufferedOutputStream;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -106,8 +107,7 @@
  * This class is thread-safe.
  */
 public abstract class Repository implements AutoCloseable {
-	private static Logger LOG = LoggerFactory.getLogger(Repository.class);
-
+	private static final Logger LOG = LoggerFactory.getLogger(Repository.class);
 	private static final ListenerList globalListeners = new ListenerList();
 
 	/** @return the global listener list observing all events in this JVM. */
@@ -245,7 +245,6 @@ public ObjectReader newObjectReader() {
 	@NonNull
 	public abstract AttributesNodeProvider createAttributesNodeProvider();
 
-
 	/**
 	 * @return the used file system abstraction, or or {@code null} if
 	 *         repository isn't local.
@@ -653,7 +652,10 @@ private Object resolve(final RevWalk rw, final String revstr)
 							// detached
 							name = Constants.HEAD;
 						if (!Repository.isValidRefName("x/" + name)) //$NON-NLS-1$
-							throw new RevisionSyntaxException(revstr);
+							throw new RevisionSyntaxException(MessageFormat
+									.format(JGitText.get().invalidRefName,
+											name),
+									revstr);
 						Ref ref = getRef(name);
 						name = null;
 						if (ref == null)
@@ -703,7 +705,10 @@ private Object resolve(final RevWalk rw, final String revstr)
 						if (name.equals("")) //$NON-NLS-1$
 							name = Constants.HEAD;
 						if (!Repository.isValidRefName("x/" + name)) //$NON-NLS-1$
-							throw new RevisionSyntaxException(revstr);
+							throw new RevisionSyntaxException(MessageFormat
+									.format(JGitText.get().invalidRefName,
+											name),
+									revstr);
 						Ref ref = getRef(name);
 						name = null;
 						if (ref == null)
@@ -752,7 +757,9 @@ private Object resolve(final RevWalk rw, final String revstr)
 			return null;
 		name = revstr.substring(done);
 		if (!Repository.isValidRefName("x/" + name)) //$NON-NLS-1$
-			throw new RevisionSyntaxException(revstr);
+			throw new RevisionSyntaxException(
+					MessageFormat.format(JGitText.get().invalidRefName, name),
+					revstr);
 		if (getRef(name) != null)
 			return name;
 		return resolveSimple(name);
@@ -869,6 +876,7 @@ public void incrementOpen() {
 	}
 
 	/** Decrement the use count, and maybe close resources. */
+	@Override
 	public void close() {
 		int newCount = useCnt.decrementAndGet();
 		if (newCount == 0) {
@@ -902,8 +910,9 @@ protected void doClose() {
 		getRefDatabase().close();
 	}
 
-	@NonNull
 	@SuppressWarnings("nls")
+	@Override
+	@NonNull
 	public String toString() {
 		String desc;
 		File directory = getDirectory();
@@ -1175,7 +1184,7 @@ public DirCache lockDirCache() throws NoWorkTreeException,
 		// we want DirCache to inform us so that we can inform registered
 		// listeners about index changes
 		IndexChangedListener l = new IndexChangedListener() {
-
+			@Override
 			public void onIndexChanged(IndexChangedEvent event) {
 				notifyIndexChanged();
 			}
@@ -1183,15 +1192,6 @@ public void onIndexChanged(IndexChangedEvent event) {
 		return DirCache.lock(this, l);
 	}
 
-	static byte[] gitInternalSlash(byte[] bytes) {
-		if (File.separatorChar == '/')
-			return bytes;
-		for (int i=0; i<bytes.length; ++i)
-			if (bytes[i] == File.separatorChar)
-				bytes[i] = '/';
-		return bytes;
-	}
-
 	/**
 	 * @return an important state
 	 */
@@ -1445,6 +1445,33 @@ public String getRemoteName(String refName) {
 	}
 
 	/**
+	 * Read the {@code GIT_DIR/description} file for gitweb.
+	 *
+	 * @return description text; null if no description has been configured.
+	 * @throws IOException
+	 *             description cannot be accessed.
+	 * @since 4.6
+	 */
+	@Nullable
+	public String getGitwebDescription() throws IOException {
+		return null;
+	}
+
+	/**
+	 * Set the {@code GIT_DIR/description} file for gitweb.
+	 *
+	 * @param description
+	 *            new description; null to clear the description.
+	 * @throws IOException
+	 *             description cannot be persisted.
+	 * @since 4.6
+	 */
+	public void setGitwebDescription(@Nullable String description)
+			throws IOException {
+		throw new IOException(JGitText.get().unsupportedRepositoryDescription);
+	}
+
+	/**
 	 * @param refName
 	 * @return a {@link ReflogReader} for the supplied refname, or {@code null}
 	 *         if the named ref does not exist.
@@ -1781,15 +1808,12 @@ private void writeHeadsFile(List<? extends ObjectId> heads, String filename)
 			throws FileNotFoundException, IOException {
 		File headsFile = new File(getDirectory(), filename);
 		if (heads != null) {
-			BufferedOutputStream bos = new SafeBufferedOutputStream(
-					new FileOutputStream(headsFile));
-			try {
+			try (OutputStream bos = new BufferedOutputStream(
+					new FileOutputStream(headsFile))) {
 				for (ObjectId id : heads) {
 					id.copyTo(bos);
 					bos.write('\n');
 				}
-			} finally {
-				bos.close();
 			}
 		} else {
 			FileUtils.delete(headsFile, FileUtils.SKIP_MISSING);
@@ -1845,4 +1869,22 @@ public Set<String> getRemoteNames() {
 		return getConfig()
 				.getSubsections(ConfigConstants.CONFIG_REMOTE_SECTION);
 	}
+
+	/**
+	 * Check whether any housekeeping is required; if yes, run garbage
+	 * collection; if not, exit without performing any work. Some JGit commands
+	 * run autoGC after performing operations that could create many loose
+	 * objects.
+	 * <p/>
+	 * Currently this option is supported for repositories of type
+	 * {@code FileRepository} only. See {@link GC#setAuto(boolean)} for
+	 * configuration details.
+	 *
+	 * @param monitor
+	 *            to report progress
+	 * @since 4.6
+	 */
+	public void autoGC(ProgressMonitor monitor) {
+		// default does nothing
+	}
 }
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 7a8d246..2f1a9e1 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCache.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCache.java
@@ -45,12 +45,8 @@
 
 import java.io.File;
 import java.io.IOException;
-import java.lang.ref.Reference;
-import java.lang.ref.SoftReference;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Iterator;
-import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ScheduledFuture;
 import java.util.concurrent.ScheduledThreadPoolExecutor;
@@ -150,7 +146,7 @@ public static void register(final Repository db) {
 	public static void close(@NonNull final Repository db) {
 		if (db.getDirectory() != null) {
 			FileKey key = FileKey.exact(db.getDirectory(), db.getFS());
-			cache.unregisterAndCloseRepository(key, db);
+			cache.unregisterAndCloseRepository(key);
 		}
 	}
 
@@ -202,8 +198,7 @@ static boolean isCached(@NonNull Repository repo) {
 			return false;
 		}
 		FileKey key = new FileKey(gitDir, repo.getFS());
-		Reference<Repository> repoRef = cache.cacheMap.get(key);
-		return repoRef != null && repoRef.get() == repo;
+		return cache.cacheMap.get(key) == repo;
 	}
 
 	/** Unregister all repositories from the cache. */
@@ -219,7 +214,7 @@ static void reconfigure(RepositoryCacheConfig repositoryCacheConfig) {
 		cache.configureEviction(repositoryCacheConfig);
 	}
 
-	private final ConcurrentHashMap<Key, Reference<Repository>> cacheMap;
+	private final ConcurrentHashMap<Key, Repository> cacheMap;
 
 	private final Lock[] openLocks;
 
@@ -228,7 +223,7 @@ static void reconfigure(RepositoryCacheConfig repositoryCacheConfig) {
 	private volatile long expireAfter;
 
 	private RepositoryCache() {
-		cacheMap = new ConcurrentHashMap<Key, Reference<Repository>>();
+		cacheMap = new ConcurrentHashMap<>();
 		openLocks = new Lock[4];
 		for (int i = 0; i < openLocks.length; i++) {
 			openLocks[i] = new Lock();
@@ -261,19 +256,15 @@ public void run() {
 		}
 	}
 
-	@SuppressWarnings("resource")
 	private Repository openRepository(final Key location,
 			final boolean mustExist) throws IOException {
-		Reference<Repository> ref = cacheMap.get(location);
-		Repository db = ref != null ? ref.get() : null;
+		Repository db = cacheMap.get(location);
 		if (db == null) {
 			synchronized (lockFor(location)) {
-				ref = cacheMap.get(location);
-				db = ref != null ? ref.get() : null;
+				db = cacheMap.get(location);
 				if (db == null) {
 					db = location.open(mustExist);
-					ref = new SoftReference<Repository>(db);
-					cacheMap.put(location, ref);
+					cacheMap.put(location, db);
 				} else {
 					db.incrementOpen();
 				}
@@ -285,16 +276,13 @@ private Repository openRepository(final Key location,
 	}
 
 	private void registerRepository(final Key location, final Repository db) {
-		SoftReference<Repository> newRef = new SoftReference<Repository>(db);
-		Reference<Repository> oldRef = cacheMap.put(location, newRef);
-		Repository oldDb = oldRef != null ? oldRef.get() : null;
+		Repository oldDb = cacheMap.put(location, db);
 		if (oldDb != null)
 			oldDb.close();
 	}
 
 	private Repository unregisterRepository(final Key location) {
-		Reference<Repository> oldRef = cacheMap.remove(location);
-		return oldRef != null ? oldRef.get() : null;
+		return cacheMap.remove(location);
 	}
 
 	private boolean isExpired(Repository db) {
@@ -302,8 +290,7 @@ private boolean isExpired(Repository db) {
 			&& (System.currentTimeMillis() - db.closedAt.get() > expireAfter);
 	}
 
-	private void unregisterAndCloseRepository(final Key location,
-			Repository db) {
+	private void unregisterAndCloseRepository(final Key location) {
 		synchronized (lockFor(location)) {
 			Repository oldDb = unregisterRepository(location);
 			if (oldDb != null) {
@@ -317,8 +304,7 @@ private Collection<Key> getKeys() {
 	}
 
 	private void clearAllExpired() {
-		for (Reference<Repository> ref : cacheMap.values()) {
-			Repository db = ref.get();
+		for (Repository db : cacheMap.values()) {
 			if (isExpired(db)) {
 				RepositoryCache.close(db);
 			}
@@ -326,9 +312,8 @@ private void clearAllExpired() {
 	}
 
 	private void clearAll() {
-		for (Iterator<Map.Entry<Key, Reference<Repository>>> i = cacheMap
-				.entrySet().iterator(); i.hasNext();) {
-			unregisterAndCloseRepository(i.next().getKey(), null);
+		for (Key k : cacheMap.keySet()) {
+			unregisterAndCloseRepository(k);
 		}
 	}
 
@@ -442,6 +427,7 @@ public final File getFile() {
 			return path;
 		}
 
+		@Override
 		public Repository open(final boolean mustExist) throws IOException {
 			if (mustExist && !isGitRepository(path, fs))
 				throw new RepositoryNotFoundException(path);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCacheConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCacheConfig.java
index 428dea3..28cdaae 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCacheConfig.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCacheConfig.java
@@ -53,8 +53,8 @@ public class RepositoryCacheConfig {
 
 	/**
 	 * Set cleanupDelayMillis to this value in order to switch off time-based
-	 * cache eviction. The JVM can still expire cache entries when heap memory
-	 * runs low.
+	 * cache eviction. Expired cache entries will only be evicted when
+	 * RepositoryCache.clearExpired or RepositoryCache.clear are called.
 	 */
 	public static final long NO_CLEANUP = 0;
 
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/TreeFormatter.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/TreeFormatter.java
index 065b8f4..777ce94 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/TreeFormatter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/TreeFormatter.java
@@ -53,6 +53,7 @@
 import java.io.IOException;
 
 import org.eclipse.jgit.errors.CorruptObjectException;
+import org.eclipse.jgit.internal.JGitText;
 import org.eclipse.jgit.revwalk.RevBlob;
 import org.eclipse.jgit.revwalk.RevCommit;
 import org.eclipse.jgit.revwalk.RevTree;
@@ -193,6 +194,34 @@ public void append(byte[] name, FileMode mode, AnyObjectId id) {
 	 */
 	public void append(byte[] nameBuf, int namePos, int nameLen, FileMode mode,
 			AnyObjectId id) {
+		append(nameBuf, namePos, nameLen, mode, id, false);
+	}
+
+	/**
+	 * Append any entry to the tree.
+	 *
+	 * @param nameBuf
+	 *            buffer holding the name of the entry. The name should be UTF-8
+	 *            encoded, but file name encoding is not a well defined concept
+	 *            in Git.
+	 * @param namePos
+	 *            first position within {@code nameBuf} of the name data.
+	 * @param nameLen
+	 *            number of bytes from {@code nameBuf} to use as the name.
+	 * @param mode
+	 *            mode describing the treatment of {@code id}.
+	 * @param id
+	 *            the ObjectId to store in this entry.
+	 * @param allowEmptyName
+	 *            allow an empty filename (creating a corrupt tree)
+	 * @since 4.6
+	 */
+	public void append(byte[] nameBuf, int namePos, int nameLen, FileMode mode,
+			AnyObjectId id, boolean allowEmptyName) {
+		if (nameLen == 0 && !allowEmptyName) {
+			throw new IllegalArgumentException(
+					JGitText.get().invalidTreeZeroLengthName);
+		}
 		if (fmtBuf(nameBuf, namePos, nameLen, mode)) {
 			id.copyRawTo(buf, ptr);
 			ptr += OBJECT_ID_LENGTH;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeConfig.java
index 9125ddf..83b143b 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeConfig.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeConfig.java
@@ -46,8 +46,8 @@
 
 import org.eclipse.jgit.api.MergeCommand.FastForwardMode;
 import org.eclipse.jgit.lib.Config;
-import org.eclipse.jgit.lib.ConfigConstants;
 import org.eclipse.jgit.lib.Config.SectionParser;
+import org.eclipse.jgit.lib.ConfigConstants;
 import org.eclipse.jgit.lib.Repository;
 
 /**
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/patch/Patch.java b/org.eclipse.jgit/src/org/eclipse/jgit/patch/Patch.java
index 383c1f8..40ea77e 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/patch/Patch.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/patch/Patch.java
@@ -44,9 +44,9 @@
 package org.eclipse.jgit.patch;
 
 import static org.eclipse.jgit.lib.Constants.encodeASCII;
-import static org.eclipse.jgit.patch.FileHeader.isHunkHdr;
 import static org.eclipse.jgit.patch.FileHeader.NEW_NAME;
 import static org.eclipse.jgit.patch.FileHeader.OLD_NAME;
+import static org.eclipse.jgit.patch.FileHeader.isHunkHdr;
 import static org.eclipse.jgit.util.RawParseUtils.match;
 import static org.eclipse.jgit.util.RawParseUtils.nextLF;
 
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revplot/PlotCommit.java b/org.eclipse.jgit/src/org/eclipse/jgit/revplot/PlotCommit.java
index 2e8aab8..98bcd1a 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/revplot/PlotCommit.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/revplot/PlotCommit.java
@@ -44,8 +44,8 @@
 package org.eclipse.jgit.revplot;
 
 import org.eclipse.jgit.lib.AnyObjectId;
-import org.eclipse.jgit.revwalk.RevCommit;
 import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.revwalk.RevCommit;
 
 /**
  * A commit reference to a commit in the DAG.
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 f1d7dc8..3609d46 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/MergeBaseGenerator.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/MergeBaseGenerator.java
@@ -45,6 +45,7 @@
 
 import java.io.IOException;
 import java.text.MessageFormat;
+import java.util.LinkedList;
 
 import org.eclipse.jgit.errors.IncorrectObjectTypeException;
 import org.eclipse.jgit.errors.MissingObjectException;
@@ -85,12 +86,15 @@ class MergeBaseGenerator extends Generator {
 
 	private int recarryMask;
 
+	private int mergeBaseAncestor = -1;
+	private LinkedList<RevCommit> ret = new LinkedList<RevCommit>();
+
 	MergeBaseGenerator(final RevWalk w) {
 		walker = w;
 		pending = new DateRevQueue();
 	}
 
-	void init(final AbstractRevQueue p) {
+	void init(final AbstractRevQueue p) throws IOException {
 		try {
 			for (;;) {
 				final RevCommit c = p.next();
@@ -98,17 +102,25 @@ void init(final AbstractRevQueue p) {
 					break;
 				add(c);
 			}
-		} finally {
-			// Always free the flags immediately. This ensures the flags
-			// will be available for reuse when the walk resets.
-			//
-			walker.freeFlag(branchMask);
-
 			// Setup the condition used by carryOntoOne to detect a late
 			// merge base and produce it on the next round.
 			//
 			recarryTest = branchMask | POPPED;
 			recarryMask = branchMask | POPPED | MERGE_BASE;
+			mergeBaseAncestor = walker.allocFlag();
+
+			for (;;) {
+				RevCommit c = _next();
+				if (c == null) {
+					break;
+				}
+				ret.add(c);
+			}
+		} finally {
+			// Always free the flags immediately. This ensures the flags
+			// will be available for reuse when the walk resets.
+			//
+			walker.freeFlag(branchMask | mergeBaseAncestor);
 		}
 	}
 
@@ -131,8 +143,7 @@ int outputType() {
 		return 0;
 	}
 
-	@Override
-	RevCommit next() throws MissingObjectException,
+	private RevCommit _next() throws MissingObjectException,
 			IncorrectObjectTypeException, IOException {
 		for (;;) {
 			final RevCommit c = pending.next();
@@ -156,7 +167,7 @@ RevCommit next() throws MissingObjectException,
 				// also flagged as being popped, so that they do not
 				// generate to the caller.
 				//
-				carry |= MERGE_BASE;
+				carry |= MERGE_BASE | mergeBaseAncestor;
 			}
 			carryOntoHistory(c, carry);
 
@@ -179,6 +190,18 @@ RevCommit next() throws MissingObjectException,
 		}
 	}
 
+	@Override
+	RevCommit next() throws MissingObjectException,
+			IncorrectObjectTypeException, IOException {
+		while (!ret.isEmpty()) {
+			RevCommit commit = ret.remove();
+			if ((commit.flags & mergeBaseAncestor) == 0) {
+				return commit;
+			}
+		}
+		return null;
+	}
+
 	private void carryOntoHistory(RevCommit c, final int carry) {
 		for (;;) {
 			final RevCommit[] pList = c.parents;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/FileBasedConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/FileBasedConfig.java
index 9a38846..2d02ad5 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/FileBasedConfig.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/FileBasedConfig.java
@@ -55,8 +55,8 @@
 import java.io.IOException;
 import java.text.MessageFormat;
 
-import org.eclipse.jgit.errors.LockFailedException;
 import org.eclipse.jgit.errors.ConfigInvalidException;
+import org.eclipse.jgit.errors.LockFailedException;
 import org.eclipse.jgit.internal.JGitText;
 import org.eclipse.jgit.internal.storage.file.FileSnapshot;
 import org.eclipse.jgit.internal.storage.file.LockFile;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/AmazonS3.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/AmazonS3.java
index 4069a64..1aebadd 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/AmazonS3.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/AmazonS3.java
@@ -529,21 +529,29 @@ IOException error(final String action, final String key,
 				Integer.valueOf(HttpSupport.response(c)),
 				c.getResponseMessage()));
 		final InputStream errorStream = c.getErrorStream();
-		if (errorStream == null)
+		if (errorStream == null) {
 			return err;
-
-		final ByteArrayOutputStream b = new ByteArrayOutputStream();
-		byte[] buf = new byte[2048];
-		for (;;) {
-			final int n = errorStream.read(buf);
-			if (n < 0)
-				break;
-			if (n > 0)
-				b.write(buf, 0, n);
 		}
-		buf = b.toByteArray();
-		if (buf.length > 0)
-			err.initCause(new IOException("\n" + new String(buf))); //$NON-NLS-1$
+
+		try {
+			final ByteArrayOutputStream b = new ByteArrayOutputStream();
+			byte[] buf = new byte[2048];
+			for (;;) {
+				final int n = errorStream.read(buf);
+				if (n < 0) {
+					break;
+				}
+				if (n > 0) {
+					b.write(buf, 0, n);
+				}
+			}
+			buf = b.toByteArray();
+			if (buf.length > 0) {
+				err.initCause(new IOException("\n" + new String(buf))); //$NON-NLS-1$
+			}
+		} finally {
+			errorStream.close();
+		}
 		return err;
 	}
 
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 754cf36..0dd907f 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackFetchConnection.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackFetchConnection.java
@@ -71,7 +71,6 @@
 import org.eclipse.jgit.lib.ObjectInserter;
 import org.eclipse.jgit.lib.ProgressMonitor;
 import org.eclipse.jgit.lib.Ref;
-import org.eclipse.jgit.transport.GitProtocolConstants.MultiAck;
 import org.eclipse.jgit.revwalk.RevCommit;
 import org.eclipse.jgit.revwalk.RevCommitList;
 import org.eclipse.jgit.revwalk.RevFlag;
@@ -80,6 +79,7 @@
 import org.eclipse.jgit.revwalk.RevWalk;
 import org.eclipse.jgit.revwalk.filter.CommitTimeRevFilter;
 import org.eclipse.jgit.revwalk.filter.RevFilter;
+import org.eclipse.jgit.transport.GitProtocolConstants.MultiAck;
 import org.eclipse.jgit.transport.PacketLineIn.AckNackResult;
 import org.eclipse.jgit.util.TemporaryBuffer;
 
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BaseReceivePack.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BaseReceivePack.java
index 0724eac..4d0803a 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BaseReceivePack.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BaseReceivePack.java
@@ -69,6 +69,7 @@
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
 
+import org.eclipse.jgit.annotations.Nullable;
 import org.eclipse.jgit.errors.InvalidObjectIdException;
 import org.eclipse.jgit.errors.MissingObjectException;
 import org.eclipse.jgit.errors.PackProtocolException;
@@ -268,6 +269,7 @@ public Set<String> getCapabilities() {
 	private PushCertificateParser pushCertificateParser;
 	private SignedPushConfig signedPushConfig;
 	private PushCertificate pushCert;
+	private ReceivedPackStatistics stats;
 
 	/**
 	 * Get the push certificate used to verify the pusher's identity.
@@ -1115,6 +1117,18 @@ public void sendAdvertisedRefs(final RefAdvertiser adv)
 	}
 
 	/**
+	 * Returns the statistics on the received pack if available. This should be
+	 * called after {@link #receivePack} is called.
+	 *
+	 * @return ReceivedPackStatistics
+	 * @since 4.6
+	 */
+	@Nullable
+	public ReceivedPackStatistics getReceivedPackStatistics() {
+		return stats;
+	}
+
+	/**
 	 * Receive a list of commands from the input.
 	 *
 	 * @throws IOException
@@ -1307,6 +1321,7 @@ private void receivePack() throws IOException {
 			parser.setMaxObjectSizeLimit(maxObjectSizeLimit);
 			packLock = parser.parse(receiving, resolving);
 			packSize = Long.valueOf(parser.getPackSize());
+			stats = parser.getReceivedPackStatistics();
 			ins.flush();
 		}
 
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/DaemonClient.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/DaemonClient.java
index 22f3438..23e3379 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/DaemonClient.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/DaemonClient.java
@@ -44,6 +44,7 @@
 package org.eclipse.jgit.transport;
 
 import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -52,7 +53,6 @@
 
 import org.eclipse.jgit.transport.resolver.ServiceNotAuthorizedException;
 import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException;
-import org.eclipse.jgit.util.io.SafeBufferedOutputStream;
 
 /** Active network client of {@link Daemon}. */
 public class DaemonClient {
@@ -95,7 +95,7 @@ public OutputStream getOutputStream() {
 	void execute(final Socket sock) throws IOException,
 			ServiceNotEnabledException, ServiceNotAuthorizedException {
 		rawIn = new BufferedInputStream(sock.getInputStream());
-		rawOut = new SafeBufferedOutputStream(sock.getOutputStream());
+		rawOut = new BufferedOutputStream(sock.getOutputStream());
 
 		if (0 < daemon.getTimeout())
 			sock.setSoTimeout(daemon.getTimeout() * 1000);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/DaemonService.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/DaemonService.java
index 4e7e123..ec6f242 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/DaemonService.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/DaemonService.java
@@ -47,8 +47,8 @@
 import java.io.IOException;
 
 import org.eclipse.jgit.lib.Config;
-import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.lib.Config.SectionParser;
+import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.transport.resolver.ServiceNotAuthorizedException;
 import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException;
 
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/HMACSHA1NonceGenerator.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/HMACSHA1NonceGenerator.java
index 622680a..319ae1e 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/HMACSHA1NonceGenerator.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/HMACSHA1NonceGenerator.java
@@ -52,7 +52,6 @@
 
 import org.eclipse.jgit.internal.storage.dfs.DfsRepository;
 import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.transport.NonceGenerator;
 import org.eclipse.jgit.transport.PushCertificate.NonceStatus;
 
 /**
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/InsecureCipherFactory.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/InsecureCipherFactory.java
new file mode 100644
index 0000000..73384a1
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/InsecureCipherFactory.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2016, Google Inc.
+ * 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.security.NoSuchAlgorithmException;
+
+import javax.crypto.Cipher;
+import javax.crypto.NoSuchPaddingException;
+
+/**
+ * <b>DO NOT USE</b> Factory to create any cipher.
+ * <p>
+ * This is a hack for {@link WalkEncryption} to create any cipher configured by
+ * the end-user. Using this class allows JGit to violate ErrorProne's security
+ * recommendations (<a
+ * href="http://errorprone.info/bugpattern/InsecureCryptoUsage"
+ * >InsecureCryptoUsage</a>), which is not secure.
+ */
+class InsecureCipherFactory {
+	static Cipher create(String algo)
+			throws NoSuchAlgorithmException, NoSuchPaddingException {
+		return Cipher.getInstance(algo);
+	}
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/JschSession.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/JschSession.java
index 1dfe5d9..fa27bfc 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/JschSession.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/JschSession.java
@@ -48,15 +48,14 @@
 
 package org.eclipse.jgit.transport;
 
+import java.io.BufferedOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
-import java.io.PipedInputStream;
-import java.io.PipedOutputStream;
 
 import org.eclipse.jgit.errors.TransportException;
 import org.eclipse.jgit.internal.JGitText;
-import org.eclipse.jgit.util.io.StreamCopyThread;
+import org.eclipse.jgit.util.io.IsolatedOutputStream;
 
 import com.jcraft.jsch.Channel;
 import com.jcraft.jsch.ChannelExec;
@@ -178,33 +177,12 @@ private void setupStreams() throws IOException {
 			// that we spawn a background thread to shuttle data through a pipe,
 			// as we can issue an interrupted write out of that. Its slower, so
 			// we only use this route if there is a timeout.
-			final OutputStream out = channel.getOutputStream();
+			OutputStream out = channel.getOutputStream();
 			if (timeout <= 0) {
 				outputStream = out;
 			} else {
-				final PipedInputStream pipeIn = new PipedInputStream();
-				final StreamCopyThread copier = new StreamCopyThread(pipeIn,
-						out);
-				final PipedOutputStream pipeOut = new PipedOutputStream(pipeIn) {
-					@Override
-					public void flush() throws IOException {
-						super.flush();
-						copier.flush();
-					}
-
-					@Override
-					public void close() throws IOException {
-						super.close();
-						try {
-							copier.join(timeout * 1000);
-						} catch (InterruptedException e) {
-							// Just wake early, the thread will terminate
-							// anyway.
-						}
-					}
-				};
-				copier.start();
-				outputStream = pipeOut;
+				IsolatedOutputStream i = new IsolatedOutputStream(out);
+				outputStream = new BufferedOutputStream(i, 16 * 1024);
 			}
 
 			errStream = channel.getErrStream();
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PackParser.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PackParser.java
index b96fe88..4bbe3f8 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PackParser.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PackParser.java
@@ -186,6 +186,9 @@ public static enum Source {
 	/** Git object size limit */
 	private long maxObjectSizeLimit;
 
+	private final ReceivedPackStatistics.Builder stats =
+			new ReceivedPackStatistics.Builder();
+
 	/**
 	 * Initialize a pack parser.
 	 *
@@ -455,8 +458,8 @@ public List<PackedObjectInfo> getSortedObjectList(
 	}
 
 	/**
-	 * Get the size of the parsed pack.
-	 *
+	 * Get the size of the newly created pack.
+	 * <p>
 	 * This will also include the pack index size if an index was created. This
 	 * method should only be called after pack parsing is finished.
 	 *
@@ -469,6 +472,18 @@ public long getPackSize() {
 	}
 
 	/**
+	 * Returns the statistics of the parsed pack.
+	 * <p>
+	 * This should only be called after pack parsing is finished.
+	 *
+	 * @return {@link ReceivedPackStatistics}
+	 * @since 4.6
+	 */
+	public ReceivedPackStatistics getReceivedPackStatistics() {
+		return stats.build();
+	}
+
+	/**
 	 * Parse the pack stream.
 	 *
 	 * @param progress
@@ -626,6 +641,7 @@ private void resolveDeltas(final PackedObjectInfo oe,
 	private void resolveDeltas(DeltaVisit visit, final int type,
 			ObjectTypeAndSize info, ProgressMonitor progress)
 			throws IOException {
+		stats.addDeltaObject(type);
 		do {
 			progress.update(1);
 			info = openDatabase(visit.delta, info);
@@ -919,6 +935,7 @@ private void readPackFooter() throws IOException {
 
 	// Cleanup all resources associated with our input parsing.
 	private void endInput() {
+		stats.setNumBytesRead(streamPosition());
 		in = null;
 	}
 
@@ -947,12 +964,14 @@ private void indexOneObject() throws IOException {
 		case Constants.OBJ_TREE:
 		case Constants.OBJ_BLOB:
 		case Constants.OBJ_TAG:
+			stats.addWholeObject(typeCode);
 			onBeginWholeObject(streamPosition, typeCode, sz);
 			onObjectHeader(Source.INPUT, hdrBuf, 0, hdrPtr);
 			whole(streamPosition, typeCode, sz);
 			break;
 
 		case Constants.OBJ_OFS_DELTA: {
+			stats.addOffsetDelta();
 			c = readFrom(Source.INPUT);
 			hdrBuf[hdrPtr++] = (byte) c;
 			long ofs = c & 127;
@@ -975,6 +994,7 @@ private void indexOneObject() throws IOException {
 		}
 
 		case Constants.OBJ_REF_DELTA: {
+			stats.addRefDelta();
 			c = fill(Source.INPUT, 20);
 			final ObjectId base = ObjectId.fromRaw(buf, c);
 			System.arraycopy(buf, c, hdrBuf, hdrPtr, 20);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PushCertificateIdent.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PushCertificateIdent.java
index 871a6f7..4c8acd2 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PushCertificateIdent.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PushCertificateIdent.java
@@ -44,7 +44,6 @@
 package org.eclipse.jgit.transport;
 
 import static java.nio.charset.StandardCharsets.UTF_8;
-
 import static org.eclipse.jgit.util.RawParseUtils.lastIndexOfTrim;
 
 import java.text.SimpleDateFormat;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java
index cc20d50..393e25a 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java
@@ -56,7 +56,9 @@
 
 import org.eclipse.jgit.annotations.Nullable;
 import org.eclipse.jgit.errors.UnpackException;
+import org.eclipse.jgit.lib.ConfigConstants;
 import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.NullProgressMonitor;
 import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.transport.ReceiveCommand.Result;
 import org.eclipse.jgit.transport.RefAdvertiser.PacketLineOutRefAdvertiser;
@@ -307,9 +309,19 @@ void sendString(final String s) throws IOException {
 				throw new UnpackException(unpackError);
 			}
 			postReceive.onPostReceive(this, filterCommands(Result.OK));
+			autoGc();
 		}
 	}
 
+	private void autoGc() {
+		Repository repo = getRepository();
+		if (!repo.getConfig().getBoolean(ConfigConstants.CONFIG_RECEIVE_SECTION,
+				ConfigConstants.CONFIG_KEY_AUTOGC, true)) {
+			return;
+		}
+		repo.autoGC(NullProgressMonitor.INSTANCE);
+	}
+
 	@Override
 	protected String getLockMessageProcessName() {
 		return "jgit receive-pack"; //$NON-NLS-1$
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivedPackStatistics.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivedPackStatistics.java
new file mode 100644
index 0000000..052d550
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivedPackStatistics.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2016, Google Inc.
+ * 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 org.eclipse.jgit.lib.Constants;
+
+/**
+ * Statistics about {@link PackParser}.
+ *
+ * @since 4.6
+ */
+public class ReceivedPackStatistics {
+	private long numBytesRead;
+
+	private long numWholeCommit;
+	private long numWholeTree;
+	private long numWholeBlob;
+	private long numWholeTag;
+	private long numOfsDelta;
+	private long numRefDelta;
+
+	private long numDeltaCommit;
+	private long numDeltaTree;
+	private long numDeltaBlob;
+	private long numDeltaTag;
+
+	/** @return number of bytes read from the input stream */
+	public long getNumBytesRead() {
+		return numBytesRead;
+	}
+
+	/** @return number of whole commit objects in the pack */
+	public long getNumWholeCommit() {
+		return numWholeCommit;
+	}
+
+	/** @return number of whole tree objects in the pack */
+	public long getNumWholeTree() {
+		return numWholeTree;
+	}
+
+	/** @return number of whole blob objects in the pack */
+	public long getNumWholeBlob() {
+		return numWholeBlob;
+	}
+
+	/** @return number of whole tag objects in the pack */
+	public long getNumWholeTag() {
+		return numWholeTag;
+	}
+
+	/** @return number of offset delta objects in the pack */
+	public long getNumOfsDelta() {
+		return numOfsDelta;
+	}
+
+	/** @return number of ref delta objects in the pack */
+	public long getNumRefDelta() {
+		return numRefDelta;
+	}
+
+	/** @return number of delta commit objects in the pack */
+	public long getNumDeltaCommit() {
+		return numDeltaCommit;
+	}
+
+	/** @return number of delta tree objects in the pack */
+	public long getNumDeltaTree() {
+		return numDeltaTree;
+	}
+
+	/** @return number of delta blob objects in the pack */
+	public long getNumDeltaBlob() {
+		return numDeltaBlob;
+	}
+
+	/** @return number of delta tag objects in the pack */
+	public long getNumDeltaTag() {
+		return numDeltaTag;
+	}
+
+	/** A builder for {@link ReceivedPackStatistics}. */
+	public static class Builder {
+		private long numBytesRead;
+
+		private long numWholeCommit;
+		private long numWholeTree;
+		private long numWholeBlob;
+		private long numWholeTag;
+		private long numOfsDelta;
+		private long numRefDelta;
+
+		private long numDeltaCommit;
+		private long numDeltaTree;
+		private long numDeltaBlob;
+		private long numDeltaTag;
+
+		/**
+		 * @param numBytesRead number of bytes read from the input stream
+		 * @return this
+		 */
+		public Builder setNumBytesRead(long numBytesRead) {
+			this.numBytesRead = numBytesRead;
+			return this;
+		}
+
+		/**
+		 * Increment a whole object count.
+		 *
+		 * @param type OBJ_COMMIT, OBJ_TREE, OBJ_BLOB, or OBJ_TAG
+		 * @return this
+		 */
+		public Builder addWholeObject(int type) {
+			switch (type) {
+				case Constants.OBJ_COMMIT:
+					numWholeCommit++;
+					break;
+				case Constants.OBJ_TREE:
+					numWholeTree++;
+					break;
+				case Constants.OBJ_BLOB:
+					numWholeBlob++;
+					break;
+				case Constants.OBJ_TAG:
+					numWholeTag++;
+					break;
+				default:
+					throw new IllegalArgumentException(
+							type + " cannot be a whole object"); //$NON-NLS-1$
+			}
+			return this;
+		}
+
+		/** @return this */
+		public Builder addOffsetDelta() {
+			numOfsDelta++;
+			return this;
+		}
+
+		/** @return this */
+		public Builder addRefDelta() {
+			numRefDelta++;
+			return this;
+		}
+
+		/**
+		 * Increment a delta object count.
+		 *
+		 * @param type OBJ_COMMIT, OBJ_TREE, OBJ_BLOB, or OBJ_TAG
+		 * @return this
+		 */
+		public Builder addDeltaObject(int type) {
+			switch (type) {
+				case Constants.OBJ_COMMIT:
+					numDeltaCommit++;
+					break;
+				case Constants.OBJ_TREE:
+					numDeltaTree++;
+					break;
+				case Constants.OBJ_BLOB:
+					numDeltaBlob++;
+					break;
+				case Constants.OBJ_TAG:
+					numDeltaTag++;
+					break;
+				default:
+					throw new IllegalArgumentException(
+							"delta should be a delta to a whole object. " + //$NON-NLS-1$
+							type + " cannot be a whole object"); //$NON-NLS-1$
+			}
+			return this;
+		}
+
+		ReceivedPackStatistics build() {
+			ReceivedPackStatistics s = new ReceivedPackStatistics();
+			s.numBytesRead = numBytesRead;
+			s.numWholeCommit = numWholeCommit;
+			s.numWholeTree = numWholeTree;
+			s.numWholeBlob = numWholeBlob;
+			s.numWholeTag = numWholeTag;
+			s.numOfsDelta = numOfsDelta;
+			s.numRefDelta = numRefDelta;
+			s.numDeltaCommit = numDeltaCommit;
+			s.numDeltaTree = numDeltaTree;
+			s.numDeltaBlob = numDeltaBlob;
+			s.numDeltaTag = numDeltaTag;
+			return s;
+		}
+	}
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ServiceMayNotContinueException.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ServiceMayNotContinueException.java
index ce5ccaa..81c5da3 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ServiceMayNotContinueException.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ServiceMayNotContinueException.java
@@ -44,6 +44,7 @@
 package org.eclipse.jgit.transport;
 
 import java.io.IOException;
+
 import javax.servlet.http.HttpServletResponse;
 
 import org.eclipse.jgit.internal.JGitText;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/Transport.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/Transport.java
index bc4843a..df86069 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/Transport.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/Transport.java
@@ -1199,6 +1199,9 @@ public FetchResult fetch(final ProgressMonitor monitor,
 
 		final FetchResult result = new FetchResult();
 		new FetchProcess(this, toFetch).execute(monitor, result);
+
+		local.autoGC(monitor);
+
 		return result;
 	}
 
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportBundleFile.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportBundleFile.java
index bbc0d0a..9b08341 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportBundleFile.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportBundleFile.java
@@ -94,7 +94,7 @@ public boolean canHandle(URIish uri, Repository local, String remoteName) {
 		public Transport open(URIish uri, Repository local, String remoteName)
 				throws NotSupportedException, TransportException {
 			if ("bundle".equals(uri.getScheme())) { //$NON-NLS-1$
-				File path = local.getFS().resolve(new File("."), uri.getPath()); //$NON-NLS-1$
+				File path = FS.DETECTED.resolve(new File("."), uri.getPath()); //$NON-NLS-1$
 				return new TransportBundleFile(local, uri, path);
 			}
 
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportGitAnon.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportGitAnon.java
index a7f42fd..c6e4c50 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportGitAnon.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportGitAnon.java
@@ -46,6 +46,7 @@
 package org.eclipse.jgit.transport;
 
 import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -62,7 +63,6 @@
 import org.eclipse.jgit.errors.TransportException;
 import org.eclipse.jgit.internal.JGitText;
 import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.util.io.SafeBufferedOutputStream;
 
 /**
  * Transport through a git-daemon waiting for anonymous TCP connections.
@@ -182,7 +182,7 @@ class TcpFetchConnection extends BasePackFetchConnection {
 				OutputStream sOut = sock.getOutputStream();
 
 				sIn = new BufferedInputStream(sIn);
-				sOut = new SafeBufferedOutputStream(sOut);
+				sOut = new BufferedOutputStream(sOut);
 
 				init(sIn, sOut);
 				service("git-upload-pack", pckOut); //$NON-NLS-1$
@@ -221,7 +221,7 @@ class TcpPushConnection extends BasePackPushConnection {
 				OutputStream sOut = sock.getOutputStream();
 
 				sIn = new BufferedInputStream(sIn);
-				sOut = new SafeBufferedOutputStream(sOut);
+				sOut = new BufferedOutputStream(sOut);
 
 				init(sIn, sOut);
 				service("git-receive-pack", pckOut); //$NON-NLS-1$
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportGitSsh.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportGitSsh.java
index 52f0f04..da98e8c 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportGitSsh.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportGitSsh.java
@@ -64,11 +64,11 @@
 import org.eclipse.jgit.internal.JGitText;
 import org.eclipse.jgit.lib.Constants;
 import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.util.FS;
 import org.eclipse.jgit.util.QuotedString;
 import org.eclipse.jgit.util.SystemReader;
 import org.eclipse.jgit.util.io.MessageWriter;
 import org.eclipse.jgit.util.io.StreamCopyThread;
-import org.eclipse.jgit.util.FS;
 
 /**
  * Transport through an SSH tunnel.
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 1166080..96a6fe1 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java
@@ -45,7 +45,9 @@
 
 package org.eclipse.jgit.transport;
 
+import static org.eclipse.jgit.lib.Constants.HEAD;
 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;
 import static org.eclipse.jgit.util.HttpSupport.HDR_ACCEPT_ENCODING;
 import static org.eclipse.jgit.util.HttpSupport.HDR_CONTENT_ENCODING;
@@ -128,6 +130,25 @@ public class TransportHttp extends HttpTransport implements WalkTransport,
 
 	private static final String SVC_RECEIVE_PACK = "git-receive-pack"; //$NON-NLS-1$
 
+	/**
+	 * Accept-Encoding header in the HTTP request
+	 * (https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html).
+	 *
+	 * @since 4.6
+	 */
+	public enum AcceptEncoding {
+		/**
+		 * Do not specify an Accept-Encoding header. In most servers this
+		 * results in the content being transmitted as-is.
+		 */
+		UNSPECIFIED,
+
+		/**
+		 * Accept gzip content encoding.
+		 */
+		GZIP
+	}
+
 	static final TransportProtocol PROTO_HTTP = new TransportProtocol() {
 		private final String[] schemeNames = { "http", "https" }; //$NON-NLS-1$ //$NON-NLS-2$
 
@@ -324,12 +345,15 @@ private WalkFetchConnection newDumbConnection(InputStream in)
 			br.close();
 		}
 
-		if (!refs.containsKey(Constants.HEAD)) {
+		if (!refs.containsKey(HEAD)) {
 			// If HEAD was not published in the info/refs file (it usually
 			// is not there) download HEAD by itself as a loose file and do
 			// the resolution by hand.
 			//
-			HttpConnection conn = httpOpen(new URL(baseUrl, Constants.HEAD));
+			HttpConnection conn = httpOpen(
+					METHOD_GET,
+					new URL(baseUrl, HEAD),
+					AcceptEncoding.GZIP);
 			int status = HttpSupport.response(conn);
 			switch (status) {
 			case HttpConnection.HTTP_OK: {
@@ -341,11 +365,11 @@ private WalkFetchConnection newDumbConnection(InputStream in)
 						Ref r = refs.get(target);
 						if (r == null)
 							r = new ObjectIdRef.Unpeeled(Ref.Storage.NEW, target, null);
-						r = new SymbolicRef(Constants.HEAD, r);
+						r = new SymbolicRef(HEAD, r);
 						refs.put(r.getName(), r);
 					} else if (line != null && ObjectId.isId(line)) {
 						Ref r = new ObjectIdRef.Unpeeled(Ref.Storage.NETWORK,
-								Constants.HEAD, ObjectId.fromString(line));
+								HEAD, ObjectId.fromString(line));
 						refs.put(r.getName(), r);
 					}
 				} finally {
@@ -455,7 +479,7 @@ private HttpConnection connect(final String service)
 		Collection<Type> ignoreTypes = null;
 		for (;;) {
 			try {
-				final HttpConnection conn = httpOpen(u);
+				final HttpConnection conn = httpOpen(METHOD_GET, u, AcceptEncoding.GZIP);
 				if (useSmartHttp) {
 					String exp = "application/x-" + service + "-advertisement"; //$NON-NLS-1$ //$NON-NLS-2$
 					conn.setRequestProperty(HDR_ACCEPT, exp + ", */*"); //$NON-NLS-1$
@@ -529,21 +553,37 @@ private HttpConnection connect(final String service)
 		}
 	}
 
-	final HttpConnection httpOpen(URL u) throws IOException {
-		return httpOpen(METHOD_GET, u);
+	/**
+	 * Open an HTTP connection, setting the accept-encoding request header to gzip.
+	 *
+	 * @param method HTTP request method
+	 * @param u url of the HTTP connection
+	 * @return the HTTP connection
+	 * @throws IOException
+	 * @since 3.3
+	 * @deprecated use {@link #httpOpen(String, URL, AcceptEncoding)} instead.
+	 */
+	@Deprecated
+	protected HttpConnection httpOpen(String method, URL u) throws IOException {
+		return httpOpen(method, u, AcceptEncoding.GZIP);
 	}
 
 	/**
 	 * Open an HTTP connection.
 	 *
-	 * @param method
-	 * @param u
-	 * @return the connection
+	 * @param method HTTP request method
+	 * @param u url of the HTTP connection
+	 * @param acceptEncoding accept-encoding header option
+	 * @return the HTTP connection
 	 * @throws IOException
-	 * @since 3.3
+	 * @since 4.6
 	 */
-	protected HttpConnection httpOpen(String method, URL u)
-			throws IOException {
+	protected HttpConnection httpOpen(String method, URL u,
+			AcceptEncoding acceptEncoding) throws IOException {
+		if (method == null || u == null || acceptEncoding == null) {
+			throw new NullPointerException();
+		}
+
 		final Proxy proxy = HttpSupport.proxyFor(proxySelector, u);
 		HttpConnection conn = connectionFactory.create(u, proxy);
 
@@ -553,7 +593,9 @@ protected HttpConnection httpOpen(String method, URL u)
 
 		conn.setRequestMethod(method);
 		conn.setUseCaches(false);
-		conn.setRequestProperty(HDR_ACCEPT_ENCODING, ENCODING_GZIP);
+		if (acceptEncoding == AcceptEncoding.GZIP) {
+			conn.setRequestProperty(HDR_ACCEPT_ENCODING, ENCODING_GZIP);
+		}
 		conn.setRequestProperty(HDR_PRAGMA, "no-cache"); //$NON-NLS-1$
 		if (UserAgent.get() != null) {
 			conn.setRequestProperty(HDR_USER_AGENT, UserAgent.get());
@@ -575,7 +617,7 @@ protected HttpConnection httpOpen(String method, URL u)
 	final InputStream openInputStream(HttpConnection conn)
 			throws IOException {
 		InputStream input = conn.getInputStream();
-		if (ENCODING_GZIP.equals(conn.getHeaderField(HDR_CONTENT_ENCODING)))
+		if (isGzipContent(conn))
 			input = new GZIPInputStream(input);
 		return input;
 	}
@@ -591,6 +633,11 @@ private boolean isSmartHttp(final HttpConnection c, final String service) {
 		return expType.equals(actType);
 	}
 
+	private boolean isGzipContent(final HttpConnection c) {
+		return ENCODING_GZIP.equals(c.getHeaderField(HDR_CONTENT_ENCODING))
+				|| ENCODING_X_GZIP.equals(c.getHeaderField(HDR_CONTENT_ENCODING));
+	}
+
 	private void readSmartHeaders(final InputStream in, final String service)
 			throws IOException {
 		// A smart reply will have a '#' after the first 4 bytes, but
@@ -655,6 +702,14 @@ WalkRemoteObjectDatabase openAlternate(final String location)
 		}
 
 		@Override
+		BufferedReader openReader(String path) throws IOException {
+			// Line oriented readable content is likely to compress well.
+			// Request gzip encoding.
+			InputStream is = open(path, AcceptEncoding.GZIP).in;
+			return new BufferedReader(new InputStreamReader(is, Constants.CHARSET));
+		}
+
+		@Override
 		Collection<String> getPackNames() throws IOException {
 			final Collection<String> packs = new ArrayList<String>();
 			try {
@@ -679,14 +734,25 @@ Collection<String> getPackNames() throws IOException {
 
 		@Override
 		FileStream open(final String path) throws IOException {
+			return open(path, AcceptEncoding.UNSPECIFIED);
+		}
+
+		FileStream open(String path, AcceptEncoding acceptEncoding)
+				throws IOException {
 			final URL base = httpObjectsUrl;
 			final URL u = new URL(base, path);
-			final HttpConnection c = httpOpen(u);
+			final HttpConnection c = httpOpen(METHOD_GET, u, acceptEncoding);
 			switch (HttpSupport.response(c)) {
 			case HttpConnection.HTTP_OK:
 				final InputStream in = openInputStream(c);
-				final int len = c.getContentLength();
-				return new FileStream(in, len);
+				// If content is being gzipped and then transferred, the content
+				// length in the header is the zipped content length, not the
+				// actual content length.
+				if (!isGzipContent(c)) {
+					final int len = c.getContentLength();
+					return new FileStream(in, len);
+				}
+				return new FileStream(in);
 			case HttpConnection.HTTP_NOT_FOUND:
 				throw new FileNotFoundException(u.toString());
 			default:
@@ -832,7 +898,10 @@ abstract class Service {
 		}
 
 		void openStream() throws IOException {
-			conn = httpOpen(METHOD_POST, new URL(baseUrl, serviceName));
+			conn = httpOpen(
+					METHOD_POST,
+					new URL(baseUrl, serviceName),
+					AcceptEncoding.GZIP);
 			conn.setInstanceFollowRedirects(false);
 			conn.setDoOutput(true);
 			conn.setRequestProperty(HDR_CONTENT_TYPE, requestType);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportLocal.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportLocal.java
index 292ba7e..1528c71 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportLocal.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportLocal.java
@@ -48,6 +48,7 @@
 package org.eclipse.jgit.transport;
 
 import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
@@ -67,7 +68,6 @@
 import org.eclipse.jgit.transport.resolver.UploadPackFactory;
 import org.eclipse.jgit.util.FS;
 import org.eclipse.jgit.util.io.MessageWriter;
-import org.eclipse.jgit.util.io.SafeBufferedOutputStream;
 import org.eclipse.jgit.util.io.StreamCopyThread;
 
 /**
@@ -258,7 +258,7 @@ class ForkLocalFetchConnection extends BasePackFetchConnection {
 			OutputStream upOut = uploadPack.getOutputStream();
 
 			upIn = new BufferedInputStream(upIn);
-			upOut = new SafeBufferedOutputStream(upOut);
+			upOut = new BufferedOutputStream(upOut);
 
 			init(upIn, upOut);
 			readAdvertisedRefs();
@@ -311,7 +311,7 @@ class ForkLocalPushConnection extends BasePackPushConnection {
 			OutputStream rpOut = receivePack.getOutputStream();
 
 			rpIn = new BufferedInputStream(rpIn);
-			rpOut = new SafeBufferedOutputStream(rpOut);
+			rpOut = new BufferedOutputStream(rpOut);
 
 			init(rpIn, rpOut);
 			readAdvertisedRefs();
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 0b1848c..b1cc5de 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java
@@ -45,8 +45,8 @@
 
 import static org.eclipse.jgit.lib.RefDatabase.ALL;
 import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_AGENT;
-import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_ALLOW_TIP_SHA1_IN_WANT;
 import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_ALLOW_REACHABLE_SHA1_IN_WANT;
+import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_ALLOW_TIP_SHA1_IN_WANT;
 import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_INCLUDE_TAG;
 import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_MULTI_ACK;
 import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_MULTI_ACK_DETAILED;
@@ -312,6 +312,7 @@ public Set<String> getOptions() {
 
 	private PackStatistics statistics;
 
+	@SuppressWarnings("deprecation")
 	private UploadPackLogger logger = UploadPackLogger.NULL;
 
 	/**
@@ -1424,6 +1425,7 @@ private boolean reportInternalServerErrorOverSideband() {
 		}
 	}
 
+	@SuppressWarnings("deprecation")
 	private void sendPack(final boolean sideband) throws IOException {
 		ProgressMonitor pm = NullProgressMonitor.INSTANCE;
 		OutputStream packOut = rawOut;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPackLogger.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPackLogger.java
index 85ebecc..0588634 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPackLogger.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPackLogger.java
@@ -56,7 +56,7 @@
  * @deprecated use {@link PostUploadHook} instead
  */
 @Deprecated
-public interface UploadPackLogger {
+public interface UploadPackLogger { // TODO remove in JGit 5.0
 	/** A simple no-op logger. */
 	public static final UploadPackLogger NULL = new UploadPackLogger() {
 		public void onPackStatistics(PackWriter.Statistics stats) {
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 fe03bdc..4c3fdd8 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkEncryption.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkEncryption.java
@@ -143,35 +143,6 @@ OutputStream encrypt(OutputStream os) {
 		}
 	}
 
-	// PBEParameterSpec factory for Java (version <= 7).
-	// Does not support AlgorithmParameterSpec.
-	static PBEParameterSpec java7PBEParameterSpec(byte[] salt,
-			int iterationCount) {
-		return new PBEParameterSpec(salt, iterationCount);
-	}
-
-	// PBEParameterSpec factory for Java (version >= 8).
-	// Adds support for AlgorithmParameterSpec.
-	static PBEParameterSpec java8PBEParameterSpec(byte[] salt,
-			int iterationCount, AlgorithmParameterSpec paramSpec) {
-		try {
-			@SuppressWarnings("boxing")
-			PBEParameterSpec instance = PBEParameterSpec.class
-					.getConstructor(byte[].class, int.class,
-							AlgorithmParameterSpec.class)
-					.newInstance(salt, iterationCount, paramSpec);
-			return instance;
-		} catch (Exception e) {
-			throw new RuntimeException(e);
-		}
-	}
-
-	// Current runtime version.
-	// https://docs.oracle.com/javase/7/docs/technotes/guides/versioning/spec/versioning2.html
-	static double javaVersion() {
-		return Double.parseDouble(System.getProperty("java.specification.version")); //$NON-NLS-1$
-	}
-
 	/**
 	 * JetS3t compatibility reference: <a href=
 	 * "https://bitbucket.org/jmurty/jets3t/src/156c00eb160598c2e9937fd6873f00d3190e28ca/src/org/jets3t/service/security/EncryptionUtil.java">
@@ -204,7 +175,7 @@ static class JetS3tV2 extends WalkEncryption {
 		// Size 16, see com.sun.crypto.provider.AESConstants.AES_BLOCK_SIZE
 		static final byte[] ZERO_AES_IV = new byte[16];
 
-		private static final String cryptoVer = VERSION;
+		private static final String CRYPTO_VER = VERSION;
 
 		private final String cryptoAlg;
 
@@ -217,7 +188,7 @@ static class JetS3tV2 extends WalkEncryption {
 			cryptoAlg = algo;
 
 			// Verify if cipher is present.
-			Cipher cipher = Cipher.getInstance(cryptoAlg);
+			Cipher cipher = InsecureCipherFactory.create(cryptoAlg);
 
 			// Standard names are not case-sensitive.
 			// http://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html
@@ -233,9 +204,7 @@ static class JetS3tV2 extends WalkEncryption {
 			boolean useIV = cryptoName.contains("AES"); //$NON-NLS-1$
 
 			// PBEParameterSpec algorithm parameters are supported from Java 8.
-			boolean isJava8 = javaVersion() >= 1.8;
-
-			if (useIV && isJava8) {
+			if (useIV) {
 				// Support IV where possible:
 				// * since JCE provider uses random IV for PBE/AES
 				// * and there is no place to store dynamic IV in JetS3t V2
@@ -245,34 +214,33 @@ static class JetS3tV2 extends WalkEncryption {
 				// https://bitbucket.org/jmurty/jets3t/raw/156c00eb160598c2e9937fd6873f00d3190e28ca/src/org/jets3t/service/security/EncryptionUtil.java
 				// http://cr.openjdk.java.net/~mullan/webrevs/ascarpin/webrev.00/raw_files/new/src/share/classes/com/sun/crypto/provider/PBES2Core.java
 				IvParameterSpec paramIV = new IvParameterSpec(ZERO_AES_IV);
-				paramSpec = java8PBEParameterSpec(SALT, ITERATIONS, paramIV);
+				paramSpec = new PBEParameterSpec(SALT, ITERATIONS, paramIV);
 			} else {
 				// Strict legacy JetS3t V2 compatibility, with no IV support.
-				paramSpec = java7PBEParameterSpec(SALT, ITERATIONS);
+				paramSpec = new PBEParameterSpec(SALT, ITERATIONS);
 			}
 
 			// Verify if cipher + key are allowed by policy.
 			cipher.init(Cipher.ENCRYPT_MODE, secretKey, paramSpec);
 			cipher.doFinal();
-
 		}
 
 		@Override
 		void request(final HttpURLConnection u, final String prefix) {
-			u.setRequestProperty(prefix + JETS3T_CRYPTO_VER, cryptoVer);
+			u.setRequestProperty(prefix + JETS3T_CRYPTO_VER, CRYPTO_VER);
 			u.setRequestProperty(prefix + JETS3T_CRYPTO_ALG, cryptoAlg);
 		}
 
 		@Override
 		void validate(final HttpURLConnection u, final String prefix)
 				throws IOException {
-			validateImpl(u, prefix, cryptoVer, cryptoAlg);
+			validateImpl(u, prefix, CRYPTO_VER, cryptoAlg);
 		}
 
 		@Override
 		OutputStream encrypt(final OutputStream os) throws IOException {
 			try {
-				final Cipher cipher = Cipher.getInstance(cryptoAlg);
+				final Cipher cipher = InsecureCipherFactory.create(cryptoAlg);
 				cipher.init(Cipher.ENCRYPT_MODE, secretKey, paramSpec);
 				return new CipherOutputStream(os, cipher);
 			} catch (GeneralSecurityException e) {
@@ -283,7 +251,7 @@ OutputStream encrypt(final OutputStream os) throws IOException {
 		@Override
 		InputStream decrypt(final InputStream in) throws IOException {
 			try {
-				final Cipher cipher = Cipher.getInstance(cryptoAlg);
+				final Cipher cipher = InsecureCipherFactory.create(cryptoAlg);
 				cipher.init(Cipher.DECRYPT_MODE, secretKey, paramSpec);
 				return new CipherInputStream(in, cipher);
 			} catch (GeneralSecurityException e) {
@@ -374,7 +342,7 @@ static abstract class SymmetricEncryption extends WalkEncryption
 			String keySalt = props.getProperty(profile + X_KEY_SALT, DEFAULT_KEY_SALT);
 
 			// Verify if cipher is present.
-			Cipher cipher = Cipher.getInstance(cipherAlgo);
+			Cipher cipher = InsecureCipherFactory.create(cipherAlgo);
 
 			// Verify if key factory is present.
 			SecretKeyFactory factory = SecretKeyFactory.getInstance(keyAlgo);
@@ -432,7 +400,7 @@ static abstract class SymmetricEncryption extends WalkEncryption
 		@Override
 		OutputStream encrypt(OutputStream output) throws IOException {
 			try {
-				Cipher cipher = Cipher.getInstance(cipherAlgo);
+				Cipher cipher = InsecureCipherFactory.create(cipherAlgo);
 				cipher.init(Cipher.ENCRYPT_MODE, secretKey);
 				AlgorithmParameters params = cipher.getParameters();
 				if (params == null) {
@@ -489,7 +457,7 @@ void validate(HttpURLConnection conn, String prefix)
 						JGitText.get().unsupportedEncryptionVersion, vers));
 			}
 			try {
-				decryptCipher = Cipher.getInstance(cipherAlgo);
+				decryptCipher = InsecureCipherFactory.create(cipherAlgo);
 				if (cont.isEmpty()) {
 					decryptCipher.init(Cipher.DECRYPT_MODE, secretKey);
 				} else {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkFetchConnection.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkFetchConnection.java
index 17edfdc..13d4a24 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkFetchConnection.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkFetchConnection.java
@@ -195,7 +195,7 @@ class WalkFetchConnection extends BaseFetchConnection {
 		local = wt.local;
 		objCheck = wt.getObjectChecker();
 		inserter = local.newObjectInserter();
-		reader = local.newObjectReader();
+		reader = inserter.newReader();
 
 		remotes = new ArrayList<WalkRemoteObjectDatabase>();
 		remotes.add(w);
@@ -240,6 +240,12 @@ protected void doFetch(final ProgressMonitor monitor,
 				downloadObject(monitor, id);
 			process(id);
 		}
+
+		try {
+			inserter.flush();
+		} catch (IOException e) {
+			throw new TransportException(e.getMessage(), e);
+		}
 	}
 
 	public Collection<PackLock> getPackLocks() {
@@ -652,7 +658,6 @@ private void verifyAndInsertLooseObject(final AnyObjectId id,
 					Constants.typeString(type),
 					Integer.valueOf(compressed.length)));
 		}
-		inserter.flush();
 	}
 
 	private Collection<WalkRemoteObjectDatabase> expandOneAlternate(
@@ -876,14 +881,17 @@ else if (tmpIdx.isFile()) {
 		void downloadPack(final ProgressMonitor monitor) throws IOException {
 			String name = "pack/" + packName; //$NON-NLS-1$
 			WalkRemoteObjectDatabase.FileStream s = connection.open(name);
-			PackParser parser = inserter.newPackParser(s.in);
-			parser.setAllowThin(false);
-			parser.setObjectChecker(objCheck);
-			parser.setLockMessage(lockMessage);
-			PackLock lock = parser.parse(monitor);
-			if (lock != null)
-				packLocks.add(lock);
-			inserter.flush();
+			try {
+				PackParser parser = inserter.newPackParser(s.in);
+				parser.setAllowThin(false);
+				parser.setObjectChecker(objCheck);
+				parser.setLockMessage(lockMessage);
+				PackLock lock = parser.parse(monitor);
+				if (lock != null)
+					packLocks.add(lock);
+			} finally {
+				s.in.close();
+			}
 		}
 	}
 }
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkPushConnection.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkPushConnection.java
index 4eaf3f9..7b449c7 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkPushConnection.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkPushConnection.java
@@ -45,6 +45,7 @@
 
 import static org.eclipse.jgit.transport.WalkRemoteObjectDatabase.ROOT_DIR;
 
+import java.io.BufferedOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.util.ArrayList;
@@ -69,7 +70,6 @@
 import org.eclipse.jgit.lib.RefWriter;
 import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.transport.RemoteRefUpdate.Status;
-import org.eclipse.jgit.util.io.SafeBufferedOutputStream;
 
 /**
  * Generic push support for dumb transport protocols.
@@ -262,21 +262,15 @@ private void sendpack(final List<RemoteRefUpdate> updates,
 			// Write the pack file, then the index, as readers look the
 			// other direction (index, then pack file).
 			//
-			final String wt = "Put " + base.substring(0, 12); //$NON-NLS-1$
-			OutputStream os = dest.writeFile(pathPack, monitor, wt + "..pack"); //$NON-NLS-1$
-			try {
-				os = new SafeBufferedOutputStream(os);
+			String wt = "Put " + base.substring(0, 12); //$NON-NLS-1$
+			try (OutputStream os = new BufferedOutputStream(
+					dest.writeFile(pathPack, monitor, wt + "..pack"))) { //$NON-NLS-1$
 				writer.writePack(monitor, monitor, os);
-			} finally {
-				os.close();
 			}
 
-			os = dest.writeFile(pathIdx, monitor, wt + "..idx"); //$NON-NLS-1$
-			try {
-				os = new SafeBufferedOutputStream(os);
+			try (OutputStream os = new BufferedOutputStream(
+					dest.writeFile(pathIdx, monitor, wt + "..idx"))) { //$NON-NLS-1$
 				writer.writeIndex(os);
-			} finally {
-				os.close();
 			}
 
 			// Record the pack at the start of the pack info list. This
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 e47913e..24f30ed 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkRemoteObjectDatabase.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkRemoteObjectDatabase.java
@@ -133,6 +133,9 @@ abstract Collection<WalkRemoteObjectDatabase> getAlternates()
 	 * Callers such as {@link WalkFetchConnection} are prepared to handle this
 	 * by validating the content received, and assuming content that fails to
 	 * match its hash is an incorrectly phrased FileNotFoundException.
+	 * <p>
+	 * This method is recommended for already compressed files like loose objects
+	 * and pack files. For text files, see {@link #openReader(String)}.
 	 *
 	 * @param path
 	 *            location of the file to read, relative to this objects
@@ -346,8 +349,8 @@ void writeInfoPacks(final Collection<String> packNames) throws IOException {
 	/**
 	 * Open a buffered reader around a file.
 	 * <p>
-	 * This is shorthand for calling {@link #open(String)} and then wrapping it
-	 * in a reader suitable for line oriented files like the alternates list.
+	 * This method is suitable for for reading line-oriented resources like
+	 * <code>info/packs</code>, <code>info/refs</code>, and the alternates list.
 	 *
 	 * @return a stream to read from the file. Never null.
 	 * @param path
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/AbstractTreeIterator.java b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/AbstractTreeIterator.java
index 07fc829..6d4c342 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/AbstractTreeIterator.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/AbstractTreeIterator.java
@@ -49,8 +49,8 @@
 import java.nio.ByteBuffer;
 import java.nio.CharBuffer;
 
-import org.eclipse.jgit.attributes.AttributesNode;
 import org.eclipse.jgit.attributes.AttributesHandler;
+import org.eclipse.jgit.attributes.AttributesNode;
 import org.eclipse.jgit.dircache.DirCacheCheckout;
 import org.eclipse.jgit.errors.CorruptObjectException;
 import org.eclipse.jgit.errors.IncorrectObjectTypeException;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/FileTreeIterator.java b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/FileTreeIterator.java
index db81e1a..afa2ed9 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/FileTreeIterator.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/FileTreeIterator.java
@@ -426,4 +426,9 @@ public File getEntryFile() {
 	protected byte[] idSubmodule(final Entry e) {
 		return idSubmodule(getDirectory(), e);
 	}
+
+	@Override
+	protected String readSymlinkTarget(Entry entry) throws IOException {
+		return fs.readSymLink(getEntryFile());
+	}
 }
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/TreeWalk.java b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/TreeWalk.java
index 911b7ff..5dfebe9 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/TreeWalk.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/TreeWalk.java
@@ -53,10 +53,11 @@
 import org.eclipse.jgit.api.errors.JGitInternalException;
 import org.eclipse.jgit.attributes.Attribute;
 import org.eclipse.jgit.attributes.Attributes;
+import org.eclipse.jgit.attributes.AttributesHandler;
 import org.eclipse.jgit.attributes.AttributesNodeProvider;
 import org.eclipse.jgit.attributes.AttributesProvider;
+import org.eclipse.jgit.attributes.FilterCommandRegistry;
 import org.eclipse.jgit.dircache.DirCacheBuildIterator;
-import org.eclipse.jgit.attributes.AttributesHandler;
 import org.eclipse.jgit.dircache.DirCacheIterator;
 import org.eclipse.jgit.errors.CorruptObjectException;
 import org.eclipse.jgit.errors.IncorrectObjectTypeException;
@@ -64,6 +65,7 @@
 import org.eclipse.jgit.errors.StopWalkException;
 import org.eclipse.jgit.lib.AnyObjectId;
 import org.eclipse.jgit.lib.Config;
+import org.eclipse.jgit.lib.ConfigConstants;
 import org.eclipse.jgit.lib.Constants;
 import org.eclipse.jgit.lib.CoreConfig.EolStreamType;
 import org.eclipse.jgit.lib.FileMode;
@@ -313,6 +315,8 @@ public static TreeWalk forPath(final Repository db, final String path,
 
 	private Config config;
 
+	private Set<String> filterCommands;
+
 	/**
 	 * Create a new tree walker for a given repository.
 	 *
@@ -357,6 +361,8 @@ private TreeWalk(final @Nullable Repository repo, final ObjectReader or,
 		if (repo != null) {
 			config = repo.getConfig();
 			attributesNodeProvider = repo.createAttributesNodeProvider();
+			filterCommands = FilterCommandRegistry
+					.getRegisteredFilterCommands();
 		} else {
 			config = null;
 			attributesNodeProvider = null;
@@ -1367,10 +1373,22 @@ private String getFilterCommandDefinition(String filterDriverName,
 		String filterCommand = filterCommandsByNameDotType.get(key);
 		if (filterCommand != null)
 			return filterCommand;
-		filterCommand = config.getString(Constants.ATTR_FILTER,
+		filterCommand = config.getString(ConfigConstants.CONFIG_FILTER_SECTION,
 				filterDriverName, filterCommandType);
-		if (filterCommand != null)
+		boolean useBuiltin = config.getBoolean(
+				ConfigConstants.CONFIG_FILTER_SECTION,
+				filterDriverName, ConfigConstants.CONFIG_KEY_USEJGITBUILTIN, false);
+		if (useBuiltin) {
+			String builtinFilterCommand = Constants.BUILTIN_FILTER_PREFIX
+					+ filterDriverName + '/' + filterCommandType;
+			if (filterCommands != null
+					&& filterCommands.contains(builtinFilterCommand)) {
+				filterCommand = builtinFilterCommand;
+			}
+		}
+		if (filterCommand != null) {
 			filterCommandsByNameDotType.put(key, filterCommand);
+		}
 		return filterCommand;
 	}
 }
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java
index 9a3fa80..52477cb 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java
@@ -65,6 +65,8 @@
 import org.eclipse.jgit.api.errors.FilterFailedException;
 import org.eclipse.jgit.attributes.AttributesNode;
 import org.eclipse.jgit.attributes.AttributesRule;
+import org.eclipse.jgit.attributes.FilterCommand;
+import org.eclipse.jgit.attributes.FilterCommandRegistry;
 import org.eclipse.jgit.diff.RawText;
 import org.eclipse.jgit.dircache.DirCache;
 import org.eclipse.jgit.dircache.DirCacheEntry;
@@ -93,6 +95,8 @@
 import org.eclipse.jgit.util.IO;
 import org.eclipse.jgit.util.Paths;
 import org.eclipse.jgit.util.RawParseUtils;
+import org.eclipse.jgit.util.TemporaryBuffer;
+import org.eclipse.jgit.util.TemporaryBuffer.LocalFile;
 import org.eclipse.jgit.util.io.AutoLFInputStream;
 import org.eclipse.jgit.util.io.EolStreamTypeUtil;
 
@@ -263,7 +267,6 @@ public boolean hasId() {
 			// If there is a matching DirCacheIterator, we can reuse
 			// its idBuffer, but only if we appear to be clean against
 			// the cached index information for the path.
-			//
 			DirCacheIterator i = state.walk.getTree(state.dirCacheTree,
 							DirCacheIterator.class);
 			if (i != null) {
@@ -393,15 +396,9 @@ && getEolStreamType(opType) == EolStreamType.DIRECT) {
 
 		if (len <= MAXIMUM_FILE_SIZE_TO_READ_FULLY) {
 			ByteBuffer rawbuf = IO.readWholeStream(is, (int) len);
-			byte[] raw = rawbuf.array();
-			int n = rawbuf.limit();
-			if (!isBinary(raw, n)) {
-				rawbuf = filterClean(raw, n, opType);
-				raw = rawbuf.array();
-				n = rawbuf.limit();
-			}
-			canonLen = n;
-			return new ByteArrayInputStream(raw, 0, n);
+			rawbuf = filterClean(rawbuf.array(), rawbuf.limit(), opType);
+			canonLen = rawbuf.limit();
+			return new ByteArrayInputStream(rawbuf.array(), 0, (int) canonLen);
 		}
 
 		if (getCleanFilterCommand() == null && isBinary(e)) {
@@ -429,10 +426,6 @@ private static void safeClose(final InputStream in) {
 		}
 	}
 
-	private static boolean isBinary(byte[] content, int sz) {
-		return RawText.isBinary(content, sz);
-	}
-
 	private static boolean isBinary(Entry entry) throws IOException {
 		InputStream in = entry.openInputStream();
 		try {
@@ -461,6 +454,16 @@ private InputStream filterClean(InputStream in, OperationType opType)
 		in = handleAutoCRLF(in, opType);
 		String filterCommand = getCleanFilterCommand();
 		if (filterCommand != null) {
+			if (FilterCommandRegistry.isRegistered(filterCommand)) {
+				LocalFile buffer = new TemporaryBuffer.LocalFile(null);
+				FilterCommand command = FilterCommandRegistry
+						.createFilterCommand(filterCommand, repository, in,
+								buffer);
+				while (command.run() != -1) {
+					// loop as long as command.run() tells there is work to do
+				}
+				return buffer.openInputStream();
+			}
 			FS fs = repository.getFS();
 			ProcessBuilder filterProcessBuilder = fs.runInShell(filterCommand,
 					new String[0]);
@@ -1005,10 +1008,10 @@ private boolean contentCheck(DirCacheEntry entry, ObjectReader reader)
 
 			return false;
 		} else {
-			if (mode == FileMode.SYMLINK.getBits())
-				return !new File(readContentAsNormalizedString(current()))
-						.equals(new File((readContentAsNormalizedString(entry,
-								reader))));
+			if (mode == FileMode.SYMLINK.getBits()) {
+				return !new File(readSymlinkTarget(current())).equals(
+						new File(readContentAsNormalizedString(entry, reader)));
+			}
 			// Content differs: that's a real change, perhaps
 			if (reader == null) // deprecated use, do no further checks
 				return true;
@@ -1054,12 +1057,30 @@ private static String readContentAsNormalizedString(DirCacheEntry entry,
 		return FS.detect().normalize(RawParseUtils.decode(cachedBytes));
 	}
 
-	private static String readContentAsNormalizedString(Entry entry) throws IOException {
+	/**
+	 * Reads the target of a symlink as a string. This default implementation
+	 * fully reads the entry's input stream and converts it to a normalized
+	 * string. Subclasses may override to provide more specialized
+	 * implementations.
+	 *
+	 * @param entry
+	 *            to read
+	 * @return the entry's content as a normalized string
+	 * @throws IOException
+	 *             if the entry cannot be read or does not denote a symlink
+	 * @since 4.6
+	 */
+	protected String readSymlinkTarget(Entry entry) throws IOException {
+		if (!entry.getMode().equals(FileMode.SYMLINK)) {
+			throw new java.nio.file.NotLinkException(entry.getName());
+		}
 		long length = entry.getLength();
 		byte[] content = new byte[(int) length];
-		InputStream is = entry.openInputStream();
-		IO.readFully(is, content, 0, (int) length);
-		return FS.detect().normalize(RawParseUtils.decode(content));
+		try (InputStream is = entry.openInputStream()) {
+			int bytesRead = IO.readFully(is, content, 0);
+			return FS.detect()
+					.normalize(RawParseUtils.decode(content, 0, bytesRead));
+		}
 	}
 
 	private static long computeLength(InputStream in) throws IOException {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeOptions.java b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeOptions.java
index dea07c1..112ce8f 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeOptions.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeOptions.java
@@ -44,8 +44,8 @@
 package org.eclipse.jgit.treewalk;
 
 import org.eclipse.jgit.lib.Config;
-import org.eclipse.jgit.lib.ConfigConstants;
 import org.eclipse.jgit.lib.Config.SectionParser;
+import org.eclipse.jgit.lib.ConfigConstants;
 import org.eclipse.jgit.lib.CoreConfig.AutoCRLF;
 import org.eclipse.jgit.lib.CoreConfig.CheckStat;
 import org.eclipse.jgit.lib.CoreConfig.EOL;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/ChangeIdUtil.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/ChangeIdUtil.java
index e14096e..f1f6053 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/ChangeIdUtil.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/ChangeIdUtil.java
@@ -45,8 +45,8 @@
 import java.util.regex.Pattern;
 
 import org.eclipse.jgit.lib.Constants;
-import org.eclipse.jgit.lib.ObjectInserter;
 import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectInserter;
 import org.eclipse.jgit.lib.PersonIdent;
 
 /**
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java
index 530b1d4..4a2a2d6 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java
@@ -165,7 +165,7 @@ public int getRc() {
 	/** The auto-detected implementation selected for this operating system and JRE. */
 	public static final FS DETECTED = detect();
 
-	private static FSFactory factory;
+	private volatile static FSFactory factory;
 
 	/**
 	 * Auto-detect the appropriate file system abstraction.
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX.java
index 4ecaf9c..f63c437 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX.java
@@ -99,6 +99,7 @@ protected FS_POSIX(FS src) {
 		}
 	}
 
+	@SuppressWarnings("boxing")
 	private void determineAtomicFileCreationSupport() {
 		// @TODO: enhance SystemReader to support this without copying code
 		Boolean ret = getAtomicFileCreationSupportOption(
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/HttpSupport.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/HttpSupport.java
index 202645b..251381a 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/HttpSupport.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/HttpSupport.java
@@ -144,6 +144,12 @@ public class HttpSupport {
 	/** The {@code gzip} encoding value for {@link #HDR_ACCEPT_ENCODING}. */
 	public static final String ENCODING_GZIP = "gzip"; //$NON-NLS-1$
 
+	/**
+	 * The {@code x-gzip} encoding value for {@link #HDR_ACCEPT_ENCODING}.
+	 * @since 4.6
+	 */
+	public static final String ENCODING_X_GZIP = "x-gzip"; //$NON-NLS-1$
+
 	/** The standard {@code text/plain} MIME type. */
 	public static final String TEXT_PLAIN = "text/plain"; //$NON-NLS-1$
 
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/SystemReader.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/SystemReader.java
index 9860ef0..b36fc23 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/SystemReader.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/SystemReader.java
@@ -56,10 +56,12 @@
 import java.util.Locale;
 import java.util.TimeZone;
 
-import org.eclipse.jgit.storage.file.FileBasedConfig;
 import org.eclipse.jgit.errors.CorruptObjectException;
 import org.eclipse.jgit.lib.Config;
 import org.eclipse.jgit.lib.ObjectChecker;
+import org.eclipse.jgit.storage.file.FileBasedConfig;
+import org.eclipse.jgit.util.time.MonotonicClock;
+import org.eclipse.jgit.util.time.MonotonicSystemClock;
 
 /**
  * Interface to read values from the system.
@@ -231,6 +233,14 @@ protected final void setPlatformChecker() {
 	public abstract long getCurrentTime();
 
 	/**
+	 * @return clock instance preferred by this system.
+	 * @since 4.6
+	 */
+	public MonotonicClock getClock() {
+		return new MonotonicSystemClock();
+	}
+
+	/**
 	 * @param when TODO
 	 * @return the local time zone
 	 */
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/TemporaryBuffer.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/TemporaryBuffer.java
index 3cd5929..57bcfbd 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/TemporaryBuffer.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/TemporaryBuffer.java
@@ -56,7 +56,6 @@
 import org.eclipse.jgit.internal.JGitText;
 import org.eclipse.jgit.lib.NullProgressMonitor;
 import org.eclipse.jgit.lib.ProgressMonitor;
-import org.eclipse.jgit.util.io.SafeBufferedOutputStream;
 
 /**
  * A fully buffered output stream.
@@ -360,7 +359,7 @@ private void switchToOverflow() throws IOException {
 			overflow.write(b.buffer, 0, b.count);
 		blocks = null;
 
-		overflow = new SafeBufferedOutputStream(overflow, Block.SZ);
+		overflow = new BufferedOutputStream(overflow, Block.SZ);
 		overflow.write(last.buffer, 0, last.count);
 	}
 
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/io/IsolatedOutputStream.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/io/IsolatedOutputStream.java
new file mode 100644
index 0000000..3598a7b
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/io/IsolatedOutputStream.java
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2016, Google Inc.
+ * 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.util.io;
+
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.io.OutputStream;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.eclipse.jgit.internal.JGitText;
+
+/**
+ * OutputStream isolated from interrupts.
+ * <p>
+ * Wraps an OutputStream to prevent interrupts during writes from being made
+ * visible to that stream instance. This works around buggy or difficult
+ * OutputStream implementations like JSch that cannot gracefully handle an
+ * interrupt during write.
+ * <p>
+ * Every write (or flush) requires a context switch to another thread. Callers
+ * should wrap this stream with {@code BufferedOutputStream} using a suitable
+ * buffer size to amortize the cost of context switches.
+ *
+ * @since 4.6
+ */
+public class IsolatedOutputStream extends OutputStream {
+	private final OutputStream dst;
+	private final ExecutorService copier;
+	private Future<Void> pending;
+
+	/**
+	 * Wraps an OutputStream.
+	 *
+	 * @param out
+	 *            stream to send all writes to.
+	 */
+	public IsolatedOutputStream(OutputStream out) {
+		dst = out;
+		copier = new ThreadPoolExecutor(1, 1, 0, TimeUnit.MILLISECONDS,
+				new ArrayBlockingQueue<Runnable>(1), new NamedThreadFactory());
+	}
+
+	@Override
+	public void write(int ch) throws IOException {
+		write(new byte[] { (byte) ch }, 0, 1);
+	}
+
+	@Override
+	public void write(final byte[] buf, final int pos, final int cnt)
+			throws IOException {
+		checkClosed();
+		execute(new Callable<Void>() {
+			@Override
+			public Void call() throws IOException {
+				dst.write(buf, pos, cnt);
+				return null;
+			}
+		});
+	}
+
+	@Override
+	public void flush() throws IOException {
+		checkClosed();
+		execute(new Callable<Void>() {
+			@Override
+			public Void call() throws IOException {
+				dst.flush();
+				return null;
+			}
+		});
+	}
+
+	@Override
+	public void close() throws IOException {
+		if (!copier.isShutdown()) {
+			try {
+				if (pending == null || tryCleanClose()) {
+					cleanClose();
+				} else {
+					dirtyClose();
+				}
+			} finally {
+				copier.shutdown();
+			}
+		}
+	}
+
+	private boolean tryCleanClose() {
+		/*
+		 * If the caller stopped waiting for a prior write or flush, they could
+		 * be trying to close a stream that is still in-use. Check if the prior
+		 * operation ended in a predictable way.
+		 */
+		try {
+			pending.get(0, TimeUnit.MILLISECONDS);
+			pending = null;
+			return true;
+		} catch (TimeoutException | InterruptedException e) {
+			return false;
+		} catch (ExecutionException e) {
+			pending = null;
+			return true;
+		}
+	}
+
+	private void cleanClose() throws IOException {
+		execute(new Callable<Void>() {
+			@Override
+			public Void call() throws IOException {
+				dst.close();
+				return null;
+			}
+		});
+	}
+
+	private void dirtyClose() throws IOException {
+		/*
+		 * Interrupt any still pending write or flush operation. This may cause
+		 * massive failures inside of the stream, but its going to be closed as
+		 * the next step.
+		 */
+		pending.cancel(true);
+
+		Future<Void> close;
+		try {
+			close = copier.submit(new Callable<Void>() {
+				@Override
+				public Void call() throws IOException {
+					dst.close();
+					return null;
+				}
+			});
+		} catch (RejectedExecutionException e) {
+			throw new IOException(e);
+		}
+		try {
+			close.get(200, TimeUnit.MILLISECONDS);
+		} catch (InterruptedException | TimeoutException e) {
+			close.cancel(true);
+			throw new IOException(e);
+		} catch (ExecutionException e) {
+			throw new IOException(e.getCause());
+		}
+	}
+
+	private void checkClosed() throws IOException {
+		if (copier.isShutdown()) {
+			throw new IOException(JGitText.get().closed);
+		}
+	}
+
+	private void execute(Callable<Void> task) throws IOException {
+		if (pending != null) {
+			// Check (and rethrow) any prior failed operation.
+			checkedGet(pending);
+		}
+		try {
+			pending = copier.submit(task);
+		} catch (RejectedExecutionException e) {
+			throw new IOException(e);
+		}
+		checkedGet(pending);
+		pending = null;
+	}
+
+	private static void checkedGet(Future<Void> future) throws IOException {
+		try {
+			future.get();
+		} catch (InterruptedException e) {
+			throw interrupted(e);
+		} catch (ExecutionException e) {
+			throw new IOException(e.getCause());
+		}
+	}
+
+	private static InterruptedIOException interrupted(InterruptedException c) {
+		InterruptedIOException e = new InterruptedIOException();
+		e.initCause(c);
+		return e;
+	}
+
+	private static class NamedThreadFactory implements ThreadFactory {
+		private static final AtomicInteger cnt = new AtomicInteger();
+
+		@Override
+		public Thread newThread(Runnable r) {
+			int n = cnt.incrementAndGet();
+			String name = IsolatedOutputStream.class.getSimpleName() + '-' + n;
+			return new Thread(r, name);
+		}
+	}
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/io/SafeBufferedOutputStream.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/io/SafeBufferedOutputStream.java
index 68f250d..84c3398 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/io/SafeBufferedOutputStream.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/io/SafeBufferedOutputStream.java
@@ -43,20 +43,13 @@
 package org.eclipse.jgit.util.io;
 
 import java.io.BufferedOutputStream;
-import java.io.IOException;
 import java.io.OutputStream;
 
 /**
- * A BufferedOutputStream that throws an error if the final flush fails on
- * close.
- * <p>
- * Java's BufferedOutputStream swallows errors that occur when the output stream
- * tries to write the final bytes to the output during close. This may result in
- * corrupted files without notice.
- * </p>
+ * @deprecated use BufferedOutputStream in Java 8 and later.
  */
+@Deprecated
 public class SafeBufferedOutputStream extends BufferedOutputStream {
-
 	/**
 	 * @see BufferedOutputStream#BufferedOutputStream(OutputStream)
 	 * @param out
@@ -76,13 +69,4 @@ public SafeBufferedOutputStream(OutputStream out) {
 	public SafeBufferedOutputStream(OutputStream out, int size) {
 		super(out, size);
 	}
-
-	@Override
-	public void close() throws IOException {
-		try {
-			flush();
-		} finally {
-			super.close();
-		}
-	}
 }
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/io/StreamCopyThread.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/io/StreamCopyThread.java
index 8d39a22..7aba0a5 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/io/StreamCopyThread.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/io/StreamCopyThread.java
@@ -47,7 +47,6 @@
 import java.io.InputStream;
 import java.io.InterruptedIOException;
 import java.io.OutputStream;
-import java.util.concurrent.atomic.AtomicInteger;
 
 /** Thread to copy from an input stream to an output stream. */
 public class StreamCopyThread extends Thread {
@@ -59,7 +58,8 @@ public class StreamCopyThread extends Thread {
 
 	private volatile boolean done;
 
-	private final AtomicInteger flushCount = new AtomicInteger(0);
+	/** Lock held by flush to avoid interrupting a write. */
+	private final Object writeLock;
 
 	/**
 	 * Create a thread to copy data from an input stream to an output stream.
@@ -75,6 +75,7 @@ public StreamCopyThread(final InputStream i, final OutputStream o) {
 		setName(Thread.currentThread().getName() + "-StreamCopy"); //$NON-NLS-1$
 		src = i;
 		dst = o;
+		writeLock = new Object();
 	}
 
 	/**
@@ -84,9 +85,11 @@ public StreamCopyThread(final InputStream i, final OutputStream o) {
 	 * happen at some future point in time, when the thread wakes up to process
 	 * the request.
 	 */
+	@Deprecated
 	public void flush() {
-		flushCount.incrementAndGet();
-		interrupt();
+		synchronized (writeLock) {
+			interrupt();
+		}
 	}
 
 	/**
@@ -113,25 +116,23 @@ public void halt() throws InterruptedException {
 	public void run() {
 		try {
 			final byte[] buf = new byte[BUFFER_SIZE];
-			int flushCountBeforeRead = 0;
 			boolean readInterrupted = false;
 			for (;;) {
 				try {
 					if (readInterrupted) {
-						dst.flush();
-						readInterrupted = false;
-						if (!flushCount.compareAndSet(flushCountBeforeRead, 0)) {
-							// There was a flush() call since last blocked read.
-							// Set interrupt status, so next blocked read will throw
-							// an InterruptedIOException and we will flush again.
-							interrupt();
+						synchronized (writeLock) {
+							boolean interruptedAgain = Thread.interrupted();
+							dst.flush();
+							if (interruptedAgain) {
+								interrupt();
+							}
 						}
+						readInterrupted = false;
 					}
 
 					if (done)
 						break;
 
-					flushCountBeforeRead = flushCount.get();
 					final int n;
 					try {
 						n = src.read(buf);
@@ -142,20 +143,12 @@ public void run() {
 					if (n < 0)
 						break;
 
-					boolean writeInterrupted = false;
-					for (;;) {
-						try {
-							dst.write(buf, 0, n);
-						} catch (InterruptedIOException wakey) {
-							writeInterrupted = true;
-							continue;
-						}
-
-						// set interrupt status, which will be checked
-						// when we block in src.read
-						if (writeInterrupted || flushCount.get() > 0)
+					synchronized (writeLock) {
+						boolean writeInterrupted = Thread.interrupted();
+						dst.write(buf, 0, n);
+						if (writeInterrupted) {
 							interrupt();
-						break;
+						}
 					}
 				} catch (IOException e) {
 					break;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/time/MonotonicClock.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/time/MonotonicClock.java
new file mode 100644
index 0000000..794d851
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/time/MonotonicClock.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2016, Google Inc.
+ * 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.util.time;
+
+import java.time.Duration;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A provider of time.
+ * <p>
+ * Clocks should provide wall clock time, obtained from a reasonable clock
+ * source, such as the local system clock.
+ * <p>
+ * MonotonicClocks provide the following behavior, with the assertion always
+ * being true if {@link ProposedTimestamp#blockUntil(Duration)} is used:
+ *
+ * <pre>
+ *   MonotonicClock clk = ...;
+ *   long r1;
+ *   try (ProposedTimestamp t1 = clk.propose()) {
+ *   	r1 = t1.millis();
+ *   	t1.blockUntil(...);
+ *   }
+ *
+ *   try (ProposedTimestamp t2 = clk.propose()) {
+ *   	assert t2.millis() > r1;
+ *   }
+ * </pre>
+ *
+ * @since 4.6
+ */
+public interface MonotonicClock {
+	/**
+	 * Obtain a timestamp close to "now".
+	 * <p>
+	 * Proposed times are close to "now", but may not yet be certainly in the
+	 * past. This allows the calling thread to interleave other useful work
+	 * while waiting for the clock instance to create an assurance it will never
+	 * in the future propose a time earlier than the returned time.
+	 * <p>
+	 * A hypothetical implementation could read the local system clock (managed
+	 * by NTP) and return that proposal, concurrently sending network messages
+	 * to closely collaborating peers in the same cluster to also ensure their
+	 * system clocks are ahead of this time. In such an implementation the
+	 * {@link ProposedTimestamp#blockUntil(Duration)} method would wait for
+	 * replies from the peers indicating their own system clocks have moved past
+	 * the proposed time.
+	 *
+	 * @return "now". The value can be immediately accessed by
+	 *         {@link ProposedTimestamp#read(TimeUnit)} and friends, but the
+	 *         caller must use {@link ProposedTimestamp#blockUntil(Duration)} to
+	 *         ensure ordering holds.
+	 */
+	ProposedTimestamp propose();
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/time/MonotonicSystemClock.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/time/MonotonicSystemClock.java
new file mode 100644
index 0000000..a9f4830
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/time/MonotonicSystemClock.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2016, Google Inc.
+ * 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.util.time;
+
+import static java.util.concurrent.TimeUnit.MICROSECONDS;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+
+import java.time.Duration;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * A {@link MonotonicClock} based on {@code System.currentTimeMillis}.
+ *
+ * @since 4.6
+ */
+public class MonotonicSystemClock implements MonotonicClock {
+	private static final AtomicLong before = new AtomicLong();
+
+	private static long nowMicros() {
+		long now = MILLISECONDS.toMicros(System.currentTimeMillis());
+		for (;;) {
+			long o = before.get();
+			long n = Math.max(o + 1, now);
+			if (before.compareAndSet(o, n)) {
+				return n;
+			}
+		}
+	}
+
+	@Override
+	public ProposedTimestamp propose() {
+		final long u = nowMicros();
+		return new ProposedTimestamp() {
+			@Override
+			public long read(TimeUnit unit) {
+				return unit.convert(u, MICROSECONDS);
+			}
+
+			@Override
+			public void blockUntil(Duration maxWait) {
+				// Assume system clock never goes backwards.
+			}
+		};
+	}
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/time/ProposedTimestamp.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/time/ProposedTimestamp.java
new file mode 100644
index 0000000..c09ab32
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/time/ProposedTimestamp.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2016, Google Inc.
+ * 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.util.time;
+
+import static java.util.concurrent.TimeUnit.MICROSECONDS;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+
+import java.sql.Timestamp;
+import java.time.Duration;
+import java.time.Instant;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * A timestamp generated by {@link MonotonicClock#propose()}.
+ * <p>
+ * ProposedTimestamp implements AutoCloseable so that implementations can
+ * release resources associated with obtaining certainty about time elapsing.
+ * For example the constructing MonotonicClock may start network IO with peers
+ * when creating the ProposedTimestamp, and {@link #close()} can ensure those
+ * network resources are released in a timely fashion.
+ *
+ * @since 4.6
+ */
+public abstract class ProposedTimestamp implements AutoCloseable {
+	/**
+	 * Wait for several timestamps.
+	 *
+	 * @param times
+	 *            timestamps to wait on.
+	 * @param maxWait
+	 *            how long to wait for the timestamps.
+	 * @throws InterruptedException
+	 *             current thread was interrupted before the waiting process
+	 *             completed normally.
+	 * @throws TimeoutException
+	 *             the timeout was reached without the proposed timestamp become
+	 *             certainly in the past.
+	 */
+	public static void blockUntil(Iterable<ProposedTimestamp> times,
+			Duration maxWait) throws TimeoutException, InterruptedException {
+		Iterator<ProposedTimestamp> itr = times.iterator();
+		if (!itr.hasNext()) {
+			return;
+		}
+
+		long now = System.currentTimeMillis();
+		long deadline = now + maxWait.toMillis();
+		for (;;) {
+			long w = deadline - now;
+			if (w < 0) {
+				throw new TimeoutException();
+			}
+			itr.next().blockUntil(Duration.ofMillis(w));
+			if (itr.hasNext()) {
+				now = System.currentTimeMillis();
+			} else {
+				break;
+			}
+		}
+	}
+
+	/**
+	 * Read the timestamp as {@code unit} since the epoch.
+	 * <p>
+	 * The timestamp value for a specific {@code ProposedTimestamp} object never
+	 * changes, and can be read before {@link #blockUntil(Duration)}.
+	 *
+	 * @param unit
+	 *            what unit to return the timestamp in. The timestamp will be
+	 *            rounded if the unit is bigger than the clock's granularity.
+	 * @return {@code unit} since the epoch.
+	 */
+	public abstract long read(TimeUnit unit);
+
+	/**
+	 * Wait for this proposed timestamp to be certainly in the recent past.
+	 * <p>
+	 * This method forces the caller to wait up to {@code timeout} for
+	 * {@code this} to pass sufficiently into the past such that the creating
+	 * {@link MonotonicClock} instance will not create an earlier timestamp.
+	 *
+	 * @param maxWait
+	 *            how long the implementation may block the caller.
+	 * @throws InterruptedException
+	 *             current thread was interrupted before the waiting process
+	 *             completed normally.
+	 * @throws TimeoutException
+	 *             the timeout was reached without the proposed timestamp
+	 *             becoming certainly in the past.
+	 */
+	public abstract void blockUntil(Duration maxWait)
+			throws InterruptedException, TimeoutException;
+
+	/** @return milliseconds since epoch; {@code read(MILLISECONDS}). */
+	public long millis() {
+		return read(MILLISECONDS);
+	}
+
+	/** @return microseconds since epoch; {@code read(MICROSECONDS}). */
+	public long micros() {
+		return read(MICROSECONDS);
+	}
+
+	/** @return time since epoch, with up to microsecond resolution. */
+	public Instant instant() {
+		long usec = micros();
+		long secs = usec / 1000000L;
+		long nanos = (usec % 1000000L) * 1000L;
+		return Instant.ofEpochSecond(secs, nanos);
+	}
+
+	/** @return time since epoch, with up to microsecond resolution. */
+	public Timestamp timestamp() {
+		return Timestamp.from(instant());
+	}
+
+	/** @return time since epoch, with up to millisecond resolution. */
+	public Date date() {
+		return new Date(millis());
+	}
+
+	/** Release resources allocated by this timestamp. */
+	@Override
+	public void close() {
+		// Do nothing by default.
+	}
+
+	@Override
+	public String toString() {
+		return instant().toString();
+	}
+}
diff --git a/pom.xml b/pom.xml
index d7694ac..588f364 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>4.5.7-SNAPSHOT</version>
+  <version>4.6.2-SNAPSHOT</version>
 
   <name>JGit - Parent</name>
   <url>${jgit-url}</url>
@@ -190,25 +190,23 @@
     <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
     <maven.build.timestamp.format>yyyyMMddHHmm</maven.build.timestamp.format>
     <bundle-manifest>${project.build.directory}/META-INF/MANIFEST.MF</bundle-manifest>
-    <!-- set JDK_HOME to JAVA_HOME path of JDK7 installation in order to compile against JDK 7 class library -->
-    <JDK_HOME>${JAVA_HOME}</JDK_HOME>
 
     <jgit-last-release-version>4.2.0.201601211800-r</jgit-last-release-version>
     <jsch-version>0.1.53</jsch-version>
-    <javaewah-version>0.7.9</javaewah-version>
+    <javaewah-version>1.1.6</javaewah-version>
     <junit-version>4.12</junit-version>
     <test-fork-count>1C</test-fork-count>
     <args4j-version>2.0.15</args4j-version>
     <commons-compress-version>1.6</commons-compress-version>
     <osgi-core-version>4.3.1</osgi-core-version>
     <servlet-api-version>3.1.0</servlet-api-version>
-    <jetty-version>9.2.13.v20150730</jetty-version>
+    <jetty-version>9.3.17.v20170317</jetty-version>
     <japicmp-version>0.5.3</japicmp-version>
     <httpclient-version>4.3.6</httpclient-version>
     <slf4j-version>1.7.2</slf4j-version>
     <log4j-version>1.2.15</log4j-version>
-    <maven-javadoc-plugin-version>2.10.3</maven-javadoc-plugin-version>
-    <tycho-extras-version>0.25.0</tycho-extras-version>
+    <maven-javadoc-plugin-version>2.10.4</maven-javadoc-plugin-version>
+    <tycho-extras-version>0.26.0</tycho-extras-version>
     <gson-version>2.2.4</gson-version>
     <spotbugs-maven-plugin-version>3.1.6</spotbugs-maven-plugin-version>
 
@@ -242,7 +240,7 @@
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-jar-plugin</artifactId>
-          <version>2.6</version>
+          <version>3.0.2</version>
           <configuration>
             <archive>
               <manifestEntries>
@@ -261,15 +259,59 @@
 
         <plugin>
           <artifactId>maven-compiler-plugin</artifactId>
-          <version>3.5.1</version>
+          <version>3.6.0</version>
           <configuration>
             <encoding>UTF-8</encoding>
-            <source>1.7</source>
-            <target>1.7</target>
-            <compilerArguments>
-              <bootclasspath>${JDK_HOME}${file.separator}jre${file.separator}lib${file.separator}rt.jar${path.separator}${JDK_HOME}${file.separator}jre${file.separator}lib${file.separator}jsse.jar${path.separator}${JDK_HOME}${file.separator}jre${file.separator}lib${file.separator}jce.jar</bootclasspath>
-            </compilerArguments>
+            <source>1.8</source>
+            <target>1.8</target>
           </configuration>
+          <executions>
+            <execution>
+              <id>default-compile</id>
+              <phase>compile</phase>
+              <goals>
+                <goal>compile</goal>
+              </goals>
+              <configuration>
+                <includes>
+                  <include>org/eclipse/jgit/transport/InsecureCipherFactory.java</include>
+                </includes>
+              </configuration>
+            </execution>
+            <execution>
+              <id>compile-with-errorprone</id>
+              <phase>compile</phase>
+              <goals>
+                <goal>compile</goal>
+              </goals>
+              <configuration>
+                <compilerId>javac-with-errorprone</compilerId>
+                <forceJavacCompilerUse>true</forceJavacCompilerUse>
+                <excludes>
+                  <exclude>org/eclipse/jgit/transport/InsecureCipherFactory.java</exclude>
+                </excludes>
+              </configuration>
+            </execution>
+          </executions>
+          <dependencies>
+            <dependency>
+              <groupId>org.codehaus.plexus</groupId>
+              <artifactId>plexus-compiler-javac</artifactId>
+              <version>2.8.1</version>
+            </dependency>
+            <dependency>
+              <groupId>org.codehaus.plexus</groupId>
+              <artifactId>plexus-compiler-javac-errorprone</artifactId>
+              <version>2.8.1</version>
+            </dependency>
+            <!-- override plexus-compiler-javac-errorprone's dependency on
+                 Error Prone with the latest version -->
+            <dependency>
+              <groupId>com.google.errorprone</groupId>
+              <artifactId>error_prone_core</artifactId>
+              <version>2.0.15</version>
+            </dependency>
+          </dependencies>
         </plugin>
 
         <plugin>
@@ -292,13 +334,13 @@
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-dependency-plugin</artifactId>
-          <version>2.10</version>
+          <version>3.0.0</version>
         </plugin>
 
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-source-plugin</artifactId>
-          <version>3.0.0</version>
+          <version>3.0.1</version>
         </plugin>
 
         <plugin>
@@ -320,7 +362,7 @@
         <plugin>
           <groupId>org.codehaus.mojo</groupId>
           <artifactId>build-helper-maven-plugin</artifactId>
-          <version>1.10</version>
+          <version>1.12</version>
         </plugin>
 
         <plugin>
@@ -343,11 +385,11 @@
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-pmd-plugin</artifactId>
-          <version>3.6</version>
+          <version>3.7</version>
           <configuration>
             <sourceEncoding>utf-8</sourceEncoding>
             <minimumTokens>100</minimumTokens>
-            <targetJdk>1.7</targetJdk>
+            <targetJdk>1.8</targetJdk>
             <format>xml</format>
             <failOnViolation>false</failOnViolation>
           </configuration>
@@ -378,12 +420,12 @@
         <plugin>
           <groupId>org.jacoco</groupId>
           <artifactId>jacoco-maven-plugin</artifactId>
-          <version>0.7.6.201602180812</version>
+          <version>0.7.8</version>
         </plugin>
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-site-plugin</artifactId>
-          <version>3.5.1</version>
+          <version>3.6</version>
           <dependencies>
             <dependency><!-- add support for ssh/scp -->
               <groupId>org.apache.maven.wagon</groupId>
@@ -460,7 +502,7 @@
           <quiet>true</quiet>
           <excludePackageNames>org.eclipse.jgit.http.test</excludePackageNames>
           <links>
-            <link>http://docs.oracle.com/javase/7/docs/api</link>
+            <link>http://docs.oracle.com/javase/8/docs/api</link>
           </links>
         </configuration>
         <executions>
@@ -669,12 +711,6 @@
 
   <profiles>
     <profile>
-      <id>jgit.java7</id>
-      <activation>
-        <jdk>[1.7,)</jdk>
-      </activation>
-    </profile>
-    <profile>
       <id>jgit.java8</id>
       <activation>
         <jdk>[1.8,)</jdk>
diff --git a/tools/eclipse-JGit-Format.xml b/tools/eclipse-JGit-Format.xml
index 278b449..490758a 100644
--- a/tools/eclipse-JGit-Format.xml
+++ b/tools/eclipse-JGit-Format.xml
@@ -45,7 +45,7 @@
 <setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_binary_operator" value="insert"/>
 <setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
-<setting id="org.eclipse.jdt.core.compiler.source" value="1.7"/>
+<setting id="org.eclipse.jdt.core.compiler.source" value="1.8"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
 <setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="true"/>
@@ -156,7 +156,7 @@
 <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
 <setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
-<setting id="org.eclipse.jdt.core.compiler.compliance" value="1.7"/>
+<setting id="org.eclipse.jdt.core.compiler.compliance" value="1.8"/>
 <setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
@@ -227,7 +227,7 @@
 <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
 <setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/>
-<setting id="org.eclipse.jdt.core.compiler.codegen.targetPlatform" value="1.7"/>
+<setting id="org.eclipse.jdt.core.compiler.codegen.targetPlatform" value="1.8"/>
 <setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
 <setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member" value="insert"/>