Merge 'http-msys-paths' into HEAD
diff --git a/Documentation/config.txt b/Documentation/config.txt
index c55c22a..a82b1f1 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -212,6 +212,12 @@
 will probe and set core.fileMode false if appropriate when the
 repository is created.
 
+core.hideDotFiles::
+	(Windows-only) If true (which is the default), mark newly-created
+	directories and files whose name starts with a dot as hidden.
+	If 'dotGitOnly', only the .git/ directory is hidden, but no other
+	files starting with a dot.
+
 core.ignorecase::
 	If true, this option enables various workarounds to enable
 	Git to work better on filesystems that are not case sensitive,
@@ -776,6 +782,7 @@
 	instead of merging the default branch from the default remote when
 	"git pull" is run. See "pull.rebase" for doing this in a non
 	branch-specific manner.
+	When the value is `interactive`, the rebase is run in interactive mode.
 +
 	When preserve, also pass `--preserve-merges` along to 'git rebase'
 	so that locally committed merge commits will not be flattened
@@ -2076,6 +2083,11 @@
 	print a warning of such a push to stderr, but allow the push to
 	proceed. If set to false or "ignore", allow such pushes with no
 	message. Defaults to "refuse".
++
+There are two more options that are meant for Git experts: "updateInstead"
+which will run `read-tree -u -m HEAD` and "detachInstead" which will detach
+the HEAD so it does not need to change.  Both options come with their own
+set of possible *complications*, but can be appropriate in rare workflows.
 
 receive.denyNonFastForwards::
 	If set to true, git-receive-pack will deny a ref update which is
diff --git a/Documentation/git-pull.txt b/Documentation/git-pull.txt
index 200eb22..2f626dc 100644
--- a/Documentation/git-pull.txt
+++ b/Documentation/git-pull.txt
@@ -104,7 +104,7 @@
 include::merge-options.txt[]
 
 -r::
---rebase[=false|true|preserve]::
+--rebase[=false|true|preserve|interactive]::
 	When true, rebase the current branch on top of the upstream
 	branch after fetching. If there is a remote-tracking branch
 	corresponding to the upstream branch and the upstream branch
@@ -117,6 +117,8 @@
 +
 When false, merge the current branch into the upstream branch.
 +
+When `interactive`, enable the interactive mode of rebase.
++
 See `pull.rebase`, `branch.<name>.rebase` and `branch.autosetuprebase` in
 linkgit:git-config[1] if you want to make `git pull` always use
 `--rebase` instead of merging.
diff --git a/Makefile b/Makefile
index 2320de5..b4d3c06 100644
--- a/Makefile
+++ b/Makefile
@@ -1148,13 +1148,11 @@
 	REMOTE_CURL_NAMES = $(REMOTE_CURL_PRIMARY) $(REMOTE_CURL_ALIASES)
 	PROGRAM_OBJS += http-fetch.o
 	PROGRAMS += $(REMOTE_CURL_NAMES)
-	curl_check := $(shell (echo 070908; curl-config --vernum) 2>/dev/null | sort -r | sed -ne 2p)
-	ifeq "$(curl_check)" "070908"
-		ifndef NO_EXPAT
+	ifndef NO_EXPAT
+		ifndef NO_CURL_MULTI
 			PROGRAM_OBJS += http-push.o
 		endif
-	endif
-	ifndef NO_EXPAT
+
 		ifdef EXPATDIR
 			BASIC_CFLAGS += -I$(EXPATDIR)/include
 			EXPAT_LIBEXPAT = -L$(EXPATDIR)/$(lib) $(CC_LD_DYNPATH)$(EXPATDIR)/$(lib) -lexpat
@@ -1479,6 +1477,9 @@
 	COMPAT_CFLAGS += -Icompat/regex
 	COMPAT_OBJS += compat/regex/regex.o
 endif
+ifdef NATIVE_CRLF
+	BASIC_CFLAGS += -DNATIVE_CRLF
+endif
 
 ifdef USE_NED_ALLOCATOR
        COMPAT_CFLAGS += -Icompat/nedmalloc
diff --git a/builtin/clone.c b/builtin/clone.c
index bbd169c..1dfd21d 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -947,7 +947,9 @@
 			}
 
 		if (!is_local && !complete_refs_before_fetch)
-			transport_fetch_refs(transport, mapped_refs);
+			if (transport_fetch_refs(transport, mapped_refs))
+				die(_("could not fetch refs from %s"),
+				    transport->url);
 
 		remote_head = find_ref_by_name(refs, "HEAD");
 		remote_head_points_at =
diff --git a/builtin/fast-export.c b/builtin/fast-export.c
index 92b4624..a230c45 100644
--- a/builtin/fast-export.c
+++ b/builtin/fast-export.c
@@ -571,9 +571,20 @@
 	}
 }
 
+static void handle_reset(const char *name, struct object *object)
+{
+	int mark = get_object_mark(object);
+
+	if (mark)
+		printf("reset %s\nfrom :%d\n\n", name,
+		       get_object_mark(object));
+	else
+		printf("reset %s\nfrom %s\n\n", name,
+		       sha1_to_hex(object->sha1));
+}
+
 static void handle_tags_and_duplicates(void)
 {
-	struct commit *commit;
 	int i;
 
 	for (i = extra_refs.nr - 1; i >= 0; i--) {
@@ -585,9 +596,7 @@
 			break;
 		case OBJ_COMMIT:
 			/* create refs pointing to already seen commits */
-			commit = (struct commit *)object;
-			printf("reset %s\nfrom :%d\n\n", name,
-			       get_object_mark(&commit->object));
+			handle_reset(name, object);
 			show_progress();
 			break;
 		}
diff --git a/builtin/init-db.c b/builtin/init-db.c
index 56f85e2..ca433df 100644
--- a/builtin/init-db.c
+++ b/builtin/init-db.c
@@ -385,6 +385,7 @@
 	check_repository_format();
 
 	reinit = create_default_files(template_dir);
+	mark_as_git_dir(get_git_dir());
 
 	create_object_directory();
 
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index f93ac45..2fb7ed1 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -22,7 +22,9 @@
 	DENY_UNCONFIGURED,
 	DENY_IGNORE,
 	DENY_WARN,
-	DENY_REFUSE
+	DENY_REFUSE,
+	DENY_UPDATE_INSTEAD,
+	DENY_DETACH_INSTEAD,
 };
 
 static int deny_deletes;
@@ -100,7 +102,12 @@
 	}
 
 	if (!strcmp(var, "receive.denycurrentbranch")) {
-		deny_current_branch = parse_deny_action(var, value);
+		if (value && !strcasecmp(value, "updateinstead"))
+			deny_current_branch = DENY_UPDATE_INSTEAD;
+		else if (value && !strcasecmp(value, "detachinstead"))
+			deny_current_branch = DENY_DETACH_INSTEAD;
+		else
+			deny_current_branch = parse_deny_action(var, value);
 		return 0;
 	}
 
@@ -468,6 +475,44 @@
 	return 0;
 }
 
+static void merge_worktree(unsigned char *sha1)
+{
+	const char *update_refresh[] = {
+		"update-index", "--ignore-submodules", "--refresh", NULL
+	};
+	const char *read_tree[] = {
+		"read-tree", "-u", "-m", sha1_to_hex(sha1), NULL
+	};
+	struct child_process child;
+	struct strbuf git_env = STRBUF_INIT;
+	const char *env[2];
+
+	if (is_bare_repository())
+		die ("denyCurrentBranch = updateInstead needs a worktree");
+
+	strbuf_addf(&git_env, "GIT_DIR=%s", absolute_path(get_git_dir()));
+	env[0] = git_env.buf;
+	env[1] = NULL;
+
+	memset(&child, 0, sizeof(child));
+	child.argv = update_refresh;
+	child.env = env;
+	child.dir = git_work_tree_cfg ? git_work_tree_cfg : "..";
+	child.stdout_to_stderr = 1;
+	child.git_cmd = 1;
+	if (run_command(&child))
+		die ("Could not refresh the index");
+
+	child.argv = read_tree;
+	child.no_stdin = 1;
+	child.no_stdout = 1;
+	child.stdout_to_stderr = 0;
+	if (run_command(&child))
+		die ("Could not merge working tree with new HEAD.  Good luck.");
+
+	strbuf_release(&git_env);
+}
+
 static const char *update(struct command *cmd, struct shallow_info *si)
 {
 	const char *name = cmd->ref_name;
@@ -499,6 +544,13 @@
 			if (deny_current_branch == DENY_UNCONFIGURED)
 				refuse_unconfigured_deny();
 			return "branch is currently checked out";
+		case DENY_UPDATE_INSTEAD:
+			merge_worktree(new_sha1);
+			break;
+		case DENY_DETACH_INSTEAD:
+			update_ref("push into current branch (detach)", "HEAD",
+				old_sha1, NULL, REF_NODEREF, UPDATE_REFS_DIE_ON_ERR);
+			break;
 		}
 	}
 
@@ -527,6 +579,8 @@
 					refuse_unconfigured_deny_delete_current();
 				rp_error("refusing to delete the current branch: %s", name);
 				return "deletion of the current branch prohibited";
+			default:
+				die ("Invalid denyDeleteCurrent setting");
 			}
 		}
 	}
diff --git a/builtin/remote.c b/builtin/remote.c
index 9a4640d..eee9ef4 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -243,7 +243,7 @@
 struct branch_info {
 	char *remote_name;
 	struct string_list merge;
-	int rebase;
+	enum { NO_REBASE, NORMAL_REBASE, INTERACTIVE_REBASE } rebase;
 };
 
 static struct string_list branch_list;
@@ -304,6 +304,8 @@
 				info->rebase = v;
 			else if (!strcmp(value, "preserve"))
 				info->rebase = 1;
+			else if (!strcmp(value, "interactive"))
+				info->rebase = INTERACTIVE_REBASE;
 		}
 	}
 	return 0;
@@ -999,7 +1001,9 @@
 
 	printf("    %-*s ", show_info->width, item->string);
 	if (branch_info->rebase) {
-		printf_ln(_("rebases onto remote %s"), merge->items[0].string);
+		printf_ln(_(branch_info->rebase == INTERACTIVE_REBASE ?
+			"rebases interactively onto remote %s" :
+			"rebases onto remote %s"), merge->items[0].string);
 		return 0;
 	} else if (show_info->any_rebase) {
 		printf_ln(_(" merges with remote %s"), merge->items[0].string);
diff --git a/cache.h b/cache.h
index fcb511d..cf5431b 100644
--- a/cache.h
+++ b/cache.h
@@ -641,6 +641,13 @@
 extern char comment_line_char;
 extern int auto_comment_line_char;
 
+enum hide_dotfiles_type {
+	HIDE_DOTFILES_FALSE = 0,
+	HIDE_DOTFILES_TRUE,
+	HIDE_DOTFILES_DOTGITONLY,
+};
+extern enum hide_dotfiles_type hide_dotfiles;
+
 enum branch_track {
 	BRANCH_TRACK_UNSPECIFIED = -1,
 	BRANCH_TRACK_NEVER = 0,
diff --git a/compat/mingw.c b/compat/mingw.c
index c5c37e5..f7b6b26 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -7,6 +7,7 @@
 #include "../cache.h"
 
 static const int delay[] = { 0, 1, 10, 20, 40 };
+unsigned int _CRT_fmode = _O_BINARY;
 
 int err_win_to_posix(DWORD winerr)
 {
@@ -284,6 +285,27 @@
 	return ret;
 }
 
+static int make_hidden(const wchar_t *path)
+{
+	DWORD attribs = GetFileAttributesW(path);
+	if (SetFileAttributesW(path, FILE_ATTRIBUTE_HIDDEN | attribs))
+		return 0;
+	errno = err_win_to_posix(GetLastError());
+	return -1;
+}
+
+void mingw_mark_as_git_dir(const char *dir)
+{
+	wchar_t wdir[MAX_PATH];
+	if (hide_dotfiles != HIDE_DOTFILES_FALSE && !is_bare_repository())
+		if (xutftowcs_path(wdir, dir) < 0 || make_hidden(wdir))
+			warning("Failed to make '%s' hidden", dir);
+	git_config_set("core.hideDotFiles",
+		hide_dotfiles == HIDE_DOTFILES_FALSE ? "false" :
+		(hide_dotfiles == HIDE_DOTFILES_DOTGITONLY ?
+		 "dotGitOnly" : "true"));
+}
+
 int mingw_mkdir(const char *path, int mode)
 {
 	int ret;
@@ -291,6 +313,16 @@
 	if (xutftowcs_path(wpath, path) < 0)
 		return -1;
 	ret = _wmkdir(wpath);
+	if (!ret && hide_dotfiles == HIDE_DOTFILES_TRUE) {
+		/*
+		 * In Windows a file or dir starting with a dot is not
+		 * automatically hidden. So lets mark it as hidden when
+		 * such a directory is created.
+		 */
+		const char *start = basename((char*)path);
+		if (*start == '.')
+			return make_hidden(wpath);
+	}
 	return ret;
 }
 
@@ -317,6 +349,17 @@
 		if (attrs != INVALID_FILE_ATTRIBUTES && (attrs & FILE_ATTRIBUTE_DIRECTORY))
 			errno = EISDIR;
 	}
+	if ((oflags & O_CREAT) && fd >= 0 &&
+	    hide_dotfiles == HIDE_DOTFILES_TRUE) {
+		/*
+		 * In Windows a file or dir starting with a dot is not
+		 * automatically hidden. So lets mark it as hidden when
+		 * such a file is created.
+		 */
+		const char *start = basename((char*)filename);
+		if (*start == '.' && make_hidden(wfilename))
+			warning("Could not mark '%s' as hidden.", filename);
+	}
 	return fd;
 }
 
@@ -348,27 +391,39 @@
 #undef fopen
 FILE *mingw_fopen (const char *filename, const char *otype)
 {
+	int hide = 0;
 	FILE *file;
 	wchar_t wfilename[MAX_PATH], wotype[4];
+	if (hide_dotfiles == HIDE_DOTFILES_TRUE &&
+	    basename((char*)filename)[0] == '.')
+		hide = access(filename, F_OK);
 	if (filename && !strcmp(filename, "/dev/null"))
 		filename = "nul";
 	if (xutftowcs_path(wfilename, filename) < 0 ||
 		xutftowcs(wotype, otype, ARRAY_SIZE(wotype)) < 0)
 		return NULL;
 	file = _wfopen(wfilename, wotype);
+	if (file && hide && make_hidden(wfilename))
+		warning("Could not mark '%s' as hidden.", filename);
 	return file;
 }
 
 FILE *mingw_freopen (const char *filename, const char *otype, FILE *stream)
 {
+	int hide = 0;
 	FILE *file;
 	wchar_t wfilename[MAX_PATH], wotype[4];
+	if (hide_dotfiles == HIDE_DOTFILES_TRUE &&
+	    basename((char*)filename)[0] == '.')
+		hide = access(filename, F_OK);
 	if (filename && !strcmp(filename, "/dev/null"))
 		filename = "nul";
 	if (xutftowcs_path(wfilename, filename) < 0 ||
 		xutftowcs(wotype, otype, ARRAY_SIZE(wotype)) < 0)
 		return NULL;
 	file = _wfreopen(wfilename, wotype, stream);
+	if (file && hide && make_hidden(wfilename))
+		warning("Could not mark '%s' as hidden.", filename);
 	return file;
 }
 
diff --git a/config.c b/config.c
index 058505c..bd851a0 100644
--- a/config.c
+++ b/config.c
@@ -872,6 +872,15 @@
 		return 0;
 	}
 
+	if (!strcmp(var, "core.hidedotfiles")) {
+		if (value && !strcasecmp(value, "dotgitonly")) {
+			hide_dotfiles = HIDE_DOTFILES_DOTGITONLY;
+			return 0;
+		}
+		hide_dotfiles = git_config_bool(var, value);
+		return 0;
+	}
+
 	/* Add other config variables here and to Documentation/config.txt. */
 	return 0;
 }
diff --git a/configure.ac b/configure.ac
index 4b1ae7c..890ef61 100644
--- a/configure.ac
+++ b/configure.ac
@@ -521,6 +521,17 @@
 [NO_CURL=],
 [NO_CURL=YesPlease])
 
+if test -z "$NO_CURL"; then
+
+AC_CHECK_DECLS([curl_multi_init],
+[NO_CURL_MULTI=],
+[NO_CURL_MULTI=UnfortunatelyYes],
+[[#include <curl/curl.h>]])
+
+GIT_CONF_SUBST([NO_CURL_MULTI])
+
+fi
+
 GIT_UNSTASH_FLAGS($CURLDIR)
 
 GIT_CONF_SUBST([NO_CURL])
diff --git a/contrib/credential/wincred/git-credential-wincred.c b/contrib/credential/wincred/git-credential-wincred.c
index a1d38f0..219999d 100644
--- a/contrib/credential/wincred/git-credential-wincred.c
+++ b/contrib/credential/wincred/git-credential-wincred.c
@@ -94,6 +94,12 @@
 static void write_item(const char *what, LPCWSTR wbuf, int wlen)
 {
 	char *buf;
+
+	if (!wbuf || !wlen) {
+		printf("%s=\n", what);
+		return;
+	}
+
 	int len = WideCharToMultiByte(CP_UTF8, 0, wbuf, wlen, NULL, 0, NULL,
 	    FALSE);
 	buf = xmalloc(len);
@@ -141,7 +147,7 @@
 static int match_cred(const CREDENTIALW *cred)
 {
 	LPCWSTR target = cred->TargetName;
-	if (wusername && wcscmp(wusername, cred->UserName))
+	if (wusername && wcscmp(wusername, cred->UserName ? cred->UserName : L""))
 		return 0;
 
 	return match_part(&target, L"git", L":") &&
@@ -164,7 +170,7 @@
 	for (i = 0; i < num_creds; ++i)
 		if (match_cred(creds[i])) {
 			write_item("username", creds[i]->UserName,
-				wcslen(creds[i]->UserName));
+				creds[i]->UserName ? wcslen(creds[i]->UserName) : 0);
 			write_item("password",
 				(LPCWSTR)creds[i]->CredentialBlob,
 				creds[i]->CredentialBlobSize / sizeof(WCHAR));
diff --git a/environment.c b/environment.c
index 565f652..2fd3830 100644
--- a/environment.c
+++ b/environment.c
@@ -63,6 +63,7 @@
 int precomposed_unicode = -1; /* see probe_utf8_pathname_composition() */
 struct startup_info *startup_info;
 unsigned long pack_size_limit_cfg;
+enum hide_dotfiles_type hide_dotfiles = HIDE_DOTFILES_DOTGITONLY;
 
 /*
  * The character that begins a commented line in user-editable file
diff --git a/git-am.sh b/git-am.sh
index ee61a77..98f8b47 100755
--- a/git-am.sh
+++ b/git-am.sh
@@ -184,7 +184,9 @@
 }
 
 clean_abort () {
-	test $# = 0 || echo >&2 "$@"
+	test $# = 0 || cat >&2 <<EOF
+$@
+EOF
 	rm -fr "$dotest"
 	exit 1
 }
@@ -593,7 +595,8 @@
 	'')
 		files=$(git ls-files) ;;
 	?*)
-		files=$(git diff-index --cached --name-only HEAD --) ;;
+		files=$(git diff-index --ignore-submodules --cached \
+			--name-only HEAD --) ;;
 	esac || exit
 	if test "$files"
 	then
@@ -767,7 +770,8 @@
 		case "$resolved$interactive" in
 		tt)
 			# This is used only for interactive view option.
-			git diff-index -p --cached HEAD -- >"$dotest/patch"
+			git diff-index --ignore-submodules -p --cached \
+				HEAD -- >"$dotest/patch"
 			;;
 		esac
 	esac
@@ -843,7 +847,7 @@
 		# trust what the user has in the index file and the
 		# working tree.
 		resolved=
-		git diff-index --quiet --cached HEAD -- && {
+		git diff-index --ignore-submodules --quiet --cached HEAD -- && {
 			gettextln "No changes - did you forget to use 'git add'?
 If there is nothing left to stage, chances are that something else
 already introduced the same changes; you might want to skip this patch."
@@ -867,7 +871,8 @@
 		then
 		    # Applying the patch to an earlier tree and merging the
 		    # result may have produced the same tree as ours.
-		    git diff-index --quiet --cached HEAD -- && {
+		    git diff-index --ignore-submodules --quiet --cached \
+				HEAD -- && {
 			say "$(gettext "No changes -- Patch already applied.")"
 			go_next
 			continue
diff --git a/git-compat-util.h b/git-compat-util.h
index f587749..fc9beb0 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -790,4 +790,8 @@
 #define gmtime_r git_gmtime_r
 #endif
 
+#ifndef mark_as_git_dir
+#define mark_as_git_dir(x) /* noop */
+#endif
+
 #endif
diff --git a/git-gui/Makefile b/git-gui/Makefile
index cde8b2e..e10b1d1 100644
--- a/git-gui/Makefile
+++ b/git-gui/Makefile
@@ -290,6 +290,7 @@
 	$(QUIET)$(INSTALL_D0)'$(DESTDIR_SQ)$(gitexecdir_SQ)' $(INSTALL_D1)
 	$(QUIET)$(INSTALL_X0)git-gui $(INSTALL_X1) '$(DESTDIR_SQ)$(gitexecdir_SQ)'
 	$(QUIET)$(INSTALL_X0)git-gui--askpass $(INSTALL_X1) '$(DESTDIR_SQ)$(gitexecdir_SQ)'
+	$(QUIET)$(INSTALL_X0)git-gui--askyesno $(INSTALL_X1) '$(DESTDIR_SQ)$(gitexecdir_SQ)'
 	$(QUIET)$(foreach p,$(GITGUI_BUILT_INS), $(INSTALL_L0)'$(DESTDIR_SQ)$(gitexecdir_SQ)/$p' $(INSTALL_L1)'$(DESTDIR_SQ)$(gitexecdir_SQ)/git-gui' $(INSTALL_L2)'$(DESTDIR_SQ)$(gitexecdir_SQ)/$p' $(INSTALL_L3) &&) true
 ifdef GITGUI_WINDOWS_WRAPPER
 	$(QUIET)$(INSTALL_R0)git-gui.tcl $(INSTALL_R1) '$(DESTDIR_SQ)$(gitexecdir_SQ)'
@@ -308,6 +309,7 @@
 	$(QUIET)$(CLEAN_DST) '$(DESTDIR_SQ)$(gitexecdir_SQ)'
 	$(QUIET)$(REMOVE_F0)'$(DESTDIR_SQ)$(gitexecdir_SQ)'/git-gui $(REMOVE_F1)
 	$(QUIET)$(REMOVE_F0)'$(DESTDIR_SQ)$(gitexecdir_SQ)'/git-gui--askpass $(REMOVE_F1)
+	$(QUIET)$(REMOVE_F0)'$(DESTDIR_SQ)$(gitexecdir_SQ)'/git-gui--askyesno $(REMOVE_F1)
 	$(QUIET)$(foreach p,$(GITGUI_BUILT_INS), $(REMOVE_F0)'$(DESTDIR_SQ)$(gitexecdir_SQ)'/$p $(REMOVE_F1) &&) true
 ifdef GITGUI_WINDOWS_WRAPPER
 	$(QUIET)$(REMOVE_F0)'$(DESTDIR_SQ)$(gitexecdir_SQ)'/git-gui.tcl $(REMOVE_F1)
diff --git a/git-gui/git-gui--askyesno b/git-gui/git-gui--askyesno
new file mode 100755
index 0000000..2a6e6fd
--- /dev/null
+++ b/git-gui/git-gui--askyesno
@@ -0,0 +1,51 @@
+#!/bin/sh
+# Tcl ignores the next line -*- tcl -*- \
+exec wish "$0" -- "$@"
+
+# This is an implementation of a simple yes no dialog
+# which is injected into the git commandline by git gui
+# in case a yesno question needs to be answered.
+
+set NS {}
+set use_ttk [package vsatisfies [package provide Tk] 8.5]
+if {$use_ttk} {
+	set NS ttk
+}
+
+if {$argc < 1} {
+	puts stderr "Usage: $argv0 <question>"
+	exit 1
+} else {
+	set prompt [join $argv " "]
+}
+
+${NS}::frame .t
+${NS}::label .t.m -text $prompt -justify center -width 40
+.t.m configure -wraplength 400
+pack .t.m -side top -fill x -padx 20 -pady 20 -expand 1
+pack .t -side top -fill x -ipadx 20 -ipady 20 -expand 1
+
+${NS}::frame .b
+${NS}::frame .b.left -width 200
+${NS}::button .b.yes -text Yes -command yes
+${NS}::button .b.no  -text No  -command no
+
+
+pack .b.left -side left -expand 1 -fill x
+pack .b.yes -side left -expand 1
+pack .b.no -side right -expand 1 -ipadx 5
+pack .b -side bottom -fill x -ipadx 20 -ipady 15
+
+bind . <Key-Return> {exit 0}
+bind . <Key-Escape> {exit 1}
+
+proc no {} {
+	exit 1
+}
+
+proc yes {} {
+	exit 0
+}
+
+wm title . "Question?"
+tk::PlaceWindow .
diff --git a/git-gui/git-gui.sh b/git-gui/git-gui.sh
index b186329..3f1fe0a 100755
--- a/git-gui/git-gui.sh
+++ b/git-gui/git-gui.sh
@@ -548,6 +548,9 @@
 
 	_trace_exec [concat $opt $cmdp $args]
 	set result [eval exec $opt $cmdp $args]
+	if {[encoding system] != "utf-8"} {
+		set result [encoding convertfrom utf-8 [encoding convertto $result]]
+	}
 	if {$::_trace} {
 		puts stderr "< $result"
 	}
@@ -1104,7 +1107,7 @@
 				[list git_read config] \
 				$args \
 				[list --null --list]]
-			fconfigure $fd_rc -translation binary
+			fconfigure $fd_rc -translation binary -encoding utf-8
 			set buf [read $fd_rc]
 			close $fd_rc
 		}
@@ -1241,6 +1244,12 @@
 if {![info exists env(SSH_ASKPASS)]} {
 	set env(SSH_ASKPASS) [gitexec git-gui--askpass]
 }
+if {![info exists env(GIT_ASKPASS)]} {
+	set env(GIT_ASKPASS) [gitexec git-gui--askpass]
+}
+if {![info exists env(GIT_ASK_YESNO)]} {
+	set env(GIT_ASK_YESNO) [gitexec git-gui--askyesno]
+}
 
 ######################################################################
 ##
@@ -1337,9 +1346,6 @@
 	set _reponame [lindex $_reponame end]
 }
 
-set env(GIT_DIR) $_gitdir
-set env(GIT_WORK_TREE) $_gitworktree
-
 ######################################################################
 ##
 ## global init
@@ -1682,7 +1688,7 @@
 		set i [split [string range $buf_rdi $c [expr {$z1 - 2}]] { }]
 		set p [string range $buf_rdi $z1 [expr {$z2 - 1}]]
 		merge_state \
-			[encoding convertfrom $p] \
+			[encoding convertfrom utf-8 $p] \
 			[lindex $i 4]? \
 			[list [lindex $i 0] [lindex $i 2]] \
 			[list]
@@ -1715,7 +1721,7 @@
 		set i [split [string range $buf_rdf $c [expr {$z1 - 2}]] { }]
 		set p [string range $buf_rdf $z1 [expr {$z2 - 1}]]
 		merge_state \
-			[encoding convertfrom $p] \
+			[encoding convertfrom utf-8 $p] \
 			?[lindex $i 4] \
 			[list] \
 			[list [lindex $i 0] [lindex $i 2]]
@@ -1738,7 +1744,7 @@
 	set pck [split $buf_rlo "\0"]
 	set buf_rlo [lindex $pck end]
 	foreach p [lrange $pck 0 end-1] {
-		set p [encoding convertfrom $p]
+		set p [encoding convertfrom utf-8 $p]
 		if {[string index $p end] eq {/}} {
 			set p [string range $p 0 end-1]
 		}
@@ -2159,7 +2165,7 @@
 
 proc do_gitk {revs {is_submodule false}} {
 	global current_diff_path file_states current_diff_side ui_index
-	global _gitdir _gitworktree
+	global _gitworktree
 
 	# -- Always start gitk through whatever we were loaded with.  This
 	#    lets us bypass using shell process on Windows systems.
@@ -2171,12 +2177,19 @@
 	} else {
 		global env
 
+		if {[info exists env(GIT_DIR)]} {
+			set old_GIT_DIR $env(GIT_DIR)
+		} else {
+			set old_GIT_DIR {}
+		}
+
 		set pwd [pwd]
 
 		if {!$is_submodule} {
 			if {![is_bare]} {
 				cd $_gitworktree
 			}
+			set env(GIT_DIR) [file normalize [gitdir]]
 		} else {
 			cd $current_diff_path
 			if {$revs eq {--}} {
@@ -2197,18 +2210,15 @@
 				}
 				set revs $old_sha1...$new_sha1
 			}
-			# GIT_DIR and GIT_WORK_TREE for the submodule are not the ones
-			# we've been using for the main repository, so unset them.
-			# TODO we could make life easier (start up faster?) for gitk
-			# by setting these to the appropriate values to allow gitk
-			# to skip the heuristics to find their proper value
-			unset env(GIT_DIR)
-			unset env(GIT_WORK_TREE)
+			if {[info exists env(GIT_DIR)]} {
+				unset env(GIT_DIR)
+			}
 		}
 		eval exec $cmd $revs "--" "--" &
 
-		set env(GIT_DIR) $_gitdir
-		set env(GIT_WORK_TREE) $_gitworktree
+		if {$old_GIT_DIR ne {}} {
+			set env(GIT_DIR) $old_GIT_DIR
+		}
 		cd $pwd
 
 		ui_status $::starting_gitk_msg
@@ -2229,20 +2239,22 @@
 		error_popup [mc "Couldn't find git gui in PATH"]
 	} else {
 		global env
-		global _gitdir _gitworktree
 
-		# see note in do_gitk about unsetting these vars when
-		# running tools in a submodule
-		unset env(GIT_DIR)
-		unset env(GIT_WORK_TREE)
+		if {[info exists env(GIT_DIR)]} {
+			set old_GIT_DIR $env(GIT_DIR)
+			unset env(GIT_DIR)
+		} else {
+			set old_GIT_DIR {}
+		}
 
 		set pwd [pwd]
 		cd $current_diff_path
 
 		eval exec $exe gui &
 
-		set env(GIT_DIR) $_gitdir
-		set env(GIT_WORK_TREE) $_gitworktree
+		if {$old_GIT_DIR ne {}} {
+			set env(GIT_DIR) $old_GIT_DIR
+		}
 		cd $pwd
 
 		ui_status $::starting_gitk_msg
diff --git a/git-gui/lib/browser.tcl b/git-gui/lib/browser.tcl
index 0328338..555db89 100644
--- a/git-gui/lib/browser.tcl
+++ b/git-gui/lib/browser.tcl
@@ -197,7 +197,7 @@
 	$w conf -state disabled
 
 	set fd [git_read ls-tree -z $tree_id]
-	fconfigure $fd -blocking 0 -translation binary -encoding binary
+	fconfigure $fd -blocking 0 -translation binary -encoding utf-8
 	fileevent $fd readable [cb _read $fd]
 }
 
diff --git a/git-gui/lib/index.tcl b/git-gui/lib/index.tcl
index 74a81a7..d10ffe9 100644
--- a/git-gui/lib/index.tcl
+++ b/git-gui/lib/index.tcl
@@ -115,7 +115,7 @@
 		set info [lindex $s 2]
 		if {$info eq {}} continue
 
-		puts -nonewline $fd "$info\t[encoding convertto $path]\0"
+		puts -nonewline $fd "$info\t[encoding convertto utf-8 $path]\0"
 		display_file $path $new
 	}
 
@@ -186,7 +186,7 @@
 		?M {set new M_}
 		?? {continue}
 		}
-		puts -nonewline $fd "[encoding convertto $path]\0"
+		puts -nonewline $fd "[encoding convertto utf-8 $path]\0"
 		display_file $path $new
 	}
 
@@ -247,7 +247,7 @@
 		?M -
 		?T -
 		?D {
-			puts -nonewline $fd "[encoding convertto $path]\0"
+			puts -nonewline $fd "[encoding convertto utf-8 $path]\0"
 			display_file $path ?_
 		}
 		}
diff --git a/git-merge-octopus.sh b/git-merge-octopus.sh
index 8643f74..2226eeb 100755
--- a/git-merge-octopus.sh
+++ b/git-merge-octopus.sh
@@ -71,7 +71,9 @@
 
 	case "$LF$common$LF" in
 	*"$LF$SHA1$LF"*)
-		echo "Already up-to-date with $pretty_name"
+		cat << EOF
+Already up-to-date with $pretty_name
+EOF
 		continue
 		;;
 	esac
@@ -83,7 +85,9 @@
 		# tree as the intermediate result of the merge.
 		# We still need to count this as part of the parent set.
 
-		echo "Fast-forwarding to: $pretty_name"
+		cat << EOF
+Fast-forwarding to: $pretty_name
+EOF
 		git read-tree -u -m $head $SHA1 || exit
 		MRC=$SHA1 MRT=$(git write-tree)
 		continue
@@ -91,7 +95,9 @@
 
 	NON_FF_MERGE=1
 
-	echo "Trying simple merge with $pretty_name"
+	cat << EOF
+Trying simple merge with $pretty_name
+EOF
 	git read-tree -u -m --aggressive  $common $MRT $SHA1 || exit 2
 	next=$(git write-tree 2>/dev/null)
 	if test $? -ne 0
diff --git a/git-pull.sh b/git-pull.sh
index 18a394f..2a17930 100755
--- a/git-pull.sh
+++ b/git-pull.sh
@@ -135,6 +135,7 @@
 		;;
 	--no-r|--no-re|--no-reb|--no-reba|--no-rebas|--no-rebase)
 		rebase=false
+
 		;;
 	--recurse-submodules)
 		recurse_submodules=--recurse-submodules
@@ -175,6 +176,10 @@
 done
 
 case "$rebase" in
+i|interactive)
+	rebase=true
+	rebase_args=-i
+	;;
 preserve)
 	rebase=true
 	rebase_args=--preserve-merges
@@ -182,7 +187,7 @@
 true|false|'')
 	;;
 *)
-	echo "Invalid value for --rebase, should be true, false, or preserve"
+	echo "Invalid value for --rebase, should be true, false, interactive or preserve"
 	usage
 	exit 1
 	;;
diff --git a/git-sh-setup.sh b/git-sh-setup.sh
index 9447980..5adc011 100644
--- a/git-sh-setup.sh
+++ b/git-sh-setup.sh
@@ -59,7 +59,9 @@
 say () {
 	if test -z "$GIT_QUIET"
 	then
-		printf '%s\n' "$*"
+		cat <<EOF
+$*
+EOF
 	fi
 }
 
diff --git a/git-submodule.sh b/git-submodule.sh
index 9245abf..a0d8705 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -434,9 +434,11 @@
 
 	if test -z "$force" && ! git add --dry-run --ignore-missing "$sm_path" > /dev/null 2>&1
 	then
-		eval_gettextln "The following path is ignored by one of your .gitignore files:
-\$sm_path
-Use -f if you really want to add it." >&2
+		cat >&2 <<EOF
+The following path is ignored by one of your .gitignore files:
+$(eval_gettextln $sm_path)
+Use -f if you really want to add it.
+EOF
 		exit 1
 	fi
 
diff --git a/gitk-git/gitk b/gitk-git/gitk
index 3520bda..90e83a6 100755
--- a/gitk-git/gitk
+++ b/gitk-git/gitk
@@ -404,7 +404,7 @@
 	if {$revs eq {}} {
 	    return 0
 	}
-	set args [concat $vflags($view) $revs]
+	set args [limit_arg_length [concat $vflags($view) $revs]]
     } else {
 	set args $vorigargs($view)
     }
@@ -7557,7 +7557,7 @@
 	if {[string index $fname 0] eq "\""} {
 	    set fname [lindex $fname 0]
 	}
-	set fname [encoding convertfrom $fname]
+	set fname [encoding convertfrom utf-8 $fname]
 	lappend treefilelist($id) $fname
     }
     if {![eof $gtf]} {
@@ -7819,7 +7819,7 @@
 	    if {[string index $file 0] eq "\""} {
 		set file [lindex $file 0]
 	    }
-	    set file [encoding convertfrom $file]
+	    set file [encoding convertfrom utf-8 $file]
 	    if {$file ne [lindex $treediff end]} {
 		lappend treediff $file
 		lappend sublist $file
@@ -7964,7 +7964,7 @@
     global ctext curdiffstart treediffs diffencoding
     global ctext_file_names jump_to_here targetline diffline
 
-    set fname [encoding convertfrom $fname]
+    set fname [encoding convertfrom utf-8 $fname]
     set diffencoding [get_path_encoding $fname]
     set i [lsearch -exact $treediffs($ids) $fname]
     if {$i >= 0} {
@@ -8021,7 +8021,7 @@
 
     if {![string compare -length 5 "diff " $line]} {
 	if {![regexp {^diff (--cc|--git) } $line m type]} {
-	    set line [encoding convertfrom $line]
+	    set line [encoding convertfrom utf-8 $line]
 	    $ctext insert end "$line\n" hunksep
 	    continue
 	}
@@ -8068,7 +8068,7 @@
 	makediffhdr $fname $ids
 
     } elseif {![string compare -length 16 "* Unmerged path " $line]} {
-	set fname [encoding convertfrom [string range $line 16 end]]
+	set fname [encoding convertfrom utf-8 [string range $line 16 end]]
 	$ctext insert end "\n"
 	set curdiffstart [$ctext index "end - 1c"]
 	lappend ctext_file_names $fname
@@ -8123,7 +8123,7 @@
 	    if {[string index $fname 0] eq "\""} {
 		set fname [lindex $fname 0]
 	    }
-	    set fname [encoding convertfrom $fname]
+	    set fname [encoding convertfrom utf-8 $fname]
 	    set i [lsearch -exact $treediffs($ids) $fname]
 	    if {$i >= 0} {
 		setinlist difffilestart $i $curdiffstart
@@ -8142,6 +8142,7 @@
 	    set diffinhdr 0
 	    return
 	}
+	set line [encoding convertfrom utf-8 $line]
 	$ctext insert end "$line\n" filesep
 
     } else {
@@ -9969,7 +9970,8 @@
 	}
     }
     if {$ids ne {}} {
-	set fd [open [concat $cmd $ids] r]
+	set cmd [limit_arg_length [concat $cmd $ids]]
+	set fd [open $cmd r]
 	fconfigure $fd -blocking 0
 	incr allcommits
 	nowbusy allcommits
@@ -9979,6 +9981,21 @@
     }
 }
 
+# The maximum command line length for the CreateProcess function is 32767 characters, see
+# http://blogs.msdn.com/oldnewthing/archive/2003/12/10/56028.aspx
+# Be a little conservative in case Tcl adds some more stuff to the command line we do not
+# know about and truncate the command line at a SHA1-boundary below 32000 characters.
+proc limit_arg_length {cmd} {
+    if {[tk windowingsystem] == "win32" &&
+       [string length $cmd] > 32000} {
+        set ndx [string last " " $cmd 32000]
+        if {$ndx != -1} {
+            return [string range $cmd 0 $ndx]
+        }
+    }
+    return $cmd
+}
+
 # Since most commits have 1 parent and 1 child, we group strings of
 # such commits into "arcs" joining branch/merge points (BMPs), which
 # are commits that either don't have 1 parent or don't have 1 child.
@@ -11952,7 +11969,7 @@
 	    foreach row [split $rlist "\n"] {
 		if {[regexp "(.*): $attr: (.*)" $row m path value]} {
 		    if {[string index $path 0] eq "\""} {
-			set path [encoding convertfrom [lindex $path 0]]
+			set path [encoding convertfrom utf-8 [lindex $path 0]]
 		    }
 		    set path_attr_cache($attr,$path) $value
 		}
@@ -12135,7 +12152,6 @@
     set gitk_prefix [file dirname [file dirname [file normalize $argv0]]]
     set gitk_libdir [file join $gitk_prefix share gitk lib]
     set gitk_msgsdir [file join $gitk_libdir msgs]
-    unset gitk_prefix
 }
 
 ## Internationalization (i18n) through msgcat and gettext. See
@@ -12314,28 +12330,32 @@
 set worktree [exec git rev-parse --show-toplevel]
 setcoords
 makewindow
-catch {
-    image create photo gitlogo      -width 16 -height 16
+if {$::tcl_platform(platform) eq {windows} && [file exists $gitk_prefix/etc/git.ico]} {
+    wm iconbitmap . -default $gitk_prefix/etc/git.ico
+} else {
+    catch {
+        image create photo gitlogo      -width 16 -height 16
 
-    image create photo gitlogominus -width  4 -height  2
-    gitlogominus put #C00000 -to 0 0 4 2
-    gitlogo copy gitlogominus -to  1 5
-    gitlogo copy gitlogominus -to  6 5
-    gitlogo copy gitlogominus -to 11 5
-    image delete gitlogominus
+        image create photo gitlogominus -width  4 -height  2
+        gitlogominus put #C00000 -to 0 0 4 2
+        gitlogo copy gitlogominus -to  1 5
+        gitlogo copy gitlogominus -to  6 5
+        gitlogo copy gitlogominus -to 11 5
+        image delete gitlogominus
 
-    image create photo gitlogoplus  -width  4 -height  4
-    gitlogoplus  put #008000 -to 1 0 3 4
-    gitlogoplus  put #008000 -to 0 1 4 3
-    gitlogo copy gitlogoplus  -to  1 9
-    gitlogo copy gitlogoplus  -to  6 9
-    gitlogo copy gitlogoplus  -to 11 9
-    image delete gitlogoplus
+        image create photo gitlogoplus  -width  4 -height  4
+        gitlogoplus  put #008000 -to 1 0 3 4
+        gitlogoplus  put #008000 -to 0 1 4 3
+        gitlogo copy gitlogoplus  -to  1 9
+        gitlogo copy gitlogoplus  -to  6 9
+        gitlogo copy gitlogoplus  -to 11 9
+        image delete gitlogoplus
 
-    image create photo gitlogo32    -width 32 -height 32
-    gitlogo32 copy gitlogo -zoom 2 2
+        image create photo gitlogo32    -width 32 -height 32
+        gitlogo32 copy gitlogo -zoom 2 2
 
-    wm iconphoto . -default gitlogo gitlogo32
+        wm iconphoto . -default gitlogo gitlogo32
+    }
 }
 # wait for the window to become visible
 tkwait visibility .
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index a9f57d6..7cd317a 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -4543,6 +4543,29 @@
 			print $cgi->a({-href => href(action=>"blob_plain", file_name=>$file_name,
 			                             hash_base=>$hb),
 			              -title => $name}, esc_path($basename));
+			if (gitweb_check_feature('highlight')) {
+				print '&nbsp;&nbsp;&nbsp;&nbsp;
+<a id="lineNoToggle" href="#" onclick="toggleLineNumbers();"></a>
+<script>
+function toggleLineNumbers() {
+        e = document.getElementById("lineNoStyle");
+        e2 = document.getElementById("lineNoToggle");
+        if (e2.innerHTML == "[Hide line numbers]") {
+                e.innerHTML = ".linenr { display:none; }";
+                e2.innerHTML = "[Show line numbers]";
+        }
+        else {
+                e.innerHTML = "";
+                e2.innerHTML = "[Hide line numbers]";
+        }
+}
+var style = document.createElement("style");
+style.setAttribute("id", "lineNoStyle");
+document.getElementsByTagName("head")[0].appendChild(style);
+toggleLineNumbers();
+</script>
+';
+			}
 		} elsif (defined $type && $type eq 'tree') {
 			print $cgi->a({-href => href(action=>"tree", file_name=>$file_name,
 			                             hash_base=>$hb),
@@ -7054,7 +7077,19 @@
 	# we can have blame only for text/* mimetype
 	$have_blame &&= ($mimetype =~ m!^text/!);
 
+	my $highlight_js = gitweb_check_feature('syntaxhighlighter_js');
+	if ($highlight_js) {
+		push @stylesheets, $highlight_js->{url} . '/styles/shCore'
+			. $highlight_js->{style} . '.css';
+		push @stylesheets, $highlight_js->{url} . '/styles/shTheme'
+			. $highlight_js->{theme} . '.css';
+	}
+
 	my $highlight = gitweb_check_feature('highlight');
+	if ($highlight_js && $highlight) {
+		die_error(500, 'The highlight and syntaxhighlighter_js are'
+			. 'mutually exclusive');
+	}
 	my $syntax = guess_file_syntax($highlight, $mimetype, $file_name);
 	$fd = run_highlighter($fd, $highlight, $syntax)
 		if $syntax;
@@ -7102,6 +7137,72 @@
 		      href(action=>"blob_plain", hash=>$hash,
 		           hash_base=>$hash_base, file_name=>$file_name) .
 		      qq!" />\n!;
+	} elsif ($highlight_js) {
+		my $ext = $file_name;
+		$ext =~ s/.*\.//;
+		print qq!<pre class="brush:!.$ext.qq!">!;
+		while (my $line = <$fd>) {
+			$line =~ s!&!\&#38;!g;
+			$line =~ s!<!\&#60;!g;
+			print $line;
+		}
+		print qq!</pre>!;
+		foreach my $name ('Core', 'Autoloader') {
+			print qq!<script src="!.$highlight_js->{url}
+				.qq!/scripts/sh!.$name
+				.qq!.js" type="text/javascript"></script>!;
+		}
+		print qq!<script type="text/javascript">!;
+		print qq!SyntaxHighlighter.defaults["pad-line-numbers"] = 3;!;
+		print qq!SyntaxHighlighter.defaults["toolbar"] = false;!;
+		# for XHTML compliance
+		print qq!SyntaxHighlighter.config["space"] = '&#160;';!;
+		print qq!SyntaxHighlighter.autoloader(!;
+		my $brush_prefix = $highlight_js->{url} . '/scripts/shBrush';
+		foreach my $language ('applescript AppleScript',
+				'actionscript3 as3 AS3',
+				'bash shell Bash',
+				'clj Clojure',
+				'coldfusion cf ColdFusion',
+				'cpp c Cpp',
+				'c# c-sharp csharp CSharp',
+				'css Css',
+				'delphi pascal Delphi',
+				'diff patch pas Diff',
+				'erl erlang Erlang',
+				'groovy Groovy',
+				'java Java',
+				'jfx javafx JavaFX',
+				'js jscript javascript JScript',
+				'perl pl Perl',
+				'php Php',
+				'text plain Plain',
+				'py python Python',
+				'ruby rails ror rb Ruby',
+				'scala Scala',
+				'scm Scheme',
+				'sql Sql',
+				'vb vbnet Vb',
+				'xml xhtml xslt html Xml') {
+			my $lang = $language;
+			$lang =~ s! (\S+)$! $brush_prefix$1!;
+			print "'".$lang.qq!.js',!;
+		}
+		print qq!''); SyntaxHighlighter.all();!
+			.qq!function scrollTo(number) {!
+			.qq!  var elements = document.getElementsByClassName(number);!
+			.qq!  if (elements.length == 0) setTimeout('scrollTo("' + number + '");', 50);!
+			.qq!  else {!
+			.qq!    window.scroll(0, elements[0].offsetTop);!
+			.qq!    window.scrollTo(0, elements[0].offsetTop);!
+			.qq!    elements[0].style.color = '#ff0000';!
+			.qq!  }!
+			.qq!}!
+			.qq!var lineRegex = /#l(\\d+)\$/;!
+			.qq!var lineNumber = lineRegex.exec(document.URL);!
+			.qq!if (lineNumber)!
+			.qq!  scrollTo('number' + lineNumber[1]);!
+			.qq!</script>!;
 	} else {
 		my $nr;
 		while (my $line = <$fd>) {
diff --git a/t/annotate-tests.sh b/t/annotate-tests.sh
index 071e4d7..80262ed 100644
--- a/t/annotate-tests.sh
+++ b/t/annotate-tests.sh
@@ -263,27 +263,27 @@
 '
 
 test_expect_success 'blame -L /RE/ (RE to end)' '
-	check_count -L/evil/ C 1 "A U Thor" 1
+	check_count -L/\;*evil/ C 1 "A U Thor" 1
 '
 
 test_expect_success 'blame -L /RE/,/RE2/' '
-	check_count -L/robot/,/green/ A 1 B 1 B2 1 D 1 E 1
+	check_count -L/\;*robot/,/\;*green/ A 1 B 1 B2 1 D 1 E 1
 '
 
 test_expect_success 'blame -L X,/RE/' '
-	check_count -L5,/evil/ B1 1 D 1 "A U Thor" 1
+	check_count -L5,/\;*evil/ B1 1 D 1 "A U Thor" 1
 '
 
 test_expect_success 'blame -L /RE/,Y' '
-	check_count -L/99/,7 B1 1 D 1 "A U Thor" 1
+	check_count -L/\;*99/,7 B1 1 D 1 "A U Thor" 1
 '
 
 test_expect_success 'blame -L /RE/,+N' '
-	check_count -L/99/,+3 B1 1 D 1 "A U Thor" 1
+	check_count -L/\;*99/,+3 B1 1 D 1 "A U Thor" 1
 '
 
 test_expect_success 'blame -L /RE/,-N' '
-	check_count -L/99/,-3 B 1 B2 1 D 1
+	check_count -L/\;*99/,-3 B 1 B2 1 D 1
 '
 
 # 'file' ends with an incomplete line, so 'wc' reports one fewer lines than
@@ -349,19 +349,19 @@
 '
 
 test_expect_success 'blame -L /RE/ (relative)' '
-	check_count -L3,3 -L/fox/ B1 1 B2 1 C 1 D 1 "A U Thor" 1
+	check_count -L3,3 -L/\;*fox/ B1 1 B2 1 C 1 D 1 "A U Thor" 1
 '
 
 test_expect_success 'blame -L /RE/ (relative: no preceding range)' '
-	check_count -L/dog/ A 1 B 1 B1 1 B2 1 C 1 D 1 "A U Thor" 1
+	check_count -L/\;*dog/ A 1 B 1 B1 1 B2 1 C 1 D 1 "A U Thor" 1
 '
 
 test_expect_success 'blame -L /RE/ (relative: adjacent)' '
-	check_count -L1,1 -L/dog/,+1 A 1 E 1
+	check_count -L1,1 -L/\;*dog/,+1 A 1 E 1
 '
 
 test_expect_success 'blame -L /RE/ (relative: not found)' '
-	test_must_fail $PROG -L4,4 -L/dog/ file
+	test_must_fail $PROG -L4,4 -L/\;*dog/ file
 '
 
 test_expect_success 'blame -L /RE/ (relative: end-of-file)' '
@@ -369,11 +369,11 @@
 '
 
 test_expect_success 'blame -L ^/RE/ (absolute)' '
-	check_count -L3,3 -L^/dog/,+2 A 1 B2 1
+	check_count -L3,3 -L^/\;*dog/,+2 A 1 B2 1
 '
 
 test_expect_success 'blame -L ^/RE/ (absolute: no preceding range)' '
-	check_count -L^/dog/,+2 A 1 B2 1
+	check_count -L^/\;*dog/,+2 A 1 B2 1
 '
 
 test_expect_success 'blame -L ^/RE/ (absolute: not found)' '
diff --git a/t/lib-credential.sh b/t/lib-credential.sh
index 9e7d796..c58f50b 100755
--- a/t/lib-credential.sh
+++ b/t/lib-credential.sh
@@ -44,6 +44,7 @@
 	reject $1 https example.com user2
 	reject $1 http path.tld user
 	reject $1 https timeout.tld user
+	reject $1 https sso.tld
 }
 
 reject() {
@@ -250,6 +251,24 @@
 		password=pass2
 		EOF
 	'
+
+	test_expect_success "helper ($HELPER) can store empty username" '
+		check approve $HELPER <<-\EOF &&
+		protocol=https
+		host=sso.tld
+		username=
+		password=
+		EOF
+		check fill $HELPER <<-\EOF
+		protocol=https
+		host=sso.tld
+		--
+		protocol=https
+		host=sso.tld
+		username=
+		password=
+		EOF
+	'
 }
 
 helper_test_timeout() {
diff --git a/t/lib-git-daemon.sh b/t/lib-git-daemon.sh
index bc4b341..9b1271c 100644
--- a/t/lib-git-daemon.sh
+++ b/t/lib-git-daemon.sh
@@ -23,6 +23,11 @@
 	test_done
 fi
 
+if ! test_have_prereq PIPE
+then
+	test_skip_or_die $GIT_TEST_GIT_DAEMON "file system does not support FIFOs"
+fi
+
 LIB_GIT_DAEMON_PORT=${LIB_GIT_DAEMON_PORT-${this_test#t}}
 
 GIT_DAEMON_PID=
diff --git a/t/t0001-init.sh b/t/t0001-init.sh
index e62c0ff..71b8d8f 100755
--- a/t/t0001-init.sh
+++ b/t/t0001-init.sh
@@ -332,4 +332,32 @@
 	test_path_is_dir realgitdir/refs
 '
 
+# Tests for the hidden file attribute on windows
+is_hidden () {
+	test "1" -eq "$(echo puts [file attributes $1 -hidden]|tclsh)"
+}
+
+test_expect_success MINGW 'plain hidden' '
+	rm -rf newdir &&
+	(
+		unset GIT_DIR GIT_WORK_TREE
+		mkdir newdir &&
+		cd newdir &&
+		git init &&
+		is_hidden .git
+	) &&
+	check_config newdir/.git false unset
+'
+
+test_expect_success MINGW 'plain bare not hidden' '
+	rm -rf newdir
+	(
+		unset GIT_DIR GIT_WORK_TREE GIT_CONFIG
+		mkdir newdir &&
+		cd newdir &&
+		git --bare init
+	) &&
+	! is_hidden newdir
+'
+
 test_done
diff --git a/t/t0008-ignores.sh b/t/t0008-ignores.sh
index 39e55a1..f197c3a 100755
--- a/t/t0008-ignores.sh
+++ b/t/t0008-ignores.sh
@@ -5,7 +5,13 @@
 . ./test-lib.sh
 
 init_vars () {
-	global_excludes="$(pwd)/global-excludes"
+	# On Windows, avoid using "C:" in the global-excludes paths.
+	if test_have_prereq MINGW
+	then
+		global_excludes="global-excludes"
+	else
+		global_excludes="$(pwd)/global-excludes"
+	fi
 }
 
 enable_global_excludes () {
diff --git a/t/t0026-eol-config.sh b/t/t0026-eol-config.sh
index 4807b0f..43a580a 100755
--- a/t/t0026-eol-config.sh
+++ b/t/t0026-eol-config.sh
@@ -80,4 +80,22 @@
 	test -z "$onediff" && test -z "$twodiff"
 '
 
+test_expect_success NATIVE_CRLF 'eol native is crlf' '
+
+	rm -rf native_eol && mkdir native_eol &&
+	( cd native_eol &&
+	printf "*.txt text\n" > .gitattributes
+	printf "one\r\ntwo\r\nthree\r\n" > filedos.txt
+	printf "one\ntwo\nthree\n" > fileunix.txt
+	git init &&
+	git config core.autocrlf false &&
+	git config core.eol native &&
+	git add filedos.txt fileunix.txt &&
+	git commit -m "first" &&
+	rm file*.txt &&
+	git reset --hard HEAD &&
+	has_cr filedos.txt && has_cr fileunix.txt
+	)
+'
+
 test_done
diff --git a/t/t1050-large.sh b/t/t1050-large.sh
index aea4936..4be4a56 100755
--- a/t/t1050-large.sh
+++ b/t/t1050-large.sh
@@ -9,10 +9,10 @@
 	# clone does not allow us to pass core.bigfilethreshold to
 	# new repos, so set core.bigfilethreshold globally
 	git config --global core.bigfilethreshold 200k &&
-	echo X | dd of=large1 bs=1k seek=2000 &&
-	echo X | dd of=large2 bs=1k seek=2000 &&
-	echo X | dd of=large3 bs=1k seek=2000 &&
-	echo Y | dd of=huge bs=1k seek=2500 &&
+	perl -e "print \"\\0\" x 2048000; print \"X\\n\";" > large1 &&
+	perl -e "print \"\\0\" x 2048000; print \"X\\n\";" > large2 &&
+	perl -e "print \"\\0\" x 2048000; print \"X\\n\";" > large3 &&
+	perl -e "print \"\\0\" x 2560000; print \"Y\\n\";" > huge &&
 	GIT_ALLOC_LIMIT=1500 &&
 	export GIT_ALLOC_LIMIT
 '
diff --git a/t/t1501-worktree.sh b/t/t1501-worktree.sh
index 8f36aa9..06982bd 100755
--- a/t/t1501-worktree.sh
+++ b/t/t1501-worktree.sh
@@ -339,6 +339,10 @@
 	git --git-dir="$(pwd)//repo.git" --work-tree="$(pwd)" add dummy_file
 '
 
+test_have_prereq MINGW &&
+# make sure to test DOS path on Windows
+TRASH_DIRECTORY="$(cd "$TRASH_DIRECTORY" && pwd)"
+
 test_expect_success 'relative $GIT_WORK_TREE and git subprocesses' '
 	GIT_DIR=repo.git GIT_WORK_TREE=repo.git/work \
 	test-subprocess --setup-work-tree rev-parse --show-toplevel >actual &&
diff --git a/t/t3102-ls-tree-wildcards.sh b/t/t3102-ls-tree-wildcards.sh
index c286854..766af3d 100755
--- a/t/t3102-ls-tree-wildcards.sh
+++ b/t/t3102-ls-tree-wildcards.sh
@@ -4,14 +4,14 @@
 
 . ./test-lib.sh
 
-test_expect_success 'setup' '
+test_expect_success NOT_MINGW 'setup' '
 	mkdir a aa "a[a]" &&
 	touch a/one aa/two "a[a]/three" &&
 	git add a/one aa/two "a[a]/three" &&
 	git commit -m test
 '
 
-test_expect_success 'ls-tree a[a] matches literally' '
+test_expect_success NOT_MINGW 'ls-tree a* matches literally' '
 	cat >expected <<EOF &&
 100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391	a[a]/three
 EOF
diff --git a/t/t4130-apply-criss-cross-rename.sh b/t/t4130-apply-criss-cross-rename.sh
index d173acd..bf7049e 100755
--- a/t/t4130-apply-criss-cross-rename.sh
+++ b/t/t4130-apply-criss-cross-rename.sh
@@ -14,8 +14,8 @@
 
 test_expect_success 'setup' '
 	create_file file1 "File1 contents" &&
-	create_file file2 "File2 contents" &&
-	create_file file3 "File3 contents" &&
+	create_file file2 "File2 more contents" &&
+	create_file file3 "File3 even more contents" &&
 	git add file1 file2 file3 &&
 	git commit -m 1
 '
diff --git a/t/t5504-fetch-receive-strict.sh b/t/t5504-fetch-receive-strict.sh
index 69ee13c..bb8bc94 100755
--- a/t/t5504-fetch-receive-strict.sh
+++ b/t/t5504-fetch-receive-strict.sh
@@ -101,7 +101,7 @@
 		git config transfer.fsckobjects false
 	) &&
 	test_must_fail git push --porcelain dst master:refs/heads/test >act &&
-	test_cmp exp act
+	test_cmp exp act || test ! -s act
 '
 
 test_expect_success 'push with transfer.fsckobjects' '
@@ -112,7 +112,7 @@
 		git config transfer.fsckobjects true
 	) &&
 	test_must_fail git push --porcelain dst master:refs/heads/test >act &&
-	test_cmp exp act
+	test_cmp exp act || test ! -s act
 '
 
 test_done
diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
index 67e0ab3..0df3210 100755
--- a/t/t5516-fetch-push.sh
+++ b/t/t5516-fetch-push.sh
@@ -1277,4 +1277,40 @@
 	git push --no-thin --receive-pack="$rcvpck" no-thin/.git refs/heads/master:refs/heads/foo
 '
 
+test_expect_success 'receive.denyCurrentBranch = updateInstead' '
+	git push testrepo master &&
+	(cd testrepo &&
+		git reset --hard &&
+		git config receive.denyCurrentBranch updateInstead
+	) &&
+	test_commit third path2 &&
+	git push testrepo master &&
+	test $(git rev-parse HEAD) = $(cd testrepo && git rev-parse HEAD) &&
+	test third = "$(cat testrepo/path2)" &&
+	(cd testrepo &&
+		git update-index --refresh &&
+		git diff-files --quiet &&
+		git diff-index --cached HEAD --
+	)
+'
+
+test_expect_success 'receive.denyCurrentBranch = detachInstead' '
+	(cd testrepo &&
+		git reset --hard &&
+		git config receive.denyCurrentBranch detachInstead
+	) &&
+	OLDHEAD=$(cd testrepo && git rev-parse HEAD) &&
+	test_commit fourth path2 &&
+	test fourth = "$(cat path2)" &&
+	git push testrepo master &&
+	test $OLDHEAD = $(cd testrepo && git rev-parse HEAD) &&
+	test fourth != "$(cat testrepo/path2)" &&
+	(cd testrepo &&
+		test_must_fail git symbolic-ref HEAD &&
+		git update-index --refresh &&
+		git diff-files --quiet &&
+		git diff-index --cached HEAD --
+	)
+'
+
 test_done
diff --git a/t/t6038-merge-text-auto.sh b/t/t6038-merge-text-auto.sh
index d9c2d38..85c10b0 100755
--- a/t/t6038-merge-text-auto.sh
+++ b/t/t6038-merge-text-auto.sh
@@ -72,6 +72,10 @@
 	same line
 	EOF
 
+	if test_have_prereq NATIVE_CRLF; then
+		append_cr <expected >expected.temp &&
+		mv expected.temp expected
+	fi &&
 	git config merge.renormalize true &&
 	git rm -fr . &&
 	rm -f .gitattributes &&
@@ -86,6 +90,10 @@
 	same line
 	EOF
 
+	if test_have_prereq NATIVE_CRLF; then
+		append_cr <expected >expected.temp &&
+		mv expected.temp expected
+	fi &&
 	git config merge.renormalize true &&
 	git rm -fr . &&
 	rm -f .gitattributes &&
@@ -95,16 +103,19 @@
 '
 
 test_expect_success 'Detect CRLF/LF conflict after setting text=auto' '
-	q_to_cr <<-\EOF >expected &&
-	<<<<<<<
-	first line
-	same line
-	=======
-	first lineQ
-	same lineQ
-	>>>>>>>
-	EOF
-
+	echo "<<<<<<<" >expected &&
+	if test_have_prereq NATIVE_CRLF; then
+		echo first line | append_cr >>expected &&
+		echo same line | append_cr >>expected &&
+		echo ======= | append_cr >>expected
+	else
+		echo first line >>expected &&
+		echo same line >>expected &&
+		echo ======= >>expected
+	fi &&
+	echo first line | append_cr >>expected &&
+	echo same line | append_cr >>expected &&
+	echo ">>>>>>>" >>expected &&
 	git config merge.renormalize false &&
 	rm -f .gitattributes &&
 	git reset --hard a &&
@@ -114,16 +125,19 @@
 '
 
 test_expect_success 'Detect LF/CRLF conflict from addition of text=auto' '
-	q_to_cr <<-\EOF >expected &&
-	<<<<<<<
-	first lineQ
-	same lineQ
-	=======
-	first line
-	same line
-	>>>>>>>
-	EOF
-
+	echo "<<<<<<<" >expected &&
+	echo first line | append_cr >>expected &&
+	echo same line | append_cr >>expected &&
+	if test_have_prereq NATIVE_CRLF; then
+		echo ======= | append_cr >>expected &&
+		echo first line | append_cr >>expected &&
+		echo same line | append_cr >>expected
+	else
+		echo ======= >>expected &&
+		echo first line >>expected &&
+		echo same line >>expected
+	fi &&
+	echo ">>>>>>>" >>expected &&
 	git config merge.renormalize false &&
 	rm -f .gitattributes &&
 	git reset --hard b &&
diff --git a/t/t9350-fast-export.sh b/t/t9350-fast-export.sh
index 66c8b0a..b7dedb1 100755
--- a/t/t9350-fast-export.sh
+++ b/t/t9350-fast-export.sh
@@ -522,4 +522,15 @@
 	test_cmp expected actual
 '
 
+cat > expected << EOF
+reset refs/heads/master
+from $(git rev-parse master)
+
+EOF
+
+test_expect_failure 'refs are updated even if no commits need to be exported' '
+	git fast-export master..master > actual &&
+	test_cmp expected actual
+'
+
 test_done
diff --git a/t/test-lib.sh b/t/test-lib.sh
index b1bc65b..eb9c219 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -15,6 +15,10 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see http://www.gnu.org/licenses/ .
 
+# for git on windows so stdin will not be misdetected as attached to a
+# terminal
+exec < /dev/null
+
 # Keep the original TERM for say_color
 ORIGINAL_TERM=$TERM
 
@@ -871,6 +875,7 @@
 	# exec does not inherit the PID
 	test_set_prereq MINGW
 	test_set_prereq NOT_CYGWIN
+	test_set_prereq NATIVE_CRLF
 	test_set_prereq SED_STRIPS_CR
 	test_set_prereq GREP_STRIPS_CR
 	GIT_TEST_CMP=mingw_test_cmp
diff --git a/transport-helper.c b/transport-helper.c
index 3d8fe7d..9bf11e4 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -14,6 +14,8 @@
 #include "refs.h"
 
 static int debug;
+/* TODO: put somewhere sensible, e.g. git_transport_options? */
+static int auto_gc = 1;
 
 struct helper_data {
 	const char *name;
@@ -435,10 +437,25 @@
 	for (i = 0; i < revlist_args->nr; i++)
 		argv_array_push(&fastexport->args, revlist_args->items[i].string);
 
+	argv_array_push(&fastexport->args, "--");
+
 	fastexport->git_cmd = 1;
 	return start_command(fastexport);
 }
 
+static void check_helper_status(struct helper_data *data)
+{
+	int pid, status;
+
+	pid = waitpid(data->helper->pid, &status, WNOHANG);
+	if (pid < 0)
+		die("Could not retrieve status of remote helper '%s'",
+		    data->name);
+	if (pid > 0 && WIFEXITED(status))
+		die("Remote helper '%s' died with %d",
+		    data->name, WEXITSTATUS(status));
+}
+
 static int fetch_with_import(struct transport *transport,
 			     int nr_heads, struct ref **to_fetch)
 {
@@ -474,6 +491,7 @@
 
 	if (finish_command(&fastimport))
 		die("Error while running fast-import");
+	check_helper_status(data);
 
 	/*
 	 * The fast-import stream of a remote helper that advertises
@@ -505,6 +523,12 @@
 		}
 	}
 	strbuf_release(&buf);
+	if (auto_gc) {
+		const char *argv_gc_auto[] = {
+			"gc", "--auto", "--quiet", NULL,
+		};
+		run_command_v_opt(argv_gc_auto, RUN_GIT_CMD);
+	}
 	return 0;
 }
 
@@ -913,6 +937,7 @@
 
 	if (finish_command(&exporter))
 		die("Error while running fast-export");
+	check_helper_status(data);
 	if (push_update_refs_status(data, remote_refs, flags))
 		return 1;