Merge branch 'stable-3.0'

* stable-3.0:
  JGit v3.0.3.201309161630-r
  Add org.eclipse.jgit.java7.source to jgit source feature

Change-Id: I738afcfbc78ea1ac56d0d0ab7d4f7717167dd8dd
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
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 bff6760..98d6f9e 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
@@ -66,7 +66,7 @@
 org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
 org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
 org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
-org.eclipse.jdt.core.compiler.problem.parameterAssignment=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
 org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=error
 org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
 org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
diff --git a/org.eclipse.jgit.ant.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.ant.test/META-INF/MANIFEST.MF
index bb535a2..1377335 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: 3.0.3.201309161630-r
+Bundle-Version: 3.1.0.qualifier
 Bundle-ActivationPolicy: lazy
 Bundle-RequiredExecutionEnvironment: J2SE-1.5
 Import-Package: org.apache.tools.ant,
- org.eclipse.jgit.ant.tasks;version="3.0.3",
- org.eclipse.jgit.internal.storage.file;version="3.0.3",
- org.eclipse.jgit.junit,
- org.eclipse.jgit.lib;version="3.0.3",
- org.eclipse.jgit.util;version="3.0.3",
- org.hamcrest;version="1.1.0",
+ org.eclipse.jgit.ant.tasks;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.internal.storage.file;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.junit;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.lib;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.util;version="[3.1.0,3.2.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/pom.xml b/org.eclipse.jgit.ant.test/pom.xml
index d229151..359d477 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>3.0.3.201309161630-r</version>
+    <version>3.1.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.ant.test</artifactId>
@@ -105,7 +105,7 @@
       <plugin>
         <artifactId>maven-surefire-plugin</artifactId>
         <configuration>
-          <argLine>-Xmx256m -Dfile.encoding=UTF-8</argLine>
+          <argLine>-Xmx256m -Dfile.encoding=UTF-8 -Djava.io.tmpdir=${project.build.directory}</argLine>
         </configuration>
       </plugin>
     </plugins>
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 bbee32a..da7e061 100644
--- a/org.eclipse.jgit.ant/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit.ant/.settings/org.eclipse.jdt.core.prefs
@@ -66,7 +66,7 @@
 org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
 org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
 org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
-org.eclipse.jdt.core.compiler.problem.parameterAssignment=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
 org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=error
 org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
 org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
diff --git a/org.eclipse.jgit.ant/META-INF/MANIFEST.MF b/org.eclipse.jgit.ant/META-INF/MANIFEST.MF
index 11d7e7e..30d98d3 100644
--- a/org.eclipse.jgit.ant/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.ant/META-INF/MANIFEST.MF
@@ -2,10 +2,10 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %Bundle-Name
 Bundle-SymbolicName: org.eclipse.jgit.ant
-Bundle-Version: 3.0.3.201309161630-r
+Bundle-Version: 3.1.0.qualifier
 Bundle-RequiredExecutionEnvironment: J2SE-1.5
 Import-Package: org.apache.tools.ant,
-  org.eclipse.jgit.storage.file;version="[3.0.3,3.1.0)"
+  org.eclipse.jgit.storage.file;version="[3.1.0,3.2.0)"
 Bundle-Localization: plugin
 Bundle-Vendor: %Provider-Name
-Export-Package: org.eclipse.jgit.ant.tasks;version="3.0.3"
+Export-Package: org.eclipse.jgit.ant.tasks;version="3.1.0"
diff --git a/org.eclipse.jgit.ant/pom.xml b/org.eclipse.jgit.ant/pom.xml
index 251fa58..e6d0e8a 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>3.0.3.201309161630-r</version>
+		<version>3.1.0-SNAPSHOT</version>
 	</parent>
 
 	<artifactId>org.eclipse.jgit.ant</artifactId>
diff --git a/org.eclipse.jgit.archive/.classpath b/org.eclipse.jgit.archive/.classpath
new file mode 100644
index 0000000..304e861
--- /dev/null
+++ b/org.eclipse.jgit.archive/.classpath
@@ -0,0 +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/J2SE-1.5"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/org.eclipse.jgit.archive/.gitignore b/org.eclipse.jgit.archive/.gitignore
new file mode 100644
index 0000000..09e3bc9
--- /dev/null
+++ b/org.eclipse.jgit.archive/.gitignore
@@ -0,0 +1,2 @@
+/bin/
+/target/
diff --git a/org.eclipse.jgit.archive/.project b/org.eclipse.jgit.archive/.project
new file mode 100644
index 0000000..4c7f394
--- /dev/null
+++ b/org.eclipse.jgit.archive/.project
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.jgit.archive</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ManifestBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.SchemaBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.api.tools.apiAnalysisBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.pde.api.tools.apiAnalysisNature</nature>
+	</natures>
+</projectDescription>
diff --git a/org.eclipse.jgit.archive/.settings/org.eclipse.core.resources.prefs b/org.eclipse.jgit.archive/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..66ac15c
--- /dev/null
+++ b/org.eclipse.jgit.archive/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Mon Aug 11 16:46:12 PDT 2008
+eclipse.preferences.version=1
+encoding/<project>=UTF-8
diff --git a/org.eclipse.jgit.archive/.settings/org.eclipse.core.runtime.prefs b/org.eclipse.jgit.archive/.settings/org.eclipse.core.runtime.prefs
new file mode 100644
index 0000000..006e07e
--- /dev/null
+++ b/org.eclipse.jgit.archive/.settings/org.eclipse.core.runtime.prefs
@@ -0,0 +1,3 @@
+#Mon Mar 24 18:55:50 EDT 2008
+eclipse.preferences.version=1
+line.separator=\n
diff --git a/org.eclipse.jgit.archive/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit.archive/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..6a1454e
--- /dev/null
+++ b/org.eclipse.jgit.archive/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,393 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
+org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
+org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
+org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.doc.comment.support=enabled
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=warning
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=error
+org.eclipse.jdt.core.compiler.problem.deadCode=error
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=error
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=enabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=error
+org.eclipse.jdt.core.compiler.problem.invalidJavadoc=error
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=private
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=error
+org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=error
+org.eclipse.jdt.core.compiler.problem.missingJavadocComments=error
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=protected
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=return_tag
+org.eclipse.jdt.core.compiler.problem.missingJavadocTags=error
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=private
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=error
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=error
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=warning
+org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
+org.eclipse.jdt.core.compiler.problem.nullReference=error
+org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
+org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=error
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
+org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning
+org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=error
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=warning
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=error
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=warning
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=error
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=error
+org.eclipse.jdt.core.compiler.problem.unusedLabel=error
+org.eclipse.jdt.core.compiler.problem.unusedLocal=error
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameter=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=error
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
+org.eclipse.jdt.core.compiler.source=1.5
+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
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=1
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=false
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
+org.eclipse.jdt.core.formatter.comment.line_length=80
+org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
+org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
+org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
+org.eclipse.jdt.core.formatter.indentation.size=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=true
+org.eclipse.jdt.core.formatter.join_wrapped_lines=true
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=80
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=tab
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_on_off_tags=true
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
+org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
diff --git a/org.eclipse.jgit.archive/.settings/org.eclipse.jdt.ui.prefs b/org.eclipse.jgit.archive/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..c336cce
--- /dev/null
+++ b/org.eclipse.jgit.archive/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,61 @@
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=_JGit Format
+formatter_settings_version=12
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=java;javax;org;com;
+org.eclipse.jdt.ui.ondemandthreshold=99
+org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8"?><templates/>
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=false
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_methods=false
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=true
+sp_cleanup.add_missing_override_annotations_interface_methods=false
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=false
+sp_cleanup.always_use_this_for_non_static_method_access=false
+sp_cleanup.convert_to_enhanced_for_loop=false
+sp_cleanup.correct_indentation=false
+sp_cleanup.format_source_code=true
+sp_cleanup.format_source_code_changes_only=true
+sp_cleanup.make_local_variable_final=false
+sp_cleanup.make_parameters_final=false
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_type_abstract_if_missing_method=false
+sp_cleanup.make_variable_declarations_final=false
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.organize_imports=false
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_trailing_whitespaces=true
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_casts=false
+sp_cleanup.remove_unnecessary_nls_tags=false
+sp_cleanup.remove_unused_imports=false
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.use_blocks=false
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_parentheses_in_expressions=false
+sp_cleanup.use_this_for_non_static_field_access=false
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+sp_cleanup.use_this_for_non_static_method_access=false
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
diff --git a/org.eclipse.jgit.archive/.settings/org.eclipse.mylyn.tasks.ui.prefs b/org.eclipse.jgit.archive/.settings/org.eclipse.mylyn.tasks.ui.prefs
new file mode 100644
index 0000000..823c0f5
--- /dev/null
+++ b/org.eclipse.jgit.archive/.settings/org.eclipse.mylyn.tasks.ui.prefs
@@ -0,0 +1,4 @@
+#Tue Jul 19 20:11:28 CEST 2011
+eclipse.preferences.version=1
+project.repository.kind=bugzilla
+project.repository.url=https\://bugs.eclipse.org/bugs
diff --git a/org.eclipse.jgit.archive/.settings/org.eclipse.mylyn.team.ui.prefs b/org.eclipse.jgit.archive/.settings/org.eclipse.mylyn.team.ui.prefs
new file mode 100644
index 0000000..0cba949
--- /dev/null
+++ b/org.eclipse.jgit.archive/.settings/org.eclipse.mylyn.team.ui.prefs
@@ -0,0 +1,3 @@
+#Tue Jul 19 20:11:28 CEST 2011
+commit.comment.template=${task.description} \n\nBug\: ${task.key}
+eclipse.preferences.version=1
diff --git a/org.eclipse.jgit.archive/.settings/org.eclipse.pde.api.tools.prefs b/org.eclipse.jgit.archive/.settings/org.eclipse.pde.api.tools.prefs
new file mode 100644
index 0000000..cd148d9
--- /dev/null
+++ b/org.eclipse.jgit.archive/.settings/org.eclipse.pde.api.tools.prefs
@@ -0,0 +1,94 @@
+#Tue Oct 18 00:52:01 CEST 2011
+ANNOTATION_ELEMENT_TYPE_ADDED_METHOD_WITHOUT_DEFAULT_VALUE=Error
+ANNOTATION_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+ANNOTATION_ELEMENT_TYPE_REMOVED_FIELD=Error
+ANNOTATION_ELEMENT_TYPE_REMOVED_METHOD=Error
+ANNOTATION_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_API_TYPE=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_REEXPORTED_API_TYPE=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_REEXPORTED_TYPE=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_TYPE=Error
+CLASS_ELEMENT_TYPE_ADDED_METHOD=Error
+CLASS_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error
+CLASS_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+CLASS_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error
+CLASS_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+CLASS_ELEMENT_TYPE_CHANGED_NON_ABSTRACT_TO_ABSTRACT=Error
+CLASS_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error
+CLASS_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+CLASS_ELEMENT_TYPE_REMOVED_CONSTRUCTOR=Error
+CLASS_ELEMENT_TYPE_REMOVED_FIELD=Error
+CLASS_ELEMENT_TYPE_REMOVED_METHOD=Error
+CLASS_ELEMENT_TYPE_REMOVED_SUPERCLASS=Error
+CLASS_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+CLASS_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+CONSTRUCTOR_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+CONSTRUCTOR_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+CONSTRUCTOR_ELEMENT_TYPE_CHANGED_VARARGS_TO_ARRAY=Error
+CONSTRUCTOR_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+ENUM_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error
+ENUM_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+ENUM_ELEMENT_TYPE_REMOVED_ENUM_CONSTANT=Error
+ENUM_ELEMENT_TYPE_REMOVED_FIELD=Error
+ENUM_ELEMENT_TYPE_REMOVED_METHOD=Error
+ENUM_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+FIELD_ELEMENT_TYPE_ADDED_VALUE=Error
+FIELD_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+FIELD_ELEMENT_TYPE_CHANGED_FINAL_TO_NON_FINAL_STATIC_CONSTANT=Error
+FIELD_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error
+FIELD_ELEMENT_TYPE_CHANGED_NON_STATIC_TO_STATIC=Error
+FIELD_ELEMENT_TYPE_CHANGED_STATIC_TO_NON_STATIC=Error
+FIELD_ELEMENT_TYPE_CHANGED_TYPE=Error
+FIELD_ELEMENT_TYPE_CHANGED_VALUE=Error
+FIELD_ELEMENT_TYPE_REMOVED_TYPE_ARGUMENT=Error
+FIELD_ELEMENT_TYPE_REMOVED_VALUE=Error
+ILLEGAL_EXTEND=Warning
+ILLEGAL_IMPLEMENT=Warning
+ILLEGAL_INSTANTIATE=Warning
+ILLEGAL_OVERRIDE=Warning
+ILLEGAL_REFERENCE=Warning
+INTERFACE_ELEMENT_TYPE_ADDED_FIELD=Error
+INTERFACE_ELEMENT_TYPE_ADDED_METHOD=Error
+INTERFACE_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error
+INTERFACE_ELEMENT_TYPE_ADDED_SUPER_INTERFACE_WITH_METHODS=Error
+INTERFACE_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+INTERFACE_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error
+INTERFACE_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_FIELD=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_METHOD=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+INVALID_JAVADOC_TAG=Ignore
+INVALID_REFERENCE_IN_SYSTEM_LIBRARIES=Error
+LEAK_EXTEND=Warning
+LEAK_FIELD_DECL=Warning
+LEAK_IMPLEMENT=Warning
+LEAK_METHOD_PARAM=Warning
+LEAK_METHOD_RETURN_TYPE=Warning
+METHOD_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error
+METHOD_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+METHOD_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+METHOD_ELEMENT_TYPE_CHANGED_NON_ABSTRACT_TO_ABSTRACT=Error
+METHOD_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error
+METHOD_ELEMENT_TYPE_CHANGED_NON_STATIC_TO_STATIC=Error
+METHOD_ELEMENT_TYPE_CHANGED_STATIC_TO_NON_STATIC=Error
+METHOD_ELEMENT_TYPE_CHANGED_VARARGS_TO_ARRAY=Error
+METHOD_ELEMENT_TYPE_REMOVED_ANNOTATION_DEFAULT_VALUE=Error
+METHOD_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+TYPE_PARAMETER_ELEMENT_TYPE_ADDED_CLASS_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_ADDED_INTERFACE_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_CHANGED_CLASS_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_CHANGED_INTERFACE_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_REMOVED_CLASS_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_REMOVED_INTERFACE_BOUND=Error
+UNUSED_PROBLEM_FILTERS=Warning
+automatically_removed_unused_problem_filters=false
+eclipse.preferences.version=1
+incompatible_api_component_version=Error
+incompatible_api_component_version_include_major_without_breaking_change=Disabled
+incompatible_api_component_version_include_minor_without_api_change=Disabled
+invalid_since_tag_version=Error
+malformed_since_tag=Error
+missing_since_tag=Error
+report_api_breakage_when_major_version_incremented=Disabled
+report_resolution_errors_api_component=Warning
diff --git a/org.eclipse.jgit.archive/.settings/org.eclipse.pde.core.prefs b/org.eclipse.jgit.archive/.settings/org.eclipse.pde.core.prefs
new file mode 100644
index 0000000..82793f2
--- /dev/null
+++ b/org.eclipse.jgit.archive/.settings/org.eclipse.pde.core.prefs
@@ -0,0 +1,3 @@
+#Thu Jan 14 14:34:32 CST 2010
+eclipse.preferences.version=1
+resolve.requirebundle=false
diff --git a/org.eclipse.jgit.archive/META-INF/MANIFEST.MF b/org.eclipse.jgit.archive/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..d8626e8
--- /dev/null
+++ b/org.eclipse.jgit.archive/META-INF/MANIFEST.MF
@@ -0,0 +1,20 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %plugin_name
+Bundle-SymbolicName: org.eclipse.jgit.archive
+Bundle-Version: 3.1.0.qualifier
+Bundle-Vendor: %provider_name
+Bundle-Localization: plugin
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
+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="[3.1.0,3.2.0)",
+ org.eclipse.jgit.lib;version="[3.1.0,3.2.0)",
+ org.osgi.framework;version="[1.3.0,2.0.0)"
+Bundle-ActivationPolicy: lazy
+Bundle-Activator: org.eclipse.jgit.archive.FormatActivator
+Export-Package: org.eclipse.jgit.archive;version="3.1.0"
diff --git a/org.eclipse.jgit.archive/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.archive/META-INF/SOURCE-MANIFEST.MF
new file mode 100644
index 0000000..c41c426
--- /dev/null
+++ b/org.eclipse.jgit.archive/META-INF/SOURCE-MANIFEST.MF
@@ -0,0 +1,7 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: org.eclipse.jgit.archive - Sources
+Bundle-SymbolicName: org.eclipse.jgit.archive.source;singleton:=true
+Bundle-Vendor: Eclipse.org - JGit
+Bundle-Version: 3.1.0.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit.archive;version="3.1.0";roots="."
diff --git a/org.eclipse.jgit.archive/about.html b/org.eclipse.jgit.archive/about.html
new file mode 100644
index 0000000..230f40e
--- /dev/null
+++ b/org.eclipse.jgit.archive/about.html
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
+<title>Eclipse Distribution License - Version 1.0</title>
+<style type="text/css">
+  body {
+    size: 8.5in 11.0in;
+    margin: 0.25in 0.5in 0.25in 0.5in;
+    tab-interval: 0.5in;
+    }
+  p {
+    margin-left: auto;
+    margin-top:  0.5em;
+    margin-bottom: 0.5em;
+    }
+  p.list {
+    margin-left: 0.5in;
+    margin-top:  0.05em;
+    margin-bottom: 0.05em;
+    }
+  </style>
+
+</head>
+
+<body lang="EN-US">
+
+<p><b>Eclipse Distribution License - v 1.0</b></p>
+
+<p>Copyright (c) 2007, Eclipse Foundation, Inc. and its licensors. </p>
+
+<p>All rights reserved.</p>
+<p>Redistribution and use in source and binary forms, with or without modification,
+	are permitted provided that the following conditions are met:
+<ul><li>Redistributions of source code must retain the above copyright notice,
+	this list of conditions and the following disclaimer. </li>
+<li>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. </li>
+<li>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. </li></ul>
+</p>
+<p>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.</p>
+
+</body>
+
+</html>
diff --git a/org.eclipse.jgit.archive/build.properties b/org.eclipse.jgit.archive/build.properties
new file mode 100644
index 0000000..d944674
--- /dev/null
+++ b/org.eclipse.jgit.archive/build.properties
@@ -0,0 +1,6 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+               .,\
+               about.html,\
+               plugin.properties
diff --git a/org.eclipse.jgit.archive/plugin.properties b/org.eclipse.jgit.archive/plugin.properties
new file mode 100644
index 0000000..f4269b7
--- /dev/null
+++ b/org.eclipse.jgit.archive/plugin.properties
@@ -0,0 +1,2 @@
+plugin_name=JGit Archive Formats
+provider_name=Eclipse JGit
diff --git a/org.eclipse.jgit.archive/pom.xml b/org.eclipse.jgit.archive/pom.xml
new file mode 100644
index 0000000..797c785
--- /dev/null
+++ b/org.eclipse.jgit.archive/pom.xml
@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   Copyright (C) 2013, 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.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.eclipse.jgit</groupId>
+    <artifactId>org.eclipse.jgit-parent</artifactId>
+    <version>3.1.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>org.eclipse.jgit.archive</artifactId>
+  <name>JGit Archive Formats</name>
+
+  <description>
+    Support for archiving a Git tree in formats such as zip and tar.
+    This is a separate bundle from org.eclipse.jgit to avoid a
+    dependency by the latter on commons-compress.
+  </description>
+
+  <properties>
+    <translate-qualifier/>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-compress</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.eclipse.jgit</groupId>
+      <artifactId>org.eclipse.jgit</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.osgi</groupId>
+      <artifactId>org.osgi.core</artifactId>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <sourceDirectory>src/</sourceDirectory>
+
+    <resources>
+      <resource>
+        <directory>.</directory>
+        <includes>
+          <include>plugin.properties</include>
+          <include>about.html</include>
+        </includes>
+      </resource>
+    </resources>
+
+    <plugins>
+      <plugin>
+        <artifactId>maven-jar-plugin</artifactId>
+        <configuration>
+          <archive>
+            <manifestFile>${bundle-manifest}</manifestFile>
+          </archive>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/ArchiveFormats.java b/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/ArchiveFormats.java
new file mode 100644
index 0000000..f065871
--- /dev/null
+++ b/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/ArchiveFormats.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2013 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.archive;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jgit.api.ArchiveCommand;
+
+/**
+ * Registers all format types from the org.eclipse.jgit.archive
+ * package for use via the ArchiveCommand API.
+ *
+ * See {@link FormatActivator} for an OSGi bundle activator
+ * that performs the same registration automatically.
+ */
+public class ArchiveFormats {
+	private static final List<String> myFormats = new ArrayList<String>();
+
+	private static final void register(String name, ArchiveCommand.Format<?> fmt) {
+		myFormats.add(name);
+		ArchiveCommand.registerFormat(name, fmt);
+	}
+
+	/**
+	 * Register all included archive formats so they can be used
+	 * as arguments to the ArchiveCommand.setFormat() method.
+	 *
+	 * Should not be called twice without a call to stop() in between.
+	 * Not thread-safe.
+	 */
+	public static void registerAll() {
+		register("tar", new TarFormat());
+		register("tgz", new TgzFormat());
+		register("tbz2", new Tbz2Format());
+		register("txz", new TxzFormat());
+		register("zip", new ZipFormat());
+	}
+
+	/**
+	 * Clean up by deregistering all formats that were registered
+	 * by registerAll().
+	 *
+	 * Not thread-safe.
+	 */
+	public static void unregisterAll() {
+		for (String name : myFormats) {
+			ArchiveCommand.unregisterFormat(name);
+		}
+		myFormats.clear();
+	}
+}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/Gc.java b/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/FormatActivator.java
similarity index 63%
copy from org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/Gc.java
copy to org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/FormatActivator.java
index 615d50f..a6a954f 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/Gc.java
+++ b/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/FormatActivator.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012, Christian Halstrick <christian.halstrick@sap.com>
+ * Copyright (C) 2013 Google Inc.
  * and other copyright owners as documented in the project's IP log.
  *
  * This program and the accompanying materials are made available
@@ -40,19 +40,42 @@
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
+package org.eclipse.jgit.archive;
 
-package org.eclipse.jgit.pgm.debug;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
 
-import org.eclipse.jgit.internal.storage.file.FileRepository;
-import org.eclipse.jgit.internal.storage.file.GC;
-import org.eclipse.jgit.lib.TextProgressMonitor;
-import org.eclipse.jgit.pgm.TextBuiltin;
+/**
+ * This activator registers all format types from the
+ * org.eclipse.jgit.archive package for use via the ArchiveCommand
+ * API.
+ *
+ * This registration happens automatically behind the scenes
+ * when the package is loaded as an OSGi bundle (and the corresponding
+ * deregistration happens when the bundle is unloaded, to avoid
+ * leaks).
+ */
+public class FormatActivator implements BundleActivator {
+	/**
+	 * Registers all included archive formats by calling
+	 * {@link ArchiveFormats#registerAll()}. This method is called by the OSGi
+	 * framework when the bundle is started.
+	 *
+	 * @param context
+	 *            unused
+	 */
+	public void start(BundleContext context) {
+		ArchiveFormats.registerAll();
+	}
 
-class Gc extends TextBuiltin {
-	@Override
-	protected void run() throws Exception {
-		GC gc = new GC((FileRepository) db);
-		gc.setProgressMonitor(new TextProgressMonitor());
-		gc.gc();
+	/**
+	 * Cleans up after {@link #start(BundleContext)} by calling
+	 * {@link ArchiveFormats#unregisterAll}.
+	 *
+	 * @param context
+	 *            unused
+	 */
+	public void stop(BundleContext context) {
+		ArchiveFormats.unregisterAll();
 	}
 }
diff --git a/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/TarFormat.java b/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/TarFormat.java
new file mode 100644
index 0000000..f90573e
--- /dev/null
+++ b/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/TarFormat.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2012 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.archive;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.commons.compress.archivers.ArchiveOutputStream;
+import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
+import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
+import org.apache.commons.compress.archivers.tar.TarConstants;
+import org.eclipse.jgit.api.ArchiveCommand;
+import org.eclipse.jgit.lib.FileMode;
+import org.eclipse.jgit.lib.ObjectLoader;
+
+/**
+ * Unix TAR format (ustar + some PAX extensions).
+ */
+public class TarFormat implements ArchiveCommand.Format<ArchiveOutputStream> {
+	private static final List<String> SUFFIXES =
+			Collections.unmodifiableList(Arrays.asList(".tar"));
+
+	public ArchiveOutputStream createArchiveOutputStream(OutputStream s) {
+		TarArchiveOutputStream out = new TarArchiveOutputStream(s, "UTF-8"); //$NON-NLS-1$
+		out.setLongFileMode(TarArchiveOutputStream.LONGFILE_POSIX);
+		out.setBigNumberMode(TarArchiveOutputStream.BIGNUMBER_POSIX);
+		return out;
+	}
+
+	public void putEntry(ArchiveOutputStream out,
+			String path, FileMode mode, ObjectLoader loader)
+			throws IOException {
+		if (mode == FileMode.SYMLINK) {
+			final TarArchiveEntry entry = new TarArchiveEntry(
+					path, TarConstants.LF_SYMLINK);
+			entry.setLinkName(new String(
+					loader.getCachedBytes(100), "UTF-8")); //$NON-NLS-1$
+			out.putArchiveEntry(entry);
+			out.closeArchiveEntry();
+			return;
+		}
+
+		final TarArchiveEntry entry = new TarArchiveEntry(path);
+		if (mode == FileMode.REGULAR_FILE ||
+		    mode == FileMode.EXECUTABLE_FILE) {
+			entry.setMode(mode.getBits());
+		} else {
+			// TODO(jrn): Let the caller know the tree contained
+			// an entry with unsupported mode (e.g., a submodule).
+		}
+		entry.setSize(loader.getSize());
+		out.putArchiveEntry(entry);
+		try {
+			loader.copyTo(out);
+		} finally {
+			out.closeArchiveEntry();
+		}
+	}
+
+	public Iterable<String> suffixes() {
+		return SUFFIXES;
+	}
+}
diff --git a/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/Tbz2Format.java b/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/Tbz2Format.java
new file mode 100644
index 0000000..d3482d1
--- /dev/null
+++ b/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/Tbz2Format.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2013 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.archive;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.commons.compress.archivers.ArchiveOutputStream;
+import org.apache.commons.compress.compressors.bzip2.BZip2CompressorOutputStream;
+import org.eclipse.jgit.api.ArchiveCommand;
+import org.eclipse.jgit.lib.FileMode;
+import org.eclipse.jgit.lib.ObjectLoader;
+
+/**
+ * bzip2-compressed tarball (tar.bz2) format.
+ */
+public class Tbz2Format implements ArchiveCommand.Format<ArchiveOutputStream> {
+	private static final List<String> SUFFIXES =
+			Collections.unmodifiableList(Arrays.asList(
+				".tar.bz2", ".tbz", ".tbz2"));
+
+	private final ArchiveCommand.Format<ArchiveOutputStream> tarFormat = new TarFormat();
+
+	public ArchiveOutputStream createArchiveOutputStream(OutputStream s)
+			throws IOException {
+		BZip2CompressorOutputStream out = new BZip2CompressorOutputStream(s);
+		return tarFormat.createArchiveOutputStream(out);
+	}
+
+	public void putEntry(ArchiveOutputStream out,
+			String path, FileMode mode, ObjectLoader loader)
+			throws IOException {
+		tarFormat.putEntry(out, path, mode, loader);
+	}
+
+	public Iterable<String> suffixes() {
+		return SUFFIXES;
+	}
+}
diff --git a/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/TgzFormat.java b/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/TgzFormat.java
new file mode 100644
index 0000000..fe1350c
--- /dev/null
+++ b/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/TgzFormat.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2013 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.archive;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.commons.compress.archivers.ArchiveOutputStream;
+import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream;
+import org.eclipse.jgit.api.ArchiveCommand;
+import org.eclipse.jgit.lib.FileMode;
+import org.eclipse.jgit.lib.ObjectLoader;
+
+/**
+ * gzip-compressed tarball (tar.gz) format.
+ */
+public class TgzFormat implements ArchiveCommand.Format<ArchiveOutputStream> {
+	private static final List<String> SUFFIXES =
+			Collections.unmodifiableList(Arrays.asList(
+				".tar.gz", ".tgz"));
+
+	private final ArchiveCommand.Format<ArchiveOutputStream> tarFormat = new TarFormat();
+
+	public ArchiveOutputStream createArchiveOutputStream(OutputStream s)
+			throws IOException {
+		GzipCompressorOutputStream out = new GzipCompressorOutputStream(s);
+		return tarFormat.createArchiveOutputStream(out);
+	}
+
+	public void putEntry(ArchiveOutputStream out,
+			String path, FileMode mode, ObjectLoader loader)
+			throws IOException {
+		tarFormat.putEntry(out, path, mode, loader);
+	}
+
+	public Iterable<String> suffixes() {
+		return SUFFIXES;
+	}
+}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/Gc.java b/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/TxzFormat.java
similarity index 60%
copy from org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/Gc.java
copy to org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/TxzFormat.java
index 615d50f..c09b062 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/Gc.java
+++ b/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/TxzFormat.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012, Christian Halstrick <christian.halstrick@sap.com>
+ * Copyright (C) 2013 Google Inc.
  * and other copyright owners as documented in the project's IP log.
  *
  * This program and the accompanying materials are made available
@@ -40,19 +40,43 @@
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
+package org.eclipse.jgit.archive;
 
-package org.eclipse.jgit.pgm.debug;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
 
-import org.eclipse.jgit.internal.storage.file.FileRepository;
-import org.eclipse.jgit.internal.storage.file.GC;
-import org.eclipse.jgit.lib.TextProgressMonitor;
-import org.eclipse.jgit.pgm.TextBuiltin;
+import org.apache.commons.compress.archivers.ArchiveOutputStream;
+import org.apache.commons.compress.compressors.xz.XZCompressorOutputStream;
+import org.eclipse.jgit.api.ArchiveCommand;
+import org.eclipse.jgit.lib.FileMode;
+import org.eclipse.jgit.lib.ObjectLoader;
 
-class Gc extends TextBuiltin {
-	@Override
-	protected void run() throws Exception {
-		GC gc = new GC((FileRepository) db);
-		gc.setProgressMonitor(new TextProgressMonitor());
-		gc.gc();
+/**
+ * Xz-compressed tar (tar.xz) format.
+ */
+public class TxzFormat implements ArchiveCommand.Format<ArchiveOutputStream> {
+	private static final List<String> SUFFIXES =
+			Collections.unmodifiableList(Arrays.asList(
+				".tar.xz", ".txz"));
+
+	private final ArchiveCommand.Format<ArchiveOutputStream> tarFormat = new TarFormat();
+
+	public ArchiveOutputStream createArchiveOutputStream(OutputStream s)
+			throws IOException {
+		XZCompressorOutputStream out = new XZCompressorOutputStream(s);
+		return tarFormat.createArchiveOutputStream(out);
+	}
+
+	public void putEntry(ArchiveOutputStream out,
+			String path, FileMode mode, ObjectLoader loader)
+			throws IOException {
+		tarFormat.putEntry(out, path, mode, loader);
+	}
+
+	public Iterable<String> suffixes() {
+		return SUFFIXES;
 	}
 }
diff --git a/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/ZipFormat.java b/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/ZipFormat.java
new file mode 100644
index 0000000..be7264b
--- /dev/null
+++ b/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/ZipFormat.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2012 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.archive;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.commons.compress.archivers.ArchiveOutputStream;
+import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
+import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
+import org.eclipse.jgit.api.ArchiveCommand;
+import org.eclipse.jgit.lib.FileMode;
+import org.eclipse.jgit.lib.ObjectLoader;
+
+/**
+ * PKWARE's ZIP format.
+ */
+public class ZipFormat implements ArchiveCommand.Format<ArchiveOutputStream> {
+	private static final List<String> SUFFIXES =
+			Collections.unmodifiableList(Arrays.asList(".zip"));
+
+	public ArchiveOutputStream createArchiveOutputStream(OutputStream s) {
+		return new ZipArchiveOutputStream(s);
+	}
+
+	public void putEntry(ArchiveOutputStream out,
+			String path, FileMode mode, ObjectLoader loader)
+			throws IOException {
+		final ZipArchiveEntry entry = new ZipArchiveEntry(path);
+
+		if (mode == FileMode.REGULAR_FILE) {
+			// ok
+		} else if (mode == FileMode.EXECUTABLE_FILE
+				|| mode == FileMode.SYMLINK) {
+			entry.setUnixMode(mode.getBits());
+		} else {
+			// TODO(jrn): Let the caller know the tree contained
+			// an entry with unsupported mode (e.g., a submodule).
+		}
+		entry.setSize(loader.getSize());
+		out.putArchiveEntry(entry);
+		try {
+			loader.copyTo(out);
+		} finally {
+			out.closeArchiveEntry();
+		}
+	}
+
+	public Iterable<String> suffixes() {
+		return SUFFIXES;
+	}
+}
diff --git a/org.eclipse.jgit.console/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit.console/.settings/org.eclipse.jdt.core.prefs
index 755845d..325d0c6 100644
--- a/org.eclipse.jgit.console/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit.console/.settings/org.eclipse.jdt.core.prefs
@@ -66,7 +66,7 @@
 org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
 org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
 org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
-org.eclipse.jdt.core.compiler.problem.parameterAssignment=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
 org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=error
 org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
 org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
diff --git a/org.eclipse.jgit.console/META-INF/MANIFEST.MF b/org.eclipse.jgit.console/META-INF/MANIFEST.MF
index 8413cab..d175175 100644
--- a/org.eclipse.jgit.console/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.console/META-INF/MANIFEST.MF
@@ -3,11 +3,11 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %plugin_name
 Bundle-SymbolicName: org.eclipse.jgit.console
-Bundle-Version: 3.0.3.201309161630-r
+Bundle-Version: 3.1.0.qualifier
 Bundle-Vendor: %provider_name
 Bundle-RequiredExecutionEnvironment: JavaSE-1.6
-Export-Package: org.eclipse.jgit.console;version="3.0.3"
-Import-Package: org.eclipse.jgit.errors;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.nls;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.transport;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.util;version="[3.0.3,3.1.0)"
+Export-Package: org.eclipse.jgit.console;version="3.1.0"
+Import-Package: org.eclipse.jgit.errors;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.nls;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.transport;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.util;version="[3.1.0,3.2.0)"
diff --git a/org.eclipse.jgit.console/pom.xml b/org.eclipse.jgit.console/pom.xml
index 0f4aafb..009ee5c 100644
--- a/org.eclipse.jgit.console/pom.xml
+++ b/org.eclipse.jgit.console/pom.xml
@@ -52,7 +52,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>org.eclipse.jgit-parent</artifactId>
-    <version>3.0.3.201309161630-r</version>
+    <version>3.1.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.console</artifactId>
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 bbee32a..da7e061 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
@@ -66,7 +66,7 @@
 org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
 org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
 org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
-org.eclipse.jdt.core.compiler.problem.parameterAssignment=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
 org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=error
 org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
 org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
diff --git a/org.eclipse.jgit.http.server/META-INF/MANIFEST.MF b/org.eclipse.jgit.http.server/META-INF/MANIFEST.MF
index 7627ff2..e397549 100644
--- a/org.eclipse.jgit.http.server/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.http.server/META-INF/MANIFEST.MF
@@ -2,22 +2,22 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %plugin_name
 Bundle-SymbolicName: org.eclipse.jgit.http.server
-Bundle-Version: 3.0.3.201309161630-r
+Bundle-Version: 3.1.0.qualifier
 Bundle-Localization: plugin
 Bundle-Vendor: %provider_name
 Export-Package: 
- org.eclipse.jgit.http.server;version="3.0.3",
- org.eclipse.jgit.http.server.glue;version="3.0.3",
- org.eclipse.jgit.http.server.resolver;version="3.0.3"
+ org.eclipse.jgit.http.server;version="3.1.0",
+ org.eclipse.jgit.http.server.glue;version="3.1.0",
+ org.eclipse.jgit.http.server.resolver;version="3.1.0"
 Bundle-ActivationPolicy: lazy
 Bundle-RequiredExecutionEnvironment: J2SE-1.5
 Import-Package: javax.servlet;version="[2.5.0,3.0.0)",
  javax.servlet.http;version="[2.5.0,3.0.0)",
- org.eclipse.jgit.errors;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.internal.storage.file;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.lib;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.nls;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.revwalk;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.transport;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.transport.resolver;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.util;version="[3.0.3,3.1.0)"
+ org.eclipse.jgit.errors;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.internal.storage.file;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.lib;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.nls;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.revwalk;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.transport;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.transport.resolver;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.util;version="[3.1.0,3.2.0)"
diff --git a/org.eclipse.jgit.http.server/pom.xml b/org.eclipse.jgit.http.server/pom.xml
index 09d59de..9f47c1a 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>3.0.3.201309161630-r</version>
+    <version>3.1.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.http.server</artifactId>
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 29533ff..6845d3f 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
@@ -66,7 +66,7 @@
 org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
 org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
 org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
-org.eclipse.jdt.core.compiler.problem.parameterAssignment=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
 org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=error
 org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
 org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
diff --git a/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF
index a09af45..d9b86a1 100644
--- a/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %plugin_name
 Bundle-SymbolicName: org.eclipse.jgit.http.test
-Bundle-Version: 3.0.3.201309161630-r
+Bundle-Version: 3.1.0.qualifier
 Bundle-Vendor: %provider_name
 Bundle-Localization: plugin
 Bundle-RequiredExecutionEnvironment: J2SE-1.5
@@ -22,20 +22,20 @@
  org.eclipse.jetty.util.log;version="[7.6.0,8.0.0)",
  org.eclipse.jetty.util.security;version="[7.6.0,8.0.0)",
  org.eclipse.jetty.util.thread;version="[7.6.0,8.0.0)",
- org.eclipse.jgit.errors;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.http.server;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.http.server.glue;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.http.server.resolver;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.internal;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.internal.storage.file;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.junit;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.junit.http;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.lib;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.nls;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.revwalk;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.storage.file;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.transport;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.transport.resolver;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.util;version="[3.0.3,3.1.0)",
+ org.eclipse.jgit.errors;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.http.server;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.http.server.glue;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.http.server.resolver;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.internal;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.internal.storage.file;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.junit;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.junit.http;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.lib;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.nls;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.revwalk;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.storage.file;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.transport;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.transport.resolver;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.util;version="[3.1.0,3.2.0)",
  org.hamcrest.core;version="[1.1.0,2.0.0)",
  org.junit;version="[4.0.0,5.0.0)"
diff --git a/org.eclipse.jgit.http.test/org.eclipse.jgit.http--All-Tests.launch b/org.eclipse.jgit.http.test/org.eclipse.jgit.http--All-Tests.launch
index f22dc4b..146c0b5 100644
--- a/org.eclipse.jgit.http.test/org.eclipse.jgit.http--All-Tests.launch
+++ b/org.eclipse.jgit.http.test/org.eclipse.jgit.http--All-Tests.launch
@@ -6,6 +6,10 @@
 <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
 <listEntry value="4"/>
 </listAttribute>
+<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.http.test"/>
 <booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/>
 <stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/>
diff --git a/org.eclipse.jgit.http.test/pom.xml b/org.eclipse.jgit.http.test/pom.xml
index d75e06f..c24ef1c 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>3.0.3.201309161630-r</version>
+    <version>3.1.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.http.test</artifactId>
@@ -126,7 +126,7 @@
       <plugin>
         <artifactId>maven-surefire-plugin</artifactId>
         <configuration>
-          <argLine>-Djava.io.tmpdir=${project.build.directory}</argLine>
+          <argLine>-Djava.io.tmpdir=${project.build.directory}  -Xmx300m</argLine>
         </configuration>
       </plugin>
     </plugins>
diff --git a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/HttpClientTests.java b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/HttpClientTests.java
index b686d16..6fb1302 100644
--- a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/HttpClientTests.java
+++ b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/HttpClientTests.java
@@ -376,4 +376,20 @@ public void testListRemote_Smart_UploadPackDisabled() throws Exception {
 			t.close();
 		}
 	}
+
+	@Test
+	public void testListRemoteWithoutLocalRepository() throws Exception {
+		Transport t = Transport.open(smartAuthNoneURI);
+		try {
+			FetchConnection c = t.openFetch();
+			try {
+				Ref head = c.getRef(Constants.HEAD);
+				assertNotNull(head);
+			} finally {
+				c.close();
+			}
+		} finally {
+			t.close();
+		}
+	}
 }
diff --git a/org.eclipse.jgit.java7.test/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit.java7.test/.settings/org.eclipse.jdt.core.prefs
index e1efe00..c04bc01 100644
--- a/org.eclipse.jgit.java7.test/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit.java7.test/.settings/org.eclipse.jdt.core.prefs
@@ -66,7 +66,7 @@
 org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
 org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
 org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
-org.eclipse.jdt.core.compiler.problem.parameterAssignment=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
 org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=error
 org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
 org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
diff --git a/org.eclipse.jgit.java7.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.java7.test/META-INF/MANIFEST.MF
index e6c8097..7876480 100644
--- a/org.eclipse.jgit.java7.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.java7.test/META-INF/MANIFEST.MF
@@ -2,9 +2,13 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %plugin_name
 Bundle-SymbolicName: org.eclipse.jgit.java7.test
-Bundle-Version: 3.0.3.201309161630-r
+Bundle-Version: 3.1.0.qualifier
 Bundle-Vendor: %provider_name
 Bundle-RequiredExecutionEnvironment: JavaSE-1.7
-Import-Package: org.eclipse.jgit.junit;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.lib;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.util;version="[3.0.3,3.1.0)"
+Import-Package: org.eclipse.jgit.api;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.internal.storage.file;version="3.1.0",
+ org.eclipse.jgit.junit;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.lib;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.revwalk;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.storage.file;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.util;version="[3.1.0,3.2.0)"
diff --git a/org.eclipse.jgit.java7.test/pom.xml b/org.eclipse.jgit.java7.test/pom.xml
index c7dbfe1..1762e44 100644
--- a/org.eclipse.jgit.java7.test/pom.xml
+++ b/org.eclipse.jgit.java7.test/pom.xml
@@ -50,7 +50,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>org.eclipse.jgit-parent</artifactId>
-    <version>3.0.3.201309161630-r</version>
+    <version>3.1.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.java7.test</artifactId>
diff --git a/org.eclipse.jgit.java7.test/src/org/eclipse/jgit/lib/DirCacheCheckoutTestWithSymlinks.java b/org.eclipse.jgit.java7.test/src/org/eclipse/jgit/lib/DirCacheCheckoutTestWithSymlinks.java
new file mode 100644
index 0000000..b0d31cd
--- /dev/null
+++ b/org.eclipse.jgit.java7.test/src/org/eclipse/jgit/lib/DirCacheCheckoutTestWithSymlinks.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2013, 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.lib;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.internal.storage.file.FileRepository;
+import org.eclipse.jgit.junit.RepositoryTestCase;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
+import org.eclipse.jgit.util.FS;
+import org.eclipse.jgit.util.FileUtils;
+import org.junit.Before;
+import org.junit.Test;
+
+public class DirCacheCheckoutTestWithSymlinks extends RepositoryTestCase {
+	@Before
+	public void beforeMethod() {
+		// If this assumption fails the tests are skipped. When running on a
+		// filesystem not supporting symlinks I don't want this tests
+		org.junit.Assume.assumeTrue(FS.DETECTED.supportsSymlinks());
+	}
+
+	@Test
+	public void testDontDeleteSymlinkOnTopOfRootDir() throws Exception {
+		// create a parent folder containing a folder with a test repository
+		File repos = createTempDirectory("repos");
+		File testRepo = new File(repos, "repo");
+		testRepo.mkdirs();
+		Git git = Git.init().setDirectory(testRepo).call();
+		db = (FileRepository) git.getRepository();
+
+		// Create a situation where a checkout of master whould delete a file in
+		// a subfolder of the root of the worktree. No other files/folders exist
+		writeTrashFile("d/f", "f");
+		git.add().addFilepattern(".").call();
+		RevCommit initial = git.commit().setMessage("inital").call();
+		git.rm().addFilepattern("d/f").call();
+		git.commit().setMessage("modifyOnMaster").call();
+		git.checkout().setCreateBranch(true).setName("side")
+				.setStartPoint(initial).call();
+		writeTrashFile("d/f", "f2");
+		git.add().addFilepattern(".").call();
+		git.commit().setMessage("modifyOnSide").call();
+		git.getRepository().close();
+
+		// Create a symlink pointing to the parent folder of the repo and open
+		// the repo with the path containing the symlink
+		File reposSymlink = createTempFile();
+		FileUtils.createSymLink(reposSymlink, repos.getPath());
+
+		Repository symlinkDB = FileRepositoryBuilder.create(new File(
+				reposSymlink, "repo/.git"));
+		Git symlinkRepo = Git.wrap(symlinkDB);
+		symlinkRepo.checkout().setName("master").call();
+
+		// check that the symlink still exists
+		assertTrue("The symlink to the repo should exist after a checkout",
+				reposSymlink.exists());
+	}
+}
diff --git a/org.eclipse.jgit.java7/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit.java7/.settings/org.eclipse.jdt.core.prefs
index c479807..9a79ba6 100644
--- a/org.eclipse.jgit.java7/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit.java7/.settings/org.eclipse.jdt.core.prefs
@@ -66,7 +66,7 @@
 org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
 org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
 org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
-org.eclipse.jdt.core.compiler.problem.parameterAssignment=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
 org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=error
 org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
 org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
diff --git a/org.eclipse.jgit.java7/META-INF/MANIFEST.MF b/org.eclipse.jgit.java7/META-INF/MANIFEST.MF
index bbb56fd..7a0c212 100644
--- a/org.eclipse.jgit.java7/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.java7/META-INF/MANIFEST.MF
@@ -1,10 +1,10 @@
 Manifest-Version: 1.0
 Bundle-ManifestVersion: 2
-Fragment-Host: org.eclipse.jgit;bundle-version="3.0.3"
+Fragment-Host: org.eclipse.jgit;bundle-version="3.1.0"
 Bundle-Name: %plugin_name
 Bundle-SymbolicName: org.eclipse.jgit.java7
-Bundle-Version: 3.0.3.201309161630-r
+Bundle-Version: 3.1.0.qualifier
 Bundle-Localization: plugin
 Bundle-Vendor: %provider_name
 Bundle-RequiredExecutionEnvironment: JavaSE-1.7
-Export-Package: org.eclipse.jgit.util;version="3.0.3"
+Export-Package: org.eclipse.jgit.util;version="3.1.0"
diff --git a/org.eclipse.jgit.java7/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.java7/META-INF/SOURCE-MANIFEST.MF
index 965be6e..8db0b33 100644
--- a/org.eclipse.jgit.java7/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.java7/META-INF/SOURCE-MANIFEST.MF
@@ -3,6 +3,6 @@
 Bundle-Name: org.eclipse.jgit.java7 - Sources
 Bundle-SymbolicName: org.eclipse.jgit.java7.source;singleton:=true
 Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 3.0.3.201309161630-r
-Eclipse-SourceBundle: org.eclipse.jgit.java7;version="3.0.3.201309161630-r";roots="."
+Bundle-Version: 3.1.0.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit.java7;version="3.1.0";roots="."
 
diff --git a/org.eclipse.jgit.java7/pom.xml b/org.eclipse.jgit.java7/pom.xml
index 3f0e6a5..235861e 100644
--- a/org.eclipse.jgit.java7/pom.xml
+++ b/org.eclipse.jgit.java7/pom.xml
@@ -50,7 +50,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>org.eclipse.jgit-parent</artifactId>
-    <version>3.0.3.201309161630-r</version>
+    <version>3.1.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.java7</artifactId>
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 29533ff..6845d3f 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
@@ -66,7 +66,7 @@
 org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
 org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
 org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
-org.eclipse.jdt.core.compiler.problem.parameterAssignment=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
 org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=error
 org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
 org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
diff --git a/org.eclipse.jgit.junit.http/META-INF/MANIFEST.MF b/org.eclipse.jgit.junit.http/META-INF/MANIFEST.MF
index f8a8be3..723b793 100644
--- a/org.eclipse.jgit.junit.http/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.junit.http/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %plugin_name
 Bundle-SymbolicName: org.eclipse.jgit.junit.http
-Bundle-Version: 3.0.3.201309161630-r
+Bundle-Version: 3.1.0.qualifier
 Bundle-Localization: plugin
 Bundle-Vendor: %provider_name
 Bundle-ActivationPolicy: lazy
@@ -19,13 +19,13 @@
  org.eclipse.jetty.util.component;version="[7.6.0,8.0.0)",
  org.eclipse.jetty.util.log;version="[7.6.0,8.0.0)",
  org.eclipse.jetty.util.security;version="[7.6.0,8.0.0)",
- org.eclipse.jgit.errors;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.http.server;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.internal.storage.file;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.junit;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.lib;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.revwalk;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.transport;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.transport.resolver;version="[3.0.3,3.1.0)",
+ org.eclipse.jgit.errors;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.http.server;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.internal.storage.file;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.junit;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.lib;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.revwalk;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.transport;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.transport.resolver;version="[3.1.0,3.2.0)",
  org.junit;version="[4.0.0,5.0.0)"
-Export-Package: org.eclipse.jgit.junit.http;version="3.0.3"
+Export-Package: org.eclipse.jgit.junit.http;version="3.1.0"
diff --git a/org.eclipse.jgit.junit.http/pom.xml b/org.eclipse.jgit.junit.http/pom.xml
index 894fd79..d9bfb83 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>3.0.3.201309161630-r</version>
+    <version>3.1.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.junit.http</artifactId>
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 29533ff..6845d3f 100644
--- a/org.eclipse.jgit.junit/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit.junit/.settings/org.eclipse.jdt.core.prefs
@@ -66,7 +66,7 @@
 org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
 org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
 org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
-org.eclipse.jdt.core.compiler.problem.parameterAssignment=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
 org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=error
 org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
 org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
diff --git a/org.eclipse.jgit.junit/META-INF/MANIFEST.MF b/org.eclipse.jgit.junit/META-INF/MANIFEST.MF
index 4208af9..bc4e4f8 100644
--- a/org.eclipse.jgit.junit/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.junit/META-INF/MANIFEST.MF
@@ -2,23 +2,23 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %plugin_name
 Bundle-SymbolicName: org.eclipse.jgit.junit
-Bundle-Version: 3.0.3.201309161630-r
+Bundle-Version: 3.1.0.qualifier
 Bundle-Localization: plugin
 Bundle-Vendor: %provider_name
 Bundle-ActivationPolicy: lazy
 Bundle-RequiredExecutionEnvironment: J2SE-1.5
-Import-Package: org.eclipse.jgit.api;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.api.errors;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.dircache;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.errors;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.internal.storage.file;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.internal.storage.pack;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.lib;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.revwalk;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.storage.file;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.treewalk;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.treewalk.filter;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.util;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.util.io;version="[3.0.3,3.1.0)",
+Import-Package: org.eclipse.jgit.api;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.api.errors;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.dircache;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.errors;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.internal.storage.file;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.internal.storage.pack;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.lib;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.revwalk;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.storage.file;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.treewalk;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.treewalk.filter;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.util;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.util.io;version="[3.1.0,3.2.0)",
  org.junit;version="[4.0.0,5.0.0)"
-Export-Package: org.eclipse.jgit.junit;version="3.0.3"
+Export-Package: org.eclipse.jgit.junit;version="3.1.0"
diff --git a/org.eclipse.jgit.junit/pom.xml b/org.eclipse.jgit.junit/pom.xml
index c6496ff..76a330b 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>3.0.3.201309161630-r</version>
+    <version>3.1.0-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 565f934..7c53e8d 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
@@ -55,7 +55,6 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.UUID;
 import java.util.concurrent.TimeUnit;
 
 import org.eclipse.jgit.internal.storage.file.FileRepository;
@@ -89,10 +88,6 @@
  * descriptors or address space for the test process.
  */
 public abstract class LocalDiskRepositoryTestCase {
-	private static Thread shutdownHook;
-
-	private static int testCount;
-
 	private static final boolean useMMAP = "true".equals(System
 			.getProperty("jgit.junit.usemmap"));
 
@@ -102,36 +97,20 @@ public abstract class LocalDiskRepositoryTestCase {
 	/** A fake (but stable) identity for committer fields in the test. */
 	protected PersonIdent committer;
 
-	private final File trash = new File(new File("target"), "trash");
-
 	private final List<Repository> toClose = new ArrayList<Repository>();
+	private File tmp;
 
 	private MockSystemReader mockSystemReader;
 
 	@Before
 	public void setUp() throws Exception {
-
-		synchronized(this) {
-			if (shutdownHook == null) {
-				shutdownHook = new Thread() {
-					@Override
-					public void run() {
-						// On windows accidentally open files or memory
-						// mapped regions may prevent files from being deleted.
-						// Suggesting a GC increases the likelihood that our
-						// test repositories actually get removed after the
-						// tests, even in the case of failure.
-						System.gc();
-						recursiveDelete("SHUTDOWN", trash, false, false);
-					}
-				};
-				Runtime.getRuntime().addShutdownHook(shutdownHook);
-			}
-		}
-		recursiveDelete(testId(), trash, true, false);
+		tmp = File.createTempFile("jgit_test_", "_tmp");
+		CleanupThread.deleteOnShutdown(tmp);
+		if (!tmp.delete() || !tmp.mkdir())
+			throw new IOException("Cannot create " + tmp);
 
 		mockSystemReader = new MockSystemReader();
-		mockSystemReader.userGitConfig = new FileBasedConfig(new File(trash,
+		mockSystemReader.userGitConfig = new FileBasedConfig(new File(tmp,
 				"usergitconfig"), FS.DETECTED);
 		ceilTestDirectories(getCeilings());
 		SystemReader.setInstance(mockSystemReader);
@@ -152,9 +131,12 @@ public void run() {
 		c.install();
 	}
 
+	protected File getTemporaryDirectory() {
+		return tmp.getAbsoluteFile();
+	}
 
 	protected List<File> getCeilings() {
-		return Collections.singletonList(trash.getParentFile().getAbsoluteFile());
+		return Collections.singletonList(getTemporaryDirectory());
 	}
 
 	private void ceilTestDirectories(List<File> ceilings) {
@@ -184,8 +166,10 @@ public void tearDown() throws Exception {
 		//
 		if (useMMAP)
 			System.gc();
-
-		recursiveDelete(testId(), trash, false, true);
+		if (tmp != null)
+			recursiveDelete(tmp, false, true);
+		if (tmp != null && !tmp.exists())
+			CleanupThread.removed(tmp);
 	}
 
 	/** Increment the {@link #author} and {@link #committer} times. */
@@ -206,11 +190,11 @@ protected void tick() {
 	 *            the recursively directory to delete, if present.
 	 */
 	protected void recursiveDelete(final File dir) {
-		recursiveDelete(testId(), dir, false, true);
+		recursiveDelete(dir, false, true);
 	}
 
-	private static boolean recursiveDelete(final String testName,
-			final File dir, boolean silent, boolean failOnError) {
+	private static boolean recursiveDelete(final File dir,
+			boolean silent, boolean failOnError) {
 		assert !(silent && failOnError);
 		if (!dir.exists())
 			return silent;
@@ -219,31 +203,24 @@ private static boolean recursiveDelete(final String testName,
 			for (int k = 0; k < ls.length; k++) {
 				final File e = ls[k];
 				if (e.isDirectory())
-					silent = recursiveDelete(testName, e, silent, failOnError);
+					silent = recursiveDelete(e, silent, failOnError);
 				else if (!e.delete()) {
 					if (!silent)
-						reportDeleteFailure(testName, failOnError, e);
+						reportDeleteFailure(failOnError, e);
 					silent = !failOnError;
 				}
 			}
 		if (!dir.delete()) {
 			if (!silent)
-				reportDeleteFailure(testName, failOnError, dir);
+				reportDeleteFailure(failOnError, dir);
 			silent = !failOnError;
 		}
 		return silent;
 	}
 
-	private static void reportDeleteFailure(final String testName,
-			final boolean failOnError, final File e) {
-		final String severity;
-		if (failOnError)
-			severity = "ERROR";
-		else
-			severity = "WARNING";
-
-		final String msg = severity + ": Failed to delete " + e + " in "
-				+ testName;
+	private static void reportDeleteFailure(boolean failOnError, File e) {
+		String severity = failOnError ? "ERROR" : "WARNING";
+		String msg = severity + ": Failed to delete " + e;
 		if (failOnError)
 			fail(msg);
 		else
@@ -302,10 +279,6 @@ public void addRepoToClose(Repository r) {
 		toClose.add(r);
 	}
 
-	private static String createUniqueTestFolderPrefix() {
-		return "test" + (System.currentTimeMillis() + "_" + (testCount++));
-	}
-
 	/**
 	 * Creates a unique directory for a test
 	 *
@@ -315,9 +288,7 @@ private static String createUniqueTestFolderPrefix() {
 	 * @throws IOException
 	 */
 	protected File createTempDirectory(String name) throws IOException {
-		String gitdirName = createUniqueTestFolderPrefix();
-		File parent = new File(trash, gitdirName);
-		File directory = new File(parent, name);
+		File directory = new File(createTempFile(), name);
 		FileUtils.mkdirs(directory);
 		return directory.getCanonicalFile();
 	}
@@ -332,16 +303,31 @@ protected File createTempDirectory(String name) throws IOException {
 	 * @throws IOException
 	 */
 	protected File createUniqueTestGitDir(boolean bare) throws IOException {
-		String gitdirName = createUniqueTestFolderPrefix();
+		String gitdirName = createTempFile().getPath();
 		if (!bare)
 			gitdirName += "/";
-		gitdirName += Constants.DOT_GIT;
-		File gitdir = new File(trash, gitdirName);
-		return gitdir.getCanonicalFile();
+		return new File(gitdirName + Constants.DOT_GIT);
 	}
 
+	/**
+	 * Allocates a new unique file path that does not exist.
+	 * <p>
+	 * Unlike the standard {@code File.createTempFile} the returned path does
+	 * not exist, but may be created by another thread in a race with the
+	 * caller. Good luck.
+	 * <p>
+	 * This method is inherently unsafe due to a race condition between creating
+	 * the name and the first use that reserves it.
+	 *
+	 * @return a unique path that does not exist.
+	 * @throws IOException
+	 */
 	protected File createTempFile() throws IOException {
-		return new File(trash, "tmp-" + UUID.randomUUID()).getCanonicalFile();
+		File p = File.createTempFile("tmp_", "", tmp);
+		if (!p.delete()) {
+			throw new IOException("Cannot obtain unique path " + tmp);
+		}
+		return p;
 	}
 
 	/**
@@ -399,7 +385,7 @@ private static void putPersonIdent(final Map<String, String> env,
 	 *             the file could not be written.
 	 */
 	protected File write(final String body) throws IOException {
-		final File f = File.createTempFile("temp", "txt", trash);
+		final File f = File.createTempFile("temp", "txt", tmp);
 		try {
 			write(f, body);
 			return f;
@@ -449,8 +435,41 @@ private static HashMap<String, String> cloneEnv() {
 		return new HashMap<String, String>(System.getenv());
 	}
 
-	private String testId() {
-		return getClass().getName() + "." + testCount;
-	}
+	private static final class CleanupThread extends Thread {
+		private static final CleanupThread me;
+		static {
+			me = new CleanupThread();
+			Runtime.getRuntime().addShutdownHook(me);
+		}
 
+		static void deleteOnShutdown(File tmp) {
+			synchronized (me) {
+				me.toDelete.add(tmp);
+			}
+		}
+
+		static void removed(File tmp) {
+			synchronized (me) {
+				me.toDelete.remove(tmp);
+			}
+		}
+
+		private final List<File> toDelete = new ArrayList<File>();
+
+		@Override
+		public void run() {
+			// On windows accidentally open files or memory
+			// mapped regions may prevent files from being deleted.
+			// Suggesting a GC increases the likelihood that our
+			// test repositories actually get removed after the
+			// tests, even in the case of failure.
+			System.gc();
+			synchronized (this) {
+				boolean silent = false;
+				boolean failOnError = false;
+				for (File tmp : toDelete)
+					recursiveDelete(tmp, silent, failOnError);
+			}
+		}
+	}
 }
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 0d65dd7..9f67192 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="3.0.3.201309161630-r"
+      version="3.1.0.qualifier"
       provider-name="%providerName">
 
    <description url="http://www.eclipse.org/jgit/">
@@ -30,6 +30,13 @@
          unpack="false"/>
 
    <plugin
+         id="org.eclipse.jgit.archive"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
          id="com.jcraft.jsch"
          download-size="0"
          install-size="0"
@@ -43,4 +50,11 @@
          version="0.0.0"
          unpack="false"/>
 
+   <plugin
+         id="org.apache.commons.compress"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
 </feature>
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 a2e1871..f7d83f6 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>3.0.3.201309161630-r</version>
+    <version>3.1.0-SNAPSHOT</version>
   </parent>
 
   <groupId>org.eclipse.jgit.feature</groupId>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.java7.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.java7.feature/feature.xml
index 7be3c21..0460f5d 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.java7.feature/feature.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.java7.feature/feature.xml
@@ -2,7 +2,7 @@
 <feature
       id="org.eclipse.jgit.java7"
       label="%featureName"
-      version="3.0.3.201309161630-r"
+      version="3.1.0.qualifier"
       provider-name="%providerName">
 
    <description url="http://www.eclipse.org/jgit/">
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.java7.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.java7.feature/pom.xml
index b27f327..9e0c1c7 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.java7.feature/pom.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.java7.feature/pom.xml
@@ -50,7 +50,7 @@
   <parent>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>jgit.tycho.parent</artifactId>
-    <version>3.0.3.201309161630-r</version>
+    <version>3.1.0-SNAPSHOT</version>
   </parent>
 
   <groupId>org.eclipse.jgit.feature</groupId>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/feature.xml
index 3372716..dcd67e3 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="3.0.3.201309161630-r"
+      version="3.1.0.qualifier"
       provider-name="%providerName">
 
    <description url="http://www.eclipse.org/jgit/">
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/pom.xml
index 9f19037..3fefc0b 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>3.0.3.201309161630-r</version>
+    <version>3.1.0-SNAPSHOT</version>
   </parent>
 
   <groupId>org.eclipse.jgit.feature</groupId>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/feature.xml
index 26d22a6..a97ec57 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="3.0.3.201309161630-r"
+      version="3.1.0.qualifier"
       provider-name="%providerName">
 
    <description url="http://www.eclipse.org/jgit/">
@@ -22,8 +22,12 @@
       <discovery label="%updateSiteName" url="http://download.eclipse.org/egit/updates"/>
    </url>
 
+   <includes
+         id="org.eclipse.jgit"
+         version="0.0.0"/>
+
    <requires>
-      <import feature="org.eclipse.jgit" version="3.0.3" match="equivalent"/>
+      <import feature="org.eclipse.jgit" version="3.1.0" match="equivalent"/>
    </requires>
 
    <plugin
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/pom.xml
index c6886e9..0618dc2 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>3.0.3.201309161630-r</version>
+    <version>3.1.0-SNAPSHOT</version>
   </parent>
 
   <groupId>org.eclipse.jgit.feature</groupId>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.source.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.source.feature/feature.xml
index 127b25e..f7b7866 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="3.0.3.201309161630-r"
+      version="3.1.0.qualifier"
       provider-name="%providerName">
 
    <description url="http://www.eclipse.org/jgit/">
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.source.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.source.feature/pom.xml
index be31f0d..9c665c3 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>3.0.3.201309161630-r</version>
+    <version>3.1.0-SNAPSHOT</version>
   </parent>
 
   <groupId>org.eclipse.jgit.feature</groupId>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.repository/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.repository/pom.xml
index bdc985e..22d4d57 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>3.0.3.201309161630-r</version>
+    <version>3.1.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.repository</artifactId>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/feature.xml
index 61543fc..b072103 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="3.0.3.201309161630-r"
+      version="3.1.0.qualifier"
       provider-name="%providerName">
 
    <description url="http://www.eclipse.org/jgit/">
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/pom.xml
index 12d8908..0b53fb9 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>3.0.3.201309161630-r</version>
+    <version>3.1.0-SNAPSHOT</version>
   </parent>
 
   <groupId>org.eclipse.jgit.feature</groupId>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/META-INF/MANIFEST.MF b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/META-INF/MANIFEST.MF
index e32c5d7..72b4df8 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: 3.0.3.201309161630-r
+Bundle-Version: 3.1.0.qualifier
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 5706460..df8bacc 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>3.0.3.201309161630-r</version>
+    <version>3.1.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.target</artifactId>
diff --git a/org.eclipse.jgit.packaging/pom.xml b/org.eclipse.jgit.packaging/pom.xml
index 4ff521d..b5bb59d 100644
--- a/org.eclipse.jgit.packaging/pom.xml
+++ b/org.eclipse.jgit.packaging/pom.xml
@@ -53,7 +53,7 @@
 
   <groupId>org.eclipse.jgit</groupId>
   <artifactId>jgit.tycho.parent</artifactId>
-  <version>3.0.3.201309161630-r</version>
+  <version>3.1.0-SNAPSHOT</version>
   <packaging>pom</packaging>
 
   <name>JGit Tycho Parent</name>
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 29533ff..6845d3f 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
@@ -66,7 +66,7 @@
 org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
 org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
 org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
-org.eclipse.jdt.core.compiler.problem.parameterAssignment=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
 org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=error
 org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
 org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
diff --git a/org.eclipse.jgit.pgm.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.pgm.test/META-INF/MANIFEST.MF
index d736db5..bfad292 100644
--- a/org.eclipse.jgit.pgm.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.pgm.test/META-INF/MANIFEST.MF
@@ -2,24 +2,25 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %plugin_name
 Bundle-SymbolicName: org.eclipse.jgit.pgm.test
-Bundle-Version: 3.0.3.201309161630-r
+Bundle-Version: 3.1.0.qualifier
 Bundle-Vendor: %provider_name
 Bundle-Localization: plugin
 Bundle-ActivationPolicy: lazy
 Bundle-RequiredExecutionEnvironment: J2SE-1.5
-Import-Package: org.eclipse.jgit.api;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.dircache;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.java7;version="[3.0.3,3.1.0)";resolution:=optional,
- org.eclipse.jgit.junit;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.lib;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.merge;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.pgm;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.pgm.internal;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.pgm.opt;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.revwalk;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.storage.file;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.util;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.util.io;version="[3.0.3,3.1.0)",
+Import-Package: org.eclipse.jgit.api;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.dircache;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.java7;version="[3.1.0,3.2.0)";resolution:=optional,
+ org.eclipse.jgit.junit;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.lib;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.merge;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.pgm;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.pgm.internal;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.pgm.opt;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.revwalk;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.storage.file;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.util;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.util.io;version="[3.1.0,3.2.0)",
  org.hamcrest.core;bundle-version="[1.1.0,2.0.0)",
  org.junit;version="[4.4.0,5.0.0)",
  org.kohsuke.args4j;version="[2.0.12,2.1.0)"
+Require-Bundle: org.tukaani.xz;bundle-version="[1.3.0,2.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"
index 7dac988..600ce7b 100644
--- "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"
@@ -7,6 +7,10 @@
 <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=""/>
diff --git a/org.eclipse.jgit.pgm.test/org.eclipse.jgit.pgm--All-Tests.launch b/org.eclipse.jgit.pgm.test/org.eclipse.jgit.pgm--All-Tests.launch
index 46829ca..77c0466 100644
--- a/org.eclipse.jgit.pgm.test/org.eclipse.jgit.pgm--All-Tests.launch
+++ b/org.eclipse.jgit.pgm.test/org.eclipse.jgit.pgm--All-Tests.launch
@@ -7,6 +7,10 @@
 <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=""/>
diff --git a/org.eclipse.jgit.pgm.test/pom.xml b/org.eclipse.jgit.pgm.test/pom.xml
index c10c67a..bf08d7c 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>3.0.3.201309161630-r</version>
+    <version>3.1.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.pgm.test</artifactId>
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 bcf2728..87137b4 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
@@ -46,9 +46,11 @@
 import static org.junit.Assert.fail;
 import static org.junit.Assume.assumeNoException;
 
+import java.io.BufferedInputStream;
 import java.io.BufferedReader;
 import java.io.ByteArrayInputStream;
 import java.io.File;
+import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.InputStreamReader;
 import java.io.IOException;
@@ -91,7 +93,7 @@ public void setUp() throws Exception {
 	@Test
 	public void testEmptyArchive() throws Exception {
 		final byte[] result = CLIGitCommand.rawExecute( //
-				"git archive " + emptyTree, db);
+				"git archive --format=zip " + emptyTree, db);
 		assertArrayEquals(new String[0], listZipEntries(result));
 	}
 
@@ -103,6 +105,13 @@ public void testEmptyTar() throws Exception {
 	}
 
 	@Test
+	public void testUnrecognizedFormat() throws Exception {
+		final String[] expect = new String[] { "fatal: Unknown archive format 'nonsense'" };
+		final String[] actual = execute("git archive --format=nonsense " + emptyTree);
+		assertArrayEquals(expect, actual);
+	}
+
+	@Test
 	public void testArchiveWithFiles() throws Exception {
 		writeTrashFile("a", "a file with content!");
 		writeTrashFile("c", ""); // empty file
@@ -112,11 +121,171 @@ public void testArchiveWithFiles() throws Exception {
 		git.commit().setMessage("populate toplevel").call();
 
 		final byte[] result = CLIGitCommand.rawExecute( //
-				"git archive HEAD", db);
+				"git archive --format=zip HEAD", db);
 		assertArrayEquals(new String[] { "a", "c" }, //
 				listZipEntries(result));
 	}
 
+	private void commitGreeting() throws Exception {
+		writeTrashFile("greeting", "hello, world!");
+		git.add().addFilepattern("greeting").call();
+		git.commit().setMessage("a commit with a file").call();
+	}
+
+	@Test
+	public void testDefaultFormatIsTar() throws Exception {
+		commitGreeting();
+		final byte[] result = CLIGitCommand.rawExecute( //
+				"git archive HEAD", db);
+		assertArrayEquals(new String[] { "greeting" }, //
+				listTarEntries(result));
+	}
+
+	private static String shellQuote(String s) {
+		return "'" + s.replace("'", "'\\''") + "'";
+	}
+
+	@Test
+	public void testFormatOverridesFilename() throws Exception {
+		final File archive = new File(db.getWorkTree(), "format-overrides-name.tar");
+		final String path = archive.getAbsolutePath();
+
+		commitGreeting();
+		assertArrayEquals(new String[] { "" },
+				execute("git archive " +
+					"--format=zip " +
+					shellQuote("--output=" + path) + " " +
+					"HEAD"));
+		assertContainsEntryWithMode(path, "", "greeting");
+		assertIsZip(archive);
+	}
+
+	@Test
+	public void testUnrecognizedExtensionMeansTar() throws Exception {
+		final File archive = new File(db.getWorkTree(), "example.txt");
+		final String path = archive.getAbsolutePath();
+
+		commitGreeting();
+		assertArrayEquals(new String[] { "" },
+				execute("git archive " +
+					shellQuote("--output=" + path) + " " +
+					"HEAD"));
+		assertTarContainsEntry(path, "", "greeting");
+		assertIsTar(archive);
+	}
+
+	@Test
+	public void testNoExtensionMeansTar() throws Exception {
+		final File archive = new File(db.getWorkTree(), "example");
+		final String path = archive.getAbsolutePath();
+
+		commitGreeting();
+		assertArrayEquals(new String[] { "" },
+				execute("git archive " +
+					shellQuote("--output=" + path) + " " +
+					"HEAD"));
+		assertIsTar(archive);
+	}
+
+	@Test
+	public void testExtensionMatchIsAnchored() throws Exception {
+		final File archive = new File(db.getWorkTree(), "two-extensions.zip.bak");
+		final String path = archive.getAbsolutePath();
+
+		commitGreeting();
+		assertArrayEquals(new String[] { "" },
+				execute("git archive " +
+					shellQuote("--output=" + path) + " " +
+					"HEAD"));
+		assertIsTar(archive);
+	}
+
+	@Test
+	public void testZipExtension() throws Exception {
+		final File archiveWithDot = new File(db.getWorkTree(), "greeting.zip");
+		final File archiveNoDot = new File(db.getWorkTree(), "greetingzip");
+
+		commitGreeting();
+		execute("git archive " +
+			shellQuote("--output=" + archiveWithDot.getAbsolutePath()) + " " +
+			"HEAD");
+		execute("git archive " +
+			shellQuote("--output=" + archiveNoDot.getAbsolutePath()) + " " +
+			"HEAD");
+		assertIsZip(archiveWithDot);
+		assertIsTar(archiveNoDot);
+	}
+
+	@Test
+	public void testTarExtension() throws Exception {
+		final File archive = new File(db.getWorkTree(), "tarball.tar");
+		final String path = archive.getAbsolutePath();
+
+		commitGreeting();
+		assertArrayEquals(new String[] { "" },
+				execute("git archive " +
+					shellQuote("--output=" + path) + " " +
+					"HEAD"));
+		assertIsTar(archive);
+	}
+
+	@Test
+	public void testTgzExtensions() throws Exception {
+		commitGreeting();
+
+		for (String ext : Arrays.asList("tar.gz", "tgz")) {
+			final File archiveWithDot = new File(db.getWorkTree(), "tarball." + ext);
+			final File archiveNoDot = new File(db.getWorkTree(), "tarball" + ext);
+
+			execute("git archive " +
+				shellQuote("--output=" + archiveWithDot.getAbsolutePath()) + " " +
+				"HEAD");
+			execute("git archive " +
+				shellQuote("--output=" + archiveNoDot.getAbsolutePath()) + " " +
+				"HEAD");
+			assertIsGzip(archiveWithDot);
+			assertIsTar(archiveNoDot);
+		}
+	}
+
+	@Test
+	public void testTbz2Extension() throws Exception {
+		commitGreeting();
+
+		for (String ext : Arrays.asList("tar.bz2", "tbz", "tbz2")) {
+			final File archiveWithDot = new File(db.getWorkTree(), "tarball." + ext);
+			final File archiveNoDot = new File(db.getWorkTree(), "tarball" + ext);
+
+			execute("git archive " +
+				shellQuote("--output=" + archiveWithDot.getAbsolutePath()) + " " +
+				"HEAD");
+			execute("git archive " +
+				shellQuote("--output=" + archiveNoDot.getAbsolutePath()) + " " +
+				"HEAD");
+			assertIsBzip2(archiveWithDot);
+			assertIsTar(archiveNoDot);
+		}
+	}
+
+	@Test
+	public void testTxzExtension() throws Exception {
+		commitGreeting();
+
+		for (String ext : Arrays.asList("tar.xz", "txz")) {
+			final File archiveWithDot = new File(db.getWorkTree(), "tarball." + ext);
+			final File archiveNoDot = new File(db.getWorkTree(), "tarball" + ext);
+
+			execute("git archive " +
+				shellQuote("--output=" + archiveWithDot.getAbsolutePath()) + " " +
+				"HEAD");
+			execute("git archive " +
+				shellQuote("--output=" + archiveNoDot.getAbsolutePath()) + " " +
+				"HEAD");
+			assertIsXz(archiveWithDot);
+			assertIsTar(archiveNoDot);
+		}
+	}
+
 	@Test
 	public void testArchiveWithSubdir() throws Exception {
 		writeTrashFile("a", "a file with content!");
@@ -134,7 +303,7 @@ public void testArchiveWithSubdir() throws Exception {
 		git.commit().setMessage("add subdir").call();
 
 		final byte[] result = CLIGitCommand.rawExecute( //
-				"git archive master", db);
+				"git archive --format=zip master", db);
 		String[] expect = { "a", "b.c", "b0c", "b/a", "b/b", "c" };
 		String[] actual = listZipEntries(result);
 
@@ -188,7 +357,7 @@ public void testArchivePreservesMode() throws Exception {
 		git.commit().setMessage("three files with different modes").call();
 
 		final byte[] zipData = CLIGitCommand.rawExecute( //
-				"git archive master", db);
+				"git archive --format=zip master", db);
 		writeRaw("zip-with-modes.zip", zipData);
 		assertContainsEntryWithMode("zip-with-modes.zip", "-rw-", "plain");
 		assertContainsEntryWithMode("zip-with-modes.zip", "-rwx", "executable");
@@ -222,6 +391,36 @@ public void testTarPreservesMode() throws Exception {
 	}
 
 	@Test
+	public void testArchiveWithLongFilename() throws Exception {
+		String filename = "1234567890";
+		for (int i = 0; i < 20; i++)
+			filename = filename + "/1234567890";
+		writeTrashFile(filename, "file with long path");
+		git.add().addFilepattern("1234567890").call();
+		git.commit().setMessage("file with long name").call();
+
+		final byte[] result = CLIGitCommand.rawExecute( //
+				"git archive --format=zip HEAD", db);
+		assertArrayEquals(new String[] { filename },
+				listZipEntries(result));
+	}
+
+	@Test
+	public void testTarWithLongFilename() throws Exception {
+		String filename = "1234567890";
+		for (int i = 0; i < 20; i++)
+			filename = filename + "/1234567890";
+		writeTrashFile(filename, "file with long path");
+		git.add().addFilepattern("1234567890").call();
+		git.commit().setMessage("file with long name").call();
+
+		final byte[] result = CLIGitCommand.rawExecute( //
+				"git archive --format=tar HEAD", db);
+		assertArrayEquals(new String[] { filename },
+				listTarEntries(result));
+	}
+
+	@Test
 	public void testArchivePreservesContent() throws Exception {
 		final String payload = "“The quick brown fox jumps over the lazy dog!”";
 		writeTrashFile("xyzzy", payload);
@@ -229,7 +428,7 @@ public void testArchivePreservesContent() throws Exception {
 		git.commit().setMessage("add file with content").call();
 
 		final byte[] result = CLIGitCommand.rawExecute( //
-				"git archive HEAD", db);
+				"git archive --format=zip HEAD", db);
 		assertArrayEquals(new String[] { payload }, //
 				zipEntryContent(result, "xyzzy"));
 	}
@@ -286,6 +485,44 @@ private void grepForEntry(String name, String mode, String... cmdline) //
 		}
 	}
 
+	private void assertMagic(long offset, byte[] magicBytes, File file) throws Exception {
+		BufferedInputStream in = new BufferedInputStream(
+				new FileInputStream(file));
+		try {
+			in.skip(offset);
+
+			byte[] actual = new byte[magicBytes.length];
+			in.read(actual);
+			assertArrayEquals(magicBytes, actual);
+		} finally {
+			in.close();
+		}
+	}
+
+	private void assertMagic(byte[] magicBytes, File file) throws Exception {
+		assertMagic(0, magicBytes, file);
+	}
+
+	private void assertIsTar(File file) throws Exception {
+		assertMagic(257, new byte[] { 'u', 's', 't', 'a', 'r', 0 }, file);
+	}
+
+	private void assertIsZip(File file) throws Exception {
+		assertMagic(new byte[] { 'P', 'K', 3, 4 }, file);
+	}
+
+	private void assertIsGzip(File file) throws Exception {
+		assertMagic(new byte[] { 037, (byte) 0213 }, file);
+	}
+
+	private void assertIsBzip2(File file) throws Exception {
+		assertMagic(new byte[] { 'B', 'Z', 'h' }, file);
+	}
+
+	private void assertIsXz(File file) throws Exception {
+		assertMagic(new byte[] { (byte) 0xfd, '7', 'z', 'X', 'Z', 0 }, file);
+	}
+
 	private void assertContainsEntryWithMode(String zipFilename, String mode, String name) //
 			throws Exception {
 		grepForEntry(name, mode, "zipinfo", zipFilename);
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 9704453..6a1454e 100644
--- a/org.eclipse.jgit.pgm/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit.pgm/.settings/org.eclipse.jdt.core.prefs
@@ -66,7 +66,7 @@
 org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
 org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
 org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
-org.eclipse.jdt.core.compiler.problem.parameterAssignment=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
 org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=error
 org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
 org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
diff --git a/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF b/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF
index c70e028..a6cf0f8 100644
--- a/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF
@@ -2,41 +2,42 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %plugin_name
 Bundle-SymbolicName: org.eclipse.jgit.pgm
-Bundle-Version: 3.0.3.201309161630-r
+Bundle-Version: 3.1.0.qualifier
 Bundle-Vendor: %provider_name
 Bundle-Localization: plugin
 Bundle-RequiredExecutionEnvironment: J2SE-1.5
 Import-Package: 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.jgit.api;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.api.errors;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.awtui;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.blame;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.diff;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.dircache;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.errors;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.internal.storage.file;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.internal.storage.pack;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.lib;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.merge;version="3.0.3",
- org.eclipse.jgit.nls;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.notes;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.revplot;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.revwalk;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.revwalk.filter;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.storage.file;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.storage.pack;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.transport;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.transport.resolver;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.treewalk;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.treewalk.filter;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.util;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.util.io;version="[3.0.3,3.1.0)",
+ org.eclipse.jgit.api;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.api.errors;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.archive;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.awtui;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.blame;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.diff;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.dircache;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.errors;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.internal.storage.file;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.internal.storage.pack;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.lib;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.merge;version="3.1.0",
+ org.eclipse.jgit.nls;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.notes;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.revplot;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.revwalk;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.revwalk.filter;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.storage.file;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.storage.pack;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.transport;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.transport.resolver;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.treewalk;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.treewalk.filter;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.util;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.util.io;version="[3.1.0,3.2.0)",
  org.kohsuke.args4j;version="[2.0.12,2.1.0)",
  org.kohsuke.args4j.spi;version="[2.0.12,2.1.0)"
 Bundle-ActivationPolicy: lazy
-Export-Package: org.eclipse.jgit.pgm;version="3.0.3";
+Export-Package: org.eclipse.jgit.pgm;version="3.1.0";
   uses:="org.eclipse.jgit.lib,
    org.eclipse.jgit.nls,
    org.eclipse.jgit.treewalk,
@@ -45,8 +46,8 @@
    org.eclipse.jgit.pgm.opt,
    org.eclipse.jgit.awtui,
    org.eclipse.jgit.transport",
- org.eclipse.jgit.pgm.debug;version="3.0.3",
- org.eclipse.jgit.pgm.internal;version="3.0.3";x-friends:="org.eclipse.jgit.pgm.test,org.eclipse.jgit.test",
- org.eclipse.jgit.pgm.opt;version="3.0.3"
+ org.eclipse.jgit.pgm.debug;version="3.1.0",
+ org.eclipse.jgit.pgm.internal;version="3.1.0";x-friends:="org.eclipse.jgit.pgm.test,org.eclipse.jgit.test",
+ org.eclipse.jgit.pgm.opt;version="3.1.0"
 Main-Class: org.eclipse.jgit.pgm.Main
 Implementation-Title: JGit Command Line Interface
diff --git a/org.eclipse.jgit.pgm/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.pgm/META-INF/SOURCE-MANIFEST.MF
index 9122b87..905f5c4 100644
--- a/org.eclipse.jgit.pgm/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.pgm/META-INF/SOURCE-MANIFEST.MF
@@ -3,6 +3,5 @@
 Bundle-Name: org.eclipse.jgit.pgm - Sources
 Bundle-SymbolicName: org.eclipse.jgit.pgm.source;singleton:=true
 Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 3.0.3.201309161630-r
-Eclipse-SourceBundle: org.eclipse.jgit.pgm;version="3.0.3.201309161630-r";roots="."
-
+Bundle-Version: 3.1.0.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit.pgm;version="3.1.0";roots="."
diff --git a/org.eclipse.jgit.pgm/META-INF/services/org.eclipse.jgit.pgm.TextBuiltin b/org.eclipse.jgit.pgm/META-INF/services/org.eclipse.jgit.pgm.TextBuiltin
index 9d59bd8..841f4bb 100644
--- a/org.eclipse.jgit.pgm/META-INF/services/org.eclipse.jgit.pgm.TextBuiltin
+++ b/org.eclipse.jgit.pgm/META-INF/services/org.eclipse.jgit.pgm.TextBuiltin
@@ -11,6 +11,7 @@
 org.eclipse.jgit.pgm.Diff
 org.eclipse.jgit.pgm.DiffTree
 org.eclipse.jgit.pgm.Fetch
+org.eclipse.jgit.pgm.Gc
 org.eclipse.jgit.pgm.Glog
 org.eclipse.jgit.pgm.IndexPack
 org.eclipse.jgit.pgm.Init
@@ -34,7 +35,6 @@
 org.eclipse.jgit.pgm.Version
 
 org.eclipse.jgit.pgm.debug.DiffAlgorithms
-org.eclipse.jgit.pgm.debug.Gc
 org.eclipse.jgit.pgm.debug.MakeCacheTree
 org.eclipse.jgit.pgm.debug.ReadDirCache
 org.eclipse.jgit.pgm.debug.RebuildCommitGraph
diff --git a/org.eclipse.jgit.pgm/pom.xml b/org.eclipse.jgit.pgm/pom.xml
index 176d972..ff80beb 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>3.0.3.201309161630-r</version>
+    <version>3.1.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.pgm</artifactId>
@@ -78,6 +78,12 @@
 
     <dependency>
       <groupId>org.eclipse.jgit</groupId>
+      <artifactId>org.eclipse.jgit.archive</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.eclipse.jgit</groupId>
       <artifactId>org.eclipse.jgit</artifactId>
       <version>${project.version}</version>
     </dependency>
diff --git a/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties b/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties
index cdf7123..bda8f78 100644
--- a/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties
+++ b/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties
@@ -46,7 +46,6 @@
 doesNotExist={0} does not exist
 dontOverwriteLocalChanges=error: Your local changes to the following file would be overwritten by merge:
 everythingUpToDate=Everything up-to-date
-exceptionCaughtDuringExecutionOfArchiveCommand=Exception caught during execution of archive command
 expectedNumberOfbytes=Expected {0} bytes.
 exporting=Exporting {0}
 failedToCommitIndex=failed to commit index
@@ -187,16 +186,36 @@
 usage_CreateABareRepository=Create a bare repository
 usage_CreateATag=Create a tag
 usage_CreateAnEmptyGitRepository=Create an empty git repository
+usage_DiffAlgorithms=Test performance of jgit's diff algorithms
 usage_DisplayTheVersionOfJgit=Display the version of jgit
+usage_Gc=Cleanup unnecessary files and optimize the local repository
+usage_Glog=View commit history as a graph
+usage_IndexPack=Build pack index file for an existing packed archive
+usage_LsRemote=List references in a remote repository
+usage_LsTree=List the contents of a tree object
+usage_MakeCacheTree=Show the current cache tree structure
+usage_MergeBase=Find as good common ancestors as possible for a merge
 usage_MergesTwoDevelopmentHistories=Merges two development histories
+usage_ReadDirCache= Read the DirCache 100 times
+usage_RebuildCommitGraph=Recreate a repository from another one's commit graph
 usage_RepositoryToReadFrom=Repository to read from
 usage_RepositoryToReceiveInto=Repository to receive into
+usage_RevList=List commit objects in reverse chronological order
+usage_RevParse=Pick out and massage parameters
+usage_RevParseAll=Show all refs found in refs/
 usage_ServerSideBackendForJgitFetch=Server side backend for 'jgit fetch'
 usage_ServerSideBackendForJgitPush=Server side backend for 'jgit push'
+usage_ShowCacheTree=Show cache tree
 usage_ShowDiffs=Show diffs
+usage_ShowDiffTree=Compare the content and mode of blobs found via two tree objects
+usage_ShowDirCache= Show the DirCache
+usage_ShowPackDelta=Show pack delta for given object
+usage_ShowRef=List references in a local repository
 usage_Status=Show the working tree status
 usage_StopTrackingAFile=Stop tracking a file
+usage_TextHashFunctions=Scan repository to compute maximum number of collisions for hash functions
 usage_UpdateRemoteRepositoryFromLocalRefs=Update remote repository from local refs
+usage_WriteDirCache=Write the DirCache
 usage_abbrevCommits=abbreviate commits to N + 1 digits
 usage_abortConnectionIfNoActivity=abort connection if no activity
 usage_actOnRemoteTrackingBranches=act on remote-tracking branches
@@ -205,6 +224,7 @@
 usage_approveDestructionOfRepository=approve destruction of repository
 usage_archive=zip up files from the named tree
 usage_archiveFormat=archive format. Currently supported formats: 'tar', 'zip'
+usage_archiveOutput=output file to write the archive to
 usage_blameLongRevision=show long revision
 usage_blameRange=annotate only the given range
 usage_blameRawTimestamp=show raw timestamp
@@ -221,6 +241,10 @@
 usage_checkout=Checkout a branch to the working tree
 usage_cloneRepositoryIntoNewDir=Clone a repository into a new directory
 usage_configFile=configuration file
+usage_configGlobal=use global configuration in ~/.gitconfig
+usage_configList=List all variables set in config file
+usage_configLocal=use local configuration in .git/config
+usage_configSystem=use system-wide configuration in $(prefix)/etc/gitconfig
 usage_configureTheServiceInDaemonServicename=configure the service in daemon.servicename
 usage_createBranchAndCheckout=create branch and checkout
 usage_deleteBranchEvenIfNotMerged=delete branch (even if not merged)
@@ -254,7 +278,11 @@
 usage_listCreateOrDeleteBranches=List, create, or delete branches
 usage_logAllPretty=format:%H %ct %P' output=log --all '--pretty=format:%H %ct %P' output
 usage_manageReflogInformation=Manage reflog information
-usage_mergeStrategy=Use the given merge strategy. Can be supplied more than once to specify them in the order they should be tried. If there is no -s option, the resolve strategy is used. Currently the following strategies are supported: ours, theirs, simple-two-way-in-core, resolve
+usage_mergeFf=When the merge resolves as a fast-forward, only update the branch pointer, without creating a merge commit.
+usage_mergeNoFf=Create a merge commit even when the merge resolves as a fast-forward.
+usage_mergeFfOnly=Refuse to merge and exit with a non-zero status unless the current HEAD is already up-to-date or the merge can be resolved as a fast-forward.
+usage_mergeRef=Ref to be merged
+usage_mergeStrategy=Use the given merge strategy. Can be supplied more than once to specify them in the order they should be tried. If there is no -s option, the recursive strategy is used. Currently the following strategies are supported: ours, theirs, simple-two-way-in-core, resolve, recursive
 usage_moveRenameABranch=move/rename a branch
 usage_nameStatus=show only name and status of files
 usage_noCommit=Don't commit after a successful merge
@@ -267,6 +295,7 @@
 usage_performFsckStyleChecksOnReceive=perform fsck style checks on receive
 usage_portNumberToListenOn=port number to listen on
 usage_pruneStaleTrackingRefs=prune stale tracking refs
+usage_quiet=don't show progress messages
 usage_recordChangesToRepository=Record changes to the repository
 usage_recurseIntoSubtrees=recurse into subtrees
 usage_renameLimit=limit size of rename matrix
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 815c96b..7b88a94 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
@@ -43,33 +43,63 @@
 
 package org.eclipse.jgit.pgm;
 
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+
+import org.eclipse.jgit.api.ArchiveCommand;
+import org.eclipse.jgit.api.Git;
+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.archive.ArchiveCommand;
 import org.eclipse.jgit.pgm.internal.CLIText;
 import org.kohsuke.args4j.Argument;
 import org.kohsuke.args4j.Option;
 
 @Command(common = true, usage = "usage_archive")
 class Archive extends TextBuiltin {
+	static {
+		ArchiveFormats.registerAll();
+	}
+
 	@Argument(index = 0, metaVar = "metaVar_treeish")
 	private ObjectId tree;
 
 	@Option(name = "--format", metaVar = "metaVar_archiveFormat", usage = "usage_archiveFormat")
-	private ArchiveCommand.Format format = ArchiveCommand.Format.ZIP;
+	private String format;
+
+	@Option(name = "--output", aliases = { "-o" }, metaVar = "metaVar_file", usage = "usage_archiveOutput")
+	private String output;
 
 	@Override
 	protected void run() throws Exception {
 		if (tree == null)
 			throw die(CLIText.get().treeIsRequired);
 
-		final ArchiveCommand cmd = new ArchiveCommand(db);
+		OutputStream stream = null;
 		try {
-			cmd.setTree(tree)
+			if (output != null)
+				stream = new FileOutputStream(output);
+			else
+				stream = outs;
+
+			try {
+				ArchiveCommand cmd = new Git(db).archive()
+					.setTree(tree)
 					.setFormat(format)
-					.setOutputStream(outs).call();
+					.setOutputStream(stream);
+				if (output != null)
+					cmd.setFilename(output);
+				cmd.call();
+		} catch (GitAPIException e) {
+			throw die(e.getMessage());
+		}
+		} catch (FileNotFoundException e) {
+			throw die(e.getMessage());
 		} finally {
-			cmd.release();
+			if (output != null && stream != null)
+				stream.close();
 		}
 	}
 }
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Config.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Config.java
index 0eb2204..0ec5c1e 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Config.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Config.java
@@ -52,19 +52,19 @@
 
 @Command(common = true, usage = "usage_getAndSetOptions")
 class Config extends TextBuiltin {
-	@Option(name = "--system")
+	@Option(name = "--system", usage = "usage_configSystem")
 	private boolean system;
 
-	@Option(name = "--global")
+	@Option(name = "--global", usage = "usage_configGlobal")
 	private boolean global;
 
-	@Option(name = "--local")
+	@Option(name = "--local", usage = "usage_configLocal")
 	private boolean local;
 
-	@Option(name = "--list", aliases = { "-l" })
+	@Option(name = "--list", aliases = { "-l" }, usage = "usage_configList")
 	private boolean list;
 
-	@Option(name = "--file", aliases = { "-f" })
+	@Option(name = "--file", aliases = { "-f" }, metaVar = "metaVar_file", usage = "usage_configFile")
 	private File configFile;
 
 	@Override
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 018bad0..d89053c 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
@@ -56,6 +56,7 @@
 import org.eclipse.jgit.treewalk.filter.AndTreeFilter;
 import org.eclipse.jgit.treewalk.filter.TreeFilter;
 
+@Command(usage = "usage_ShowDiffTree")
 class DiffTree extends TextBuiltin {
 	@Option(name = "--recursive", usage = "usage_recurseIntoSubtrees", aliases = { "-r" })
 	private boolean recursive;
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Fetch.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Fetch.java
index beb6e31..cc7a435 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Fetch.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Fetch.java
@@ -83,6 +83,9 @@ void nothin(@SuppressWarnings("unused") final boolean ignored) {
 		thin = Boolean.FALSE;
 	}
 
+	@Option(name = "--quiet", usage = "usage_quiet")
+	private Boolean quiet;
+
 	@Argument(index = 0, metaVar = "metaVar_uriish")
 	private String remote = Constants.DEFAULT_REMOTE_NAME;
 
@@ -105,7 +108,8 @@ protected void run() throws Exception {
 		fetch.setRemote(remote);
 		if (thin != null)
 			fetch.setThin(thin.booleanValue());
-		fetch.setProgressMonitor(new TextProgressMonitor());
+		if (quiet == null || !quiet.booleanValue())
+			fetch.setProgressMonitor(new TextProgressMonitor());
 
 		FetchResult result = fetch.call();
 		if (result.getTrackingRefUpdates().isEmpty())
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/Gc.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Gc.java
similarity index 96%
rename from org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/Gc.java
rename to org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Gc.java
index 615d50f..58813bc 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/Gc.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Gc.java
@@ -41,13 +41,13 @@
  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-package org.eclipse.jgit.pgm.debug;
+package org.eclipse.jgit.pgm;
 
 import org.eclipse.jgit.internal.storage.file.FileRepository;
 import org.eclipse.jgit.internal.storage.file.GC;
 import org.eclipse.jgit.lib.TextProgressMonitor;
-import org.eclipse.jgit.pgm.TextBuiltin;
 
+@Command(common = true, usage = "usage_Gc")
 class Gc extends TextBuiltin {
 	@Override
 	protected void run() throws Exception {
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Glog.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Glog.java
index 8b35fd1..f07c3ca 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Glog.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Glog.java
@@ -65,6 +65,7 @@
 import org.eclipse.jgit.revwalk.RevSort;
 import org.eclipse.jgit.revwalk.RevWalk;
 
+@Command(usage = "usage_Glog")
 class Glog extends RevWalkTextBuiltin {
 	final JFrame frame;
 
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/IndexPack.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/IndexPack.java
index 731ef01..9fc5882 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/IndexPack.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/IndexPack.java
@@ -52,6 +52,7 @@
 import org.eclipse.jgit.transport.PackParser;
 import org.kohsuke.args4j.Option;
 
+@Command(usage = "usage_IndexPack")
 class IndexPack extends TextBuiltin {
 	@Option(name = "--fix-thin", usage = "usage_fixAThinPackToBeComplete")
 	private boolean fixThin;
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/LsRemote.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/LsRemote.java
index 282c79d..1842b72 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/LsRemote.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/LsRemote.java
@@ -54,6 +54,7 @@
 import org.eclipse.jgit.transport.FetchConnection;
 import org.eclipse.jgit.transport.Transport;
 
+@Command(common = true, usage = "usage_LsRemote")
 class LsRemote extends TextBuiltin {
 	@Option(name = "--timeout", metaVar = "metaVar_service", usage = "usage_abortConnectionIfNoActivity")
 	int timeout = -1;
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/LsTree.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/LsTree.java
index 4fb560b..e444d21 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/LsTree.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/LsTree.java
@@ -57,6 +57,7 @@
 import org.kohsuke.args4j.Option;
 import org.kohsuke.args4j.spi.StopOptionHandler;
 
+@Command(common = true, usage = "usage_LsTree")
 class LsTree extends TextBuiltin {
 	@Option(name = "--recursive", usage = "usage_recurseIntoSubtrees", aliases = { "-r" })
 	private boolean recursive;
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 67b7cc8..b3ff527 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
@@ -78,18 +78,22 @@ class Merge extends TextBuiltin {
 
 	private MergeStrategy mergeStrategy = MergeStrategy.RECURSIVE;
 
-	@Argument(required = true)
+	@Argument(required = true, metaVar = "metaVar_ref", usage = "usage_mergeRef")
 	private String ref;
 
-	@Option(name = "--ff")
 	private FastForwardMode ff = FastForwardMode.FF;
 
-	@Option(name = "--no-ff")
+	@Option(name = "--ff", usage = "usage_mergeFf")
+	void ff(@SuppressWarnings("unused") final boolean ignored) {
+		ff = FastForwardMode.FF;
+	}
+
+	@Option(name = "--no-ff", usage = "usage_mergeNoFf")
 	void noff(@SuppressWarnings("unused") final boolean ignored) {
 		ff = FastForwardMode.NO_FF;
 	}
 
-	@Option(name = "--ff-only")
+	@Option(name = "--ff-only", usage = "usage_mergeFfOnly")
 	void ffonly(@SuppressWarnings("unused") final boolean ignored) {
 		ff = FastForwardMode.FF_ONLY;
 	}
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 34aa9b2..29cbb53 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
@@ -52,6 +52,7 @@
 import org.eclipse.jgit.revwalk.RevCommit;
 import org.eclipse.jgit.revwalk.filter.RevFilter;
 
+@Command(usage = "usage_MergeBase")
 class MergeBase extends TextBuiltin {
 	@Option(name = "--all", usage = "usage_displayAllPossibleMergeBases")
 	private boolean all;
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/RevList.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/RevList.java
index bab502b..4420abe 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/RevList.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/RevList.java
@@ -49,6 +49,7 @@
 import org.eclipse.jgit.revwalk.RevObject;
 import org.eclipse.jgit.revwalk.RevTree;
 
+@Command(usage = "usage_RevList")
 class RevList extends RevWalkTextBuiltin {
 	@Override
 	protected void show(final RevCommit c) throws Exception {
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 b564107..674c202 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
@@ -53,11 +53,12 @@
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.Ref;
 
+@Command(usage = "usage_RevParse")
 class RevParse extends TextBuiltin {
-	@Option(name = "--all")
+	@Option(name = "--all", usage = "usage_RevParseAll")
 	boolean all = false;
 
-	@Argument(index = 0, metaVar = "commit-ish")
+	@Argument(index = 0, metaVar = "metaVar_commitish")
 	private final List<ObjectId> commits = new ArrayList<ObjectId>();
 
 	@Override
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/ShowRef.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/ShowRef.java
index 2c621ac..203c92d 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/ShowRef.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/ShowRef.java
@@ -54,6 +54,7 @@
 import org.eclipse.jgit.lib.RefComparator;
 import org.eclipse.jgit.util.RefMap;
 
+@Command(usage = "usage_ShowRef")
 class ShowRef extends TextBuiltin {
 	@Override
 	protected void run() throws Exception {
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 45cfd92..0214ed0 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
@@ -52,11 +52,13 @@
 import java.util.Map;
 
 import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.StatusCommand;
 import org.eclipse.jgit.lib.Constants;
 import org.eclipse.jgit.lib.IndexDiff.StageState;
 import org.eclipse.jgit.lib.Ref;
 import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.pgm.internal.CLIText;
+import org.kohsuke.args4j.Option;
 
 @Command(usage = "usage_Status", common = true)
 class Status extends TextBuiltin {
@@ -69,6 +71,9 @@ class Status extends TextBuiltin {
 
 	protected final String statusFileListFormatUnmerged = CLIText.get().statusFileListFormatUnmerged;
 
+	@Option(name = "--", metaVar = "metaVar_path", multiValued = true)
+	protected List<String> filterPaths;
+
 	@Override
 	protected void run() throws Exception {
 		// Print current branch name
@@ -81,7 +86,11 @@ protected void run() throws Exception {
 		} else
 			outw.println(CLIText.formatLine(CLIText.get().notOnAnyBranch));
 		// List changes
-		org.eclipse.jgit.api.Status status = new Git(db).status().call();
+		StatusCommand statusCommand = new Git(db).status();
+		if (filterPaths != null && filterPaths.size() > 0)
+			for (String path : filterPaths)
+				statusCommand.addPath(path);
+		org.eclipse.jgit.api.Status status = statusCommand.call();
 		Collection<String> added = status.getAdded();
 		Collection<String> changed = status.getChanged();
 		Collection<String> removed = status.getRemoved();
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/archive/ArchiveCommand.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/archive/ArchiveCommand.java
deleted file mode 100644
index 1235d0a..0000000
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/archive/ArchiveCommand.java
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- * Copyright (C) 2012 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.pgm.archive;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.EnumMap;
-import java.util.Map;
-
-import org.apache.commons.compress.archivers.ArchiveOutputStream;
-import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
-import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
-import org.apache.commons.compress.archivers.tar.TarConstants;
-import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
-import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
-import org.eclipse.jgit.api.Git;
-import org.eclipse.jgit.api.GitCommand;
-import org.eclipse.jgit.api.errors.GitAPIException;
-import org.eclipse.jgit.api.errors.JGitInternalException;
-import org.eclipse.jgit.lib.FileMode;
-import org.eclipse.jgit.lib.MutableObjectId;
-import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.ObjectLoader;
-import org.eclipse.jgit.lib.ObjectReader;
-import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.pgm.internal.CLIText;
-import org.eclipse.jgit.revwalk.RevWalk;
-import org.eclipse.jgit.treewalk.TreeWalk;
-
-/**
- * Create an archive of files from a named tree.
- * <p>
- * Examples (<code>git</code> is a {@link Git} instance):
- * <p>
- * Create a tarball from HEAD:
- *
- * <pre>
- * cmd = new ArchiveCommand(git.getRepository());
- * try {
- *	cmd.setTree(db.resolve(&quot;HEAD&quot;))
- *		.setOutputStream(out).call();
- * } finally {
- *	cmd.release();
- * }
- * </pre>
- * <p>
- * Create a ZIP file from master:
- *
- * <pre>
- * try {
- *	cmd.setTree(db.resolve(&quot;master&quot;))
- *		.setFormat(ArchiveCommand.Format.ZIP)
- *		.setOutputStream(out).call();
- * } finally {
- *	cmd.release();
- * }
- * </pre>
- *
- * @see <a href="http://git-htmldocs.googlecode.com/git/git-archive.html"
- *      >Git documentation about archive</a>
- *
- * @since 3.0
- */
-public class ArchiveCommand extends GitCommand<OutputStream> {
-	/**
-	 * Available archival formats (corresponding to values for
-	 * the --format= option)
-	 */
-	public static enum Format {
-		/** Zip format */
-		ZIP,
-
-		/** Posix TAR-format */
-		TAR
-	}
-
-	private static interface Archiver {
-		ArchiveOutputStream createArchiveOutputStream(OutputStream s);
-		void putEntry(String path, FileMode mode, //
-				ObjectLoader loader, ArchiveOutputStream out) //
-				throws IOException;
-	}
-
-	private static final Map<Format, Archiver> formats;
-
-	static {
-		Map<Format, Archiver> fmts = new EnumMap<Format, Archiver>(Format.class);
-		fmts.put(Format.ZIP, new Archiver() {
-			public ArchiveOutputStream createArchiveOutputStream(OutputStream s) {
-				return new ZipArchiveOutputStream(s);
-			}
-
-			public void putEntry(String path, FileMode mode, //
-					ObjectLoader loader, ArchiveOutputStream out) //
-					throws IOException {
-				final ZipArchiveEntry entry = new ZipArchiveEntry(path);
-
-				if (mode == FileMode.REGULAR_FILE) {
-					// ok
-				} else if (mode == FileMode.EXECUTABLE_FILE
-						|| mode == FileMode.SYMLINK) {
-					entry.setUnixMode(mode.getBits());
-				} else {
-					// TODO(jrn): Let the caller know the tree contained
-					// an entry with unsupported mode (e.g., a submodule).
-				}
-				entry.setSize(loader.getSize());
-				out.putArchiveEntry(entry);
-				loader.copyTo(out);
-				out.closeArchiveEntry();
-			}
-		});
-		fmts.put(Format.TAR, new Archiver() {
-			public ArchiveOutputStream createArchiveOutputStream(OutputStream s) {
-				return new TarArchiveOutputStream(s);
-			}
-
-			public void putEntry(String path, FileMode mode, //
-					ObjectLoader loader, ArchiveOutputStream out) //
-					throws IOException {
-				if (mode == FileMode.SYMLINK) {
-					final TarArchiveEntry entry = new TarArchiveEntry( //
-							path, TarConstants.LF_SYMLINK);
-					entry.setLinkName(new String( //
-							loader.getCachedBytes(100), "UTF-8")); //$NON-NLS-1$
-					out.putArchiveEntry(entry);
-					out.closeArchiveEntry();
-					return;
-				}
-
-				final TarArchiveEntry entry = new TarArchiveEntry(path);
-				if (mode == FileMode.REGULAR_FILE ||
-				    mode == FileMode.EXECUTABLE_FILE) {
-					entry.setMode(mode.getBits());
-				} else {
-					// TODO(jrn): Let the caller know the tree contained
-					// an entry with unsupported mode (e.g., a submodule).
-				}
-				entry.setSize(loader.getSize());
-				out.putArchiveEntry(entry);
-				loader.copyTo(out);
-				out.closeArchiveEntry();
-			}
-		});
-		formats = fmts;
-	}
-
-	private OutputStream out;
-	private TreeWalk walk;
-	private Format format = Format.TAR;
-
-	/**
-	 * @param repo
-	 */
-	public ArchiveCommand(Repository repo) {
-		super(repo);
-		walk = new TreeWalk(repo);
-	}
-
-	/**
-	 * Release any resources used by the internal ObjectReader.
-	 * <p>
-	 * This does not close the output stream set with setOutputStream, which
-	 * belongs to the caller.
-	 */
-	public void release() {
-		walk.release();
-	}
-
-	/**
-	 * @return the stream to which the archive has been written
-	 */
-	@Override
-	public OutputStream call() throws GitAPIException {
-		final MutableObjectId idBuf = new MutableObjectId();
-		final Archiver fmt = formats.get(format);
-		final ArchiveOutputStream outa = fmt.createArchiveOutputStream(out);
-		final ObjectReader reader = walk.getObjectReader();
-
-		try {
-			try {
-				walk.setRecursive(true);
-				while (walk.next()) {
-					final String name = walk.getPathString();
-					final FileMode mode = walk.getFileMode(0);
-
-					if (mode == FileMode.TREE)
-						// ZIP entries for directories are optional.
-						// Leave them out, mimicking "git archive".
-						continue;
-
-					walk.getObjectId(idBuf, 0);
-					fmt.putEntry(name, mode, reader.open(idBuf), outa);
-				}
-			} finally {
-				outa.close();
-			}
-		} catch (IOException e) {
-			// TODO(jrn): Throw finer-grained errors.
-			throw new JGitInternalException(
-					CLIText.get().exceptionCaughtDuringExecutionOfArchiveCommand, e);
-		}
-
-		return out;
-	}
-
-	/**
-	 * @param tree
-	 *            the tag, commit, or tree object to produce an archive for
-	 * @return this
-	 * @throws IOException
-	 */
-	public ArchiveCommand setTree(ObjectId tree) throws IOException {
-		final RevWalk rw = new RevWalk(walk.getObjectReader());
-		walk.reset(rw.parseTree(tree));
-		return this;
-	}
-
-	/**
-	 * @param out
-	 *	      the stream to which to write the archive
-	 * @return this
-	 */
-	public ArchiveCommand setOutputStream(OutputStream out) {
-		this.out = out;
-		return this;
-	}
-
-	/**
-	 * @param fmt
-	 *	      archive format (e.g., Format.TAR)
-	 * @return this
-	 */
-	public ArchiveCommand setFormat(Format fmt) {
-		this.format = fmt;
-		return this;
-	}
-}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/DiffAlgorithms.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/DiffAlgorithms.java
index 3efe884..91b5917 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/DiffAlgorithms.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/DiffAlgorithms.java
@@ -70,6 +70,7 @@
 import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.lib.RepositoryBuilder;
 import org.eclipse.jgit.lib.RepositoryCache;
+import org.eclipse.jgit.pgm.Command;
 import org.eclipse.jgit.pgm.TextBuiltin;
 import org.eclipse.jgit.pgm.internal.CLIText;
 import org.eclipse.jgit.revwalk.RevCommit;
@@ -79,6 +80,7 @@
 import org.eclipse.jgit.util.FS;
 import org.kohsuke.args4j.Option;
 
+@Command(usage = "usage_DiffAlgorithms")
 class DiffAlgorithms extends TextBuiltin {
 
 	final Algorithm myers = new Algorithm() {
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/MakeCacheTree.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/MakeCacheTree.java
index 5e6195e..d3a0a3e 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/MakeCacheTree.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/MakeCacheTree.java
@@ -51,9 +51,11 @@
 
 import org.eclipse.jgit.dircache.DirCache;
 import org.eclipse.jgit.dircache.DirCacheTree;
+import org.eclipse.jgit.pgm.Command;
 import org.eclipse.jgit.pgm.TextBuiltin;
 import org.eclipse.jgit.pgm.internal.CLIText;
 
+@Command(usage = "usage_MakeCacheTree")
 class MakeCacheTree extends TextBuiltin {
 	@Override
 	protected void run() throws Exception {
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ReadDirCache.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ReadDirCache.java
index 7cef64b..07bfc4b 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ReadDirCache.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ReadDirCache.java
@@ -48,9 +48,11 @@
 
 import java.text.MessageFormat;
 
+import org.eclipse.jgit.pgm.Command;
 import org.eclipse.jgit.pgm.TextBuiltin;
 import org.eclipse.jgit.pgm.internal.CLIText;
 
+@Command(usage = "usage_ReadDirCache")
 class ReadDirCache extends TextBuiltin {
 	@Override
 	protected void run() throws Exception {
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/RebuildCommitGraph.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/RebuildCommitGraph.java
index f25956f..df59bbe 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/RebuildCommitGraph.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/RebuildCommitGraph.java
@@ -70,6 +70,7 @@
 import org.eclipse.jgit.lib.RefUpdate;
 import org.eclipse.jgit.lib.RefWriter;
 import org.eclipse.jgit.lib.TextProgressMonitor;
+import org.eclipse.jgit.pgm.Command;
 import org.eclipse.jgit.pgm.TextBuiltin;
 import org.eclipse.jgit.pgm.internal.CLIText;
 import org.eclipse.jgit.revwalk.RevWalk;
@@ -94,6 +95,7 @@
  * deleted from the current repository.
  * <p>
  */
+@Command(usage = "usage_RebuildCommitGraph")
 class RebuildCommitGraph extends TextBuiltin {
 	private static final String REALLY = "--destroy-this-repository"; //$NON-NLS-1$
 
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ShowCacheTree.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ShowCacheTree.java
index 7b0c287..e287425 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ShowCacheTree.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ShowCacheTree.java
@@ -51,9 +51,11 @@
 
 import org.eclipse.jgit.dircache.DirCache;
 import org.eclipse.jgit.dircache.DirCacheTree;
+import org.eclipse.jgit.pgm.Command;
 import org.eclipse.jgit.pgm.TextBuiltin;
 import org.eclipse.jgit.pgm.internal.CLIText;
 
+@Command(usage = "usage_ShowCacheTree")
 class ShowCacheTree extends TextBuiltin {
 	@Override
 	protected void run() throws Exception {
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ShowDirCache.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ShowDirCache.java
index e69738c..71af3d1 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ShowDirCache.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ShowDirCache.java
@@ -54,8 +54,10 @@
 import org.eclipse.jgit.dircache.DirCache;
 import org.eclipse.jgit.dircache.DirCacheEntry;
 import org.eclipse.jgit.lib.FileMode;
+import org.eclipse.jgit.pgm.Command;
 import org.eclipse.jgit.pgm.TextBuiltin;
 
+@Command(usage = "usage_ShowDirCache")
 class ShowDirCache extends TextBuiltin {
 	@Override
 	protected void run() throws Exception {
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ShowPackDelta.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ShowPackDelta.java
index 26ad931..7b5cdbf 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ShowPackDelta.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ShowPackDelta.java
@@ -60,12 +60,14 @@
 import org.eclipse.jgit.lib.NullProgressMonitor;
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.ObjectReader;
+import org.eclipse.jgit.pgm.Command;
 import org.eclipse.jgit.pgm.TextBuiltin;
 import org.eclipse.jgit.revwalk.RevObject;
 import org.eclipse.jgit.revwalk.RevWalk;
 import org.eclipse.jgit.util.TemporaryBuffer;
 import org.kohsuke.args4j.Argument;
 
+@Command(usage = "usage_ShowPackDelta")
 class ShowPackDelta extends TextBuiltin {
 	@Argument(index = 0)
 	private ObjectId objectId;
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/TextHashFunctions.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/TextHashFunctions.java
index e43c9a6..4205140 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/TextHashFunctions.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/TextHashFunctions.java
@@ -64,6 +64,7 @@
 import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.lib.RepositoryBuilder;
 import org.eclipse.jgit.lib.RepositoryCache;
+import org.eclipse.jgit.pgm.Command;
 import org.eclipse.jgit.pgm.TextBuiltin;
 import org.eclipse.jgit.pgm.internal.CLIText;
 import org.eclipse.jgit.revwalk.RevWalk;
@@ -90,6 +91,7 @@
  * type {@link Fold} and implement the logic. The test suite will automatically
  * pick up the new function through reflection.
  */
+@Command(usage = "usage_TextHashFunctions")
 class TextHashFunctions extends TextBuiltin {
 
 	/** Standard SHA-1 on the line, using the first 4 bytes as the hash code. */
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/WriteDirCache.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/WriteDirCache.java
index 4adb276..42428c7 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/WriteDirCache.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/WriteDirCache.java
@@ -45,9 +45,11 @@
 package org.eclipse.jgit.pgm.debug;
 
 import org.eclipse.jgit.dircache.DirCache;
+import org.eclipse.jgit.pgm.Command;
 import org.eclipse.jgit.pgm.TextBuiltin;
 import org.eclipse.jgit.pgm.internal.CLIText;
 
+@Command(usage = "usage_WriteDirCache")
 class WriteDirCache extends TextBuiltin {
 	@Override
 	protected void run() throws Exception {
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/internal/CLIText.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/internal/CLIText.java
index 62865d5..a8bf3d8 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/internal/CLIText.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/internal/CLIText.java
@@ -115,7 +115,6 @@ public static String formatLine(String line) {
 	/***/ public String doesNotExist;
 	/***/ public String dontOverwriteLocalChanges;
 	/***/ public String everythingUpToDate;
-	/***/ public String exceptionCaughtDuringExecutionOfArchiveCommand;
 	/***/ public String expectedNumberOfbytes;
 	/***/ public String exporting;
 	/***/ public String failedToCommitIndex;
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 29533ff..6845d3f 100644
--- a/org.eclipse.jgit.test/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit.test/.settings/org.eclipse.jdt.core.prefs
@@ -66,7 +66,7 @@
 org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
 org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
 org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
-org.eclipse.jdt.core.compiler.problem.parameterAssignment=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
 org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=error
 org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
 org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
diff --git a/org.eclipse.jgit.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.test/META-INF/MANIFEST.MF
index c15a7d4..aff1abb 100644
--- a/org.eclipse.jgit.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.test/META-INF/MANIFEST.MF
@@ -2,46 +2,47 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %plugin_name
 Bundle-SymbolicName: org.eclipse.jgit.test
-Bundle-Version: 3.0.3.201309161630-r
+Bundle-Version: 3.1.0.qualifier
 Bundle-Localization: plugin
 Bundle-Vendor: %provider_name
 Bundle-ActivationPolicy: lazy
 Bundle-RequiredExecutionEnvironment: J2SE-1.5
-Import-Package: javaewah;version="0.5.6",
- org.eclipse.jgit.api;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.api.errors;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.awtui;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.blame;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.console;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.diff;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.dircache;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.errors;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.events;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.fnmatch;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.ignore;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.internal;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.internal.storage.file;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.internal.storage.pack;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.java7;version="[3.0.3,3.1.0)";resolution:=optional,
- org.eclipse.jgit.junit;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.lib;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.merge;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.nls;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.notes;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.patch;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.pgm;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.pgm.internal;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.revplot;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.revwalk;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.revwalk.filter;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.storage.file;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.storage.pack;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.submodule;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.transport;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.treewalk;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.treewalk.filter;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.util;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.util.io;version="[3.0.3,3.1.0)",
+Import-Package: javaewah;version="[0.5.6,1.0.0)",
+ org.eclipse.jgit.api;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.api.errors;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.awtui;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.blame;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.console;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.diff;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.dircache;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.errors;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.events;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.fnmatch;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.ignore;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.internal;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.internal.storage.dfs;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.internal.storage.file;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.internal.storage.pack;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.java7;version="[3.1.0,3.2.0)";resolution:=optional,
+ org.eclipse.jgit.junit;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.lib;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.merge;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.nls;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.notes;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.patch;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.pgm;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.pgm.internal;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.revplot;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.revwalk;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.revwalk.filter;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.storage.file;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.storage.pack;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.submodule;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.transport;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.treewalk;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.treewalk.filter;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.util;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.util.io;version="[3.1.0,3.2.0)",
  org.hamcrest;version="[1.1.0,2.0.0)",
  org.junit;version="[4.4.0,5.0.0)",
  org.junit.experimental.theories;version="[4.4.0,5.0.0)",
diff --git a/org.eclipse.jgit.test/pom.xml b/org.eclipse.jgit.test/pom.xml
index c932cb1..7b9f4ca 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>3.0.3.201309161630-r</version>
+    <version>3.1.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.test</artifactId>
@@ -147,7 +147,7 @@
       <plugin>
         <artifactId>maven-surefire-plugin</artifactId>
         <configuration>
-          <argLine>-Xmx256m -Dfile.encoding=UTF-8</argLine>
+          <argLine>-Xmx256m -Dfile.encoding=UTF-8 -Djava.io.tmpdir=${project.build.directory}</argLine>
         </configuration>
       </plugin>
     </plugins>
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/LsRemoteCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/LsRemoteCommandTest.java
index 991214d..f31276d 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/LsRemoteCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/LsRemoteCommandTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011, Chris Aniszczyk <caniszczyk@gmail.com>
+ * Copyright (C) 2011, 2013 Chris Aniszczyk <caniszczyk@gmail.com> and others.
  * and other copyright owners as documented in the project's IP log.
  *
  * This program and the accompanying materials are made available
@@ -128,4 +128,12 @@ public void testLsRemoteWithHeads() throws Exception {
 		assertEquals(2, refs.size());
 	}
 
+	@Test
+	public void testLsRemoteWithoutLocalRepository() throws Exception {
+		String uri = "file://" + git.getRepository().getWorkTree().getPath();
+		Collection<Ref> refs = Git.lsRemoteRepository().setRemote(uri).setHeads(true).call();
+		assertNotNull(refs);
+		assertEquals(2, refs.size());
+	}
+
 }
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/ResetCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/ResetCommandTest.java
index da57cb3..8224976 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/ResetCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/ResetCommandTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2012, Chris Aniszczyk <caniszczyk@gmail.com>
+ * Copyright (C) 2011-2013, Chris Aniszczyk <caniszczyk@gmail.com>
  * and other copyright owners as documented in the project's IP log.
  *
  * This program and the accompanying materials are made available
@@ -404,6 +404,27 @@ public void testPathsResetWithUnmerged() throws Exception {
 	}
 
 	@Test
+	public void testPathsResetOnUnbornBranch() throws Exception {
+		git = new Git(db);
+		writeTrashFile("a.txt", "content");
+		git.add().addFilepattern("a.txt").call();
+		// Should assume an empty tree, like in C Git 1.8.2
+		git.reset().addPath("a.txt").call();
+
+		DirCache cache = db.readDirCache();
+		DirCacheEntry aEntry = cache.getEntry("a.txt");
+		assertNull(aEntry);
+	}
+
+	@Test(expected = JGitInternalException.class)
+	public void testPathsResetToNonexistingRef() throws Exception {
+		git = new Git(db);
+		writeTrashFile("a.txt", "content");
+		git.add().addFilepattern("a.txt").call();
+		git.reset().setRef("doesnotexist").addPath("a.txt").call();
+	}
+
+	@Test
 	public void testHardResetOnTag() throws Exception {
 		setupRepository();
 		String tagName = "initialtag";
@@ -453,6 +474,21 @@ public void testHardResetAfterSquashMerge() throws Exception {
 		assertNull(db.readSquashCommitMsg());
 	}
 
+	@Test
+	public void testHardResetOnUnbornBranch() throws Exception {
+		git = new Git(db);
+		File fileA = writeTrashFile("a.txt", "content");
+		git.add().addFilepattern("a.txt").call();
+		// Should assume an empty tree, like in C Git 1.8.2
+		git.reset().setMode(ResetType.HARD).call();
+
+		DirCache cache = db.readDirCache();
+		DirCacheEntry aEntry = cache.getEntry("a.txt");
+		assertNull(aEntry);
+		assertFalse(fileA.exists());
+		assertNull(db.resolve(Constants.HEAD));
+	}
+
 	private void assertReflog(ObjectId prevHead, ObjectId head)
 			throws IOException {
 		// Check the reflog for HEAD
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/StashApplyCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/StashApplyCommandTest.java
index a81beb0..16e80f1 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/StashApplyCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/StashApplyCommandTest.java
@@ -368,6 +368,7 @@ public void workingDirectoryContentConflict() throws Exception {
 			git.stashApply().call();
 			fail("Exception not thrown");
 		} catch (StashApplyFailureException e) {
+			// expected
  		}
 		assertEquals("content3", read(PATH));
 	}
@@ -398,6 +399,7 @@ public void stashedContentMerge() throws Exception {
 			git.stashApply().call();
 			fail("Expected conflict");
 		} catch (StashApplyFailureException e) {
+			// expected
 		}
 		Status status = new StatusCommand(db).call();
 		assertEquals(1, status.getConflicting().size());
@@ -446,6 +448,7 @@ public void indexContentConflict() throws Exception {
 			git.stashApply().call();
 			fail("Exception not thrown");
 		} catch (StashApplyFailureException e) {
+			// expected
 		}
 		assertEquals("content2", read(PATH));
 	}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/StatusCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/StatusCommandTest.java
index e98263a..8b3e87f 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/StatusCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/StatusCommandTest.java
@@ -132,6 +132,42 @@ public void testDifferentStates() throws IOException,
 		assertTrue(stat.getUntrackedFolders().contains("sub"));
 	}
 
+	@Test
+	public void testDifferentStatesWithPaths() throws IOException,
+			NoFilepatternException, GitAPIException {
+		Git git = new Git(db);
+		writeTrashFile("a", "content of a");
+		writeTrashFile("D/b", "content of b");
+		writeTrashFile("D/c", "content of c");
+		writeTrashFile("D/D/d", "content of d");
+		git.add().addFilepattern(".").call();
+
+		writeTrashFile("a", "new content of a");
+		writeTrashFile("D/b", "new content of b");
+		writeTrashFile("D/D/d", "new content of d");
+
+
+		// filter on an not existing path
+		Status stat = git.status().addPath("x").call();
+		assertEquals(0, stat.getModified().size());
+
+		// filter on an existing file
+		stat = git.status().addPath("a").call();
+		assertEquals(set("a"), stat.getModified());
+
+		// filter on an existing folder
+		stat = git.status().addPath("D").call();
+		assertEquals(set("D/b", "D/D/d"), stat.getModified());
+
+		// filter on an existing folder and file
+		stat = git.status().addPath("D/D").addPath("a").call();
+		assertEquals(set("a", "D/D/d"), stat.getModified());
+
+		// do not filter at all
+		stat = git.status().call();
+		assertEquals(set("a", "D/b", "D/D/d"), stat.getModified());
+	}
+
 	public static Set<String> set(String... elements) {
 		Set<String> ret = new HashSet<String>();
 		for (String element : elements)
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 ec07244..1db6c80 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
@@ -802,6 +802,46 @@ public void testUnsupportedGroupCase1() throws Exception {
 	}
 
 	@Test
+	public void testEscapedBracket1() throws Exception {
+		assertMatch("\\[", "[", true, false);
+	}
+
+	@Test
+	public void testEscapedBracket2() throws Exception {
+		assertMatch("\\[[a]", "[", false, true);
+	}
+
+	@Test
+	public void testEscapedBracket3() throws Exception {
+		assertMatch("\\[[a]", "a", false, false);
+	}
+
+	@Test
+	public void testEscapedBracket4() throws Exception {
+		assertMatch("\\[[a]", "[a", true, false);
+	}
+
+	@Test
+	public void testEscapedBracket5() throws Exception {
+		assertMatch("[a\\]]", "]", true, false);
+	}
+
+	@Test
+	public void testEscapedBracket6() throws Exception {
+		assertMatch("[a\\]]", "a", true, false);
+	}
+
+	@Test
+	public void testEscapedBackslash() throws Exception {
+		assertMatch("a\\\\b", "a\\b", true, false);
+	}
+
+	@Test
+	public void testMultipleEscapedCharacters1() throws Exception {
+		assertMatch("\\]a?c\\*\\[d\\?\\]", "]abc*[d?]", true, false);
+	}
+
+	@Test
 	public void testFilePathSimpleCase() throws Exception {
 		assertFileNameMatch("a/b", "a/b", '/', true, false);
 	}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/IgnoreNodeTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/IgnoreNodeTest.java
index 881b01c..0076ba1 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/IgnoreNodeTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/IgnoreNodeTest.java
@@ -166,6 +166,17 @@ public void testWithSlashDoesNotMatchInSubDirectory() throws IOException {
 		assertEntry(F, tracked, "src/a/b");
 	}
 
+	@Test
+	public void testNoPatterns() throws IOException {
+		writeIgnoreFile(".gitignore", "", " ", "# comment", "/");
+		writeTrashFile("a/a", "");
+
+		beginWalk();
+		assertEntry(F, tracked, ".gitignore");
+		assertEntry(D, tracked, "a");
+		assertEntry(F, tracked, "a/a");
+	}
+
 	private void beginWalk() throws CorruptObjectException {
 		walk = new TreeWalk(db);
 		walk.addTree(new FileTreeIterator(db));
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsOutputStreamTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsOutputStreamTest.java
new file mode 100644
index 0000000..fc092e6
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsOutputStreamTest.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2013, 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.dfs;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.util.RawParseUtils;
+import org.junit.Test;
+
+public class DfsOutputStreamTest {
+	@Test
+	public void testReadEmpty() throws IOException {
+		DfsOutputStream os = newDfsOutputStream(8);
+		os.write(Constants.encode(""));
+		assertEquals("", readBuffered(os.openInputStream(0)));
+		assertEquals("", readByByte(os.openInputStream(0)));
+		assertEquals("", readBuffered(os.openInputStream(1)));
+		assertEquals("", readByByte(os.openInputStream(1)));
+	}
+
+	@Test
+	public void testRead() throws IOException {
+		DfsOutputStream os = newDfsOutputStream(8);
+		os.write(Constants.encode("data"));
+		assertEquals("data", readBuffered(os.openInputStream(0)));
+		assertEquals("data", readByByte(os.openInputStream(0)));
+		assertEquals("ata", readBuffered(os.openInputStream(1)));
+		assertEquals("ata", readByByte(os.openInputStream(1)));
+		assertEquals("ta", readBuffered(os.openInputStream(2)));
+		assertEquals("ta", readByByte(os.openInputStream(2)));
+		assertEquals("a", readBuffered(os.openInputStream(3)));
+		assertEquals("a", readByByte(os.openInputStream(3)));
+		assertEquals("", readBuffered(os.openInputStream(4)));
+		assertEquals("", readByByte(os.openInputStream(4)));
+		assertEquals("", readBuffered(os.openInputStream(5)));
+		assertEquals("", readByByte(os.openInputStream(5)));
+	}
+
+	@Test
+	public void testReadSmallBuffer() throws IOException {
+		DfsOutputStream os = newDfsOutputStream(8);
+		os.write(Constants.encode("data"));
+		assertEquals("data", readBuffered(os.openInputStream(0), 2));
+		assertEquals("ata", readBuffered(os.openInputStream(1), 2));
+		assertEquals("ta", readBuffered(os.openInputStream(2), 2));
+		assertEquals("a", readBuffered(os.openInputStream(3), 2));
+		assertEquals("", readBuffered(os.openInputStream(4), 2));
+		assertEquals("", readBuffered(os.openInputStream(5), 2));
+	}
+
+	@Test
+	public void testReadMultipleBlocks() throws IOException {
+		DfsOutputStream os = newDfsOutputStream(2);
+		os.write(Constants.encode("data"));
+		assertEquals("data", readBuffered(os.openInputStream(0)));
+		assertEquals("data", readByByte(os.openInputStream(0)));
+		assertEquals("ata", readBuffered(os.openInputStream(1)));
+		assertEquals("ata", readByByte(os.openInputStream(1)));
+		assertEquals("ta", readBuffered(os.openInputStream(2)));
+		assertEquals("ta", readByByte(os.openInputStream(2)));
+		assertEquals("a", readBuffered(os.openInputStream(3)));
+		assertEquals("a", readByByte(os.openInputStream(3)));
+		assertEquals("", readBuffered(os.openInputStream(4)));
+		assertEquals("", readByByte(os.openInputStream(4)));
+		assertEquals("", readBuffered(os.openInputStream(5)));
+		assertEquals("", readByByte(os.openInputStream(5)));
+	}
+
+	private static DfsOutputStream newDfsOutputStream(final int blockSize) {
+		return new InMemoryOutputStream() {
+			@Override
+			public int blockSize() {
+				return blockSize;
+			}
+		};
+	}
+
+	private static String readBuffered(InputStream is, int bufsize)
+			throws IOException {
+		StringBuilder out = new StringBuilder();
+		byte[] buf = new byte[bufsize];
+		while (true) {
+			int n = is.read(buf, 0, buf.length);
+			if (n < 0)
+				break;
+			out.append(RawParseUtils.decode(buf, 0, n));
+		}
+		return out.toString();
+	}
+
+	private static String readBuffered(InputStream is) throws IOException {
+		return readBuffered(is, 64);
+	}
+
+	private static String readByByte(InputStream is) throws IOException {
+		StringBuilder out = new StringBuilder();
+		while (true) {
+			int c = is.read();
+			if (c < 0)
+				break;
+			out.append(RawParseUtils.decode(new byte[] {(byte) c}));
+		}
+		return out.toString();
+	}
+}
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 aa3817e..7eeb0c0 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
@@ -158,6 +158,21 @@ public void testCompareEntriesOffsetsWithFindOffsets() {
 	}
 
 	/**
+	 * Compare offset from iterator entries with output of getOffset() method.
+	 */
+	@Test
+	public void testCompareEntriesOffsetsWithGetOffsets() {
+		int i = 0;
+		for (MutableEntry me : smallIdx) {
+			assertEquals(smallIdx.getOffset(i++), me.getOffset());
+		}
+		int j = 0;
+		for (MutableEntry me : denseIdx) {
+			assertEquals(denseIdx.getOffset(j++), me.getOffset());
+		}
+	}
+
+	/**
 	 * Test partial results of iterator comparing to content of well-known
 	 * (prepared) dense index, that may need multi-level indexing.
 	 */
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/RepositorySetupWorkDirTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/RepositorySetupWorkDirTest.java
index bc47782..295ef45 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/RepositorySetupWorkDirTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/RepositorySetupWorkDirTest.java
@@ -187,16 +187,15 @@ public void testExceptionThrown_BareRepoGetIndexFile() throws Exception {
 		}
 	}
 
-	private static File getFile(String... pathComponents) throws IOException {
-		String rootPath = new File(new File("target"), "trash").getPath();
+	private File getFile(String... pathComponents) throws IOException {
+		File dir = getTemporaryDirectory();
 		for (String pathComponent : pathComponents)
-			rootPath = rootPath + File.separatorChar + pathComponent;
-		File result = new File(rootPath);
-		FileUtils.mkdirs(result, true);
-		return result;
+			dir = new File(dir, pathComponent);
+		FileUtils.mkdirs(dir, true);
+		return dir;
 	}
 
-	private static void setBare(File gitDir, boolean bare) throws IOException,
+	private void setBare(File gitDir, boolean bare) throws IOException,
 			ConfigInvalidException {
 		FileBasedConfig cfg = configFor(gitDir);
 		cfg.setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null,
@@ -204,7 +203,7 @@ private static void setBare(File gitDir, boolean bare) throws IOException,
 		cfg.save();
 	}
 
-	private static void setWorkTree(File gitDir, File workTree)
+	private void setWorkTree(File gitDir, File workTree)
 			throws IOException,
 			ConfigInvalidException {
 		String path = workTree.getAbsolutePath();
@@ -214,7 +213,7 @@ private static void setWorkTree(File gitDir, File workTree)
 		cfg.save();
 	}
 
-	private static FileBasedConfig configFor(File gitDir) throws IOException,
+	private FileBasedConfig configFor(File gitDir) throws IOException,
 			ConfigInvalidException {
 		File configPath = new File(gitDir, Constants.CONFIG);
 		FileBasedConfig cfg = new FileBasedConfig(configPath, FS.DETECTED);
@@ -222,14 +221,14 @@ private static FileBasedConfig configFor(File gitDir) throws IOException,
 		return cfg;
 	}
 
-	private static void assertGitdirPath(Repository repo, String... expected)
+	private void assertGitdirPath(Repository repo, String... expected)
 			throws IOException {
 		File exp = getFile(expected).getCanonicalFile();
 		File act = repo.getDirectory().getCanonicalFile();
 		assertEquals("Wrong Git Directory", exp, act);
 	}
 
-	private static void assertWorkdirPath(Repository repo, String... expected)
+	private void assertWorkdirPath(Repository repo, String... expected)
 			throws IOException {
 		File exp = getFile(expected).getCanonicalFile();
 		File act = repo.getWorkTree().getCanonicalFile();
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/TransportTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/TransportTest.java
index aba4e6a..b969183 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/TransportTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/TransportTest.java
@@ -57,7 +57,9 @@
 
 import org.eclipse.jgit.junit.SampleDataRepositoryTestCase;
 import org.eclipse.jgit.lib.Config;
+import org.eclipse.jgit.lib.Constants;
 import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.Ref;
 import org.eclipse.jgit.lib.Repository;
 import org.junit.After;
 import org.junit.Before;
@@ -227,6 +229,20 @@ public void testLocalTransportWithRelativePath() throws Exception {
 	}
 
 	@Test
+	public void testLocalTransportFetchWithoutLocalRepository()
+			throws Exception {
+		URIish uri = new URIish("file://" + db.getWorkTree().getPath());
+		transport = Transport.open(uri);
+		FetchConnection fetchConnection = transport.openFetch();
+		try {
+			Ref head = fetchConnection.getRef(Constants.HEAD);
+			assertNotNull(head);
+		} finally {
+			fetchConnection.close();
+		}
+	}
+
+	@Test
 	public void testSpi() {
 		List<TransportProtocol> protocols = Transport.getTransportProtocols();
 		assertNotNull(protocols);
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 9704453..6a1454e 100644
--- a/org.eclipse.jgit.ui/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit.ui/.settings/org.eclipse.jdt.core.prefs
@@ -66,7 +66,7 @@
 org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
 org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
 org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
-org.eclipse.jdt.core.compiler.problem.parameterAssignment=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
 org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=error
 org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
 org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
diff --git a/org.eclipse.jgit.ui/META-INF/MANIFEST.MF b/org.eclipse.jgit.ui/META-INF/MANIFEST.MF
index 245ee43..bb72a31 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: 3.0.3.201309161630-r
+Bundle-Version: 3.1.0.qualifier
 Bundle-Vendor: %provider_name
 Bundle-RequiredExecutionEnvironment: J2SE-1.5
-Export-Package: org.eclipse.jgit.awtui;version="3.0.3"
-Import-Package: org.eclipse.jgit.errors;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.lib;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.nls;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.revplot;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.revwalk;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.transport;version="[3.0.3,3.1.0)",
- org.eclipse.jgit.util;version="[3.0.3,3.1.0)"
+Export-Package: org.eclipse.jgit.awtui;version="3.1.0"
+Import-Package: org.eclipse.jgit.errors;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.lib;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.nls;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.revplot;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.revwalk;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.transport;version="[3.1.0,3.2.0)",
+ org.eclipse.jgit.util;version="[3.1.0,3.2.0)"
diff --git a/org.eclipse.jgit.ui/pom.xml b/org.eclipse.jgit.ui/pom.xml
index ef64934..5d3b79a 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>3.0.3.201309161630-r</version>
+    <version>3.1.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit.ui</artifactId>
diff --git a/org.eclipse.jgit/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit/.settings/org.eclipse.jdt.core.prefs
index 9704453..6a1454e 100644
--- a/org.eclipse.jgit/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit/.settings/org.eclipse.jdt.core.prefs
@@ -66,7 +66,7 @@
 org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
 org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
 org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
-org.eclipse.jdt.core.compiler.problem.parameterAssignment=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
 org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=error
 org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
 org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
diff --git a/org.eclipse.jgit/META-INF/MANIFEST.MF b/org.eclipse.jgit/META-INF/MANIFEST.MF
index 17d6fa1..4f6d874 100644
--- a/org.eclipse.jgit/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit/META-INF/MANIFEST.MF
@@ -2,44 +2,54 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %plugin_name
 Bundle-SymbolicName: org.eclipse.jgit
-Bundle-Version: 3.0.3.201309161630-r
+Bundle-Version: 3.1.0.qualifier
 Bundle-Localization: plugin
 Bundle-Vendor: %provider_name
-Export-Package: org.eclipse.jgit.api;version="3.0.3",
- org.eclipse.jgit.api.errors;version="3.0.3",
- org.eclipse.jgit.blame;version="3.0.3",
- org.eclipse.jgit.diff;version="3.0.3",
- org.eclipse.jgit.dircache;version="3.0.3",
- org.eclipse.jgit.errors;version="3.0.3",
- org.eclipse.jgit.events;version="3.0.3",
- org.eclipse.jgit.fnmatch;version="3.0.3",
- org.eclipse.jgit.ignore;version="3.0.3",
- org.eclipse.jgit.internal;version="3.0.3";x-friends:="org.eclipse.jgit.test,org.eclipse.jgit.http.test",
- org.eclipse.jgit.internal.storage.dfs;version="3.0.3";x-friends:="org.eclipse.jgit.test",
- org.eclipse.jgit.internal.storage.file;version="3.0.3";x-friends:="org.eclipse.jgit.test,
- 	org.eclipse.jgit.junit,org.eclipse.jgit.junit.http,org.eclipse.jgit.http.server",
- org.eclipse.jgit.internal.storage.pack;version="3.0.3";x-friends:="org.eclipse.jgit.test",
- org.eclipse.jgit.lib;version="3.0.3",
- org.eclipse.jgit.merge;version="3.0.3",
- org.eclipse.jgit.nls;version="3.0.3",
- org.eclipse.jgit.notes;version="3.0.3",
- org.eclipse.jgit.patch;version="3.0.3",
- org.eclipse.jgit.revplot;version="3.0.3",
- org.eclipse.jgit.revwalk;version="3.0.3",
- org.eclipse.jgit.revwalk.filter;version="3.0.3",
- org.eclipse.jgit.storage.file;version="3.0.3",
- org.eclipse.jgit.storage.pack;version="3.0.3",
- org.eclipse.jgit.submodule;version="3.0.3",
- org.eclipse.jgit.transport;version="3.0.3",
- org.eclipse.jgit.transport.resolver;version="3.0.3",
- org.eclipse.jgit.treewalk;version="3.0.3",
- org.eclipse.jgit.treewalk.filter;version="3.0.3",
- org.eclipse.jgit.util;version="3.0.3",
- org.eclipse.jgit.util.io;version="3.0.3"
+Export-Package: org.eclipse.jgit.api;version="3.1.0",
+ org.eclipse.jgit.api.errors;version="3.1.0",
+ org.eclipse.jgit.blame;version="3.1.0",
+ org.eclipse.jgit.diff;version="3.1.0",
+ org.eclipse.jgit.dircache;version="3.1.0",
+ org.eclipse.jgit.errors;version="3.1.0",
+ org.eclipse.jgit.events;version="3.1.0",
+ org.eclipse.jgit.fnmatch;version="3.1.0",
+ org.eclipse.jgit.ignore;version="3.1.0",
+ org.eclipse.jgit.internal;version="3.1.0";x-friends:="org.eclipse.jgit.test,org.eclipse.jgit.http.test",
+ org.eclipse.jgit.internal.storage.dfs;version="3.1.0";x-friends:="org.eclipse.jgit.test",
+ org.eclipse.jgit.internal.storage.file;version="3.1.0";
+  x-friends:="org.eclipse.jgit.test,
+   org.eclipse.jgit.junit,
+   org.eclipse.jgit.junit.http,
+   org.eclipse.jgit.http.server,
+   org.eclipse.jgit.java7.test,
+   org.eclipse.jgit.pgm",
+ org.eclipse.jgit.internal.storage.pack;version="3.1.0";
+  x-friends:="org.eclipse.jgit.test,
+   org.eclipse.jgit.pgm",
+ org.eclipse.jgit.internal.storage.pack;version="3.1.0";
+  x-friends:="org.eclipse.jgit.test,
+   org.eclipse.jgit.pgm",
+ org.eclipse.jgit.lib;version="3.1.0",
+ org.eclipse.jgit.merge;version="3.1.0",
+ org.eclipse.jgit.nls;version="3.1.0",
+ org.eclipse.jgit.notes;version="3.1.0",
+ org.eclipse.jgit.patch;version="3.1.0",
+ org.eclipse.jgit.revplot;version="3.1.0",
+ org.eclipse.jgit.revwalk;version="3.1.0",
+ org.eclipse.jgit.revwalk.filter;version="3.1.0",
+ org.eclipse.jgit.storage.file;version="3.1.0",
+ org.eclipse.jgit.storage.pack;version="3.1.0",
+ org.eclipse.jgit.submodule;version="3.1.0",
+ org.eclipse.jgit.transport;version="3.1.0",
+ org.eclipse.jgit.transport.resolver;version="3.1.0",
+ org.eclipse.jgit.treewalk;version="3.1.0",
+ org.eclipse.jgit.treewalk.filter;version="3.1.0",
+ org.eclipse.jgit.util;version="3.1.0",
+ org.eclipse.jgit.util.io;version="3.1.0"
 Bundle-ActivationPolicy: lazy
 Bundle-RequiredExecutionEnvironment: J2SE-1.5
 Require-Bundle: com.jcraft.jsch;bundle-version="[0.1.37,0.2.0)"
-Import-Package: javaewah;version="0.5.6",
+Import-Package: javaewah;version="[0.5.6,1.0.0)",
  javax.crypto,
  javax.net.ssl,
  org.xml.sax,
diff --git a/org.eclipse.jgit/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit/META-INF/SOURCE-MANIFEST.MF
index 3949ec6..20968e8 100644
--- a/org.eclipse.jgit/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit/META-INF/SOURCE-MANIFEST.MF
@@ -3,6 +3,5 @@
 Bundle-Name: org.eclipse.jgit - Sources
 Bundle-SymbolicName: org.eclipse.jgit.source;singleton:=true
 Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 3.0.3.201309161630-r
-Eclipse-SourceBundle: org.eclipse.jgit;version="3.0.3.201309161630-r";roots="."
-
+Bundle-Version: 3.1.0.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit;version="3.1.0";roots="."
diff --git a/org.eclipse.jgit/pom.xml b/org.eclipse.jgit/pom.xml
index 4b52d8d..ca0d73a 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>3.0.3.201309161630-r</version>
+    <version>3.1.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>org.eclipse.jgit</artifactId>
diff --git a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
index 33489eb..706dce7 100644
--- a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
+++ b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
@@ -11,6 +11,8 @@
 anExceptionOccurredWhileTryingToAddTheIdOfHEAD=An exception occurred while trying to add the Id of HEAD
 anSSHSessionHasBeenAlreadyCreated=An SSH session has been already created
 applyingCommit=Applying {0}
+archiveFormatAlreadyAbsent=Archive format already absent: {0}
+archiveFormatAlreadyRegistered=Archive format already registered: {0}
 atLeastOnePathIsRequired=At least one path is required.
 atLeastOnePatternIsRequired=At least one pattern is required.
 atLeastTwoFiltersNeeded=At least two filters needed.
@@ -182,6 +184,7 @@
 errorReadingInfoRefs=error reading info/refs
 errorSymlinksNotSupported=Symlinks are not supported with this OS/JRE
 exceptionCaughtDuringExecutionOfAddCommand=Exception caught during execution of add command
+exceptionCaughtDuringExecutionOfArchiveCommand=Exception caught during execution of archive command
 exceptionCaughtDuringExecutionOfCherryPickCommand=Exception caught during execution of cherry-pick command. {0}
 exceptionCaughtDuringExecutionOfCommitCommand=Exception caught during execution of commit command
 exceptionCaughtDuringExecutionOfFetchCommand=Exception caught during execution of fetch command
@@ -525,6 +528,7 @@
 unpackException=Exception while parsing pack stream
 unreadablePackIndex=Unreadable pack index: {0}
 unrecognizedRef=Unrecognized ref: {0}
+unsupportedArchiveFormat=Unknown archive format ''{0}''
 unsupportedCommand0=unsupported command 0
 unsupportedEncryptionAlgorithm=Unsupported encryption algorithm: {0}
 unsupportedEncryptionVersion=Unsupported encryption version: {0}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/ArchiveCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/ArchiveCommand.java
new file mode 100644
index 0000000..e8e4ffd
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/ArchiveCommand.java
@@ -0,0 +1,373 @@
+/*
+ * Copyright (C) 2012 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.api;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.text.MessageFormat;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.eclipse.jgit.api.errors.GitAPIException;
+import org.eclipse.jgit.api.errors.JGitInternalException;
+import org.eclipse.jgit.internal.JGitText;
+import org.eclipse.jgit.lib.FileMode;
+import org.eclipse.jgit.lib.MutableObjectId;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectLoader;
+import org.eclipse.jgit.lib.ObjectReader;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevWalk;
+import org.eclipse.jgit.treewalk.TreeWalk;
+
+/**
+ * Create an archive of files from a named tree.
+ * <p>
+ * Examples (<code>git</code> is a {@link Git} instance):
+ * <p>
+ * Create a tarball from HEAD:
+ *
+ * <pre>
+ * ArchiveCommand.registerFormat("tar", new TarFormat());
+ * try {
+ *	git.archive()
+ *		.setTree(db.resolve(&quot;HEAD&quot;))
+ *		.setOutputStream(out)
+ *		.call();
+ * } finally {
+ *	ArchiveCommand.unregisterFormat("tar");
+ * }
+ * </pre>
+ * <p>
+ * Create a ZIP file from master:
+ *
+ * <pre>
+ * ArchiveCommand.registerFormat("zip", new ZipFormat());
+ * try {
+ *	git.archive().
+ *		.setTree(db.resolve(&quot;master&quot;))
+ *		.setFormat("zip")
+ *		.setOutputStream(out)
+ *		.call();
+ * } finally {
+ *	ArchiveCommand.unregisterFormat("zip");
+ * }
+ * </pre>
+ *
+ * @see <a href="http://git-htmldocs.googlecode.com/git/git-archive.html" >Git
+ *      documentation about archive</a>
+ *
+ * @since 3.1
+ */
+public class ArchiveCommand extends GitCommand<OutputStream> {
+	/**
+	 * Archival format.
+	 *
+	 * Usage:
+	 *	Repository repo = git.getRepository();
+	 *	T out = format.createArchiveOutputStream(System.out);
+	 *	try {
+	 *		for (...) {
+	 *			format.putEntry(out, path, mode, repo.open(objectId));
+	 *		}
+	 *	} finally {
+	 *		out.close();
+	 *	}
+	 *
+	 * @param <T>
+	 *            type representing an archive being created.
+	 */
+	public static interface Format<T extends Closeable> {
+		/**
+		 * Start a new archive. Entries can be included in the archive using the
+		 * putEntry method, and then the archive should be closed using its
+		 * close method.
+		 *
+		 * @param s
+		 *            underlying output stream to which to write the archive.
+		 * @return new archive object for use in putEntry
+		 * @throws IOException
+		 *             thrown by the underlying output stream for I/O errors
+		 */
+		T createArchiveOutputStream(OutputStream s) throws IOException;
+
+		/**
+		 * Write an entry to an archive.
+		 *
+		 * @param out
+		 *            archive object from createArchiveOutputStream
+		 * @param path
+		 *            full filename relative to the root of the archive
+		 * @param mode
+		 *            mode (for example FileMode.REGULAR_FILE or
+		 *            FileMode.SYMLINK)
+		 * @param loader
+		 *            blob object with data for this entry
+		 * @throws IOException
+		 *            thrown by the underlying output stream for I/O errors
+		 */
+		void putEntry(T out, String path, FileMode mode,
+				ObjectLoader loader) throws IOException;
+
+		/**
+		 * Filename suffixes representing this format (e.g.,
+		 * { ".tar.gz", ".tgz" }).
+		 *
+		 * The behavior is undefined when suffixes overlap (if
+		 * one format claims suffix ".7z", no other format should
+		 * take ".tar.7z").
+		 *
+		 * @return this format's suffixes
+		 */
+		Iterable<String> suffixes();
+	}
+
+	/**
+	 * Signals an attempt to use an archival format that ArchiveCommand
+	 * doesn't know about (for example due to a typo).
+	 */
+	public static class UnsupportedFormatException extends GitAPIException {
+		private static final long serialVersionUID = 1L;
+
+		private final String format;
+
+		/**
+		 * @param format the problematic format name
+		 */
+		public UnsupportedFormatException(String format) {
+			super(MessageFormat.format(JGitText.get().unsupportedArchiveFormat, format));
+			this.format = format;
+		}
+
+		/**
+		 * @return the problematic format name
+		 */
+		public String getFormat() {
+			return format;
+		}
+	}
+
+	/**
+	 * Available archival formats (corresponding to values for
+	 * the --format= option)
+	 */
+	private static final ConcurrentMap<String, Format<?>> formats =
+			new ConcurrentHashMap<String, Format<?>>();
+
+	/**
+	 * Adds support for an additional archival format.  To avoid
+	 * unnecessary dependencies, ArchiveCommand does not have support
+	 * for any formats built in; use this function to add them.
+	 *
+	 * OSGi plugins providing formats should call this function at
+	 * bundle activation time.
+	 *
+	 * @param name name of a format (e.g., "tar" or "zip").
+	 * @param fmt archiver for that format
+	 * @throws JGitInternalException
+	 *              An archival format with that name was already registered.
+	 */
+	public static void registerFormat(String name, Format<?> fmt) {
+		// TODO(jrn): Check that suffixes don't overlap.
+
+		if (formats.putIfAbsent(name, fmt) != null)
+			throw new JGitInternalException(MessageFormat.format(
+					JGitText.get().archiveFormatAlreadyRegistered,
+					name));
+	}
+
+	/**
+	 * Removes support for an archival format so its Format can be
+	 * garbage collected.
+	 *
+	 * @param name name of format (e.g., "tar" or "zip").
+	 * @throws JGitInternalException
+	 *              No such archival format was registered.
+	 */
+	public static void unregisterFormat(String name) {
+		if (formats.remove(name) == null)
+			throw new JGitInternalException(MessageFormat.format(
+					JGitText.get().archiveFormatAlreadyAbsent,
+					name));
+	}
+
+	private static Format<?> formatBySuffix(String filenameSuffix)
+			throws UnsupportedFormatException {
+		if (filenameSuffix != null)
+			for (Format<?> fmt : formats.values())
+				for (String sfx : fmt.suffixes())
+					if (filenameSuffix.endsWith(sfx))
+						return fmt;
+		return lookupFormat("tar"); //$NON-NLS-1$
+	}
+
+	private static Format<?> lookupFormat(String formatName) throws UnsupportedFormatException {
+		Format<?> fmt = formats.get(formatName);
+		if (fmt == null)
+			throw new UnsupportedFormatException(formatName);
+		return fmt;
+	}
+
+	private OutputStream out;
+	private ObjectId tree;
+	private String format;
+
+	/** Filename suffix, for automatically choosing a format. */
+	private String suffix;
+
+	/**
+	 * @param repo
+	 */
+	public ArchiveCommand(Repository repo) {
+		super(repo);
+		setCallable(false);
+	}
+
+	private <T extends Closeable> OutputStream writeArchive(Format<T> fmt) {
+		final TreeWalk walk = new TreeWalk(repo);
+		try {
+			final T outa = fmt.createArchiveOutputStream(out);
+			try {
+				final MutableObjectId idBuf = new MutableObjectId();
+				final ObjectReader reader = walk.getObjectReader();
+				final RevWalk rw = new RevWalk(walk.getObjectReader());
+
+				walk.reset(rw.parseTree(tree));
+				walk.setRecursive(true);
+				while (walk.next()) {
+					final String name = walk.getPathString();
+					final FileMode mode = walk.getFileMode(0);
+
+					if (mode == FileMode.TREE)
+						// ZIP entries for directories are optional.
+						// Leave them out, mimicking "git archive".
+						continue;
+
+					walk.getObjectId(idBuf, 0);
+					fmt.putEntry(outa, name, mode, reader.open(idBuf));
+				}
+			} finally {
+				outa.close();
+			}
+			return out;
+		} catch (IOException e) {
+			// TODO(jrn): Throw finer-grained errors.
+			throw new JGitInternalException(
+					JGitText.get().exceptionCaughtDuringExecutionOfArchiveCommand, e);
+		} finally {
+			walk.release();
+		}
+	}
+
+	/**
+	 * @return the stream to which the archive has been written
+	 */
+	@Override
+	public OutputStream call() throws GitAPIException {
+		checkCallable();
+
+		final Format<?> fmt;
+		if (format == null)
+			fmt = formatBySuffix(suffix);
+		else
+			fmt = lookupFormat(format);
+		return writeArchive(fmt);
+	}
+
+	/**
+	 * @param tree
+	 *            the tag, commit, or tree object to produce an archive for
+	 * @return this
+	 */
+	public ArchiveCommand setTree(ObjectId tree) {
+		if (tree == null)
+			throw new IllegalArgumentException();
+
+		this.tree = tree;
+		setCallable(true);
+		return this;
+	}
+
+	/**
+	 * Set the intended filename for the produced archive. Currently the only
+	 * effect is to determine the default archive format when none is specified
+	 * with {@link #setFormat(String)}.
+	 *
+	 * @param filename
+	 *            intended filename for the archive
+	 * @return this
+	 */
+	public ArchiveCommand setFilename(String filename) {
+		int slash = filename.lastIndexOf('/');
+		int dot = filename.indexOf('.', slash + 1);
+
+		if (dot == -1)
+			this.suffix = ""; //$NON-NLS-1$
+		else
+			this.suffix = filename.substring(dot);
+		return this;
+	}
+
+	/**
+	 * @param out
+	 *	      the stream to which to write the archive
+	 * @return this
+	 */
+	public ArchiveCommand setOutputStream(OutputStream out) {
+		this.out = out;
+		return this;
+	}
+
+	/**
+	 * @param fmt
+	 *	      archive format (e.g., "tar" or "zip").
+	 *	      null means to choose automatically based on
+	 *	      the archive filename.
+	 * @return this
+	 */
+	public ArchiveCommand setFormat(String fmt) {
+		this.format = fmt;
+		return this;
+	}
+}
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 1b84411..192a377 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/CherryPickCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/CherryPickCommand.java
@@ -252,6 +252,7 @@ public CherryPickCommand setOurCommitName(String ourCommitName) {
 	 * @param prefix
 	 *            including ":"
 	 * @return {@code this}
+	 * @since 3.1
 	 */
 	public CherryPickCommand setReflogPrefix(final String prefix) {
 		this.reflogPrefix = prefix;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/CommitCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/CommitCommand.java
index 162105b..399d78e 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/CommitCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/CommitCommand.java
@@ -230,8 +230,8 @@ public RevCommit call() throws GitAPIException, NoHeadException,
 						ru.setRefLogMessage(reflogComment, false);
 					} else {
 						String prefix = amend ? "commit (amend): " //$NON-NLS-1$
-								: parents.size() == 0 ? "commit (initial): "
-										: "commit: ";
+								: parents.size() == 0 ? "commit (initial): " //$NON-NLS-1$
+										: "commit: "; //$NON-NLS-1$
 						ru.setRefLogMessage(
 								prefix + revCommit.getShortMessage(), false);
 					}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/Git.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/Git.java
index 4b8378a..b643cbe 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/Git.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/Git.java
@@ -138,6 +138,17 @@ public static CloneCommand cloneRepository() {
 	}
 
 	/**
+	 * Returns a command to list remote branches/tags without a local
+	 * repository.
+	 *
+	 * @return a {@link LsRemoteCommand}
+	 * @since 3.1
+	 */
+	public static LsRemoteCommand lsRemoteRepository() {
+		return new LsRemoteCommand(null);
+	}
+
+	/**
 	 * Returns a command object to execute a {@code init} command
 	 *
 	 * @see <a
@@ -403,6 +414,16 @@ public StatusCommand status() {
 	}
 
 	/**
+	 * Returns a command to create an archive from a tree
+	 *
+	 * @return a {@link ArchiveCommand}
+	 * @since 3.1
+	 */
+	public ArchiveCommand archive() {
+		return new ArchiveCommand(repo);
+	}
+
+	/**
 	 * Returns a command to add notes to an object
 	 *
 	 * @return a {@link AddNoteCommand}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/LogCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/LogCommand.java
index cad2790..53fc70d 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/LogCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/LogCommand.java
@@ -74,10 +74,24 @@
  * to finally execute the command. Each instance of this class should only be
  * used for one invocation of the command (means: one call to {@link #call()})
  * <p>
- * This is currently a very basic implementation which takes only one starting
- * revision as option.
+ * Examples (<code>git</code> is a {@link Git} instance):
+ * <p>
+ * Get newest 10 commits, starting from the current branch:
  *
- * TODO: add more options (revision ranges, sorting, ...)
+ * <pre>
+ * ObjectId head = repository.resolve(Constants.HEAD);
+ *
+ * Iterable&lt;RevCommit&gt; commits = git.log().add(head).setMaxCount(10).call();
+ * </pre>
+ * <p>
+ *
+ * <p>
+ * Get commits only for a specific file:
+ *
+ * <pre>
+ * git.log().add(head).addPath(&quot;dir/filename.txt&quot;).call();
+ * </pre>
+ * <p>
  *
  * @see <a href="http://www.kernel.org/pub/software/scm/git/docs/git-log.html"
  *      >Git documentation about Log</a>
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/LsRemoteCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/LsRemoteCommand.java
index 3843dc4..55ca58f 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/LsRemoteCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/LsRemoteCommand.java
@@ -61,6 +61,7 @@
 import org.eclipse.jgit.transport.FetchConnection;
 import org.eclipse.jgit.transport.RefSpec;
 import org.eclipse.jgit.transport.Transport;
+import org.eclipse.jgit.transport.URIish;
 
 /**
  * The ls-remote command
@@ -82,6 +83,8 @@ public class LsRemoteCommand extends
 
 	/**
 	 * @param repo
+	 *            local repository or null for operation without local
+	 *            repository
 	 */
 	public LsRemoteCommand(Repository repo) {
 		super(repo);
@@ -155,7 +158,10 @@ public Collection<Ref> call() throws GitAPIException,
 		Transport transport = null;
 		FetchConnection fc = null;
 		try {
-			transport = Transport.open(repo, remote);
+			if (repo != null)
+				transport = Transport.open(repo, remote);
+			else
+				transport = Transport.open(new URIish(remote));
 			transport.setOptionUploadPack(uploadPack);
 			configure(transport);
 			Collection<RefSpec> refSpecs = new ArrayList<RefSpec>(1);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeResult.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeResult.java
index c34ba6b..30edf96 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeResult.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeResult.java
@@ -186,7 +186,7 @@ public boolean isSuccessful() {
 		 **/
 		MERGED_NOT_COMMITTED {
 			public String toString() {
-				return "MergedNotCommited";
+				return "Merged-not-committed";
 			}
 
 			@Override
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 592a012..5a00679 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java
@@ -383,7 +383,7 @@ private void updateHead(String headName, RevCommit newHead, RevCommit onto)
 		if (headName.startsWith(Constants.R_REFS)) {
 			RefUpdate rup = repo.updateRef(headName);
 			rup.setNewObjectId(newHead);
-			rup.setRefLogMessage("rebase finished: " + headName + " onto " //$NON-NLS-1$
+			rup.setRefLogMessage("rebase finished: " + headName + " onto " //$NON-NLS-1$ //$NON-NLS-2$
 					+ onto.getName(), false);
 			Result res = rup.forceUpdate();
 			switch (res) {
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 6827026..3a1c209 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/ResetCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/ResetCommand.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2012, Chris Aniszczyk <caniszczyk@gmail.com>
+ * Copyright (C) 2011-2013, Chris Aniszczyk <caniszczyk@gmail.com>
  * and other copyright owners as documented in the project's IP log.
  *
  * This program and the accompanying materials are made available
@@ -67,6 +67,7 @@
 import org.eclipse.jgit.revwalk.RevWalk;
 import org.eclipse.jgit.treewalk.AbstractTreeIterator;
 import org.eclipse.jgit.treewalk.CanonicalTreeParser;
+import org.eclipse.jgit.treewalk.EmptyTreeIterator;
 import org.eclipse.jgit.treewalk.TreeWalk;
 import org.eclipse.jgit.treewalk.filter.PathFilterGroup;
 
@@ -114,7 +115,9 @@ public enum ResetType {
 		KEEP // TODO not implemented yet
 	}
 
-	private String ref = Constants.HEAD;
+	// We need to be able to distinguish whether the caller set the ref
+	// explicitly or not, so we apply the default (HEAD) only later.
+	private String ref = null;
 
 	private ResetType mode;
 
@@ -139,9 +142,6 @@ public ResetCommand(Repository repo) {
 	public Ref call() throws GitAPIException, CheckoutConflictException {
 		checkCallable();
 
-		Ref r;
-		RevCommit commit;
-
 		try {
 			RepositoryState state = repo.getRepositoryState();
 			final boolean merging = state.equals(RepositoryState.MERGING)
@@ -152,61 +152,55 @@ public Ref call() throws GitAPIException, CheckoutConflictException {
 			final boolean reverting = state.equals(RepositoryState.REVERTING)
 					|| state.equals(RepositoryState.REVERTING_RESOLVED);
 
-			// resolve the ref to a commit
-			final ObjectId commitId;
-			try {
-				commitId = repo.resolve(ref + "^{commit}"); //$NON-NLS-1$
-				if (commitId == null) {
-					// @TODO throw an InvalidRefNameException. We can't do that
-					// now because this would break the API
-					throw new JGitInternalException("Invalid ref " + ref
-							+ " specified");
-				}
-			} catch (IOException e) {
-				throw new JGitInternalException(
-						MessageFormat.format(JGitText.get().cannotRead, ref),
-						e);
+			final ObjectId commitId = resolveRefToCommitId();
+			// When ref is explicitly specified, it has to resolve
+			if (ref != null && commitId == null) {
+				// @TODO throw an InvalidRefNameException. We can't do that
+				// now because this would break the API
+				throw new JGitInternalException("Invalid ref " + ref
+						+ " specified");
 			}
-			RevWalk rw = new RevWalk(repo);
-			try {
-				commit = rw.parseCommit(commitId);
-			} catch (IOException e) {
-				throw new JGitInternalException(
-						MessageFormat.format(
-						JGitText.get().cannotReadCommit, commitId.toString()),
-						e);
-			} finally {
-				rw.release();
-			}
+
+			final ObjectId commitTree;
+			if (commitId != null)
+				commitTree = parseCommit(commitId).getTree();
+			else
+				commitTree = null;
 
 			if (!filepaths.isEmpty()) {
 				// reset [commit] -- paths
-				resetIndexForPaths(commit);
+				resetIndexForPaths(commitTree);
 				setCallable(false);
 				return repo.getRef(Constants.HEAD);
 			}
 
-			// write the ref
-			final RefUpdate ru = repo.updateRef(Constants.HEAD);
-			ru.setNewObjectId(commitId);
+			final Ref result;
+			if (commitId != null) {
+				// write the ref
+				final RefUpdate ru = repo.updateRef(Constants.HEAD);
+				ru.setNewObjectId(commitId);
 
-			String refName = Repository.shortenRefName(ref);
-			String message = refName + ": updating " + Constants.HEAD; //$NON-NLS-1$
-			ru.setRefLogMessage(message, false);
-			if (ru.forceUpdate() == RefUpdate.Result.LOCK_FAILURE)
-				throw new JGitInternalException(MessageFormat.format(
-						JGitText.get().cannotLock, ru.getName()));
+				String refName = Repository.shortenRefName(getRefOrHEAD());
+				String message = refName + ": updating " + Constants.HEAD; //$NON-NLS-1$
+				ru.setRefLogMessage(message, false);
+				if (ru.forceUpdate() == RefUpdate.Result.LOCK_FAILURE)
+					throw new JGitInternalException(MessageFormat.format(
+							JGitText.get().cannotLock, ru.getName()));
 
-			ObjectId origHead = ru.getOldObjectId();
-			if (origHead != null)
-				repo.writeOrigHead(origHead);
+				ObjectId origHead = ru.getOldObjectId();
+				if (origHead != null)
+					repo.writeOrigHead(origHead);
+				result = ru.getRef();
+			} else {
+				result = repo.getRef(Constants.HEAD);
+			}
 
 			switch (mode) {
 				case HARD:
-					checkoutIndex(commit);
+					checkoutIndex(commitTree);
 					break;
 				case MIXED:
-					resetIndex(commit);
+					resetIndex(commitTree);
 					break;
 				case SOFT: // do nothing, only the ref was changed
 					break;
@@ -228,19 +222,41 @@ else if (repo.readSquashCommitMsg() != null)
 			}
 
 			setCallable(false);
-			r = ru.getRef();
+			return result;
 		} catch (IOException e) {
 			throw new JGitInternalException(
 					JGitText.get().exceptionCaughtDuringExecutionOfResetCommand,
 					e);
 		}
+	}
 
-		return r;
+	private RevCommit parseCommit(final ObjectId commitId) {
+		RevCommit commit;
+		RevWalk rw = new RevWalk(repo);
+		try {
+			commit = rw.parseCommit(commitId);
+		} catch (IOException e) {
+			throw new JGitInternalException(MessageFormat.format(
+					JGitText.get().cannotReadCommit, commitId.toString()), e);
+		} finally {
+			rw.release();
+		}
+		return commit;
+	}
+
+	private ObjectId resolveRefToCommitId() {
+		try {
+			return repo.resolve(getRefOrHEAD() + "^{commit}"); //$NON-NLS-1$
+		} catch (IOException e) {
+			throw new JGitInternalException(
+					MessageFormat.format(JGitText.get().cannotRead, getRefOrHEAD()),
+					e);
+		}
 	}
 
 	/**
 	 * @param ref
-	 *            the ref to reset to
+	 *            the ref to reset to, defaults to HEAD if not specified
 	 * @return this instance
 	 */
 	public ResetCommand setRef(String ref) {
@@ -276,7 +292,14 @@ public ResetCommand addPath(String file) {
 		return this;
 	}
 
-	private void resetIndexForPaths(RevCommit commit) {
+	private String getRefOrHEAD() {
+		if (ref != null)
+			return ref;
+		else
+			return Constants.HEAD;
+	}
+
+	private void resetIndexForPaths(ObjectId commitTree) {
 		DirCache dc = null;
 		try {
 			dc = repo.lockDirCache();
@@ -284,7 +307,10 @@ private void resetIndexForPaths(RevCommit commit) {
 
 			final TreeWalk tw = new TreeWalk(repo);
 			tw.addTree(new DirCacheBuildIterator(builder));
-			tw.addTree(commit.getTree());
+			if (commitTree != null)
+				tw.addTree(commitTree);
+			else
+				tw.addTree(new EmptyTreeIterator());
 			tw.setFilter(PathFilterGroup.createFromStrings(filepaths));
 			tw.setRecursive(true);
 
@@ -310,14 +336,17 @@ private void resetIndexForPaths(RevCommit commit) {
 		}
 	}
 
-	private void resetIndex(RevCommit commit) throws IOException {
+	private void resetIndex(ObjectId commitTree) throws IOException {
 		DirCache dc = repo.lockDirCache();
 		TreeWalk walk = null;
 		try {
 			DirCacheBuilder builder = dc.builder();
 
 			walk = new TreeWalk(repo);
-			walk.addTree(commit.getTree());
+			if (commitTree != null)
+				walk.addTree(commitTree);
+			else
+				walk.addTree(new EmptyTreeIterator());
 			walk.addTree(new DirCacheIterator(dc));
 			walk.setRecursive(true);
 
@@ -352,12 +381,12 @@ private void resetIndex(RevCommit commit) throws IOException {
 		}
 	}
 
-	private void checkoutIndex(RevCommit commit) throws IOException,
+	private void checkoutIndex(ObjectId commitTree) throws IOException,
 			GitAPIException {
 		DirCache dc = repo.lockDirCache();
 		try {
 			DirCacheCheckout checkout = new DirCacheCheckout(repo, dc,
-					commit.getTree());
+					commitTree);
 			checkout.setFailOnConflict(false);
 			try {
 				checkout.checkout();
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/RevertCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/RevertCommand.java
index c392209..2bc9d22 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/RevertCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/RevertCommand.java
@@ -169,7 +169,7 @@ public RevCommit call() throws NoMessageException, UnmergedPathsException,
 
 				String shortMessage = "Revert \"" + srcCommit.getShortMessage() //$NON-NLS-1$
 						+ "\""; //$NON-NLS-1$
-				String newMessage = shortMessage + "\n\n"
+				String newMessage = shortMessage + "\n\n" //$NON-NLS-1$
 						+ "This reverts commit " + srcCommit.getId().getName() //$NON-NLS-1$
 						+ ".\n"; //$NON-NLS-1$
 				if (merger.merge(headCommit, srcParent)) {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/StashApplyCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/StashApplyCommand.java
index b1fde1d..020a6dc 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/StashApplyCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/StashApplyCommand.java
@@ -163,7 +163,7 @@ public ObjectId call() throws GitAPIException,
 						JGitText.get().stashCommitMissingTwoParents,
 						stashId.name()));
 
-			ObjectId headTree = repo.resolve(Constants.HEAD + "^{tree}");
+			ObjectId headTree = repo.resolve(Constants.HEAD + "^{tree}"); //$NON-NLS-1$
 			ObjectId stashIndexCommit = revWalk.parseCommit(stashCommit
 					.getParent(1));
 			ObjectId stashHeadCommit = stashCommit.getParent(0);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/StatusCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/StatusCommand.java
index b3e112f..eaf5483 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/StatusCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/StatusCommand.java
@@ -43,15 +43,19 @@
 package org.eclipse.jgit.api;
 
 import java.io.IOException;
+import java.util.LinkedList;
+import java.util.List;
 
 import org.eclipse.jgit.api.errors.GitAPIException;
 import org.eclipse.jgit.api.errors.JGitInternalException;
 import org.eclipse.jgit.errors.NoWorkTreeException;
 import org.eclipse.jgit.lib.Constants;
 import org.eclipse.jgit.lib.IndexDiff;
+import org.eclipse.jgit.lib.ProgressMonitor;
 import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.treewalk.FileTreeIterator;
 import org.eclipse.jgit.treewalk.WorkingTreeIterator;
+import org.eclipse.jgit.treewalk.filter.PathFilterGroup;
 
 /**
  * A class used to execute a {@code Status} command. It has setters for all
@@ -65,6 +69,8 @@
  */
 public class StatusCommand extends GitCommand<Status> {
 	private WorkingTreeIterator workingTreeIt;
+	private List<String> paths = null;
+	private ProgressMonitor progressMonitor = null;
 
 	/**
 	 * @param repo
@@ -74,6 +80,38 @@ protected StatusCommand(Repository repo) {
 	}
 
 	/**
+	 * Show only the status of files which match the given paths. The path must
+	 * either name a file or a directory exactly. All paths are always relative
+	 * to the repository root. If a directory is specified all files recursively
+	 * underneath that directory are matched. If this method is called multiple
+	 * times then the status of those files is reported which match at least one
+	 * of the given paths. Note that regex expressions or wildcards are not
+	 * supported.
+	 *
+	 * @param path
+	 *            a path is relative to the top level of the repository
+	 * @return {@code this}
+	 * @since 3.1
+	 */
+	public StatusCommand addPath(String path) {
+		if (paths == null)
+			paths = new LinkedList<String>();
+		paths.add(path);
+		return this;
+	}
+
+	/**
+	 * Returns the paths filtering this status.
+	 *
+	 * @return the paths for which the status is shown or <code>null</code> if
+	 *         the complete status for the whole repo is shown.
+	 * @since 3.1
+	 */
+	public List<String> getPaths() {
+		return paths;
+	}
+
+	/**
 	 * Executes the {@code Status} command with all the options and parameters
 	 * collected by the setter methods of this class. Each instance of this
 	 * class should only be used for one invocation of the command. Don't call
@@ -88,7 +126,13 @@ public Status call() throws GitAPIException, NoWorkTreeException {
 
 		try {
 			IndexDiff diff = new IndexDiff(repo, Constants.HEAD, workingTreeIt);
-			diff.diff();
+			if (paths != null)
+				diff.setFilter(PathFilterGroup.createFromStrings(paths));
+			if (progressMonitor == null)
+				diff.diff();
+			else
+				diff.diff(progressMonitor, ProgressMonitor.UNKNOWN,
+						ProgressMonitor.UNKNOWN, ""); //$NON-NLS-1$
 			return new Status(diff);
 		} catch (IOException e) {
 			throw new JGitInternalException(e.getMessage(), e);
@@ -107,4 +151,17 @@ public StatusCommand setWorkingTreeIt(WorkingTreeIterator workingTreeIt) {
 		this.workingTreeIt = workingTreeIt;
 		return this;
 	}
+
+	/**
+	 * To set the {@link ProgressMonitor} which contains callback methods to
+	 * inform you about the progress of this command.
+	 *
+	 * @param progressMonitor
+	 * @return {@code this}
+	 * @since 3.1
+	 */
+	public StatusCommand setProgressMonitor(ProgressMonitor progressMonitor) {
+		this.progressMonitor = progressMonitor;
+		return this;
+	}
 }
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/errors/GitAPIException.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/errors/GitAPIException.java
index ba38529..b251c7d 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/errors/GitAPIException.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/errors/GitAPIException.java
@@ -45,11 +45,28 @@
 public abstract class GitAPIException extends Exception {
 	private static final long serialVersionUID = 1L;
 
-	GitAPIException(String message, Throwable cause) {
+	/**
+	 * Constructs a new exception with the specified detail message and cause.
+	 *
+	 * @param message
+	 *            detail message
+	 * @param cause
+	 *            cause
+	 * @since 3.1
+	 */
+	protected GitAPIException(String message, Throwable cause) {
 		super(message, cause);
 	}
 
-	GitAPIException(String message) {
+	/**
+	 * Constructs a new exception with the specified detail message and no
+	 * cause.
+	 *
+	 * @param message
+	 *            detail message
+	 * @since 3.1
+	 */
+	protected GitAPIException(String message) {
 		super(message);
 	}
 }
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 5458426..dd9ee10 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java
@@ -280,7 +280,7 @@ public void prescanOneTree()
 		builder = dc.builder();
 
 		walk = new NameConflictTreeWalk(repo);
-		walk.addTree(mergeCommitTree);
+		addTree(walk, mergeCommitTree);
 		walk.addTree(new DirCacheBuildIterator(builder));
 		walk.addTree(workingTree);
 
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/fnmatch/FileNameMatcher.java b/org.eclipse.jgit/src/org/eclipse/jgit/fnmatch/FileNameMatcher.java
index 22840fb..02e4235 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/fnmatch/FileNameMatcher.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/fnmatch/FileNameMatcher.java
@@ -60,9 +60,9 @@
  * <p>
  * Supported are the wildcard characters * and ? and groups with:
  * <ul>
- * <li> characters e.g. [abc]</li>
- * <li> ranges e.g. [a-z]</li>
- * <li> the following character classes
+ * <li>characters e.g. [abc]</li>
+ * <li>ranges e.g. [a-z]</li>
+ * <li>the following character classes
  * <ul>
  * <li>[:alnum:]</li>
  * <li>[:alpha:]</li>
@@ -78,9 +78,10 @@
  * <li>[:word:]</li>
  * <li>[:xdigit:]</li>
  * </ul>
- * e. g. [[:xdigit:]] </li>
+ * e. g. [[:xdigit:]]</li>
  * </ul>
  * </p>
+ * Any character can be escaped by prepending it with a \
  */
 public class FileNameMatcher {
 	static final List<Head> EMPTY_HEAD_LIST = Collections.emptyList();
@@ -199,7 +200,7 @@ private static int findGroupEnd(final int indexOfStartBracket,
 		int groupEnd = -1;
 		while (groupEnd == -1) {
 
-			final int possibleGroupEnd = pattern.indexOf(']',
+			final int possibleGroupEnd = indexOfUnescaped(pattern, ']',
 					firstValidEndBracketIndex);
 			if (possibleGroupEnd == -1)
 				throw new NoClosingBracketException(indexOfStartBracket, "[", //$NON-NLS-1$
@@ -238,7 +239,7 @@ private static List<AbstractHead> parseHeads(final String pattern,
 		int currentIndex = 0;
 		List<AbstractHead> heads = new ArrayList<AbstractHead>();
 		while (currentIndex < pattern.length()) {
-			final int groupStart = pattern.indexOf('[', currentIndex);
+			final int groupStart = indexOfUnescaped(pattern, '[', currentIndex);
 			if (groupStart == -1) {
 				final String patternPart = pattern.substring(currentIndex);
 				heads.addAll(createSimpleHeads(patternPart,
@@ -264,24 +265,35 @@ private static List<AbstractHead> createSimpleHeads(
 			final String patternPart, final Character invalidWildgetCharacter) {
 		final List<AbstractHead> heads = new ArrayList<AbstractHead>(
 				patternPart.length());
+
+		boolean escaped = false;
 		for (int i = 0; i < patternPart.length(); i++) {
 			final char c = patternPart.charAt(i);
-			switch (c) {
-			case '*': {
-				final AbstractHead head = createWildCardHead(
-						invalidWildgetCharacter, true);
-				heads.add(head);
-				break;
-			}
-			case '?': {
-				final AbstractHead head = createWildCardHead(
-						invalidWildgetCharacter, false);
-				heads.add(head);
-				break;
-			}
-			default:
+			if (escaped) {
 				final CharacterHead head = new CharacterHead(c);
 				heads.add(head);
+				escaped = false;
+			} else {
+				switch (c) {
+				case '*': {
+					final AbstractHead head = createWildCardHead(
+							invalidWildgetCharacter, true);
+					heads.add(head);
+					break;
+				}
+				case '?': {
+					final AbstractHead head = createWildCardHead(
+							invalidWildgetCharacter, false);
+					heads.add(head);
+					break;
+				}
+				case '\\':
+					escaped = true;
+					break;
+				default:
+					final CharacterHead head = new CharacterHead(c);
+					heads.add(head);
+				}
 			}
 		}
 		return heads;
@@ -317,6 +329,18 @@ private void extendStringToMatchByOneCharacter(final char c) {
 		heads = newHeads;
 	}
 
+	private static int indexOfUnescaped(final String searchString,
+			final char ch, final int fromIndex) {
+		for (int i = fromIndex; i < searchString.length(); i++) {
+			char current = searchString.charAt(i);
+			if (current == ch)
+				return i;
+			if (current == '\\')
+				i++; // Skip the next char as it is escaped }
+		}
+		return -1;
+	}
+
 	/**
 	 *
 	 * @param stringToMatch
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/ignore/IgnoreNode.java b/org.eclipse.jgit/src/org/eclipse/jgit/ignore/IgnoreNode.java
index fb65e0c..2cddddb 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/ignore/IgnoreNode.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/ignore/IgnoreNode.java
@@ -102,7 +102,7 @@ public void parse(InputStream in) throws IOException {
 		String txt;
 		while ((txt = br.readLine()) != null) {
 			txt = txt.trim();
-			if (txt.length() > 0 && !txt.startsWith("#")) //$NON-NLS-1$
+			if (txt.length() > 0 && !txt.startsWith("#") && !txt.equals("/")) //$NON-NLS-1$ //$NON-NLS-2$
 				rules.add(new IgnoreRule(txt));
 		}
 	}
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 d75ed4e..8ac971a 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
@@ -73,6 +73,8 @@ public static JGitText get() {
 	/***/ public String anExceptionOccurredWhileTryingToAddTheIdOfHEAD;
 	/***/ public String anSSHSessionHasBeenAlreadyCreated;
 	/***/ public String applyingCommit;
+	/***/ public String archiveFormatAlreadyAbsent;
+	/***/ public String archiveFormatAlreadyRegistered;
 	/***/ public String atLeastOnePathIsRequired;
 	/***/ public String atLeastOnePatternIsRequired;
 	/***/ public String atLeastTwoFiltersNeeded;
@@ -244,6 +246,7 @@ public static JGitText get() {
 	/***/ public String errorReadingInfoRefs;
 	/***/ public String errorSymlinksNotSupported;
 	/***/ public String exceptionCaughtDuringExecutionOfAddCommand;
+	/***/ public String exceptionCaughtDuringExecutionOfArchiveCommand;
 	/***/ public String exceptionCaughtDuringExecutionOfCherryPickCommand;
 	/***/ public String exceptionCaughtDuringExecutionOfCommitCommand;
 	/***/ public String exceptionCaughtDuringExecutionOfFetchCommand;
@@ -587,6 +590,7 @@ public static JGitText get() {
 	/***/ public String unpackException;
 	/***/ public String unreadablePackIndex;
 	/***/ public String unrecognizedRef;
+	/***/ public String unsupportedArchiveFormat;
 	/***/ public String unsupportedCommand0;
 	/***/ public String unsupportedEncryptionAlgorithm;
 	/***/ public String unsupportedEncryptionVersion;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlock.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlock.java
index 1e447b3..7289b9e 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlock.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlock.java
@@ -55,17 +55,6 @@
 
 /** A cached slice of a {@link DfsPackFile}. */
 final class DfsBlock {
-	/**
-	 * Size in bytes to pass to {@link Inflater} at a time.
-	 * <p>
-	 * Blocks can be large (for example 1 MiB), while compressed objects inside
-	 * of them are very small (for example less than 100 bytes for a delta). JNI
-	 * forces the data supplied to the Inflater to be copied during setInput(),
-	 * so use a smaller stride to reduce the risk that too much unnecessary was
-	 * moved into the native layer.
-	 */
-	private static final int INFLATE_STRIDE = 512;
-
 	final DfsPackKey pack;
 
 	final long start;
@@ -105,29 +94,9 @@ int copy(int p, byte[] b, int o, int n) {
 		return n;
 	}
 
-	int inflate(Inflater inf, long pos, byte[] dstbuf, int dstoff)
-			throws DataFormatException {
+	void setInput(Inflater inf, long pos) {
 		int ptr = (int) (pos - start);
-		int in = Math.min(INFLATE_STRIDE, block.length - ptr);
-		if (dstoff < dstbuf.length)
-			in = Math.min(in, dstbuf.length - dstoff);
-		inf.setInput(block, ptr, in);
-
-		for (;;) {
-			int out = inf.inflate(dstbuf, dstoff, dstbuf.length - dstoff);
-			if (out == 0) {
-				if (inf.needsInput()) {
-					ptr += in;
-					in = Math.min(INFLATE_STRIDE, block.length - ptr);
-					if (in == 0)
-						return dstoff;
-					inf.setInput(block, ptr, in);
-					continue;
-				}
-				return dstoff;
-			}
-			dstoff += out;
-		}
+		inf.setInput(block, ptr, block.length - ptr);
 	}
 
 	void crc32(CRC32 out, long pos, int cnt) {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsOutputStream.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsOutputStream.java
index ef3173e..acd92d7 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsOutputStream.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsOutputStream.java
@@ -44,6 +44,7 @@
 package org.eclipse.jgit.internal.storage.dfs;
 
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.OutputStream;
 import java.nio.ByteBuffer;
 
@@ -96,4 +97,62 @@ public void write(int b) throws IOException {
 	 *             to DFS errors.
 	 */
 	public abstract int read(long position, ByteBuffer buf) throws IOException;
+
+	/**
+	 * Open a stream to read back a portion of already written data.
+	 * <p>
+	 * The writing position of the output stream is not affected by a read. The
+	 * input stream can be read up to the current writing position. Closing the
+	 * returned stream has no effect on the underlying {@link DfsOutputStream}.
+	 *
+	 * @param position
+	 *            offset to read from.
+	 * @return new input stream
+	 */
+	public InputStream openInputStream(final long position) {
+		return new ReadBackStream(position);
+	}
+
+	private class ReadBackStream extends InputStream {
+		private final ByteBuffer buf;
+		private long position;
+
+		private ReadBackStream(long position) {
+			int bs = blockSize();
+			this.position = position;
+			buf = ByteBuffer.allocate(bs > 0 ? bs : 8192);
+			buf.position(buf.limit());
+		}
+
+		@Override
+		public int read(byte[] b, int off, int len) throws IOException {
+			int cnt = 0;
+			while (0 < len) {
+				if (!buf.hasRemaining()) {
+					buf.rewind();
+					int nr = DfsOutputStream.this.read(position, buf);
+					if (nr < 0) {
+						buf.position(buf.limit());
+						break;
+					}
+					position += nr;
+					buf.flip();
+				}
+				int n = Math.min(len, buf.remaining());
+				buf.get(b, off, n);
+				off += n;
+				len -= n;
+				cnt += n;
+			}
+			if (cnt == 0 && len > 0) return -1;
+			return cnt;
+		}
+
+		@Override
+		public int read() throws IOException {
+			byte[] b = new byte[1];
+			int n = read(b);
+			return n == 1 ? b[0] & 0xff : -1;
+		}
+	}
 }
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackCompactor.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackCompactor.java
index ea56392..8372884 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackCompactor.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackCompactor.java
@@ -220,8 +220,14 @@ public void compact(ProgressMonitor pm) throws IOException {
 				pw.setReuseDeltaCommits(false);
 
 				addObjectsToPack(pw, ctx, pm);
-				if (pw.getObjectCount() == 0)
+				if (pw.getObjectCount() == 0) {
+					List<DfsPackDescription> remove = toPrune();
+					if (remove.size() > 0)
+						objdb.commitPack(
+								Collections.<DfsPackDescription>emptyList(),
+								remove);
 					return;
+				}
 
 				boolean rollback = true;
 				DfsPackDescription pack = objdb.newPack(COMPACT);
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 26fc035..d7b2228 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
@@ -616,19 +616,24 @@ int inflate(DfsPackFile pack, long position, byte[] dstbuf,
 			boolean headerOnly) throws IOException, DataFormatException {
 		prepareInflater();
 		pin(pack, position);
+		block.setInput(inf, position);
 		int dstoff = 0;
 		for (;;) {
-			dstoff = block.inflate(inf, position, dstbuf, dstoff);
-
-			if (headerOnly && dstoff == dstbuf.length)
-				return dstoff;
-			if (inf.needsInput()) {
-				position += block.remaining(position);
-				pin(pack, position);
-			} else if (inf.finished())
-				return dstoff;
-			else
+			int n = inf.inflate(dstbuf, dstoff, dstbuf.length - dstoff);
+			if (n == 0) {
+				if (headerOnly && dstoff == dstbuf.length)
+					return dstoff;
+				if (inf.needsInput()) {
+					position += block.remaining(position);
+					pin(pack, position);
+					block.setInput(inf, position);
+					continue;
+				}
+				if (inf.finished())
+					return dstoff;
 				throw new DataFormatException();
+			}
+			dstoff += n;
 		}
 	}
 
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/Gc.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/InMemoryOutputStream.java
similarity index 69%
copy from org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/Gc.java
copy to org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/InMemoryOutputStream.java
index 615d50f..9a5f6a6 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/Gc.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/InMemoryOutputStream.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012, Christian Halstrick <christian.halstrick@sap.com>
+ * Copyright (C) 2013, Google Inc.
  * and other copyright owners as documented in the project's IP log.
  *
  * This program and the accompanying materials are made available
@@ -41,18 +41,45 @@
  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-package org.eclipse.jgit.pgm.debug;
+package org.eclipse.jgit.internal.storage.dfs;
 
-import org.eclipse.jgit.internal.storage.file.FileRepository;
-import org.eclipse.jgit.internal.storage.file.GC;
-import org.eclipse.jgit.lib.TextProgressMonitor;
-import org.eclipse.jgit.pgm.TextBuiltin;
+import java.io.ByteArrayOutputStream;
+import java.nio.ByteBuffer;
 
-class Gc extends TextBuiltin {
+class InMemoryOutputStream extends DfsOutputStream {
+	private final ByteArrayOutputStream dst = new ByteArrayOutputStream();
+
+	private byte[] data;
+
 	@Override
-	protected void run() throws Exception {
-		GC gc = new GC((FileRepository) db);
-		gc.setProgressMonitor(new TextProgressMonitor());
-		gc.gc();
+	public void write(byte[] buf, int off, int len) {
+		data = null;
+		dst.write(buf, off, len);
+	}
+
+	@Override
+	public int read(long position, ByteBuffer buf) {
+		byte[] d = getData();
+		int n = Math.min(buf.remaining(), d.length - (int) position);
+		if (n <= 0)
+			return -1;
+		buf.put(d, (int) position, n);
+		return n;
+	}
+
+	byte[] getData() {
+		if (data == null)
+			data = dst.toByteArray();
+		return data;
+	}
+
+	@Override
+	public void flush() {
+		// Default implementation does nothing;
+	}
+
+	@Override
+	public void close() {
+		flush();
 	}
 }
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 56efdd6..fe4625b 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
@@ -1,6 +1,5 @@
 package org.eclipse.jgit.internal.storage.dfs;
 
-import java.io.ByteArrayOutputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.nio.ByteBuffer;
@@ -117,7 +116,7 @@ protected ReadableChannel openFile(DfsPackDescription desc, PackExt ext)
 		protected DfsOutputStream writeFile(
 				DfsPackDescription desc, final PackExt ext) throws IOException {
 			final MemPack memPack = (MemPack) desc;
-			return new Out() {
+			return new InMemoryOutputStream() {
 				@Override
 				public void flush() {
 					memPack.fileMap.put(ext, getData());
@@ -135,43 +134,6 @@ private static class MemPack extends DfsPackDescription {
 		}
 	}
 
-	private abstract static class Out extends DfsOutputStream {
-		private final ByteArrayOutputStream dst = new ByteArrayOutputStream();
-
-		private byte[] data;
-
-		@Override
-		public void write(byte[] buf, int off, int len) {
-			data = null;
-			dst.write(buf, off, len);
-		}
-
-		@Override
-		public int read(long position, ByteBuffer buf) {
-			byte[] d = getData();
-			int n = Math.min(buf.remaining(), d.length - (int) position);
-			if (n == 0)
-				return -1;
-			buf.put(d, (int) position, n);
-			return n;
-		}
-
-		byte[] getData() {
-			if (data == null)
-				data = dst.toByteArray();
-			return data;
-		}
-
-		@Override
-		public abstract void flush();
-
-		@Override
-		public void close() {
-			flush();
-		}
-
-	}
-
 	private static class ByteArrayReadableChannel implements ReadableChannel {
 		private final byte[] data;
 
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackIndex.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackIndex.java
index 44baeb1..0040aea 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackIndex.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackIndex.java
@@ -245,6 +245,19 @@ public final ObjectId getObjectId(final int nthPosition) {
 	}
 
 	/**
+	 * Get offset in a pack for the n-th object entry returned by
+	 * {@link #iterator()}.
+	 *
+	 * @param nthPosition
+	 *            unsigned 32 bit position within the traversal of
+	 *            {@link #iterator()} for which the caller needs the offset. The
+	 *            first returned {@link MutableEntry} is 0, the second is 1,
+	 *            etc. Positions past 2**31-1 are negative, but still valid.
+	 * @return the offset in a pack for the corresponding entry.
+	 */
+	abstract long getOffset(long nthPosition);
+
+	/**
 	 * Locate the file offset position for the requested object.
 	 *
 	 * @param objId
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackIndexV1.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackIndexV1.java
index 8c381fb..2d574d8 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackIndexV1.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackIndexV1.java
@@ -113,15 +113,13 @@ public long getOffset64Count() {
 		return n64;
 	}
 
-	@Override
-	public ObjectId getObjectId(final long nthPosition) {
+	private int findLevelOne(final long nthPosition) {
 		int levelOne = Arrays.binarySearch(idxHeader, nthPosition + 1);
-		long base;
 		if (levelOne >= 0) {
 			// If we hit the bucket exactly the item is in the bucket, or
 			// any bucket before it which has the same object count.
 			//
-			base = idxHeader[levelOne];
+			long base = idxHeader[levelOne];
 			while (levelOne > 0 && base == idxHeader[levelOne - 1])
 				levelOne--;
 		} else {
@@ -129,14 +127,31 @@ public ObjectId getObjectId(final long nthPosition) {
 			//
 			levelOne = -(levelOne + 1);
 		}
+		return levelOne;
+	}
 
-		base = levelOne > 0 ? idxHeader[levelOne - 1] : 0;
-		final int p = (int) (nthPosition - base);
+	private int getLevelTwo(final long nthPosition, final int levelOne) {
+		final long base = levelOne > 0 ? idxHeader[levelOne - 1] : 0;
+		return (int) (nthPosition - base);
+	}
+
+	@Override
+	public ObjectId getObjectId(final long nthPosition) {
+		final int levelOne = findLevelOne(nthPosition);
+		final int p = getLevelTwo(nthPosition, levelOne);
 		final int dataIdx = idOffset(p);
 		return ObjectId.fromRaw(idxdata[levelOne], dataIdx);
 	}
 
 	@Override
+	long getOffset(long nthPosition) {
+		final int levelOne = findLevelOne(nthPosition);
+		final int levelTwo = getLevelTwo(nthPosition, levelOne);
+		final int p = (4 + Constants.OBJECT_ID_LENGTH) * levelTwo;
+		return NB.decodeUInt32(idxdata[levelOne], p);
+	}
+
+	@Override
 	public long findOffset(final AnyObjectId objId) {
 		final int levelOne = objId.getFirstByte();
 		byte[] data = idxdata[levelOne];
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackIndexV2.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackIndexV2.java
index 9b1a5f3..9d2caa2 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackIndexV2.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackIndexV2.java
@@ -170,15 +170,13 @@ public long getOffset64Count() {
 		return offset64.length / 8;
 	}
 
-	@Override
-	public ObjectId getObjectId(final long nthPosition) {
+	private int findLevelOne(final long nthPosition) {
 		int levelOne = Arrays.binarySearch(fanoutTable, nthPosition + 1);
-		long base;
 		if (levelOne >= 0) {
 			// If we hit the bucket exactly the item is in the bucket, or
 			// any bucket before it which has the same object count.
 			//
-			base = fanoutTable[levelOne];
+			long base = fanoutTable[levelOne];
 			while (levelOne > 0 && base == fanoutTable[levelOne - 1])
 				levelOne--;
 		} else {
@@ -186,19 +184,39 @@ public ObjectId getObjectId(final long nthPosition) {
 			//
 			levelOne = -(levelOne + 1);
 		}
+		return levelOne;
+	}
 
-		base = levelOne > 0 ? fanoutTable[levelOne - 1] : 0;
-		final int p = (int) (nthPosition - base);
+	private int getLevelTwo(final long nthPosition, final int levelOne) {
+		final long base = levelOne > 0 ? fanoutTable[levelOne - 1] : 0;
+		return (int) (nthPosition - base);
+	}
+
+	@Override
+	public ObjectId getObjectId(final long nthPosition) {
+		final int levelOne = findLevelOne(nthPosition);
+		final int p = getLevelTwo(nthPosition, levelOne);
 		final int p4 = p << 2;
 		return ObjectId.fromRaw(names[levelOne], p4 + p); // p * 5
 	}
 
 	@Override
+	public long getOffset(final long nthPosition) {
+		final int levelOne = findLevelOne(nthPosition);
+		final int levelTwo = getLevelTwo(nthPosition, levelOne);
+		return getOffset(levelOne, levelTwo);
+	}
+
+	@Override
 	public long findOffset(final AnyObjectId objId) {
 		final int levelOne = objId.getFirstByte();
 		final int levelTwo = binarySearchLevelTwo(objId, levelOne);
 		if (levelTwo == -1)
 			return -1;
+		return getOffset(levelOne, levelTwo);
+	}
+
+	private long getOffset(final int levelOne, final int levelTwo) {
 		final long p = NB.decodeUInt32(offset32[levelOne], levelTwo << 2);
 		if ((p & IS_O64) != 0)
 			return NB.decodeUInt64(offset64, (8 * (int) (p & ~IS_O64)));
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackReverseIndex.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackReverseIndex.java
index c5aa5d3..fe9f700 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackReverseIndex.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackReverseIndex.java
@@ -44,7 +44,6 @@
 package org.eclipse.jgit.internal.storage.file;
 
 import java.text.MessageFormat;
-import java.util.Arrays;
 
 import org.eclipse.jgit.errors.CorruptObjectException;
 import org.eclipse.jgit.internal.JGitText;
@@ -65,21 +64,22 @@ public class PackReverseIndex {
 	/** Index we were created from, and that has our ObjectId data. */
 	private final PackIndex index;
 
-	/**
-	 * (offset31, truly) Offsets accommodating in 31 bits.
-	 */
-	private final int offsets32[];
+	/** The number of bytes per entry in the offsetIndex. */
+	private final long bucketSize;
 
 	/**
-	 * Offsets not accommodating in 31 bits.
+	 * An index into the nth mapping, where the value is the position after the
+	 * the last index that contains the values of the bucket. For example given
+	 * offset o (and bucket = o / bucketSize), the offset will be contained in
+	 * the range nth[offsetIndex[bucket - 1]] inclusive to
+	 * nth[offsetIndex[bucket]] exclusive.
+	 *
+	 * See {@link #binarySearch}
 	 */
-	private final long offsets64[];
+	private final int[] offsetIndex;
 
-	/** Position of the corresponding {@link #offsets32} in {@link #index}. */
-	private final int nth32[];
-
-	/** Position of the corresponding {@link #offsets64} in {@link #index}. */
-	private final int nth64[];
+	/** Mapping from indices in offset order to indices in SHA-1 order. */
+	private final int[] nth;
 
 	/**
 	 * Create reverse index from straight/forward pack index, by indexing all
@@ -92,38 +92,58 @@ public PackReverseIndex(final PackIndex packIndex) {
 		index = packIndex;
 
 		final long cnt = index.getObjectCount();
-		final long n64 = index.getOffset64Count();
-		final long n32 = cnt - n64;
-		if (n32 > Integer.MAX_VALUE || n64 > Integer.MAX_VALUE
-				|| cnt > 0xffffffffL)
+		if (cnt + 1 > Integer.MAX_VALUE)
 			throw new IllegalArgumentException(
 					JGitText.get().hugeIndexesAreNotSupportedByJgitYet);
 
-		offsets32 = new int[(int) n32];
-		offsets64 = new long[(int) n64];
-		nth32 = new int[offsets32.length];
-		nth64 = new int[offsets64.length];
-
-		int i32 = 0;
-		int i64 = 0;
-		for (final MutableEntry me : index) {
-			final long o = me.getOffset();
-			if (o <= Integer.MAX_VALUE)
-				offsets32[i32++] = (int) o;
-			else
-				offsets64[i64++] = o;
+		if (cnt == 0) {
+			bucketSize = Long.MAX_VALUE;
+			offsetIndex = new int[1];
+			nth = new int[0];
+			return;
 		}
 
-		Arrays.sort(offsets32);
-		Arrays.sort(offsets64);
+		final long[] offsetsBySha1 = new long[(int) cnt];
 
-		int nth = 0;
+		long maxOffset = 0;
+		int ith = 0;
 		for (final MutableEntry me : index) {
 			final long o = me.getOffset();
-			if (o <= Integer.MAX_VALUE)
-				nth32[Arrays.binarySearch(offsets32, (int) o)] = nth++;
-			else
-				nth64[Arrays.binarySearch(offsets64, o)] = nth++;
+			offsetsBySha1[ith++] = o;
+			if (o > maxOffset)
+				maxOffset = o;
+		}
+
+		bucketSize = maxOffset / cnt + 1;
+		int[] bucketIndex = new int[(int) cnt];
+		int[] bucketValues = new int[(int) cnt + 1];
+		for (int oi = 0; oi < offsetsBySha1.length; oi++) {
+			final long o = offsetsBySha1[oi];
+			final int bucket = (int) (o / bucketSize);
+			final int bucketValuesPos = oi + 1;
+			final int current = bucketIndex[bucket];
+			bucketIndex[bucket] = bucketValuesPos;
+			bucketValues[bucketValuesPos] = current;
+		}
+
+		int nthByOffset = 0;
+		nth = new int[offsetsBySha1.length];
+		offsetIndex = bucketIndex; // Reuse the allocation
+		for (int bi = 0; bi < bucketIndex.length; bi++) {
+			final int start = nthByOffset;
+			// Insertion sort of the values in the bucket.
+			for (int vi = bucketIndex[bi]; vi > 0; vi = bucketValues[vi]) {
+				final int nthBySha1 = vi - 1;
+				final long o = offsetsBySha1[nthBySha1];
+				int insertion = nthByOffset++;
+				for (; start < insertion; insertion--) {
+					if (o > offsetsBySha1[nth[insertion - 1]])
+						break;
+					nth[insertion] = nth[insertion - 1];
+				}
+				nth[insertion] = nthBySha1;
+			}
+			offsetIndex[bi] = nthByOffset;
 		}
 	}
 
@@ -136,17 +156,10 @@ public PackReverseIndex(final PackIndex packIndex) {
 	 * @return object id for this offset, or null if no object was found.
 	 */
 	public ObjectId findObject(final long offset) {
-		if (offset <= Integer.MAX_VALUE) {
-			final int i32 = Arrays.binarySearch(offsets32, (int) offset);
-			if (i32 < 0)
-				return null;
-			return index.getObjectId(nth32[i32]);
-		} else {
-			final int i64 = Arrays.binarySearch(offsets64, offset);
-			if (i64 < 0)
-				return null;
-			return index.getObjectId(nth64[i64]);
-		}
+		final int ith = binarySearch(offset);
+		if (ith < 0)
+			return null;
+		return index.getObjectId(nth[ith]);
 	}
 
 	/**
@@ -166,52 +179,40 @@ public ObjectId findObject(final long offset) {
 	 */
 	public long findNextOffset(final long offset, final long maxOffset)
 			throws CorruptObjectException {
-		if (offset <= Integer.MAX_VALUE) {
-			final int i32 = Arrays.binarySearch(offsets32, (int) offset);
-			if (i32 < 0)
-				throw new CorruptObjectException(
-						MessageFormat.format(
-								JGitText.get().cantFindObjectInReversePackIndexForTheSpecifiedOffset,
-								Long.valueOf(offset)));
+		final int ith = binarySearch(offset);
+		if (ith < 0)
+			throw new CorruptObjectException(
+					MessageFormat.format(
+							JGitText.get().cantFindObjectInReversePackIndexForTheSpecifiedOffset,
+							Long.valueOf(offset)));
 
-			if (i32 + 1 == offsets32.length) {
-				if (offsets64.length > 0)
-					return offsets64[0];
-				return maxOffset;
-			}
-			return offsets32[i32 + 1];
-		} else {
-			final int i64 = Arrays.binarySearch(offsets64, offset);
-			if (i64 < 0)
-				throw new CorruptObjectException(
-						MessageFormat.format(
-								JGitText.get().cantFindObjectInReversePackIndexForTheSpecifiedOffset,
-								Long.valueOf(offset)));
-
-			if (i64 + 1 == offsets64.length)
-				return maxOffset;
-			return offsets64[i64 + 1];
-		}
+		if (ith + 1 == nth.length)
+			return maxOffset;
+		return index.getOffset(nth[ith + 1]);
 	}
 
 	int findPostion(long offset) {
-		if (offset <= Integer.MAX_VALUE) {
-			final int i32 = Arrays.binarySearch(offsets32, (int) offset);
-			if (i32 < 0)
-				return -1;
-			return i32;
-		} else {
-			final int i64 = Arrays.binarySearch(offsets64, offset);
-			if (i64 < 0)
-				return -1;
-			return nth32.length + i64;
+		return binarySearch(offset);
+	}
+
+	private int binarySearch(final long offset) {
+		int bucket = (int) (offset / bucketSize);
+		int low = bucket == 0 ? 0 : offsetIndex[bucket - 1];
+		int high = offsetIndex[bucket];
+		while (low < high) {
+			final int mid = (low + high) >>> 1;
+			final long o = index.getOffset(nth[mid]);
+			if (offset < o)
+				high = mid;
+			else if (offset == o)
+				return mid;
+			else
+				low = mid + 1;
 		}
+		return -1;
 	}
 
 	ObjectId findObjectByPosition(int nthPosition) {
-		if (nthPosition < nth32.length)
-			return index.getObjectId(nth32[nthPosition]);
-		final int i64 = nthPosition - nth32.length;
-		return index.getObjectId(nth64[i64]);
+		return index.getObjectId(nth[nthPosition]);
 	}
 }
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevFlag.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevFlag.java
index 8068ba6e..0998a3a 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevFlag.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevFlag.java
@@ -76,7 +76,7 @@ public class RevFlag {
 	 *
 	 * @since 3.0
 	 */
-	public static final RevFlag SEEN = new StaticRevFlag("SEEN", RevWalk.SEEN);
+	public static final RevFlag SEEN = new StaticRevFlag("SEEN", RevWalk.SEEN); //$NON-NLS-1$
 
 	final RevWalk walker;
 
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 c82a0cd..f49028e 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackFetchConnection.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackFetchConnection.java
@@ -63,6 +63,7 @@
 import org.eclipse.jgit.lib.Config.SectionParser;
 import org.eclipse.jgit.lib.Constants;
 import org.eclipse.jgit.lib.MutableObjectId;
+import org.eclipse.jgit.lib.NullProgressMonitor;
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.ObjectInserter;
 import org.eclipse.jgit.lib.ProgressMonitor;
@@ -181,6 +182,13 @@ public abstract class BasePackFetchConnection extends BasePackConnection
 	 */
 	public static final String OPTION_NO_DONE = "no-done"; //$NON-NLS-1$
 
+	/**
+	 * The client supports fetching objects at the tip of any ref, even if not
+	 * advertised.
+	 * @since 3.1
+	 */
+	public static final String OPTION_ALLOW_TIP_SHA1_IN_WANT = "allow-tip-sha1-in-want"; //$NON-NLS-1$
+
 	static enum MultiAck {
 		OFF, CONTINUE, DETAILED;
 	}
@@ -214,6 +222,8 @@ static enum MultiAck {
 
 	private boolean noDone;
 
+	private boolean noProgress;
+
 	private String lockMessage;
 
 	private PackLock packLock;
@@ -232,21 +242,33 @@ static enum MultiAck {
 	public BasePackFetchConnection(final PackTransport packTransport) {
 		super(packTransport);
 
-		final FetchConfig cfg = local.getConfig().get(FetchConfig.KEY);
+		if (local != null) {
+			final FetchConfig cfg = local.getConfig().get(FetchConfig.KEY);
+			allowOfsDelta = cfg.allowOfsDelta;
+		} else {
+			allowOfsDelta = true;
+		}
 		includeTags = transport.getTagOpt() != TagOpt.NO_TAGS;
 		thinPack = transport.isFetchThin();
-		allowOfsDelta = cfg.allowOfsDelta;
 
-		walk = new RevWalk(local);
-		reachableCommits = new RevCommitList<RevCommit>();
-		REACHABLE = walk.newFlag("REACHABLE"); //$NON-NLS-1$
-		COMMON = walk.newFlag("COMMON"); //$NON-NLS-1$
-		STATE = walk.newFlag("STATE"); //$NON-NLS-1$
-		ADVERTISED = walk.newFlag("ADVERTISED"); //$NON-NLS-1$
+		if (local != null) {
+			walk = new RevWalk(local);
+			reachableCommits = new RevCommitList<RevCommit>();
+			REACHABLE = walk.newFlag("REACHABLE"); //$NON-NLS-1$
+			COMMON = walk.newFlag("COMMON"); //$NON-NLS-1$
+			STATE = walk.newFlag("STATE"); //$NON-NLS-1$
+			ADVERTISED = walk.newFlag("ADVERTISED"); //$NON-NLS-1$
 
-		walk.carry(COMMON);
-		walk.carry(REACHABLE);
-		walk.carry(ADVERTISED);
+			walk.carry(COMMON);
+			walk.carry(REACHABLE);
+			walk.carry(ADVERTISED);
+		} else {
+			walk = null;
+			REACHABLE = null;
+			COMMON = null;
+			STATE = null;
+			ADVERTISED = null;
+		}
 	}
 
 	private static class FetchConfig {
@@ -301,7 +323,9 @@ public Collection<PackLock> getPackLocks() {
 	 * Execute common ancestor negotiation and fetch the objects.
 	 *
 	 * @param monitor
-	 *            progress monitor to receive status updates.
+	 *            progress monitor to receive status updates. If the monitor is
+	 *            the {@link NullProgressMonitor#INSTANCE}, then the no-progress
+	 *            option enabled.
 	 * @param want
 	 *            the advertised remote references the caller wants to fetch.
 	 * @param have
@@ -318,6 +342,8 @@ protected void doFetch(final ProgressMonitor monitor,
 			final Collection<Ref> want, final Set<ObjectId> have,
 			OutputStream outputStream) throws TransportException {
 		try {
+			noProgress = monitor == NullProgressMonitor.INSTANCE;
+
 			markRefsAdvertised();
 			markReachable(have, maxTimeWanted(want));
 
@@ -350,7 +376,8 @@ protected void doFetch(final ProgressMonitor monitor,
 
 	@Override
 	public void close() {
-		walk.release();
+		if (walk != null)
+			walk.release();
 		super.close();
 	}
 
@@ -460,6 +487,8 @@ private boolean sendWants(final Collection<Ref> want) throws IOException {
 
 	private String enableCapabilities() throws TransportException {
 		final StringBuilder line = new StringBuilder();
+		if (noProgress)
+			wantCapability(line, OPTION_NO_PROGRESS);
 		if (includeTags)
 			includeTags = wantCapability(line, OPTION_INCLUDE_TAG);
 		if (allowOfsDelta)
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransferConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransferConfig.java
index c3e3986..3a08cd3 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransferConfig.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransferConfig.java
@@ -43,11 +43,17 @@
 
 package org.eclipse.jgit.transport;
 
+import java.util.HashMap;
+import java.util.Map;
+
 import org.eclipse.jgit.lib.Config;
 import org.eclipse.jgit.lib.Config.SectionParser;
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.lib.Repository;
 
 /**
- * The standard "transfer", "fetch" and "receive" configuration parameters.
+ * The standard "transfer", "fetch", "receive", and "uploadpack" configuration
+ * parameters.
  */
 public class TransferConfig {
 	/** Key for {@link Config#get(SectionParser)}. */
@@ -58,9 +64,18 @@ public TransferConfig parse(final Config cfg) {
 	};
 
 	private final boolean fsckObjects;
+	private final boolean allowTipSha1InWant;
+	private final String[] hideRefs;
+
+	TransferConfig(final Repository db) {
+		this(db.getConfig());
+	}
 
 	private TransferConfig(final Config rc) {
 		fsckObjects = rc.getBoolean("receive", "fsckobjects", false); //$NON-NLS-1$ //$NON-NLS-2$
+		allowTipSha1InWant = rc.getBoolean(
+				"uploadpack", "allowtipsha1inwant", false); //$NON-NLS-1$ //$NON-NLS-2$
+		hideRefs = rc.getStringList("uploadpack", null, "hiderefs"); //$NON-NLS-1$ //$NON-NLS-2$
 	}
 
 	/**
@@ -69,4 +84,43 @@ private TransferConfig(final Config rc) {
 	public boolean isFsckObjects() {
 		return fsckObjects;
 	}
+
+	/**
+	 * @return allow clients to request non-advertised tip SHA-1s?
+	 * @since 3.1
+	 */
+	public boolean isAllowTipSha1InWant() {
+		return allowTipSha1InWant;
+	}
+
+	/**
+	 * @return {@link RefFilter} respecting configured hidden refs.
+	 * @since 3.1
+	 */
+	public RefFilter getRefFilter() {
+		if (hideRefs.length == 0)
+			return RefFilter.DEFAULT;
+
+		return new RefFilter() {
+			public Map<String, Ref> filter(Map<String, Ref> refs) {
+				Map<String, Ref> result = new HashMap<String, Ref>();
+				for (Map.Entry<String, Ref> e : refs.entrySet()) {
+					boolean add = true;
+					for (String hide : hideRefs) {
+						if (e.getKey().equals(hide) || prefixMatch(hide, e.getKey())) {
+							add = false;
+							break;
+						}
+					}
+					if (add)
+						result.put(e.getKey(), e.getValue());
+				}
+				return result;
+			}
+
+			private boolean prefixMatch(String p, String s) {
+				return p.charAt(p.length() - 1) == '/' && s.startsWith(p);
+			}
+		};
+	}
 }
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 3c19610..dd04ce5 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/Transport.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/Transport.java
@@ -559,6 +559,9 @@ public static Transport open(Repository local, URIish uri, String remoteName)
 
 	/**
 	 * Open a new transport with no local repository.
+	 * <p>
+	 * Note that the resulting transport instance can not be used for fetching
+	 * or pushing, but only for reading remote refs.
 	 *
 	 * @param uri
 	 * @return new Transport instance
@@ -1238,6 +1241,9 @@ public Collection<RemoteRefUpdate> findRemoteRefUpdatesFor(
 
 	/**
 	 * Begins a new connection for fetching from the remote repository.
+	 * <p>
+	 * If the transport has no local repository, the fetch connection can only
+	 * be used for reading remote refs.
 	 *
 	 * @return a fresh connection to fetch from the remote repository.
 	 * @throws NotSupportedException
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 32de7de..bbc0d0a 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportBundleFile.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportBundleFile.java
@@ -59,6 +59,7 @@
 import org.eclipse.jgit.errors.TransportException;
 import org.eclipse.jgit.internal.JGitText;
 import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.util.FS;
 
 class TransportBundleFile extends Transport implements TransportBundle {
 	static final TransportProtocol PROTO_BUNDLE = new TransportProtocol() {
@@ -104,6 +105,15 @@ public Transport open(URIish uri, Repository local, String remoteName)
 			//
 			return TransportLocal.PROTO_LOCAL.open(uri, local, remoteName);
 		}
+
+		public Transport open(URIish uri) throws NotSupportedException,
+				TransportException {
+			if ("bundle".equals(uri.getScheme())) { //$NON-NLS-1$
+				File path = FS.DETECTED.resolve(new File("."), uri.getPath()); //$NON-NLS-1$
+				return new TransportBundleFile(uri, path);
+			}
+			return TransportLocal.PROTO_LOCAL.open(uri);
+		}
 	};
 
 	private final File bundle;
@@ -113,6 +123,11 @@ public Transport open(URIish uri, Repository local, String remoteName)
 		bundle = bundlePath;
 	}
 
+	public TransportBundleFile(URIish uri, File bundlePath) {
+		super(uri);
+		bundle = bundlePath;
+	}
+
 	@Override
 	public FetchConnection openFetch() throws NotSupportedException,
 			TransportException {
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 2f615e2..81caf66 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportLocal.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportLocal.java
@@ -65,6 +65,7 @@
 import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.lib.RepositoryBuilder;
 import org.eclipse.jgit.lib.RepositoryCache;
+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;
@@ -130,6 +131,21 @@ public Transport open(URIish uri, Repository local, String remoteName)
 				throw new NoRemoteRepositoryException(uri, JGitText.get().notFound);
 			return new TransportLocal(local, uri, gitDir);
 		}
+
+		public Transport open(URIish uri) throws NotSupportedException,
+				TransportException {
+			File path = FS.DETECTED.resolve(new File("."), uri.getPath()); //$NON-NLS-1$
+			// If the reference is to a local file, C Git behavior says
+			// assume this is a bundle, since repositories are directories.
+			if (path.isFile())
+				return new TransportBundleFile(uri, path);
+
+			File gitDir = RepositoryCache.FileKey.resolve(path, FS.DETECTED);
+			if (gitDir == null)
+				throw new NoRemoteRepositoryException(uri,
+						JGitText.get().notFound);
+			return new TransportLocal(uri, gitDir);
+		}
 	};
 
 	private final File remoteGitDir;
@@ -139,6 +155,11 @@ public Transport open(URIish uri, Repository local, String remoteName)
 		remoteGitDir = gitDir;
 	}
 
+	TransportLocal(URIish uri, File gitDir) {
+		super(uri);
+		remoteGitDir = gitDir;
+	}
+
 	UploadPack createUploadPack(final Repository dst) {
 		return new UploadPack(dst);
 	}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportSftp.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportSftp.java
index e99ba1c..70e458a 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportSftp.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportSftp.java
@@ -235,7 +235,7 @@ Collection<String> getPackNames() throws IOException {
 					files.put(ent.getFilename(), ent);
 				for (final ChannelSftp.LsEntry ent : list) {
 					final String n = ent.getFilename();
-					if (!n.startsWith("pack-") || !n.endsWith(".pack")) //$NON-NLS-1$
+					if (!n.startsWith("pack-") || !n.endsWith(".pack")) //$NON-NLS-1$ //$NON-NLS-2$
 						continue;
 
 					final String in = n.substring(0, n.length() - 5) + ".idx"; //$NON-NLS-1$
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/URIish.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/URIish.java
index deebe66..bd65182 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/URIish.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/URIish.java
@@ -88,7 +88,7 @@ public class URIish implements Serializable {
 	 * Part of a pattern which matches the host part of URIs. Defines one
 	 * capturing group containing the host name.
 	 */
-	private static final String HOST_P = "((?:[^\\\\/:]+)|(?:\\[[0-9a-f:]+\\]))";
+	private static final String HOST_P = "((?:[^\\\\/:]+)|(?:\\[[0-9a-f:]+\\]))"; //$NON-NLS-1$
 
 	/**
 	 * Part of a pattern which matches the optional port part of URIs. Defines
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 808cd73..2f56775 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java
@@ -49,6 +49,7 @@
 import java.io.OutputStream;
 import java.text.MessageFormat;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
@@ -81,6 +82,7 @@
 import org.eclipse.jgit.transport.BasePackFetchConnection.MultiAck;
 import org.eclipse.jgit.transport.RefAdvertiser.PacketLineOutRefAdvertiser;
 import org.eclipse.jgit.util.io.InterruptTimer;
+import org.eclipse.jgit.util.io.NullOutputStream;
 import org.eclipse.jgit.util.io.TimeoutInputStream;
 import org.eclipse.jgit.util.io.TimeoutOutputStream;
 
@@ -88,6 +90,8 @@
  * Implements the server side of a fetch connection, transmitting objects.
  */
 public class UploadPack {
+	static final String OPTION_ALLOW_TIP_SHA1_IN_WANT = BasePackFetchConnection.OPTION_ALLOW_TIP_SHA1_IN_WANT;
+
 	static final String OPTION_INCLUDE_TAG = BasePackFetchConnection.OPTION_INCLUDE_TAG;
 
 	static final String OPTION_MULTI_ACK = BasePackFetchConnection.OPTION_MULTI_ACK;
@@ -112,12 +116,59 @@ public class UploadPack {
 	public static enum RequestPolicy {
 		/** Client may only ask for objects the server advertised a reference for. */
 		ADVERTISED,
-		/** Client may ask for any commit reachable from a reference. */
+
+		/**
+		 * Client may ask for any commit reachable from a reference advertised by
+		 * the server.
+		 */
 		REACHABLE_COMMIT,
+
+		/**
+		 * Client may ask for objects that are the tip of any reference, even if not
+		 * advertised.
+		 * <p>
+		 * This may happen, for example, when a custom {@link RefFilter} is set.
+		 *
+		 * @since 3.1
+		 */
+		TIP,
+
+		/**
+		 * Client may ask for any commit reachable from any reference, even if that
+		 * reference wasn't advertised.
+		 *
+		 * @since 3.1
+		 */
+		REACHABLE_COMMIT_TIP,
+
 		/** Client may ask for any SHA-1 in the repository. */
 		ANY;
 	}
 
+	/**
+	 * Validator for client requests.
+	 *
+	 * @since 3.1
+	 */
+	public interface RequestValidator {
+		/**
+		 * Check a list of client wants against the request policy.
+		 *
+		 * @param up
+		 *            {@link UploadPack} instance.
+		 * @param wants
+		 *            objects the client requested that were not advertised.
+		 *
+		 * @throws PackProtocolException
+		 *            if one or more wants is not valid.
+		 * @throws IOException
+		 *            if a low-level exception occurred.
+		 * @since 3.1
+		 */
+		void checkWants(UploadPack up, List<ObjectId> wants)
+				throws PackProtocolException, IOException;
+	}
+
 	/** Data in the first line of a request, the line itself plus options. */
 	public static class FirstLine {
 		private final String line;
@@ -165,6 +216,9 @@ public Set<String> getOptions() {
 	/** Configuration to pass into the PackWriter. */
 	private PackConfig packConfig;
 
+	/** Configuration for various transfer options. */
+	private TransferConfig transferConfig;
+
 	/** Timeout in seconds to wait for client interaction. */
 	private int timeout;
 
@@ -192,6 +246,8 @@ public Set<String> getOptions() {
 
 	private PacketLineOut pckOut;
 
+	private OutputStream msgOut = NullOutputStream.INSTANCE;
+
 	/** The refs we advertised as existing at the start of the connection. */
 	private Map<String, Ref> refs;
 
@@ -250,7 +306,7 @@ public Set<String> getOptions() {
 
 	private final RevFlagSet SAVE;
 
-	private RequestPolicy requestPolicy = RequestPolicy.ADVERTISED;
+	private RequestValidator requestValidator = new AdvertisedRequestValidator();
 
 	private MultiAck multiAck = MultiAck.OFF;
 
@@ -282,6 +338,8 @@ public UploadPack(final Repository copyFrom) {
 		SAVE.add(PEER_HAS);
 		SAVE.add(COMMON);
 		SAVE.add(SATISFIED);
+
+		setTransferConfig(null);
 	}
 
 	/** @return the repository this upload is reading from. */
@@ -321,7 +379,10 @@ public void setAdvertisedRefs(Map<String, Ref> allRefs) {
 			refs = allRefs;
 		else
 			refs = db.getAllRefs();
-		refs = refFilter.filter(refs);
+		if (refFilter == RefFilter.DEFAULT)
+			refs = transferConfig.getRefFilter().filter(refs);
+		else
+			refs = refFilter.filter(refs);
 	}
 
 	/** @return timeout (in seconds) before aborting an IO operation. */
@@ -360,13 +421,24 @@ public boolean isBiDirectionalPipe() {
 	 */
 	public void setBiDirectionalPipe(final boolean twoWay) {
 		biDirectionalPipe = twoWay;
-		if (!biDirectionalPipe && requestPolicy == RequestPolicy.ADVERTISED)
-			requestPolicy = RequestPolicy.REACHABLE_COMMIT;
 	}
 
-	/** @return policy used by the service to validate client requests. */
+	/**
+	 * @return policy used by the service to validate client requests, or null for
+	 *         a custom request validator.
+	 */
 	public RequestPolicy getRequestPolicy() {
-		return requestPolicy;
+		if (requestValidator instanceof AdvertisedRequestValidator)
+			return RequestPolicy.ADVERTISED;
+		if (requestValidator instanceof ReachableCommitRequestValidator)
+			return RequestPolicy.REACHABLE_COMMIT;
+		if (requestValidator instanceof TipRequestValidator)
+			return RequestPolicy.TIP;
+		if (requestValidator instanceof ReachableCommitTipRequestValidator)
+			return RequestPolicy.REACHABLE_COMMIT_TIP;
+		if (requestValidator instanceof AnyRequestValidator)
+			return RequestPolicy.ANY;
+		return null;
 	}
 
 	/**
@@ -375,11 +447,40 @@ public RequestPolicy getRequestPolicy() {
 	 *            By default the policy is {@link RequestPolicy#ADVERTISED},
 	 *            which is the Git default requiring clients to only ask for an
 	 *            object that a reference directly points to. This may be relaxed
-	 *            to {@link RequestPolicy#REACHABLE_COMMIT} when callers
-	 *            have {@link #setBiDirectionalPipe(boolean)} set to false.
+	 *            to {@link RequestPolicy#REACHABLE_COMMIT} or
+	 *            {@link RequestPolicy#REACHABLE_COMMIT_TIP} when callers have
+	 *            {@link #setBiDirectionalPipe(boolean)} set to false.
+	 *            Overrides any policy specified in a {@link TransferConfig}.
 	 */
 	public void setRequestPolicy(RequestPolicy policy) {
-		requestPolicy = policy != null ? policy : RequestPolicy.ADVERTISED;
+		switch (policy) {
+			case ADVERTISED:
+			default:
+				requestValidator = new AdvertisedRequestValidator();
+				break;
+			case REACHABLE_COMMIT:
+				requestValidator = new ReachableCommitRequestValidator();
+				break;
+			case TIP:
+				requestValidator = new TipRequestValidator();
+				break;
+			case REACHABLE_COMMIT_TIP:
+				requestValidator = new ReachableCommitTipRequestValidator();
+				break;
+			case ANY:
+				requestValidator = new AnyRequestValidator();
+				break;
+		}
+	}
+
+	/**
+	 * @param validator
+	 *            custom validator for client want list.
+	 * @since 3.1
+	 */
+	public void setRequestValidator(RequestValidator validator) {
+		requestValidator = validator != null ? validator
+				: new AdvertisedRequestValidator();
 	}
 
 	/** @return the hook used while advertising the refs to the client */
@@ -414,7 +515,8 @@ public void setAdvertiseRefsHook(final AdvertiseRefsHook advertiseRefsHook) {
 	 * <p>
 	 * Only refs allowed by this filter will be sent to the client.
 	 * The filter is run against the refs specified by the
-	 * {@link AdvertiseRefsHook} (if applicable).
+	 * {@link AdvertiseRefsHook} (if applicable). If null or not set, uses the
+	 * filter implied by the {@link TransferConfig}.
 	 *
 	 * @param refFilter
 	 *            the filter; may be null to show all refs.
@@ -449,6 +551,18 @@ public void setPackConfig(PackConfig pc) {
 		this.packConfig = pc;
 	}
 
+	/**
+	 * @param tc
+	 *            configuration controlling transfer options. If null the source
+	 *            repository's settings will be used.
+	 * @since 3.1
+	 */
+	public void setTransferConfig(TransferConfig tc) {
+		this.transferConfig = tc != null ? tc : new TransferConfig(db);
+		setRequestPolicy(transferConfig.isAllowTipSha1InWant()
+				? RequestPolicy.TIP : RequestPolicy.ADVERTISED);
+	}
+
 	/** @return the configured logger. */
 	public UploadPackLogger getLogger() {
 		return logger;
@@ -504,6 +618,8 @@ public void upload(final InputStream input, final OutputStream output,
 		try {
 			rawIn = input;
 			rawOut = output;
+			if (messages != null)
+				msgOut = messages;
 
 			if (timeout > 0) {
 				final Thread caller = Thread.currentThread();
@@ -520,6 +636,7 @@ public void upload(final InputStream input, final OutputStream output,
 			pckOut = new PacketLineOut(rawOut);
 			service();
 		} finally {
+			msgOut = NullOutputStream.INSTANCE;
 			walk.release();
 			if (timer != null) {
 				try {
@@ -552,15 +669,10 @@ private Map<String, Ref> getAdvertisedOrDefaultRefs() {
 	private void service() throws IOException {
 		if (biDirectionalPipe)
 			sendAdvertisedRefs(new PacketLineOutRefAdvertiser(pckOut));
-		else if (requestPolicy == RequestPolicy.ANY)
+		else if (requestValidator instanceof AnyRequestValidator)
 			advertised = Collections.emptySet();
-		else {
-			advertised = new HashSet<ObjectId>();
-			for (Ref ref : getAdvertisedOrDefaultRefs().values()) {
-				if (ref.getObjectId() != null)
-					advertised.add(ref.getObjectId());
-			}
-		}
+		else
+			advertised = refIdSet(getAdvertisedOrDefaultRefs().values());
 
 		boolean sendPack;
 		try {
@@ -612,6 +724,15 @@ else if (requestPolicy == RequestPolicy.ANY)
 			sendPack();
 	}
 
+	private static Set<ObjectId> refIdSet(Collection<Ref> refs) {
+		Set<ObjectId> ids = new HashSet<ObjectId>(refs.size());
+		for (Ref ref : refs) {
+			if (ref.getObjectId() != null)
+				ids.add(ref.getObjectId());
+		}
+		return ids;
+	}
+
 	private void reportErrorDuringNegotiate(String msg) {
 		try {
 			pckOut.writeString("ERR " + msg + "\n"); //$NON-NLS-1$ //$NON-NLS-2$
@@ -687,11 +808,45 @@ public void sendAdvertisedRefs(final RefAdvertiser adv) throws IOException,
 		adv.advertiseCapability(OPTION_SHALLOW);
 		if (!biDirectionalPipe)
 			adv.advertiseCapability(OPTION_NO_DONE);
+		RequestPolicy policy = getRequestPolicy();
+		if (policy == RequestPolicy.TIP
+				|| policy == RequestPolicy.REACHABLE_COMMIT_TIP
+				|| policy == null)
+			adv.advertiseCapability(OPTION_ALLOW_TIP_SHA1_IN_WANT);
 		adv.setDerefTags(true);
 		advertised = adv.send(getAdvertisedOrDefaultRefs());
+		if (adv.isEmpty())
+			adv.advertiseId(ObjectId.zeroId(), "capabilities^{}"); //$NON-NLS-1$
 		adv.end();
 	}
 
+	/**
+	 * Send a message to the client, if it supports receiving them.
+	 * <p>
+	 * If the client doesn't support receiving messages, the message will be
+	 * discarded, with no other indication to the caller or to the client.
+	 *
+	 * @param what
+	 *            string describing the problem identified by the hook. The
+	 *            string must not end with an LF, and must not contain an LF.
+	 * @since 3.1
+	 */
+	public void sendMessage(String what) {
+		try {
+			msgOut.write(Constants.encode(what + "\n")); //$NON-NLS-1$
+		} catch (IOException e) {
+			// Ignore write failures.
+		}
+	}
+
+	/**
+	 * @return an underlying stream for sending messages to the client, or null.
+	 * @since 3.1
+	 */
+	public OutputStream getMessageOutputStream() {
+		return msgOut;
+	}
+
 	private void recvWants() throws IOException {
 		boolean isFirst = true;
 		for (;;) {
@@ -720,10 +875,13 @@ private void recvWants() throws IOException {
 			if (!line.startsWith("want ") || line.length() < 45) //$NON-NLS-1$
 				throw new PackProtocolException(MessageFormat.format(JGitText.get().expectedGot, "want", line)); //$NON-NLS-1$
 
-			if (isFirst && line.length() > 45) {
-				final FirstLine firstLine = new FirstLine(line);
-				options = firstLine.getOptions();
-				line = firstLine.getLine();
+			if (isFirst) {
+				if (line.length() > 45) {
+					FirstLine firstLine = new FirstLine(line);
+					options = firstLine.getOptions();
+					line = firstLine.getLine();
+				} else
+					options = Collections.emptySet();
 			}
 
 			wantIds.add(ObjectId.fromString(line.substring(5)));
@@ -886,30 +1044,21 @@ private ObjectId processHaveLines(List<ObjectId> peerHas, ObjectId last)
 	}
 
 	private void parseWants() throws IOException {
+		List<ObjectId> notAdvertisedWants = null;
+		for (ObjectId obj : wantIds) {
+			if (!advertised.contains(obj)) {
+				if (notAdvertisedWants == null)
+					notAdvertisedWants = new ArrayList<ObjectId>();
+				notAdvertisedWants.add(obj);
+			}
+		}
+		if (notAdvertisedWants != null)
+			requestValidator.checkWants(this, notAdvertisedWants);
+
 		AsyncRevObjectQueue q = walk.parseAny(wantIds, true);
 		try {
-			List<RevCommit> checkReachable = null;
 			RevObject obj;
 			while ((obj = q.next()) != null) {
-				if (!advertised.contains(obj)) {
-					switch (requestPolicy) {
-					case ADVERTISED:
-					default:
-						throw new PackProtocolException(MessageFormat.format(
-								JGitText.get().wantNotValid, obj));
-					case REACHABLE_COMMIT:
-						if (!(obj instanceof RevCommit)) {
-							throw new PackProtocolException(MessageFormat.format(
-								JGitText.get().wantNotValid, obj));
-						}
-						if (checkReachable == null)
-							checkReachable = new ArrayList<RevCommit>();
-						checkReachable.add((RevCommit) obj);
-						break;
-					case ANY:
-						break;
-					}
-				}
 				want(obj);
 
 				if (!(obj instanceof RevCommit))
@@ -920,8 +1069,6 @@ private void parseWants() throws IOException {
 						want(obj);
 				}
 			}
-			if (checkReachable != null)
-				checkNotAdvertisedWants(checkReachable);
 			wantIds.clear();
 		} catch (MissingObjectException notFound) {
 			ObjectId id = notFound.getObjectId();
@@ -939,17 +1086,111 @@ private void want(RevObject obj) {
 		}
 	}
 
-	private void checkNotAdvertisedWants(List<RevCommit> notAdvertisedWants)
-			throws MissingObjectException, IncorrectObjectTypeException, IOException {
-		// Walk the requested commits back to the advertised commits.
-		// If any commit exists, a branch was deleted or rewound and
-		// the repository owner no longer exports that requested item.
-		// If the requested commit is merged into an advertised branch
-		// it will be marked UNINTERESTING and no commits return.
+	/**
+	 * Validator corresponding to {@link RequestPolicy#ADVERTISED}.
+	 *
+	 * @since 3.1
+	 */
+	public static final class AdvertisedRequestValidator
+			implements RequestValidator {
+		public void checkWants(UploadPack up, List<ObjectId> wants)
+				throws PackProtocolException, IOException {
+			if (!up.isBiDirectionalPipe())
+				new ReachableCommitRequestValidator().checkWants(up, wants);
+			else if (!wants.isEmpty())
+				throw new PackProtocolException(MessageFormat.format(
+						JGitText.get().wantNotValid, wants.iterator().next().name()));
+		}
+	}
 
-		for (RevCommit c : notAdvertisedWants)
-			walk.markStart(c);
-		for (ObjectId id : advertised) {
+	/**
+	 * Validator corresponding to {@link RequestPolicy#REACHABLE_COMMIT}.
+	 *
+	 * @since 3.1
+	 */
+	public static final class ReachableCommitRequestValidator
+			implements RequestValidator {
+		public void checkWants(UploadPack up, List<ObjectId> wants)
+				throws PackProtocolException, IOException {
+			checkNotAdvertisedWants(up.getRevWalk(), wants,
+					refIdSet(up.getAdvertisedRefs().values()));
+		}
+	}
+
+	/**
+	 * Validator corresponding to {@link RequestPolicy#TIP}.
+	 *
+	 * @since 3.1
+	 */
+	public static final class TipRequestValidator implements RequestValidator {
+		public void checkWants(UploadPack up, List<ObjectId> wants)
+				throws PackProtocolException, IOException {
+			if (!up.isBiDirectionalPipe())
+				new ReachableCommitTipRequestValidator().checkWants(up, wants);
+			else if (!wants.isEmpty()) {
+				Set<ObjectId> refIds =
+					refIdSet(up.getRepository().getAllRefs().values());
+				for (ObjectId obj : wants) {
+					if (!refIds.contains(obj))
+						throw new PackProtocolException(MessageFormat.format(
+								JGitText.get().wantNotValid, obj.name()));
+				}
+			}
+		}
+	}
+
+	/**
+	 * Validator corresponding to {@link RequestPolicy#REACHABLE_COMMIT_TIP}.
+	 *
+	 * @since 3.1
+	 */
+	public static final class ReachableCommitTipRequestValidator
+			implements RequestValidator {
+		public void checkWants(UploadPack up, List<ObjectId> wants)
+				throws PackProtocolException, IOException {
+			checkNotAdvertisedWants(up.getRevWalk(), wants,
+					refIdSet(up.getRepository().getAllRefs().values()));
+		}
+	}
+
+	/**
+	 * Validator corresponding to {@link RequestPolicy#ANY}.
+	 *
+	 * @since 3.1
+	 */
+	public static final class AnyRequestValidator implements RequestValidator {
+		public void checkWants(UploadPack up, List<ObjectId> wants)
+				throws PackProtocolException, IOException {
+			// All requests are valid.
+		}
+	}
+
+	private static void checkNotAdvertisedWants(RevWalk walk,
+			List<ObjectId> notAdvertisedWants, Set<ObjectId> reachableFrom)
+			throws MissingObjectException, IncorrectObjectTypeException, IOException {
+		// Walk the requested commits back to the provided set of commits. If any
+		// commit exists, a branch was deleted or rewound and the repository owner
+		// no longer exports that requested item. If the requested commit is merged
+		// into an advertised branch it will be marked UNINTERESTING and no commits
+		// return.
+
+		AsyncRevObjectQueue q = walk.parseAny(notAdvertisedWants, true);
+		try {
+			RevObject obj;
+			while ((obj = q.next()) != null) {
+				if (!(obj instanceof RevCommit))
+					throw new PackProtocolException(MessageFormat.format(
+						JGitText.get().wantNotValid, obj.name()));
+				walk.markStart((RevCommit) obj);
+			}
+		} catch (MissingObjectException notFound) {
+			ObjectId id = notFound.getObjectId();
+			throw new PackProtocolException(MessageFormat.format(
+					JGitText.get().wantNotValid, id.name()), notFound);
+		} finally {
+			q.release();
+		}
+		for (ObjectId id : reachableFrom) {
 			try {
 				walk.markUninteresting(walk.parseCommit(id));
 			} catch (IncorrectObjectTypeException notCommit) {
@@ -1076,7 +1317,6 @@ private boolean reportInternalServerErrorOverSideband() {
 	private void sendPack(final boolean sideband) throws IOException {
 		ProgressMonitor pm = NullProgressMonitor.INSTANCE;
 		OutputStream packOut = rawOut;
-		SideBandOutputStream msgOut = null;
 
 		if (sideband) {
 			int bufsz = SideBandOutputStream.SMALL_BUF;
@@ -1098,6 +1338,7 @@ private void sendPack(final boolean sideband) throws IOException {
 			} else {
 				preUploadHook.onSendPack(this, wantAll, commonBase);
 			}
+			msgOut.flush();
 		} catch (ServiceMayNotContinueException noPack) {
 			if (sideband && noPack.getMessage() != null) {
 				noPack.setOutput();
@@ -1181,7 +1422,7 @@ else if (ref.getName().startsWith(Constants.R_HEADS))
 			pw.writePack(pm, NullProgressMonitor.INSTANCE, packOut);
 			statistics = pw.getStatistics();
 
-			if (msgOut != null) {
+			if (msgOut != NullOutputStream.INSTANCE) {
 				String msg = pw.getStatistics().getMessage() + '\n';
 				msgOut.write(Constants.encode(msg));
 				msgOut.flush();
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/PathSuffixFilter.java b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/PathSuffixFilter.java
index 2c1f20d..f54cbea 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/PathSuffixFilter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/PathSuffixFilter.java
@@ -52,17 +52,25 @@
 import org.eclipse.jgit.treewalk.TreeWalk;
 
 /**
- * Includes tree entries only if they match the configured path.
+ * Includes tree entries only if they end with the configured path (suffix
+ * match).
+ * <p>
+ * For example, <code>PathSuffixFilter.create(".txt")</code> will match all
+ * paths ending in <code>.txt</code>.
+ * <p>
+ * Using this filter is recommended instead of filtering the entries using
+ * {@link TreeWalk#getPathString()} and <code>endsWith</code> or some other type
+ * of string match function.
  */
 public class PathSuffixFilter extends TreeFilter {
 
 	/**
-	 * Create a new tree filter for a user supplied path.
+	 * Create a new tree filter for a user supplied path suffix.
 	 * <p>
 	 * Path strings use '/' to delimit directories on all platforms.
 	 *
 	 * @param path
-	 *            the path (suffix) to filter on. Must not be the empty string.
+	 *            the path suffix to filter on. Must not be the empty string.
 	 * @return a new filter for the requested path.
 	 * @throws IllegalArgumentException
 	 *             the path supplied was the empty string.
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 7487f0d..676ca9b 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/ChangeIdUtil.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/ChangeIdUtil.java
@@ -131,7 +131,7 @@ public static ObjectId computeChangeId(final ObjectId treeId,
 	private static final Pattern includeInFooterPattern = Pattern
 			.compile("^[ \\[].*$"); //$NON-NLS-1$
 
-	private static final Pattern trailingWhitespace = Pattern.compile("\\s+$");
+	private static final Pattern trailingWhitespace = Pattern.compile("\\s+$"); //$NON-NLS-1$
 
 	/**
 	 * Find the right place to insert a Change-Id and return it.
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/RelativeDateFormatter.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/RelativeDateFormatter.java
index 8f31eae..3cb3749 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/RelativeDateFormatter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/RelativeDateFormatter.java
@@ -119,7 +119,7 @@ public static String format(Date when) {
 					JGitText.get().year;
 			long months = round(ageMillis % YEAR_IN_MILLIS, MONTH_IN_MILLIS);
 			String monthLabel = (months > 1) ? JGitText.get().months : //
-					(months == 1 ? JGitText.get().month : "");
+					(months == 1 ? JGitText.get().month : ""); //$NON-NLS-1$
 			return MessageFormat.format(
 					months == 0 ? JGitText.get().years0MonthsAgo : JGitText
 							.get().yearsMonthsAgo,
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/StringUtils.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/StringUtils.java
index bfefc50..40b89fb 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/StringUtils.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/StringUtils.java
@@ -286,6 +286,7 @@ public static boolean isEmptyOrNull(String stringValue) {
 	 * @param in
 	 *            A string with line breaks
 	 * @return in without line breaks
+	 * @since 3.1
 	 */
 	public static String replaceLineBreaksWithSpace(String in) {
 		char[] buf = new char[in.length()];
diff --git a/pom.xml b/pom.xml
index 61a6d85..087c6db 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>3.0.3.201309161630-r</version>
+  <version>3.1.0-SNAPSHOT</version>
 
   <name>JGit - Parent</name>
   <url>${jgit-url}</url>
@@ -175,13 +175,14 @@
     <maven.build.timestamp.format>yyyyMMddHHmm</maven.build.timestamp.format>
     <bundle-manifest>${project.build.directory}/META-INF/MANIFEST.MF</bundle-manifest>
 
-    <jgit-last-release-version>2.3.1.201302201838-r</jgit-last-release-version>
+    <jgit-last-release-version>3.0.0.201306101825-r</jgit-last-release-version>
     <jsch-version>0.1.46</jsch-version>
     <javaewah-version>0.5.6</javaewah-version>
     <junit-version>4.11</junit-version>
     <!-- TODO: update Maven dependency for args4j to 2.0.21 as soon as available on Maven Central -->
     <args4j-version>2.0.12</args4j-version>
     <commons-compress-version>1.4.1</commons-compress-version>
+    <osgi-core-version>4.3.1</osgi-core-version>
     <servlet-api-version>2.5</servlet-api-version>
     <jetty-version>7.6.11.v20130520</jetty-version>
     <clirr-version>2.4</clirr-version>
@@ -467,6 +468,12 @@
         <artifactId>jetty-servlet</artifactId>
         <version>${jetty-version}</version>
       </dependency>
+
+      <dependency>
+        <groupId>org.osgi</groupId>
+        <artifactId>org.osgi.core</artifactId>
+        <version>${osgi-core-version}</version>
+      </dependency>
     </dependencies>
   </dependencyManagement>
 
@@ -583,6 +590,7 @@
   <modules>
     <module>org.eclipse.jgit</module>
     <module>org.eclipse.jgit.ant</module>
+    <module>org.eclipse.jgit.archive</module>
     <module>org.eclipse.jgit.ui</module>
     <module>org.eclipse.jgit.http.server</module>
     <module>org.eclipse.jgit.pgm</module>
diff --git a/tools/fix-headers.pl b/tools/fix-headers.pl
deleted file mode 100755
index 62141b3..0000000
--- a/tools/fix-headers.pl
+++ /dev/null
@@ -1,343 +0,0 @@
-#!/usr/bin/perl
-# ------------------------------------------------------------
-# This script fixes the license headers of all Java sources
-# to use the Eclipse EDL license template and updates the
-# copyright statements using author information from git blame
-#
-# To fix this in all revisions rewrite the history
-# git filter-branch --tree-filter 'fixHeaders.pl' HEAD
-# ------------------------------------------------------------
-use strict;
-
-# Table of author names, start date, end date, actual copyright owner.
-#
-my @author_employers = (
-	[ qr/spearce\@spearce.org/, 2008, 8, 9999, 12, 'Google Inc.'],
-
-	[ qr/\@(.*\.|)google.com/, 0, 0, 9999, 12, 'Google Inc.'],
-);
-
-# License text itself.
-#
-my $license_text = <<'EOF';
- 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.
-EOF
-
-my @files = @ARGV;
-unless (@files) {
-	open( F, '-|', 'git ls-files' );
-	@files = <F>;
-	chop @files;
-	close F;
-}
-
-foreach (@files) {
-	if (/\.java$/ || $_ eq 'LICENSE') {
-		next if $_ eq 'org.eclipse.jgit/src/org/eclipse/jgit/util/Base64.java';
-		update_file(\&java_file, $_);
-
-	} elsif (/pom\.xml$/) {
-		update_file(\&pom_file, $_);
-
-	} elsif (/\.sh$/) {
-		update_file(\&sh_file, $_);
-	}
-}
-
-sub java_file
-{
-	my $fd = shift;
-	my $header = '';
-	my $preamble = '';
-
-	# header is everything before package statement
-	while (<$fd>) {
-		if (/^package /) {
-			$preamble = $_;
-			last;
-		}
-		$header .= $_;
-	}
-
-	# preamble is everything with blanks or imports
-	while (<$fd>) {
-		$preamble .= $_;
-		last unless (/^import / || /^$/);
-	}
-	my $lineno = $. - 1;
-
-	return ($header, $preamble, $lineno,
-		"/*\n", sub { s/^/ */mg }, " */\n");
-}
-
-sub pom_file
-{
-	my $fd = shift;
-	my $header = '';
-	my $preamble = '';
-
-	# header is everything before project
-	while (<$fd>) {
-		if (/<project/) {
-			$preamble = $_;
-			last;
-		}
-		$header .= $_;
-	}
-	my $lineno = $. - 1;
-
-	return ($header, $preamble, $lineno,
-		qq{<?xml version="1.0" encoding="UTF-8"?>\n<!--\n},
-		sub { s/^(.)/  $1/mg },
-		qq{-->\n});
-}
-
-sub sh_file
-{
-	my $fd = shift;
-	my $top = <$fd>;
-	my $header = '';
-	my $preamble = '';
-
-	while (<$fd>) {
-		if (/^#/) {
-			$header .= $_;
-			next;
-		}
-		$preamble = $_;
-		last;
-	}
-	my $lineno = $. - 1;
-
-	return ($header, $preamble, $lineno, $top, sub { s/^/#/mg }, "");
-}
-
-sub update_file
-{
-	my $func = shift;
-	my $old_file = shift;
-	my $new_file = "$old_file.license.$$";
-
-	open(I, '<', $old_file);
-	my ($header, $preamble, $lineno,
-		$top, $fmt, $btm) = &{$func}(\*I);
-
-	my %all_years;
-	my %author_years;
-	my %minyear;
-	my %maxyear;
-
-	# find explicit copyright statements in sources
-	my @lines = split( /\n/, $header );
-	foreach my $line ( @lines ) {
-		# * Copyright (c) 2008, Example Company Inc.
-		# * Copyright (c) 2008, Joe Developer <joe.dev@example.org>
-		# * Copyright (c) 2008, 2009 Joe Developer <joe.dev@example.org>
-		# * Copyright (c) 2005-2009 Joe Developer <joe.dev@example.org>
-		# * Copyright (c) 2008, 2009 Other Examples Inc.
-		# * Copyright (c) 2008-2010 Example Company Inc.
-		# * Copyright (C) 2009-2010, Yet More Examples Ltd.
-		if( $line =~ m/Copyright \(c\) (\d{4})(?:\s*[,-]\s*(\d{4}))?,?\s*([^<>]+)\s*(<.*?>)?/i ) {
-			my ($y, $y2, $n, $e) = ($1, $2, $3, $4);
-			my $year = trim($y);
-			my $author_name = trim($n);
-			my $author_email = trim($e);
-			my $who = $author_name;
-			$who .= " $author_email" if $author_email;
-			update_author_info(\%minyear, \%maxyear, \%all_years, \%author_years, $who, $year);
-			if (my $year2 = $y2) {
-				update_author_info(\%minyear, \%maxyear, \%all_years, \%author_years, $who, $year2);
-			}
-		}
-	}
-
-	if ($old_file eq 'LICENSE') {
-	} else {
-		# add implicit copyright statements from authors found in git blame
-		my (%line_counts, %line_authors);
-		my ($last_commit, $author_name, $author_email);
-		my @blame_args = ('git', 'blame', "-L$lineno,", '-C', '-w', '-p');
-		push(@blame_args, $ENV{'GIT_COMMIT'}) if $ENV{'GIT_COMMIT'};
-		push(@blame_args, '--', $old_file);
-		open( B, '-|', @blame_args);
-		while (<B>) {
-			chop;
-			if (/^([0-9a-f]{40}) \d+ \d+ (\d+)$/) {
-				$last_commit = $1;
-				$line_counts{$1} += $2;
-				next;
-			}
-			if (/^author (.*)$/) {
-				$author_name = trim($1);
-				next;
-			}
-			if (/^author-mail (<.*>)$/) {
-				$author_email = trim($1);
-				next;
-			}
-			if (/^author-time (\d+)$/) {
-				# skip uncommitted changes
-				my $who = "$author_name $author_email";
-				next if $who eq 'Not Committed Yet <not.committed.yet>';
-				my @tm = localtime($1);
-				my $year = $tm[5] + 1900;
-				my $mon = $tm[4] + 1;
-				$who = translate_author($who, $year, $mon);
-				$line_authors{$last_commit} = [$who, $year, $mon];
-			}
-		}
-		close B;
-
-		my %author_linecounts;
-		foreach $last_commit (keys %line_counts) {
-			my $who = $line_authors{$last_commit}[0];
-			next unless $who;
-			$author_linecounts{$who} += $line_counts{$last_commit};
-		}
-
-		my $sz = 100;
-		my $count_big = 0;
-		foreach (values %author_linecounts) {
-			$count_big++ if $_ >= $sz;
-		}
-
-		my $added_count = 0;
-		foreach (values %line_authors) {
-			my ($who, $year, $mon) = @$_;
-			next if ($count_big && $author_linecounts{$who} < $sz);
-			$all_years{$year} = 1;
-			update_author_info(\%minyear, \%maxyear, \%all_years, \%author_years, $who, $year, $mon);
-		}
-	}
-
-	# rewrite file
-	open( O, '>', $new_file );
-	print O $top;
-
-	my %used_author;
-	foreach my $year ( sort { $a cmp $b } keys %all_years ) {
-		foreach my $who ( sort keys %author_years ) {
-			next if $used_author{$who}++;
-			local $_ = format_copyright($minyear{$who}, $maxyear{$who}, $who);
-			&{$fmt}();
-			print O;
-		}
-	}
-
-	local $_ = $license_text;
-	&{$fmt}();
-	print O;
-	print O $btm;
-	print O "\n";
-	print O $preamble;
-	print O while <I>;
-	close I;
-	close O;
-
-	rename( $new_file, $old_file );
-}
-
-sub trim($)
-{
-	my $string = shift;
-	$string =~ s/^\s+//;
-	$string =~ s/\s+$//;
-	return $string;
-}
-
-sub update_author_info
-{
-	my ($minyear_ref, $maxyear_ref, $all_years_ref, $author_years_ref, $who, $year, $mon) = @_;
-
-	$who = translate_author($who, $year, $mon);
-	$all_years_ref->{$year} = 1;
-	$author_years_ref->{$who}{$year} = 1;
-
-	my $y = $minyear_ref->{$who};
-	if ($y < 1900) {
-		$y = 9999;
-	}
-	if ($year < $y) {
-		$minyear_ref->{$who} = $year;
-	}
-	$y = $maxyear_ref->{$who};
-	if ($year > $y) {
-		$maxyear_ref->{$who} = $year;
-	}
-}
-
-sub date_cmp
-{
-	my ($a_year, $a_mon, $b_year, $b_mon) = @_;
-
-	if ($a_year < $b_year) {
-		return -1;
-	} elsif ($a_year == $b_year) {
-		return ($a_mon <=> $b_mon);
-	} else {
-		return 1;
-	}
-}
-
-sub translate_author
-{
-	my ($who, $year, $mon) = @_;
-
-	return $who if not defined $mon;
-
-	foreach my $spec (@author_employers) {
-		next unless $who =~ $spec->[0];
-		next if (date_cmp($year, $mon, $spec->[1], $spec->[2]) < 0);
-		next if (date_cmp($year, $mon, $spec->[3], $spec->[4]) > 0);
-		return $spec->[5];
-	}
-	return $who;
-}
-
-sub format_copyright {
-	my ($minyear, $maxyear, $who) = @_;
-	if ($minyear < $maxyear) {
-		return " Copyright (C) $minyear-$maxyear, $who\n";
-	} else {
-		return " Copyright (C) $minyear, $who\n";
-	}
-}
-
diff --git a/tools/fix-headers.tst b/tools/fix-headers.tst
deleted file mode 100644
index c47bba9..0000000
--- a/tools/fix-headers.tst
+++ /dev/null
@@ -1,11 +0,0 @@
-regex without named back references
-m/.*Copyright \(c\) ((\d{4})\s*[,-]\s*(\d{4})?)\,?(([^\r\<\>\,]*)(\<.*\>)?)\s*/i
-
- * Copyright (c) 2008, Example Company Inc.
- * Copyright (c) 2008, Joe Developer <joe.dev@example.org>
- * Copyright (c) 2008, 2009 Joe Developer <joe.dev@example.org>
- * Copyright (c) 2005-2009 Joe Developer <joe.dev@example.org>
- * Copyright (c) 2008, 2009 Other Examples Inc.
- * Copyright (c) 2008-2010 Example Company Inc.
- * Copyright (C) 2009-2010, Yet More Examples Ltd.
-
diff --git a/tools/rewrite-history.sh b/tools/rewrite-history.sh
deleted file mode 100644
index cf13cba..0000000
--- a/tools/rewrite-history.sh
+++ /dev/null
@@ -1,84 +0,0 @@
-#!/bin/sh
-# Copyright (C) 2010, 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.
-
-
-TOOLS_DIR=$(dirname $0)
-TOOLS_DIR=$(cd $TOOLS_DIR && pwd)
-export TOOLS_DIR
-
-MAP_OF_COMMITS=$(pwd)/commit.map
-export MAP_OF_COMMITS
-
-: >$MAP_OF_COMMITS
-git filter-branch \
---tree-filter '
-	export GIT_COMMIT
-	$TOOLS_DIR/fix-headers.pl
-
-	if [ -f tools/graft-old-history.sh ]; then
-		i=$(map 046198cf5f21e5a63e8ec0ecde2ef3fe21db2eae)
-		perl -pi -e "
-			s/^POST=.*/POST=$i/;
-		" tools/graft-old-history.sh
-	fi
-' \
---env-filter '
-	if [ 046198cf5f21e5a63e8ec0ecde2ef3fe21db2eae = $GIT_COMMIT ]; then
-		export GIT_AUTHOR_NAME="Git Development Community"
-		export GIT_AUTHOR_EMAIL=git@vger.kernel.org
-	fi
-' \
---parent-filter '
-	if [ 046198cf5f21e5a63e8ec0ecde2ef3fe21db2eae = $GIT_COMMIT ]; then
-		cat >/dev/null
-	else
-		cat
-	fi
-' \
---commit-filter '
-	n=$(git commit-tree "$@")
-	echo $GIT_COMMIT=$n >>$MAP_OF_COMMITS
-	echo $n
-' \
--d /tmp/jgit-rewrite-history-$$ \
-$(git for-each-ref --format='%(refname)' refs/heads refs/changes) \
---not 3a2dd9921c8a08740a9e02c421469e5b1a9e47cb