Merge branch 'maint' of git://repo.or.cz/git-gui into maint

* 'maint' of git://repo.or.cz/git-gui:
  git-gui: Work around bad interaction between Tcl and cmd.exe on ^{tree}
  git-gui: Don't linewrap within console windows
  git-gui: Correct ls-tree buffering problem in browser
  git-gui: Skip nicknames when selecting author initials
  git-gui: Ensure windows shortcuts always have .bat extension
  git-gui: Include a Push action on the left toolbar
  git-gui: Bind M1-P to push action
  git-gui: Don't bind F5/M1-R in all windows
  git-gui: Unlock the index when cancelling merge dialog
  git-gui: properly popup error if gitk should be started but is not installed
diff --git a/git-gui/git-gui.sh b/git-gui/git-gui.sh
index 4fbc408..c38aa06 100755
--- a/git-gui/git-gui.sh
+++ b/git-gui/git-gui.sh
@@ -1042,15 +1042,17 @@
 	#    lets us bypass using shell process on Windows systems.
 	#
 	set cmd [list [info nameofexecutable]]
-	lappend cmd [gitexec gitk]
+	set exe [gitexec gitk]
+	lappend cmd $exe
 	if {$revs ne {}} {
 		append cmd { }
 		append cmd $revs
 	}
 
-	if {[catch {eval exec $cmd &} err]} {
-		error_popup "Failed to start gitk:\n\n$err"
+	if {! [file exists $exe]} {
+		error_popup "Unable to start gitk:\n\n$exe does not exist"
 	} else {
+		eval exec $cmd &
 		set ui_status_value $starting_gitk_msg
 		after 10000 {
 			if {$ui_status_value eq $starting_gitk_msg} {
@@ -1523,7 +1525,8 @@
 
 	menu .mbar.push
 	.mbar.push add command -label {Push...} \
-		-command do_push_anywhere
+		-command do_push_anywhere \
+		-accelerator $M1T-P
 }
 
 if {[is_MacOSX]} {
@@ -1819,6 +1822,10 @@
 lappend disable_on_lock \
 	{.vpane.lower.commarea.buttons.commit conf -state}
 
+button .vpane.lower.commarea.buttons.push -text {Push} \
+	-command do_push_anywhere
+pack .vpane.lower.commarea.buttons.push -side top -fill x
+
 # -- Commit Message Buffer
 #
 frame .vpane.lower.commarea.buffer
@@ -2146,10 +2153,14 @@
 	bind . <$M1B-Key-n> do_create_branch
 	bind . <$M1B-Key-N> do_create_branch
 }
+if {[is_enabled transport]} {
+	bind . <$M1B-Key-p> do_push_anywhere
+	bind . <$M1B-Key-P> do_push_anywhere
+}
 
-bind all <Key-F5> do_rescan
-bind all <$M1B-Key-r> do_rescan
-bind all <$M1B-Key-R> do_rescan
+bind .   <Key-F5>     do_rescan
+bind .   <$M1B-Key-r> do_rescan
+bind .   <$M1B-Key-R> do_rescan
 bind .   <$M1B-Key-s> do_signoff
 bind .   <$M1B-Key-S> do_signoff
 bind .   <$M1B-Key-i> do_add_all
diff --git a/git-gui/lib/blame.tcl b/git-gui/lib/blame.tcl
index b523654..1d2caac 100644
--- a/git-gui/lib/blame.tcl
+++ b/git-gui/lib/blame.tcl
@@ -547,6 +547,10 @@
 			set a_name {}
 			catch {set a_name $header($cmit,author)}
 			while {$a_name ne {}} {
+				if {$author_abbr ne {}
+					&& [string index $a_name 0] eq {'}} {
+					regsub {^'[^']+'\s+} $a_name {} a_name
+				}
 				if {![regexp {^([[:upper:]])} $a_name _a]} break
 				append author_abbr $_a
 				unset _a
diff --git a/git-gui/lib/browser.tcl b/git-gui/lib/browser.tcl
index 3d6341b..e612247 100644
--- a/git-gui/lib/browser.tcl
+++ b/git-gui/lib/browser.tcl
@@ -11,6 +11,8 @@
 field browser_stack  {}
 field browser_busy   1
 
+field ls_buf     {}; # Buffered record output from ls-tree
+
 constructor new {commit} {
 	global cursor_ptr M1B
 	make_toplevel top w
@@ -160,7 +162,7 @@
 }
 
 method _ls {tree_id {name {}}} {
-	set browser_buffer {}
+	set ls_buf {}
 	set browser_files {}
 	set browser_busy 1
 
@@ -185,17 +187,19 @@
 }
 
 method _read {fd} {
-	append browser_buffer [read $fd]
-	set pck [split $browser_buffer "\0"]
-	set browser_buffer [lindex $pck end]
+	append ls_buf [read $fd]
+	set pck [split $ls_buf "\0"]
+	set ls_buf [lindex $pck end]
 
 	set n [llength $browser_files]
 	$w conf -state normal
 	foreach p [lrange $pck 0 end-1] {
-		set info [split $p "\t"]
-		set path [lindex $info 1]
-		set info [split [lindex $info 0] { }]
-		set type [lindex $info 1]
+		set tab [string first "\t" $p]
+		if {$tab == -1} continue
+
+		set info [split [string range $p 0 [expr {$tab - 1}]] { }]
+		set path [string range $p [expr {$tab + 1}] end]
+		set type   [lindex $info 1]
 		set object [lindex $info 2]
 
 		switch -- $type {
@@ -225,7 +229,7 @@
 		close $fd
 		set browser_status Ready.
 		set browser_busy 0
-		unset browser_buffer
+		set ls_buf {}
 		if {$n > 0} {
 			$w tag add in_sel 1.0 2.0
 			focus -force $w
diff --git a/git-gui/lib/commit.tcl b/git-gui/lib/commit.tcl
index f9791f6..e139f4d 100644
--- a/git-gui/lib/commit.tcl
+++ b/git-gui/lib/commit.tcl
@@ -260,7 +260,18 @@
 	# -- Verify this wasn't an empty change.
 	#
 	if {$commit_type eq {normal}} {
-		set old_tree [git rev-parse "$PARENT^{tree}"]
+		set fd_ot [open "| git cat-file commit $PARENT" r]
+		fconfigure $fd_ot -encoding binary -translation lf
+		set old_tree [gets $fd_ot]
+		close $fd_ot
+
+		if {[string equal -length 5 {tree } $old_tree]
+			&& [string length $old_tree] == 45} {
+			set old_tree [string range $old_tree 5 end]
+		} else {
+			error "Commit $PARENT appears to be corrupt"
+		}
+
 		if {$tree_id eq $old_tree} {
 			info_popup {No changes to commit.
 
diff --git a/git-gui/lib/console.tcl b/git-gui/lib/console.tcl
index ce25d92..34de5d4 100644
--- a/git-gui/lib/console.tcl
+++ b/git-gui/lib/console.tcl
@@ -31,16 +31,20 @@
 		-background white -borderwidth 1 \
 		-relief sunken \
 		-width 80 -height 10 \
+		-wrap none \
 		-font font_diff \
 		-state disabled \
+		-xscrollcommand [list $w.m.sbx set] \
 		-yscrollcommand [list $w.m.sby set]
 	label $w.m.s -text {Working... please wait...} \
 		-anchor w \
 		-justify left \
 		-font font_uibold
+	scrollbar $w.m.sbx -command [list $w.m.t xview] -orient h
 	scrollbar $w.m.sby -command [list $w.m.t yview]
 	pack $w.m.l1 -side top -fill x
 	pack $w.m.s -side bottom -fill x
+	pack $w.m.sbx -side bottom -fill x
 	pack $w.m.sby -side right -fill y
 	pack $w.m.t -side left -fill both -expand 1
 	pack $w.m -side top -fill both -expand 1 -padx 5 -pady 10
diff --git a/git-gui/lib/merge.tcl b/git-gui/lib/merge.tcl
index ae0389d..889182f 100644
--- a/git-gui/lib/merge.tcl
+++ b/git-gui/lib/merge.tcl
@@ -213,7 +213,9 @@
 	pack $w.buttons.visualize -side left
 	button $w.buttons.create -text Merge -command $_start
 	pack $w.buttons.create -side right
-	button $w.buttons.cancel -text {Cancel} -command [list destroy $w]
+	button $w.buttons.cancel \
+		-text {Cancel} \
+		-command "unlock_index;destroy $w"
 	pack $w.buttons.cancel -side right -padx 5
 	pack $w.buttons -side bottom -fill x -pady 10 -padx 10
 
diff --git a/git-gui/lib/shortcut.tcl b/git-gui/lib/shortcut.tcl
index ebf72e4..a0a1b7d 100644
--- a/git-gui/lib/shortcut.tcl
+++ b/git-gui/lib/shortcut.tcl
@@ -9,6 +9,9 @@
 		-title "[appname] ([reponame]): Create Desktop Icon" \
 		-initialfile "Git [reponame].bat"]
 	if {$fn != {}} {
+		if {[file extension $fn] ne {.bat}} {
+			set fn ${fn}.bat
+		}
 		if {[catch {
 				set fd [open $fn w]
 				puts $fd "@ECHO Entering [reponame]"
@@ -42,6 +45,9 @@
 		-initialdir $desktop \
 		-initialfile "Git [reponame].bat"]
 	if {$fn != {}} {
+		if {[file extension $fn] ne {.bat}} {
+			set fn ${fn}.bat
+		}
 		if {[catch {
 				set fd [open $fn w]
 				set sh [exec cygpath \