Merge branch 'js/rebase-i-p'

* js/rebase-i-p:
  rebase -i -p: leave a --cc patch when a merge could not be redone
  rebase -i -p: Fix --continue after a merge could not be redone
  Show a failure of rebase -p if the merge had a conflict
diff --git a/Documentation/RelNotes-1.6.1.txt b/Documentation/RelNotes-1.6.1.txt
index 0405309..002d9ec 100644
--- a/Documentation/RelNotes-1.6.1.txt
+++ b/Documentation/RelNotes-1.6.1.txt
@@ -230,6 +230,13 @@
 All of the fixes in v1.6.0.X maintenance series are included in this
 release, unless otherwise noted.
 
+* Porcelains implemented as shell scripts were utterly confused when you
+  entered to a subdirectory of a work tree from sideways, following a
+  symbolic link (this may need to be backported to older releases later).
+
+* Tracking symbolic links would work better on filesystems whose lstat()
+  returns incorrect st_size value for them.
+
 * "git add" and "git update-index" incorrectly allowed adding S/F when S
   is a tracked symlink that points at a directory D that has a path F in
   it (we still need to fix a similar nonsense when S is a submodule and F
@@ -244,6 +251,16 @@
 
 * "git filter-branch" failed to rewrite a tag name with slashes in it.
 
+* "git http-push" did not understand URI scheme other than opaquelocktoken
+  when acquiring a lock from the server (this may need to be backported to
+  older releases later).
+
+* "git revert" records relative to which parent a revert was made when
+  reverting a merge.  Together with new documentation that explains issues
+  around reverting a merge and merging from the updated branch later, this
+  hopefully will reduce user confusion (this may need to be backported to
+  older releases later).
+
 * "git rm --cached" used to allow an empty blob that was added earlier to
   be removed without --force, even when the file in the work tree has
   since been modified.
@@ -260,6 +277,6 @@
 
 --
 exec >/var/tmp/1
-O=v1.6.1-rc1-55-gd8af75d
+O=v1.6.1-rc3-74-gf66bc5f
 echo O=$(git describe master)
 git shortlog --no-merges $O..master ^maint
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 21ea165..52786c7 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -601,10 +601,6 @@
 	affects only 'git-diff' Porcelain, and not lower level
 	'diff' commands, such as 'git-diff-files'.
 
-diff.suppress-blank-empty::
-	A boolean to inhibit the standard behavior of printing a space
-	before each empty output line. Defaults to false.
-
 diff.external::
 	If this config variable is set, diff generation is not
 	performed using the internal diff machinery, but using the
@@ -639,6 +635,10 @@
 	will enable basic rename detection.  If set to "copies" or
 	"copy", it will detect copies, as well.
 
+diff.suppress-blank-empty::
+	A boolean to inhibit the standard behavior of printing a space
+	before each empty output line. Defaults to false.
+
 fetch.unpackLimit::
 	If the number of objects fetched over the git native
 	transfer is below this
diff --git a/Documentation/git-fsck.txt b/Documentation/git-fsck.txt
index d5a7647..287c4fc 100644
--- a/Documentation/git-fsck.txt
+++ b/Documentation/git-fsck.txt
@@ -79,7 +79,8 @@
 
 So for example
 
-	git fsck --unreachable HEAD $(cat .git/refs/heads/*)
+	git fsck --unreachable HEAD \
+		$(git for-each-ref --format="%(objectname)" refs/heads)
 
 will do quite a _lot_ of verification on the tree. There are a few
 extra validity tests to be added (make sure that tree objects are
diff --git a/Documentation/git-revert.txt b/Documentation/git-revert.txt
index caa0729..5e11758 100644
--- a/Documentation/git-revert.txt
+++ b/Documentation/git-revert.txt
@@ -44,6 +44,14 @@
 	option specifies the parent number (starting from 1) of
 	the mainline and allows revert to reverse the change
 	relative to the specified parent.
++
+Reverting a merge commit declares that you will never want the tree changes
+brought in by the merge.  As a result, later merges will only bring in tree
+changes introduced by commits that are not ancestors of the previously
+reverted merge.  This may or may not be what you want.
++
+See the link:howto/revert-a-faulty-merge.txt[revert-a-faulty-merge How-To] for
+more details.
 
 --no-edit::
 	With this option, 'git-revert' will not start the commit
diff --git a/Documentation/git-show-branch.txt b/Documentation/git-show-branch.txt
index fb269ff..8277577 100644
--- a/Documentation/git-show-branch.txt
+++ b/Documentation/git-show-branch.txt
@@ -172,7 +172,7 @@
 your topic branch, it is shown as well.
 
 ------------
-$ git show-branch --reflog='10,1 hour ago' --list master
+$ git show-branch --reflog="10,1 hour ago" --list master
 ------------
 
 shows 10 reflog entries going back from the tip as of 1 hour ago.
diff --git a/Documentation/howto/revert-a-faulty-merge.txt b/Documentation/howto/revert-a-faulty-merge.txt
new file mode 100644
index 0000000..39b1da4
--- /dev/null
+++ b/Documentation/howto/revert-a-faulty-merge.txt
@@ -0,0 +1,179 @@
+Date: Fri, 19 Dec 2008 00:45:19 -0800
+From: Linus Torvalds <torvalds@linux-foundation.org>, Junio C Hamano <gitster@pobox.com>
+Subject: Re: Odd merge behaviour involving reverts
+Abstract: Sometimes a branch that was already merged to the mainline
+ is later found to be faulty.  Linus and Junio give guidance on
+ recovering from such a premature merge and continuing development
+ after the offending branch is fixed.
+Message-ID: <7vocz8a6zk.fsf@gitster.siamese.dyndns.org>
+References: <alpine.LFD.2.00.0812181949450.14014@localhost.localdomain>
+
+Alan <alan@clueserver.org> said:
+
+    I have a master branch.  We have a branch off of that that some
+    developers are doing work on.  They claim it is ready. We merge it
+    into the master branch.  It breaks something so we revert the merge.
+    They make changes to the code.  they get it to a point where they say
+    it is ok and we merge again.
+
+    When examined, we find that code changes made before the revert are
+    not in the master branch, but code changes after are in the master
+    branch.
+
+and asked for help recovering from this situation.
+
+The history immediately after the "revert of the merge" would look like
+this:
+
+ ---o---o---o---M---x---x---W
+	       /
+       ---A---B
+
+where A and B are on the side development that was not so good, M is the
+merge that brings these premature changes into the mainline, x are changes
+unrelated to what the side branch did and already made on the mainline,
+and W is the "revert of the merge M" (doesn't W look M upside down?).
+IOW, "diff W^..W" is similar to "diff -R M^..M".
+
+Such a "revert" of a merge can be made with:
+
+    $ git revert -m 1 M
+
+After the develpers of the side branch fixes their mistakes, the history
+may look like this:
+
+ ---o---o---o---M---x---x---W---x
+	       /
+       ---A---B-------------------C---D
+
+where C and D are to fix what was broken in A and B, and you may already
+have some other changes on the mainline after W.
+
+If you merge the updated side branch (with D at its tip), none of the
+changes made in A nor B will be in the result, because they were reverted
+by W.  That is what Alan saw.
+
+Linus explains the situation:
+
+    Reverting a regular commit just effectively undoes what that commit
+    did, and is fairly straightforward. But reverting a merge commit also
+    undoes the _data_ that the commit changed, but it does absolutely
+    nothing to the effects on _history_ that the merge had.
+
+    So the merge will still exist, and it will still be seen as joining
+    the two branches together, and future merges will see that merge as
+    the last shared state - and the revert that reverted the merge brought
+    in will not affect that at all.
+
+    So a "revert" undoes the data changes, but it's very much _not_ an
+    "undo" in the sense that it doesn't undo the effects of a commit on
+    the repository history.
+
+    So if you think of "revert" as "undo", then you're going to always
+    miss this part of reverts. Yes, it undoes the data, but no, it doesn't
+    undo history.
+
+In such a situation, you would want to first revert the previous revert,
+which would make the history look like this:
+
+ ---o---o---o---M---x---x---W---x---Y
+	       /
+       ---A---B-------------------C---D
+
+where Y is the revert of W.  Such a "revert of the revert" can be done
+with:
+
+    $ git revert W
+
+This history would (ignoring possible conflicts between what W and W..Y
+changed) be equivalent to not having W nor Y at all in the history:
+
+ ---o---o---o---M---x---x-------x----
+	       /
+       ---A---B-------------------C---D
+
+and merging the side branch again will not have conflict arising from an
+earlier revert and revert of the revert.
+
+ ---o---o---o---M---x---x-------x-------*
+	       /                       /
+       ---A---B-------------------C---D
+
+Of course the changes made in C and D still can conflict with what was
+done by any of the x, but that is just a normal merge conflict.
+
+On the other hand, if the developers of the side branch discarded their
+faulty A and B, and redone the changes on top of the updated mainline
+after the revert, the history would have looked like this:
+
+ ---o---o---o---M---x---x---W---x---x
+	       /                 \
+       ---A---B                   A'--B'--C'
+
+If you reverted the revert in such a case as in the previous example:
+
+ ---o---o---o---M---x---x---W---x---x---Y---*
+	       /                 \         /
+       ---A---B                   A'--B'--C'
+
+where Y is the revert of W, A' and B'are rerolled A and B, and there may
+also be a further fix-up C' on the side branch.  "diff Y^..Y" is similar
+to "diff -R W^..W" (which in turn means it is similar to "diff M^..M"),
+and "diff A'^..C'" by definition would be similar but different from that,
+because it is a rerolled series of the earlier change.  There will be a
+lot of overlapping changes that result in conflicts.  So do not do "revert
+of revert" blindly without thinking..
+
+ ---o---o---o---M---x---x---W---x---x
+	       /                 \
+       ---A---B                   A'--B'--C'
+
+In the history with rebased side branch, W (and M) are behind the merge
+base of the updated branch and the tip of the mainline, and they should
+merge without the past faulty merge and its revert getting in the way.
+
+To recap, these are two very different scenarios, and they want two very
+different resolution strategies:
+
+ - If the faulty side branch was fixed by adding corrections on top, then
+   doing a revert of the previous revert would be the right thing to do.
+
+ - If the faulty side branch whose effects were discarded by an earlier
+   revert of a merge was rebuilt from scratch (i.e. rebasing and fixing,
+   as you seem to have interpreted), then re-merging the result without
+   doing anything else fancy would be the right thing to do.
+
+However, there are things to keep in mind when reverting a merge (and
+reverting such a revert).
+
+For example, think about what reverting a merge (and then reverting the
+revert) does to bisectability. Ignore the fact that the revert of a revert
+is undoing it - just think of it as a "single commit that does a lot".
+Because that is what it does.
+
+When you have a problem you are chasing down, and you hit a "revert this
+merge", what you're hitting is essentially a single commit that contains
+all the changes (but obviously in reverse) of all the commits that got
+merged. So it's debugging hell, because now you don't have lots of small
+changes that you can try to pinpoint which _part_ of it changes.
+
+But does it all work? Sure it does. You can revert a merge, and from a
+purely technical angle, git did it very naturally and had no real
+troubles. It just considered it a change from "state before merge" to
+"state after merge", and that was it. Nothing complicated, nothing odd,
+nothing really dangerous. Git will do it without even thinking about it.
+
+So from a technical angle, there's nothing wrong with reverting a merge,
+but from a workflow angle it's something that you generally should try to
+avoid.
+
+If at all possible, for example, if you find a problem that got merged
+into the main tree, rather than revert the merge, try _really_ hard to
+bisect the problem down into the branch you merged, and just fix it, or
+try to revert the individual commit that caused it.
+
+Yes, it's more complex, and no, it's not always going to work (sometimes
+the answer is: "oops, I really shouldn't have merged it, because it wasn't
+ready yet, and I really need to undo _all_ of the merge"). So then you
+really should revert the merge, but when you want to re-do the merge, you
+now need to do it by reverting the revert.
diff --git a/builtin-revert.c b/builtin-revert.c
index 4038b41..d48313c 100644
--- a/builtin-revert.c
+++ b/builtin-revert.c
@@ -352,6 +352,11 @@
 		add_to_msg(oneline_body + 1);
 		add_to_msg("\"\n\nThis reverts commit ");
 		add_to_msg(sha1_to_hex(commit->object.sha1));
+
+		if (commit->parents->next) {
+			add_to_msg(", reversing\nchanges made to ");
+			add_to_msg(sha1_to_hex(parent->object.sha1));
+		}
 		add_to_msg(".\n");
 	} else {
 		base = parent;
diff --git a/connect.c b/connect.c
index 584e04c..2f55ad2 100644
--- a/connect.c
+++ b/connect.c
@@ -480,8 +480,8 @@
 	char *p = strchr(host, ':');
 
 	if (p) {
-		strtol(p+1, &end, 10);
-		if (*end == '\0') {
+		long port = strtol(p + 1, &end, 10);
+		if (end != p + 1 && *end == '\0' && 0 <= port && port < 65536) {
 			*p = '\0';
 			return p+1;
 		}
diff --git a/contrib/workdir/git-new-workdir b/contrib/workdir/git-new-workdir
index 7959eab..993cacf 100755
--- a/contrib/workdir/git-new-workdir
+++ b/contrib/workdir/git-new-workdir
@@ -22,7 +22,7 @@
 # want to make sure that what is pointed to has a .git directory ...
 git_dir=$(cd "$orig_git" 2>/dev/null &&
   git rev-parse --git-dir 2>/dev/null) ||
-  die "\"$orig_git\" is not a git repository!"
+  die "Not a git repository: \"$orig_git\""
 
 case "$git_dir" in
 .git)
diff --git a/fast-import.c b/fast-import.c
index 171d178..a6bce66 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -1748,9 +1748,12 @@
 {
 	const char *orig_src = src;
 	char *endp, sign;
+	unsigned long date;
 
-	strtoul(src, &endp, 10);
-	if (endp == src || *endp != ' ')
+	errno = 0;
+
+	date = strtoul(src, &endp, 10);
+	if (errno || endp == src || *endp != ' ')
 		return -1;
 
 	src = endp + 1;
@@ -1758,8 +1761,8 @@
 		return -1;
 	sign = *src;
 
-	strtoul(src + 1, &endp, 10);
-	if (endp == src || *endp || (endp - orig_src) >= maxlen)
+	date = strtoul(src + 1, &endp, 10);
+	if (errno || endp == src || *endp || (endp - orig_src) >= maxlen)
 		return -1;
 
 	strcpy(result, orig_src);
diff --git a/git-send-email.perl b/git-send-email.perl
index 6114401..77ca8fe 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -361,7 +361,7 @@
 }
 
 sub split_addrs {
-	return parse_line('\s*,\s*', 1, @_);
+	return quotewords('\s*,\s*', 1, @_);
 }
 
 my %aliases;
diff --git a/git-sh-setup.sh b/git-sh-setup.sh
index dbdf209..f07d96b 100755
--- a/git-sh-setup.sh
+++ b/git-sh-setup.sh
@@ -85,8 +85,27 @@
 	cdup=$(git rev-parse --show-cdup)
 	if test ! -z "$cdup"
 	then
-		cd "$cdup" || {
-			echo >&2 "Cannot chdir to $cdup, the toplevel of the working tree"
+		case "$cdup" in
+		/*)
+			# Not quite the same as if we did "cd -P '$cdup'" when
+			# $cdup contains ".." after symlink path components.
+			# Don't fix that case at least until Git switches to
+			# "cd -P" across the board.
+			phys="$cdup"
+			;;
+		..|../*|*/..|*/../*)
+			# Interpret $cdup relative to the physical, not logical, cwd.
+			# Probably /bin/pwd is more portable than passing -P to cd or pwd.
+			phys="$(/bin/pwd)/$cdup"
+			;;
+		*)
+			# There's no "..", so no need to make things absolute.
+			phys="$cdup"
+			;;
+		esac
+
+		cd "$phys" || {
+			echo >&2 "Cannot chdir to $phys, the toplevel of the working tree"
 			exit 1
 		}
 	fi
diff --git a/gitk-git/gitk b/gitk-git/gitk
index 64a873d..dc2a439 100644
--- a/gitk-git/gitk
+++ b/gitk-git/gitk
@@ -1601,13 +1601,14 @@
     set header [string range $contents 0 [expr {$hdrend - 1}]]
     set comment [string range $contents [expr {$hdrend + 2}] end]
     foreach line [split $header "\n"] {
+	set line [split $line " "]
 	set tag [lindex $line 0]
 	if {$tag == "author"} {
 	    set audate [lindex $line end-1]
-	    set auname [lrange $line 1 end-2]
+	    set auname [join [lrange $line 1 end-2] " "]
 	} elseif {$tag == "committer"} {
 	    set comdate [lindex $line end-1]
-	    set comname [lrange $line 1 end-2]
+	    set comname [join [lrange $line 1 end-2] " "]
 	}
     }
     set headline {}
@@ -2279,7 +2280,7 @@
     bindkey b prevfile
     bindkey d "$ctext yview scroll 18 units"
     bindkey u "$ctext yview scroll -18 units"
-    bindkey / {dofind 1 1}
+    bindkey / {focus $fstring}
     bindkey <Key-Return> {dofind 1 1}
     bindkey ? {dofind -1 1}
     bindkey f nextfile
@@ -2660,7 +2661,7 @@
 [mc "<%s-F>		Find" $M1T]
 [mc "<%s-G>		Move to next find hit" $M1T]
 [mc "<Return>	Move to next find hit"]
-[mc "/		Move to next find hit, or redo find"]
+[mc "/		Focus the search box"]
 [mc "?		Move to previous find hit"]
 [mc "f		Scroll diff view to next file"]
 [mc "<%s-S>		Search for next hit in diff view" $M1T]
@@ -3318,8 +3319,27 @@
     return {}
 }
 
+# Turn an absolute path into one relative to the current directory
+proc make_relative {f} {
+    set elts [file split $f]
+    set here [file split [pwd]]
+    set ei 0
+    set hi 0
+    set res {}
+    foreach d $here {
+	if {$ei < $hi || $ei >= [llength $elts] || [lindex $elts $ei] ne $d} {
+	    lappend res ".."
+	} else {
+	    incr ei
+	}
+	incr hi
+    }
+    set elts [concat $res [lrange $elts $ei end]]
+    return [eval file join $elts]
+}
+
 proc external_blame {parent_idx {line {}}} {
-    global flist_menu_file
+    global flist_menu_file gitdir
     global nullid nullid2
     global parentlist selectedline currentid
 
@@ -3338,7 +3358,12 @@
     if {$line ne {} && $line > 1} {
 	lappend cmdline "--line=$line"
     }
-    lappend cmdline $base_commit $flist_menu_file
+    set f [file join [file dirname $gitdir] $flist_menu_file]
+    # Unfortunately it seems git gui blame doesn't like
+    # being given an absolute path...
+    set f [make_relative $f]
+    lappend cmdline $base_commit $f
+    puts "cmdline={$cmdline}"
     if {[catch {eval exec $cmdline &} err]} {
 	error_popup "[mc "git gui blame: command failed:"] $err"
     }
@@ -3382,6 +3407,8 @@
 		    error_popup [mc "Error reading index: %s" $err]
 		    return
 		}
+	    } else {
+		set id $parents($curview,$currentid)
 	    }
 	} else {
 	    set id [lindex $parents($curview,$currentid) $pi]
@@ -3398,7 +3425,7 @@
     } else {
 	lappend blameargs $id
     }
-    lappend blameargs -- $flist_menu_file
+    lappend blameargs -- [file join [file dirname $gitdir] $flist_menu_file]
     if {[catch {
 	set f [open $blameargs r]
     } err]} {
@@ -7953,7 +7980,7 @@
     if {$id ne $nullid && $id ne $nullid2} {
 	set menu $rowctxmenu
 	if {$mainhead ne {}} {
-	    $menu entryconfigure 7 -label [mc "Reset %s branch to here" $mainhead]
+	    $menu entryconfigure 7 -label [mc "Reset %s branch to here" $mainhead] -state normal
 	} else {
 	    $menu entryconfigure 7 -label [mc "Detached head: can't reset" $mainhead] -state disabled
 	}
@@ -10079,15 +10106,11 @@
 	-font optionfont
     spinbox $top.maxpct -from 1 -to 100 -width 4 -textvariable maxgraphpct
     grid x $top.maxpctl $top.maxpct -sticky w
-    frame $top.showlocal
-    label $top.showlocal.l -text [mc "Show local changes"] -font optionfont
-    checkbutton $top.showlocal.b -variable showlocalchanges
-    pack $top.showlocal.b $top.showlocal.l -side left
+    checkbutton $top.showlocal -text [mc "Show local changes"] \
+	-font optionfont -variable showlocalchanges
     grid x $top.showlocal -sticky w
-    frame $top.autoselect
-    label $top.autoselect.l -text [mc "Auto-select SHA1"] -font optionfont
-    checkbutton $top.autoselect.b -variable autoselect
-    pack $top.autoselect.b $top.autoselect.l -side left
+    checkbutton $top.autoselect -text [mc "Auto-select SHA1"] \
+	-font optionfont -variable autoselect
     grid x $top.autoselect -sticky w
 
     label $top.ddisp -text [mc "Diff display options"]
@@ -10095,20 +10118,14 @@
     label $top.tabstopl -text [mc "Tab spacing"] -font optionfont
     spinbox $top.tabstop -from 1 -to 20 -width 4 -textvariable tabstop
     grid x $top.tabstopl $top.tabstop -sticky w
-    frame $top.ntag
-    label $top.ntag.l -text [mc "Display nearby tags"] -font optionfont
-    checkbutton $top.ntag.b -variable showneartags
-    pack $top.ntag.b $top.ntag.l -side left
+    checkbutton $top.ntag -text [mc "Display nearby tags"] \
+	-font optionfont -variable showneartags
     grid x $top.ntag -sticky w
-    frame $top.ldiff
-    label $top.ldiff.l -text [mc "Limit diffs to listed paths"] -font optionfont
-    checkbutton $top.ldiff.b -variable limitdiffs
-    pack $top.ldiff.b $top.ldiff.l -side left
+    checkbutton $top.ldiff -text [mc "Limit diffs to listed paths"] \
+	-font optionfont -variable limitdiffs
     grid x $top.ldiff -sticky w
-    frame $top.lattr
-    label $top.lattr.l -text [mc "Support per-file encodings"] -font optionfont
-    checkbutton $top.lattr.b -variable perfile_attrs
-    pack $top.lattr.b $top.lattr.l -side left
+    checkbutton $top.lattr -text [mc "Support per-file encodings"] \
+	-font optionfont -variable perfile_attrs
     grid x $top.lattr -sticky w
 
     entry $top.extdifft -textvariable extdifftool
@@ -10124,26 +10141,26 @@
     grid $top.cdisp - -sticky w -pady 10
     label $top.bg -padx 40 -relief sunk -background $bgcolor
     button $top.bgbut -text [mc "Background"] -font optionfont \
-	-command [list choosecolor bgcolor {} $top.bg background setbg]
+	-command [list choosecolor bgcolor {} $top.bg [mc "background"] setbg]
     grid x $top.bgbut $top.bg -sticky w
     label $top.fg -padx 40 -relief sunk -background $fgcolor
     button $top.fgbut -text [mc "Foreground"] -font optionfont \
-	-command [list choosecolor fgcolor {} $top.fg foreground setfg]
+	-command [list choosecolor fgcolor {} $top.fg [mc "foreground"] setfg]
     grid x $top.fgbut $top.fg -sticky w
     label $top.diffold -padx 40 -relief sunk -background [lindex $diffcolors 0]
     button $top.diffoldbut -text [mc "Diff: old lines"] -font optionfont \
-	-command [list choosecolor diffcolors 0 $top.diffold "diff old lines" \
+	-command [list choosecolor diffcolors 0 $top.diffold [mc "diff old lines"] \
 		      [list $ctext tag conf d0 -foreground]]
     grid x $top.diffoldbut $top.diffold -sticky w
     label $top.diffnew -padx 40 -relief sunk -background [lindex $diffcolors 1]
     button $top.diffnewbut -text [mc "Diff: new lines"] -font optionfont \
-	-command [list choosecolor diffcolors 1 $top.diffnew "diff new lines" \
+	-command [list choosecolor diffcolors 1 $top.diffnew [mc "diff new lines"] \
 		      [list $ctext tag conf dresult -foreground]]
     grid x $top.diffnewbut $top.diffnew -sticky w
     label $top.hunksep -padx 40 -relief sunk -background [lindex $diffcolors 2]
     button $top.hunksepbut -text [mc "Diff: hunk header"] -font optionfont \
 	-command [list choosecolor diffcolors 2 $top.hunksep \
-		      "diff hunk header" \
+		      [mc "diff hunk header"] \
 		      [list $ctext tag conf hunksep -foreground]]
     grid x $top.hunksepbut $top.hunksep -sticky w
     label $top.markbgsep -padx 40 -relief sunk -background $markbgcolor
@@ -10154,7 +10171,7 @@
     grid x $top.markbgbut $top.markbgsep -sticky w
     label $top.selbgsep -padx 40 -relief sunk -background $selectbgcolor
     button $top.selbgbut -text [mc "Select bg"] -font optionfont \
-	-command [list choosecolor selectbgcolor {} $top.selbgsep background setselbg]
+	-command [list choosecolor selectbgcolor {} $top.selbgsep [mc "background"] setselbg]
     grid x $top.selbgbut $top.selbgsep -sticky w
 
     label $top.cfont -text [mc "Fonts: press to choose"]
@@ -10897,4 +10914,9 @@
 	addviewmenu $n
     }
 }
+
+if {[tk windowingsystem] eq "win32"} {
+    focus -force .
+}
+
 getcommits {}
diff --git a/gitk-git/po/de.po b/gitk-git/po/de.po
index e0a6dee..825dc98 100644
--- a/gitk-git/po/de.po
+++ b/gitk-git/po/de.po
@@ -7,8 +7,8 @@
 msgstr ""
 "Project-Id-Version: git-gui\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-10-25 13:18+0200\n"
-"PO-Revision-Date: 2008-10-25 13:23+0200\n"
+"POT-Creation-Date: 2008-12-06 20:40+0100\n"
+"PO-Revision-Date: 2008-12-06 20:45+0100\n"
 "Last-Translator: Christian Stimming <stimming@tuhh.de>\n"
 "Language-Team: German\n"
 "MIME-Version: 1.0\n"
@@ -90,7 +90,11 @@
 msgid "List references"
 msgstr "Zweige/Markierungen auflisten"
 
-#: gitk:1815
+#: gitk:1915
+msgid "Start git gui"
+msgstr "»git gui« starten"
+
+#: gitk:1917
 msgid "Quit"
 msgstr "Beenden"
 
@@ -295,7 +299,15 @@
 msgid "Blame parent commit"
 msgstr "Annotieren der Elternversion"
 
-#: gitk:2488
+#: gitk:2360
+msgid "Show origin of this line"
+msgstr "Herkunft dieser Zeile anzeigen"
+
+#: gitk:2361
+msgid "Run git gui blame on this line"
+msgstr "Annotieren (»git gui blame«) von dieser Zeile"
+
+#: gitk:2606
 msgid ""
 "\n"
 "Gitk - a commit viewer for git\n"
@@ -501,7 +513,38 @@
 msgid "git gui blame: command failed:"
 msgstr "git gui blame: Kommando fehlgeschlagen:"
 
-#: gitk:3092
+#: gitk:3398
+#, tcl-format
+msgid "Couldn't read merge head: %s"
+msgstr "Zusammenführungs-Spitze konnte nicht gelesen werden: %s"
+
+#: gitk:3406
+#, tcl-format
+msgid "Error reading index: %s"
+msgstr "Fehler beim Lesen der Bereitstellung (»index«): %s"
+
+#: gitk:3431
+#, tcl-format
+msgid "Couldn't start git blame: %s"
+msgstr "»git blame« konnte nicht gestartet werden: %s"
+
+#: gitk:3434 gitk:6160
+msgid "Searching"
+msgstr "Suchen"
+
+#: gitk:3466
+#, tcl-format
+msgid "Error running git blame: %s"
+msgstr "Fehler beim Ausführen von »git blame«: %s"
+
+#: gitk:3494
+#, tcl-format
+msgid "That line comes from commit %s,  which is not in this view"
+msgstr ""
+"Diese Zeile stammt aus Version %s, welche nicht in dieser Ansicht gezeigt "
+"wird."
+
+#: gitk:3508
 msgid "External diff viewer failed:"
 msgstr "Externes Vergleich-(Diff-)Programm fehlgeschlagen:"
 
@@ -509,11 +552,7 @@
 msgid "Gitk view definition"
 msgstr "Gitk Ansichten"
 
-#: gitk:3225
-msgid "Name"
-msgstr "Name"
-
-#: gitk:3228
+#: gitk:3630
 msgid "Remember this view"
 msgstr "Diese Ansicht speichern"
 
@@ -521,15 +560,55 @@
 msgid "Commits to include (arguments to git log):"
 msgstr "Versionen anzeigen (Argumente von git-log):"
 
-#: gitk:3239
+#: gitk:3632
+msgid "Use all refs"
+msgstr "Alle Zweige verwenden"
+
+#: gitk:3633
+msgid "Strictly sort by date"
+msgstr "Streng nach Datum sortieren"
+
+#: gitk:3634
+msgid "Mark branch sides"
+msgstr "Zweig-Seiten markieren"
+
+#: gitk:3635
+msgid "Since date:"
+msgstr "Von Datum:"
+
+#: gitk:3636
+msgid "Until date:"
+msgstr "Bis Datum:"
+
+#: gitk:3637
+msgid "Max count:"
+msgstr "Max. Anzahl:"
+
+#: gitk:3638
+msgid "Skip:"
+msgstr "Überspringen:"
+
+#: gitk:3639
+msgid "Limit to first parent"
+msgstr "Auf erste Elternversion beschränken"
+
+#: gitk:3640
 msgid "Command to generate more commits to include:"
 msgstr "Versionsliste durch folgendes Kommando erzeugen lassen:"
 
-#: gitk:3246
+#: gitk:3749
+msgid "Name"
+msgstr "Name"
+
+#: gitk:3797
 msgid "Enter files and directories to include, one per line:"
 msgstr "Folgende Dateien und Verzeichnisse anzeigen (eine pro Zeile):"
 
-#: gitk:3293
+#: gitk:3811
+msgid "Apply (F5)"
+msgstr "Anwenden (F5)"
+
+#: gitk:3849
 msgid "Error in commit selection arguments:"
 msgstr "Fehler in den ausgewählten Versionen:"
 
@@ -569,11 +648,7 @@
 msgid "Local uncommitted changes, not checked in to index"
 msgstr "Lokale Änderungen, nicht bereitgestellt"
 
-#: gitk:5549
-msgid "Searching"
-msgstr "Suchen"
-
-#: gitk:6049
+#: gitk:6673
 msgid "Tags:"
 msgstr "Markierungen:"
 
@@ -597,11 +672,12 @@
 msgid "Precedes"
 msgstr "Vorgänger von"
 
-#: gitk:6378
-msgid "Error getting merge diffs:"
-msgstr "Fehler beim Laden des Vergleichs:"
+#: gitk:7209
+#, tcl-format
+msgid "Error getting diffs: %s"
+msgstr "Fehler beim Laden des Vergleichs: %s"
 
-#: gitk:7113
+#: gitk:7748
 msgid "Goto:"
 msgstr "Gehe zu:"
 
@@ -722,7 +798,12 @@
 msgid "Please specify a name for the new branch"
 msgstr "Bitte geben Sie einen Namen für den neuen Zweig an."
 
-#: gitk:7703
+#: gitk:8328
+#, tcl-format
+msgid "Branch '%s' already exists. Overwrite?"
+msgstr "Zweig »%s« existiert bereits. Soll er überschrieben werden?"
+
+#: gitk:8394
 #, tcl-format
 msgid "Commit %s is already included in branch %s -- really re-apply it?"
 msgstr ""
@@ -733,7 +814,26 @@
 msgid "Cherry-picking"
 msgstr "Version pflücken"
 
-#: gitk:7720
+#: gitk:8408
+#, tcl-format
+msgid ""
+"Cherry-pick failed because of local changes to file '%s'.\n"
+"Please commit, reset or stash your changes and try again."
+msgstr ""
+"Pflücken fehlgeschlagen, da noch lokale Änderungen in Datei »%s«\n"
+"vorliegen. Bitte diese Änderungen eintragen, zurücksetzen oder\n"
+"zwischenspeichern (»git stash») und dann erneut versuchen."
+
+#: gitk:8414
+msgid ""
+"Cherry-pick failed because of merge conflict.\n"
+"Do you wish to run git citool to resolve it?"
+msgstr ""
+"Pflücken fehlgeschlagen, da ein Zusammenführungs-Konflikt aufgetreten\n"
+"ist. Soll das »git citool« (Zusammenführungs-Werkzeug) aufgerufen\n"
+"werden, um diesen Konflikt aufzulösen?"
+
+#: gitk:8430
 msgid "No changes committed"
 msgstr "Keine Änderungen eingetragen"
 
@@ -889,23 +989,51 @@
 msgid "Background"
 msgstr "Hintergrund"
 
-#: gitk:9435
+#: gitk:10153 gitk:10183
+msgid "background"
+msgstr "Hintergrund"
+
+#: gitk:10156
 msgid "Foreground"
 msgstr "Vordergrund"
 
-#: gitk:9439
+#: gitk:10157
+msgid "foreground"
+msgstr "Vordergrund"
+
+#: gitk:10160
 msgid "Diff: old lines"
 msgstr "Vergleich: Alte Zeilen"
 
-#: gitk:9444
+#: gitk:10161
+msgid "diff old lines"
+msgstr "Vergleich - Alte Zeilen"
+
+#: gitk:10165
 msgid "Diff: new lines"
 msgstr "Vergleich: Neue Zeilen"
 
-#: gitk:9449
+#: gitk:10166
+msgid "diff new lines"
+msgstr "Vergleich - Neue Zeilen"
+
+#: gitk:10170
 msgid "Diff: hunk header"
 msgstr "Vergleich: Änderungstitel"
 
-#: gitk:9455
+#: gitk:10172
+msgid "diff hunk header"
+msgstr "Vergleich - Änderungstitel"
+
+#: gitk:10176
+msgid "Marked line bg"
+msgstr "Markierte Zeile Hintergrund"
+
+#: gitk:10178
+msgid "marked line background"
+msgstr "markierte Zeile Hintergrund"
+
+#: gitk:10182
 msgid "Select bg"
 msgstr "Hintergrundfarbe Auswählen"
 
diff --git a/http-push.c b/http-push.c
index 5cecef4..7c64609 100644
--- a/http-push.c
+++ b/http-push.c
@@ -595,7 +595,7 @@
 	lock->refreshing = 1;
 
 	if_header = xmalloc(strlen(lock->token) + 25);
-	sprintf(if_header, "If: (<opaquelocktoken:%s>)", lock->token);
+	sprintf(if_header, "If: (<%s>)", lock->token);
 	sprintf(timeout_header, "Timeout: Second-%ld", lock->timeout);
 	dav_headers = curl_slist_append(dav_headers, if_header);
 	dav_headers = curl_slist_append(dav_headers, timeout_header);
@@ -1120,10 +1120,8 @@
 				lock->timeout =
 					strtol(ctx->cdata + 7, NULL, 10);
 		} else if (!strcmp(ctx->name, DAV_ACTIVELOCK_TOKEN)) {
-			if (!prefixcmp(ctx->cdata, "opaquelocktoken:")) {
-				lock->token = xmalloc(strlen(ctx->cdata) - 15);
-				strcpy(lock->token, ctx->cdata + 16);
-			}
+			lock->token = xmalloc(strlen(ctx->cdata) + 1);
+			strcpy(lock->token, ctx->cdata);
 		}
 	}
 }
@@ -1308,7 +1306,7 @@
 	int rc = 0;
 
 	lock_token_header = xmalloc(strlen(lock->token) + 31);
-	sprintf(lock_token_header, "Lock-Token: <opaquelocktoken:%s>",
+	sprintf(lock_token_header, "Lock-Token: <%s>",
 		lock->token);
 	dav_headers = curl_slist_append(dav_headers, lock_token_header);
 
@@ -1722,7 +1720,7 @@
 	struct curl_slist *dav_headers = NULL;
 
 	if_header = xmalloc(strlen(lock->token) + 25);
-	sprintf(if_header, "If: (<opaquelocktoken:%s>)", lock->token);
+	sprintf(if_header, "If: (<%s>)", lock->token);
 	dav_headers = curl_slist_append(dav_headers, if_header);
 
 	strbuf_addf(&out_buffer.buf, "%s\n", sha1_to_hex(sha1));
@@ -1941,7 +1939,7 @@
 		  add_remote_info_ref, &buffer.buf);
 	if (!aborted) {
 		if_header = xmalloc(strlen(lock->token) + 25);
-		sprintf(if_header, "If: (<opaquelocktoken:%s>)", lock->token);
+		sprintf(if_header, "If: (<%s>)", lock->token);
 		dav_headers = curl_slist_append(dav_headers, if_header);
 
 		slot = get_active_slot();
diff --git a/lockfile.c b/lockfile.c
index 6d75608..8589155 100644
--- a/lockfile.c
+++ b/lockfile.c
@@ -140,6 +140,7 @@
 			signal(SIGHUP, remove_lock_file_on_signal);
 			signal(SIGTERM, remove_lock_file_on_signal);
 			signal(SIGQUIT, remove_lock_file_on_signal);
+			signal(SIGPIPE, remove_lock_file_on_signal);
 			atexit(remove_lock_file);
 		}
 		lk->owner = getpid();
diff --git a/perl/Git.pm b/perl/Git.pm
index dde9105..8392a68 100644
--- a/perl/Git.pm
+++ b/perl/Git.pm
@@ -204,14 +204,14 @@
 
 			unless (-d "$dir/refs" and -d "$dir/objects" and -e "$dir/HEAD") {
 				# Mimick git-rev-parse --git-dir error message:
-				throw Error::Simple('fatal: Not a git repository');
+				throw Error::Simple("fatal: Not a git repository: $dir");
 			}
 			my $search = Git->repository(Repository => $dir);
 			try {
 				$search->command('symbolic-ref', 'HEAD');
 			} catch Git::Error::Command with {
 				# Mimick git-rev-parse --git-dir error message:
-				throw Error::Simple('fatal: Not a git repository');
+				throw Error::Simple("fatal: Not a git repository: $dir");
 			}
 
 			$opts{Repository} = abs_path($dir);
diff --git a/setup.c b/setup.c
index 833ced2..6b277b6 100644
--- a/setup.c
+++ b/setup.c
@@ -468,7 +468,7 @@
 				*nongit_ok = 1;
 				return NULL;
 			}
-			die("Not a git repository");
+			die("Not a git repository (or any of the parent directories): %s", DEFAULT_GIT_DIR_ENVIRONMENT);
 		}
 		if (chdir(".."))
 			die("Cannot change to %s/..: %s", cwd, strerror(errno));
diff --git a/t/t2300-cd-to-toplevel.sh b/t/t2300-cd-to-toplevel.sh
new file mode 100755
index 0000000..beddb4e
--- /dev/null
+++ b/t/t2300-cd-to-toplevel.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+
+test_description='cd_to_toplevel'
+
+. ./test-lib.sh
+
+test_cd_to_toplevel () {
+	test_expect_success "$2" '
+		(
+			cd '"'$1'"' &&
+			. git-sh-setup &&
+			cd_to_toplevel &&
+			[ "$(/bin/pwd)" = "$TOPLEVEL" ]
+		)
+	'
+}
+
+TOPLEVEL="$(/bin/pwd)/repo"
+mkdir -p repo/sub/dir
+mv .git repo/
+SUBDIRECTORY_OK=1
+
+test_cd_to_toplevel repo 'at physical root'
+
+test_cd_to_toplevel repo/sub/dir 'at physical subdir'
+
+ln -s repo symrepo
+test_cd_to_toplevel symrepo 'at symbolic root'
+
+ln -s repo/sub/dir subdir-link
+test_cd_to_toplevel subdir-link 'at symbolic subdir'
+
+cd repo
+ln -s sub/dir internal-link
+test_cd_to_toplevel internal-link 'at internal symbolic subdir'
+
+test_done
diff --git a/t/t3600-rm.sh b/t/t3600-rm.sh
index b7d46e5..95542e9 100755
--- a/t/t3600-rm.sh
+++ b/t/t3600-rm.sh
@@ -251,4 +251,21 @@
 
 '
 
+test_expect_success 'choking "git rm" should not let it die with cruft' '
+	git reset -q --hard &&
+	H=0000000000000000000000000000000000000000 &&
+	i=0 &&
+	while test $i -lt 12000
+	do
+	    echo "100644 $H 0	some-file-$i"
+	    i=$(( $i + 1 ))
+	done | git update-index --index-info &&
+	git rm -n "some-file-*" | :;
+	test -f .git/index.lock
+	status=$?
+	rm -f .git/index.lock
+	git reset -q --hard
+	test "$status" != 0
+'
+
 test_done
diff --git a/t/t5521-pull-symlink.sh b/t/t5521-pull-symlink.sh
new file mode 100755
index 0000000..5672b51
--- /dev/null
+++ b/t/t5521-pull-symlink.sh
@@ -0,0 +1,78 @@
+#!/bin/sh
+
+test_description='pulling from symlinked subdir'
+
+. ./test-lib.sh
+
+# The scenario we are building:
+#
+#   trash\ directory/
+#     clone-repo/
+#       subdir/
+#         bar
+#     subdir-link -> clone-repo/subdir/
+#
+# The working directory is subdir-link.
+
+mkdir subdir
+echo file >subdir/file
+git add subdir/file
+git commit -q -m file
+git clone -q . clone-repo
+ln -s clone-repo/subdir/ subdir-link
+
+
+# Demonstrate that things work if we just avoid the symlink
+#
+test_expect_success 'pulling from real subdir' '
+	(
+		echo real >subdir/file &&
+		git commit -m real subdir/file &&
+		cd clone-repo/subdir/ &&
+		git pull &&
+		test real = $(cat file)
+	)
+'
+
+# From subdir-link, pulling should work as it does from
+# clone-repo/subdir/.
+#
+# Instead, the error pull gave was:
+#
+#   fatal: 'origin': unable to chdir or not a git archive
+#   fatal: The remote end hung up unexpectedly
+#
+# because git would find the .git/config for the "trash directory"
+# repo, not for the clone-repo repo.  The "trash directory" repo
+# had no entry for origin.  Git found the wrong .git because
+# git rev-parse --show-cdup printed a path relative to
+# clone-repo/subdir/, not subdir-link/.  Git rev-parse --show-cdup
+# used the correct .git, but when the git pull shell script did
+# "cd `git rev-parse --show-cdup`", it ended up in the wrong
+# directory.  A POSIX shell's "cd" works a little differently
+# than chdir() in C; "cd -P" is much closer to chdir().
+#
+test_expect_success 'pulling from symlinked subdir' '
+	(
+		echo link >subdir/file &&
+		git commit -m link subdir/file &&
+		cd subdir-link/ &&
+		git pull &&
+		test link = $(cat file)
+	)
+'
+
+# Prove that the remote end really is a repo, and other commands
+# work fine in this context.  It's just that "git pull" breaks.
+#
+test_expect_success 'pushing from symlinked subdir' '
+	(
+		cd subdir-link/ &&
+		echo push >file &&
+		git commit -m push ./file &&
+		git push
+	) &&
+	test push = $(git show HEAD:subdir/file)
+'
+
+test_done
diff --git a/t/t9129-git-svn-i18n-commitencoding.sh b/t/t9129-git-svn-i18n-commitencoding.sh
index 938b7fe..8a9dde4 100755
--- a/t/t9129-git-svn-i18n-commitencoding.sh
+++ b/t/t9129-git-svn-i18n-commitencoding.sh
@@ -60,21 +60,25 @@
 	'
 done
 
-test_expect_success 'ISO-8859-1 should match UTF-8 in svn' '
-(
-	cd ISO-8859-1 &&
-	compare_svn_head_with "$TEST_DIRECTORY"/t3900/1-UTF-8.txt
-)
-'
-
-for H in EUCJP ISO-2022-JP
-do
-	test_expect_success '$H should match UTF-8 in svn' '
+if locale -a |grep -q en_US.utf8; then
+	test_expect_success 'ISO-8859-1 should match UTF-8 in svn' '
 	(
-		cd $H &&
-		compare_svn_head_with "$TEST_DIRECTORY"/t3900/2-UTF-8.txt
+		cd ISO-8859-1 &&
+		compare_svn_head_with "$TEST_DIRECTORY"/t3900/1-UTF-8.txt
 	)
 	'
-done
+
+	for H in EUCJP ISO-2022-JP
+	do
+		test_expect_success '$H should match UTF-8 in svn' '
+		(
+			cd $H &&
+			compare_svn_head_with "$TEST_DIRECTORY"/t3900/2-UTF-8.txt
+		)
+		'
+	done
+else
+	say "UTF-8 locale not available, test skipped"
+fi
 
 test_done