summary refs log tree commit diff
path: root/gitk-git
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2008-05-14 21:27:55 -0700
committerJunio C Hamano <gitster@pobox.com>2008-05-14 21:27:55 -0700
commitc7ea453618e41e05a06f05e3ab63d555d0ddd7d9 (patch)
treece56252f7a962fdd663a2e76276727a35d1c15e4 /gitk-git
parent4b172de81b878cdc8b10803fd0cd79b3ca66a621 (diff)
parent08ba820fd7d82cd798d271a9ef6caaf83ffed387 (diff)
Merge git://git.kernel.org/pub/scm/gitk/gitk
* git://git.kernel.org/pub/scm/gitk/gitk: (44 commits)
  gitk: Add a progress bar for checking out a head
  gitk: Show current row number and total number of rows
  gitk: Allow users to view diffs in external diff viewer
  gitk: Synchronize highlighting in file view for 'f' and 'b' commands
  gitk: Make updates go faster
  gitk: Disable "Reset %s branch to here" when on a detached head
  gitk: German translation again updated
  gitk: Update German translation
  gitk: Makefile/install: force permissions when installing files and dirs
  gitk: Initial Swedish translation.
  gitk: Spanish translation of gitk
  gitk: Fix handling of tree file list with special chars in names
  gitk: Reorganize processing of arguments for git log
  gitk: Fix problem with target row not being in scroll region
  gitk: Avoid a crash in selectline if commitinfo($id) isn't set
  gitk: Fix some corner cases in computing vrowmod and displayorder
  gitk: Correct a few strings and comments to say "git log"
  gitk: Don't filter view arguments through git rev-parse
  gitk: Fix problems with target row stuff
  gitk: Handle updating with path limiting better
  ...
Diffstat (limited to 'gitk-git')
-rw-r--r--gitk-git/Makefile6
-rw-r--r--gitk-git/gitk2606
-rw-r--r--gitk-git/gitk-git/po/es.po890
-rw-r--r--gitk-git/po/de.po527
-rw-r--r--gitk-git/po/sv.po887
5 files changed, 4028 insertions, 888 deletions
diff --git a/gitk-git/Makefile b/gitk-git/Makefile
index f90dfabffa..e1b6045605 100644
--- a/gitk-git/Makefile
+++ b/gitk-git/Makefile
@@ -40,9 +40,9 @@ endif
 all:: gitk-wish $(ALL_MSGFILES)
 
 install:: all
-	$(INSTALL) gitk-wish '$(DESTDIR_SQ)$(bindir_SQ)'/gitk
-	$(INSTALL) -d '$(DESTDIR_SQ)$(msgsdir_SQ)'
-	$(foreach p,$(ALL_MSGFILES), $(INSTALL) $p '$(DESTDIR_SQ)$(msgsdir_SQ)' &&) true
+	$(INSTALL) -m 755 gitk-wish '$(DESTDIR_SQ)$(bindir_SQ)'/gitk
+	$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(msgsdir_SQ)'
+	$(foreach p,$(ALL_MSGFILES), $(INSTALL) -m 644 $p '$(DESTDIR_SQ)$(msgsdir_SQ)' &&) true
 
 uninstall::
 	$(foreach p,$(ALL_MSGFILES), $(RM) '$(DESTDIR_SQ)$(msgsdir_SQ)'/$(notdir $p) &&) true
diff --git a/gitk-git/gitk b/gitk-git/gitk
index 9a4d9c40cf..9ab6dbaa46 100644
--- a/gitk-git/gitk
+++ b/gitk-git/gitk
@@ -2,7 +2,7 @@
 # Tcl ignores the next line -*- tcl -*- \
 exec wish "$0" -- "$@"
 
-# Copyright (C) 2005-2006 Paul Mackerras.  All rights reserved.
+# Copyright © 2005-2008 Paul Mackerras.  All rights reserved.
 # This program is free software; it may be used, copied, modified
 # and distributed under the terms of the GNU General Public Licence,
 # either version 2, or (at your option) any later version.
@@ -47,12 +47,24 @@ proc filereadable {fd script} {
     lappend runq [list $fd $script]
 }
 
+proc nukefile {fd} {
+    global runq
+
+    for {set i 0} {$i < [llength $runq]} {} {
+	if {[lindex $runq $i 0] eq $fd} {
+	    set runq [lreplace $runq $i $i]
+	} else {
+	    incr i
+	}
+    }
+}
+
 proc dorunq {} {
     global isonrunq runq
 
     set tstart [clock clicks -milliseconds]
     set t0 $tstart
-    while {$runq ne {}} {
+    while {[llength $runq] > 0} {
 	set fd [lindex $runq 0 0]
 	set script [lindex $runq 0 1]
 	set repeat [eval $script]
@@ -78,41 +90,274 @@ proc dorunq {} {
     }
 }
 
-# Start off a git rev-list process and arrange to read its output
+proc unmerged_files {files} {
+    global nr_unmerged
+
+    # find the list of unmerged files
+    set mlist {}
+    set nr_unmerged 0
+    if {[catch {
+	set fd [open "| git ls-files -u" r]
+    } err]} {
+	show_error {} . "[mc "Couldn't get list of unmerged files:"] $err"
+	exit 1
+    }
+    while {[gets $fd line] >= 0} {
+	set i [string first "\t" $line]
+	if {$i < 0} continue
+	set fname [string range $line [expr {$i+1}] end]
+	if {[lsearch -exact $mlist $fname] >= 0} continue
+	incr nr_unmerged
+	if {$files eq {} || [path_filter $files $fname]} {
+	    lappend mlist $fname
+	}
+    }
+    catch {close $fd}
+    return $mlist
+}
+
+proc parseviewargs {n arglist} {
+    global vdatemode vmergeonly vflags vdflags vrevs vfiltered vorigargs
+
+    set vdatemode($n) 0
+    set vmergeonly($n) 0
+    set glflags {}
+    set diffargs {}
+    set nextisval 0
+    set revargs {}
+    set origargs $arglist
+    set allknown 1
+    set filtered 0
+    set i -1
+    foreach arg $arglist {
+	incr i
+	if {$nextisval} {
+	    lappend glflags $arg
+	    set nextisval 0
+	    continue
+	}
+	switch -glob -- $arg {
+	    "-d" -
+	    "--date-order" {
+		set vdatemode($n) 1
+		# remove from origargs in case we hit an unknown option
+		set origargs [lreplace $origargs $i $i]
+		incr i -1
+	    }
+	    # These request or affect diff output, which we don't want.
+	    # Some could be used to set our defaults for diff display.
+	    "-[puabwcrRBMC]" -
+	    "--no-renames" - "--full-index" - "--binary" - "--abbrev=*" -
+	    "--find-copies-harder" - "-l*" - "--ext-diff" - "--no-ext-diff" -
+	    "--src-prefix=*" - "--dst-prefix=*" - "--no-prefix" -
+	    "-O*" - "--text" - "--full-diff" - "--ignore-space-at-eol" -
+	    "--ignore-space-change" - "-U*" - "--unified=*" {
+		lappend diffargs $arg
+	    }
+	    # These cause our parsing of git log's output to fail, or else
+	    # they're options we want to set ourselves, so ignore them.
+	    "--raw" - "--patch-with-raw" - "--patch-with-stat" -
+	    "--name-only" - "--name-status" - "--color" - "--color-words" -
+	    "--log-size" - "--pretty=*" - "--decorate" - "--abbrev-commit" -
+	    "--cc" - "-z" - "--header" - "--parents" - "--boundary" -
+	    "--no-color" - "-g" - "--walk-reflogs" - "--no-walk" -
+	    "--timestamp" - "relative-date" - "--date=*" - "--stdin" -
+	    "--objects" - "--objects-edge" - "--reverse" {
+	    }
+	    # These are harmless, and some are even useful
+	    "--stat=*" - "--numstat" - "--shortstat" - "--summary" -
+	    "--check" - "--exit-code" - "--quiet" - "--topo-order" -
+	    "--full-history" - "--dense" - "--sparse" -
+	    "--follow" - "--left-right" - "--encoding=*" {
+		lappend glflags $arg
+	    }
+	    # These mean that we get a subset of the commits
+	    "--diff-filter=*" - "--no-merges" - "--unpacked" -
+	    "--max-count=*" - "--skip=*" - "--since=*" - "--after=*" -
+	    "--until=*" - "--before=*" - "--max-age=*" - "--min-age=*" -
+	    "--author=*" - "--committer=*" - "--grep=*" - "-[iE]" -
+	    "--remove-empty" - "--first-parent" - "--cherry-pick" -
+	    "-S*" - "--pickaxe-all" - "--pickaxe-regex" - {
+		set filtered 1
+		lappend glflags $arg
+	    }
+	    # This appears to be the only one that has a value as a
+	    # separate word following it
+	    "-n" {
+		set filtered 1
+		set nextisval 1
+		lappend glflags $arg
+	    }
+	    "--not" {
+		set notflag [expr {!$notflag}]
+		lappend revargs $arg
+	    }
+	    "--all" {
+		lappend revargs $arg
+	    }
+	    "--merge" {
+		set vmergeonly($n) 1
+		# git rev-parse doesn't understand --merge
+		lappend revargs --gitk-symmetric-diff-marker MERGE_HEAD...HEAD
+	    }
+	    # Other flag arguments including -<n>
+	    "-*" {
+		if {[string is digit -strict [string range $arg 1 end]]} {
+		    set filtered 1
+		} else {
+		    # a flag argument that we don't recognize;
+		    # that means we can't optimize
+		    set allknown 0
+		}
+		lappend glflags $arg
+	    }
+	    # Non-flag arguments specify commits or ranges of commits
+	    default {
+		if {[string match "*...*" $arg]} {
+		    lappend revargs --gitk-symmetric-diff-marker
+		}
+		lappend revargs $arg
+	    }
+	}
+    }
+    set vdflags($n) $diffargs
+    set vflags($n) $glflags
+    set vrevs($n) $revargs
+    set vfiltered($n) $filtered
+    set vorigargs($n) $origargs
+    return $allknown
+}
+
+proc parseviewrevs {view revs} {
+    global vposids vnegids
+
+    if {$revs eq {}} {
+	set revs HEAD
+    }
+    if {[catch {set ids [eval exec git rev-parse $revs]} err]} {
+	# we get stdout followed by stderr in $err
+	# for an unknown rev, git rev-parse echoes it and then errors out
+	set errlines [split $err "\n"]
+	set badrev {}
+	for {set l 0} {$l < [llength $errlines]} {incr l} {
+	    set line [lindex $errlines $l]
+	    if {!([string length $line] == 40 && [string is xdigit $line])} {
+		if {[string match "fatal:*" $line]} {
+		    if {[string match "fatal: ambiguous argument*" $line]
+			&& $badrev ne {}} {
+			if {[llength $badrev] == 1} {
+			    set err "unknown revision $badrev"
+			} else {
+			    set err "unknown revisions: [join $badrev ", "]"
+			}
+		    } else {
+			set err [join [lrange $errlines $l end] "\n"]
+		    }
+		    break
+		}
+		lappend badrev $line
+	    }
+	}		    
+	error_popup "Error parsing revisions: $err"
+	return {}
+    }
+    set ret {}
+    set pos {}
+    set neg {}
+    set sdm 0
+    foreach id [split $ids "\n"] {
+	if {$id eq "--gitk-symmetric-diff-marker"} {
+	    set sdm 4
+	} elseif {[string match "^*" $id]} {
+	    if {$sdm != 1} {
+		lappend ret $id
+		if {$sdm == 3} {
+		    set sdm 0
+		}
+	    }
+	    lappend neg [string range $id 1 end]
+	} else {
+	    if {$sdm != 2} {
+		lappend ret $id
+	    } else {
+		lset ret end [lindex $ret end]...$id
+	    }
+	    lappend pos $id
+	}
+	incr sdm -1
+    }
+    set vposids($view) $pos
+    set vnegids($view) $neg
+    return $ret
+}
+
+# Start off a git log process and arrange to read its output
 proc start_rev_list {view} {
-    global startmsecs
-    global commfd leftover tclencoding datemode
-    global viewargs viewargscmd viewfiles commitidx viewcomplete vnextroot
+    global startmsecs commitidx viewcomplete curview
+    global commfd leftover tclencoding
+    global viewargs viewargscmd viewfiles vfilelimit
     global showlocalchanges commitinterest mainheadid
-    global progressdirn progresscoords proglastnc curview
+    global viewactive loginstance viewinstances vmergeonly
+    global pending_select mainheadid
+    global vcanopt vflags vrevs vorigargs
 
     set startmsecs [clock clicks -milliseconds]
     set commitidx($view) 0
-    set viewcomplete($view) 0
-    set vnextroot($view) 0
+    # these are set this way for the error exits
+    set viewcomplete($view) 1
+    set viewactive($view) 0
+    varcinit $view
+
     set args $viewargs($view)
     if {$viewargscmd($view) ne {}} {
 	if {[catch {
 	    set str [exec sh -c $viewargscmd($view)]
 	} err]} {
 	    error_popup "Error executing --argscmd command: $err"
-	    exit 1
+	    return 0
 	}
 	set args [concat $args [split $str "\n"]]
     }
-    set order "--topo-order"
-    if {$datemode} {
-	set order "--date-order"
+    set vcanopt($view) [parseviewargs $view $args]
+
+    set files $viewfiles($view)
+    if {$vmergeonly($view)} {
+	set files [unmerged_files $files]
+	if {$files eq {}} {
+	    global nr_unmerged
+	    if {$nr_unmerged == 0} {
+		error_popup [mc "No files selected: --merge specified but\
+			     no files are unmerged."]
+	    } else {
+		error_popup [mc "No files selected: --merge specified but\
+			     no unmerged files are within file limit."]
+	    }
+	    return 0
+	}
     }
+    set vfilelimit($view) $files
+
+    if {$vcanopt($view)} {
+	set revs [parseviewrevs $view $vrevs($view)]
+	if {$revs eq {}} {
+	    return 0
+	}
+	set args [concat $vflags($view) $revs]
+    } else {
+	set args $vorigargs($view)
+    }
+
     if {[catch {
-	set fd [open [concat | git log --no-color -z --pretty=raw $order --parents \
-			 --boundary $args "--" $viewfiles($view)] r]
+	set fd [open [concat | git log --no-color -z --pretty=raw --parents \
+			 --boundary $args "--" $files] r]
     } err]} {
-	error_popup "[mc "Error executing git rev-list:"] $err"
-	exit 1
+	error_popup "[mc "Error executing git log:"] $err"
+	return 0
     }
-    set commfd($view) $fd
-    set leftover($view) {}
+    set i [incr loginstance]
+    set viewinstances($view) [list $i]
+    set commfd($i) $fd
+    set leftover($i) {}
     if {$showlocalchanges} {
 	lappend commitinterest($mainheadid) {dodiffindex}
     }
@@ -120,35 +365,152 @@ proc start_rev_list {view} {
     if {$tclencoding != {}} {
 	fconfigure $fd -encoding $tclencoding
     }
-    filerun $fd [list getcommitlines $fd $view]
+    filerun $fd [list getcommitlines $fd $i $view 0]
     nowbusy $view [mc "Reading"]
     if {$view == $curview} {
-	set progressdirn 1
-	set progresscoords {0 0}
-	set proglastnc 0
+	set pending_select $mainheadid
     }
+    set viewcomplete($view) 0
+    set viewactive($view) 1
+    return 1
 }
 
-proc stop_rev_list {} {
-    global commfd curview
+proc stop_rev_list {view} {
+    global commfd viewinstances leftover
 
-    if {![info exists commfd($curview)]} return
-    set fd $commfd($curview)
-    catch {
-	set pid [pid $fd]
-	exec kill $pid
+    foreach inst $viewinstances($view) {
+	set fd $commfd($inst)
+	catch {
+	    set pid [pid $fd]
+	    exec kill $pid
+	}
+	catch {close $fd}
+	nukefile $fd
+	unset commfd($inst)
+	unset leftover($inst)
     }
-    catch {close $fd}
-    unset commfd($curview)
+    set viewinstances($view) {}
 }
 
 proc getcommits {} {
-    global phase canv curview
+    global canv curview need_redisplay viewactive
 
-    set phase getcommits
     initlayout
-    start_rev_list $curview
-    show_status [mc "Reading commits..."]
+    if {[start_rev_list $curview]} {
+	show_status [mc "Reading commits..."]
+	set need_redisplay 1
+    } else {
+	show_status [mc "No commits selected"]
+    }
+}
+
+proc updatecommits {} {
+    global curview vcanopt vorigargs vfilelimit viewinstances
+    global viewactive viewcomplete loginstance tclencoding mainheadid
+    global startmsecs commfd showneartags showlocalchanges leftover
+    global mainheadid pending_select
+    global isworktree
+    global varcid vposids vnegids vflags vrevs
+
+    set isworktree [expr {[exec git rev-parse --is-inside-work-tree] == "true"}]
+    set oldmainid $mainheadid
+    rereadrefs
+    if {$showlocalchanges} {
+	if {$mainheadid ne $oldmainid} {
+	    dohidelocalchanges
+	}
+	if {[commitinview $mainheadid $curview]} {
+	    dodiffindex
+	}
+    }
+    set view $curview
+    if {$vcanopt($view)} {
+	set oldpos $vposids($view)
+	set oldneg $vnegids($view)
+	set revs [parseviewrevs $view $vrevs($view)]
+	if {$revs eq {}} {
+	    return
+	}
+	# note: getting the delta when negative refs change is hard,
+	# and could require multiple git log invocations, so in that
+	# case we ask git log for all the commits (not just the delta)
+	if {$oldneg eq $vnegids($view)} {
+	    set newrevs {}
+	    set npos 0
+	    # take out positive refs that we asked for before or
+	    # that we have already seen
+	    foreach rev $revs {
+		if {[string length $rev] == 40} {
+		    if {[lsearch -exact $oldpos $rev] < 0
+			&& ![info exists varcid($view,$rev)]} {
+			lappend newrevs $rev
+			incr npos
+		    }
+		} else {
+		    lappend $newrevs $rev
+		}
+	    }
+	    if {$npos == 0} return
+	    set revs $newrevs
+	    set vposids($view) [lsort -unique [concat $oldpos $vposids($view)]]
+	}
+	set args [concat $vflags($view) $revs --not $oldpos]
+    } else {
+	set args $vorigargs($view)
+    }
+    if {[catch {
+	set fd [open [concat | git log --no-color -z --pretty=raw --parents \
+			  --boundary $args "--" $vfilelimit($view)] r]
+    } err]} {
+	error_popup "Error executing git log: $err"
+	return
+    }
+    if {$viewactive($view) == 0} {
+	set startmsecs [clock clicks -milliseconds]
+    }
+    set i [incr loginstance]
+    lappend viewinstances($view) $i
+    set commfd($i) $fd
+    set leftover($i) {}
+    fconfigure $fd -blocking 0 -translation lf -eofchar {}
+    if {$tclencoding != {}} {
+	fconfigure $fd -encoding $tclencoding
+    }
+    filerun $fd [list getcommitlines $fd $i $view 1]
+    incr viewactive($view)
+    set viewcomplete($view) 0
+    set pending_select $mainheadid
+    nowbusy $view "Reading"
+    if {$showneartags} {
+	getallcommits
+    }
+}
+
+proc reloadcommits {} {
+    global curview viewcomplete selectedline currentid thickerline
+    global showneartags treediffs commitinterest cached_commitrow
+    global targetid
+
+    if {!$viewcomplete($curview)} {
+	stop_rev_list $curview
+    }
+    resetvarcs $curview
+    catch {unset selectedline}
+    catch {unset currentid}
+    catch {unset thickerline}
+    catch {unset treediffs}
+    readrefs
+    changedrefs
+    if {$showneartags} {
+	getallcommits
+    }
+    clear_display
+    catch {unset commitinterest}
+    catch {unset cached_commitrow}
+    catch {unset targetid}
+    setcanvscroll
+    getcommits
+    return 0
 }
 
 # This makes a string representation of a positive integer which
@@ -164,46 +526,759 @@ proc strrep {n} {
     return [format "z%.8x" $n]
 }
 
-proc getcommitlines {fd view}  {
-    global commitlisted commitinterest
-    global leftover commfd
-    global displayorder commitidx viewcomplete commitrow commitdata
-    global parentlist children curview hlview
-    global vparentlist vdisporder vcmitlisted
-    global ordertok vnextroot idpending
+# Procedures used in reordering commits from git log (without
+# --topo-order) into the order for display.
+
+proc varcinit {view} {
+    global varcstart vupptr vdownptr vleftptr vbackptr varctok varcrow
+    global vtokmod varcmod vrowmod varcix vlastins
+
+    set varcstart($view) {{}}
+    set vupptr($view) {0}
+    set vdownptr($view) {0}
+    set vleftptr($view) {0}
+    set vbackptr($view) {0}
+    set varctok($view) {{}}
+    set varcrow($view) {{}}
+    set vtokmod($view) {}
+    set varcmod($view) 0
+    set vrowmod($view) 0
+    set varcix($view) {{}}
+    set vlastins($view) {0}
+}
+
+proc resetvarcs {view} {
+    global varcid varccommits parents children vseedcount ordertok
+
+    foreach vid [array names varcid $view,*] {
+	unset varcid($vid)
+	unset children($vid)
+	unset parents($vid)
+    }
+    # some commits might have children but haven't been seen yet
+    foreach vid [array names children $view,*] {
+	unset children($vid)
+    }
+    foreach va [array names varccommits $view,*] {
+	unset varccommits($va)
+    }
+    foreach vd [array names vseedcount $view,*] {
+	unset vseedcount($vd)
+    }
+    catch {unset ordertok}
+}
+
+# returns a list of the commits with no children
+proc seeds {v} {
+    global vdownptr vleftptr varcstart
+
+    set ret {}
+    set a [lindex $vdownptr($v) 0]
+    while {$a != 0} {
+	lappend ret [lindex $varcstart($v) $a]
+	set a [lindex $vleftptr($v) $a]
+    }
+    return $ret
+}
+
+proc newvarc {view id} {
+    global varcid varctok parents children vdatemode
+    global vupptr vdownptr vleftptr vbackptr varcrow varcix varcstart
+    global commitdata commitinfo vseedcount varccommits vlastins
+
+    set a [llength $varctok($view)]
+    set vid $view,$id
+    if {[llength $children($vid)] == 0 || $vdatemode($view)} {
+	if {![info exists commitinfo($id)]} {
+	    parsecommit $id $commitdata($id) 1
+	}
+	set cdate [lindex $commitinfo($id) 4]
+	if {![string is integer -strict $cdate]} {
+	    set cdate 0
+	}
+	if {![info exists vseedcount($view,$cdate)]} {
+	    set vseedcount($view,$cdate) -1
+	}
+	set c [incr vseedcount($view,$cdate)]
+	set cdate [expr {$cdate ^ 0xffffffff}]
+	set tok "s[strrep $cdate][strrep $c]"
+    } else {
+	set tok {}
+    }
+    set ka 0
+    if {[llength $children($vid)] > 0} {
+	set kid [lindex $children($vid) end]
+	set k $varcid($view,$kid)
+	if {[string compare [lindex $varctok($view) $k] $tok] > 0} {
+	    set ki $kid
+	    set ka $k
+	    set tok [lindex $varctok($view) $k]
+	}
+    }
+    if {$ka != 0} {
+	set i [lsearch -exact $parents($view,$ki) $id]
+	set j [expr {[llength $parents($view,$ki)] - 1 - $i}]
+	append tok [strrep $j]
+    }
+    set c [lindex $vlastins($view) $ka]
+    if {$c == 0 || [string compare $tok [lindex $varctok($view) $c]] < 0} {
+	set c $ka
+	set b [lindex $vdownptr($view) $ka]
+    } else {
+	set b [lindex $vleftptr($view) $c]
+    }
+    while {$b != 0 && [string compare $tok [lindex $varctok($view) $b]] >= 0} {
+	set c $b
+	set b [lindex $vleftptr($view) $c]
+    }
+    if {$c == $ka} {
+	lset vdownptr($view) $ka $a
+	lappend vbackptr($view) 0
+    } else {
+	lset vleftptr($view) $c $a
+	lappend vbackptr($view) $c
+    }
+    lset vlastins($view) $ka $a
+    lappend vupptr($view) $ka
+    lappend vleftptr($view) $b
+    if {$b != 0} {
+	lset vbackptr($view) $b $a
+    }
+    lappend varctok($view) $tok
+    lappend varcstart($view) $id
+    lappend vdownptr($view) 0
+    lappend varcrow($view) {}
+    lappend varcix($view) {}
+    set varccommits($view,$a) {}
+    lappend vlastins($view) 0
+    return $a
+}
+
+proc splitvarc {p v} {
+    global varcid varcstart varccommits varctok
+    global vupptr vdownptr vleftptr vbackptr varcix varcrow vlastins
+
+    set oa $varcid($v,$p)
+    set ac $varccommits($v,$oa)
+    set i [lsearch -exact $varccommits($v,$oa) $p]
+    if {$i <= 0} return
+    set na [llength $varctok($v)]
+    # "%" sorts before "0"...
+    set tok "[lindex $varctok($v) $oa]%[strrep $i]"
+    lappend varctok($v) $tok
+    lappend varcrow($v) {}
+    lappend varcix($v) {}
+    set varccommits($v,$oa) [lrange $ac 0 [expr {$i - 1}]]
+    set varccommits($v,$na) [lrange $ac $i end]
+    lappend varcstart($v) $p
+    foreach id $varccommits($v,$na) {
+	set varcid($v,$id) $na
+    }
+    lappend vdownptr($v) [lindex $vdownptr($v) $oa]
+    lappend vlastins($v) [lindex $vlastins($v) $oa]
+    lset vdownptr($v) $oa $na
+    lset vlastins($v) $oa 0
+    lappend vupptr($v) $oa
+    lappend vleftptr($v) 0
+    lappend vbackptr($v) 0
+    for {set b [lindex $vdownptr($v) $na]} {$b != 0} {set b [lindex $vleftptr($v) $b]} {
+	lset vupptr($v) $b $na
+    }
+}
+
+proc renumbervarc {a v} {
+    global parents children varctok varcstart varccommits
+    global vupptr vdownptr vleftptr vbackptr vlastins varcid vtokmod vdatemode
+
+    set t1 [clock clicks -milliseconds]
+    set todo {}
+    set isrelated($a) 1
+    set kidchanged($a) 1
+    set ntot 0
+    while {$a != 0} {
+	if {[info exists isrelated($a)]} {
+	    lappend todo $a
+	    set id [lindex $varccommits($v,$a) end]
+	    foreach p $parents($v,$id) {
+		if {[info exists varcid($v,$p)]} {
+		    set isrelated($varcid($v,$p)) 1
+		}
+	    }
+	}
+	incr ntot
+	set b [lindex $vdownptr($v) $a]
+	if {$b == 0} {
+	    while {$a != 0} {
+		set b [lindex $vleftptr($v) $a]
+		if {$b != 0} break
+		set a [lindex $vupptr($v) $a]
+	    }
+	}
+	set a $b
+    }
+    foreach a $todo {
+	if {![info exists kidchanged($a)]} continue
+	set id [lindex $varcstart($v) $a]
+	if {[llength $children($v,$id)] > 1} {
+	    set children($v,$id) [lsort -command [list vtokcmp $v] \
+				      $children($v,$id)]
+	}
+	set oldtok [lindex $varctok($v) $a]
+	if {!$vdatemode($v)} {
+	    set tok {}
+	} else {
+	    set tok $oldtok
+	}
+	set ka 0
+	set kid [last_real_child $v,$id]
+	if {$kid ne {}} {
+	    set k $varcid($v,$kid)
+	    if {[string compare [lindex $varctok($v) $k] $tok] > 0} {
+		set ki $kid
+		set ka $k
+		set tok [lindex $varctok($v) $k]
+	    }
+	}
+	if {$ka != 0} {
+	    set i [lsearch -exact $parents($v,$ki) $id]
+	    set j [expr {[llength $parents($v,$ki)] - 1 - $i}]
+	    append tok [strrep $j]
+	}
+	if {$tok eq $oldtok} {
+	    continue
+	}
+	set id [lindex $varccommits($v,$a) end]
+	foreach p $parents($v,$id) {
+	    if {[info exists varcid($v,$p)]} {
+		set kidchanged($varcid($v,$p)) 1
+	    } else {
+		set sortkids($p) 1
+	    }
+	}
+	lset varctok($v) $a $tok
+	set b [lindex $vupptr($v) $a]
+	if {$b != $ka} {
+	    if {[string compare [lindex $varctok($v) $ka] $vtokmod($v)] < 0} {
+		modify_arc $v $ka
+	    }
+	    if {[string compare [lindex $varctok($v) $b] $vtokmod($v)] < 0} {
+		modify_arc $v $b
+	    }
+	    set c [lindex $vbackptr($v) $a]
+	    set d [lindex $vleftptr($v) $a]
+	    if {$c == 0} {
+		lset vdownptr($v) $b $d
+	    } else {
+		lset vleftptr($v) $c $d
+	    }
+	    if {$d != 0} {
+		lset vbackptr($v) $d $c
+	    }
+	    if {[lindex $vlastins($v) $b] == $a} {
+		lset vlastins($v) $b $c
+	    }
+	    lset vupptr($v) $a $ka
+	    set c [lindex $vlastins($v) $ka]
+	    if {$c == 0 || \
+		    [string compare $tok [lindex $varctok($v) $c]] < 0} {
+		set c $ka
+		set b [lindex $vdownptr($v) $ka]
+	    } else {
+		set b [lindex $vleftptr($v) $c]
+	    }
+	    while {$b != 0 && \
+		      [string compare $tok [lindex $varctok($v) $b]] >= 0} {
+		set c $b
+		set b [lindex $vleftptr($v) $c]
+	    }
+	    if {$c == $ka} {
+ 		lset vdownptr($v) $ka $a
+		lset vbackptr($v) $a 0
+	    } else {
+		lset vleftptr($v) $c $a
+		lset vbackptr($v) $a $c
+	    }
+	    lset vleftptr($v) $a $b
+	    if {$b != 0} {
+		lset vbackptr($v) $b $a
+	    }
+	    lset vlastins($v) $ka $a
+	}
+    }
+    foreach id [array names sortkids] {
+	if {[llength $children($v,$id)] > 1} {
+	    set children($v,$id) [lsort -command [list vtokcmp $v] \
+				      $children($v,$id)]
+	}
+    }
+    set t2 [clock clicks -milliseconds]
+    #puts "renumbervarc did [llength $todo] of $ntot arcs in [expr {$t2-$t1}]ms"
+}
+
+# Fix up the graph after we have found out that in view $v,
+# $p (a commit that we have already seen) is actually the parent
+# of the last commit in arc $a.
+proc fix_reversal {p a v} {
+    global varcid varcstart varctok vupptr
+
+    set pa $varcid($v,$p)
+    if {$p ne [lindex $varcstart($v) $pa]} {
+	splitvarc $p $v
+	set pa $varcid($v,$p)
+    }
+    # seeds always need to be renumbered
+    if {[lindex $vupptr($v) $pa] == 0 ||
+	[string compare [lindex $varctok($v) $a] \
+	     [lindex $varctok($v) $pa]] > 0} {
+	renumbervarc $pa $v
+    }
+}
+
+proc insertrow {id p v} {
+    global cmitlisted children parents varcid varctok vtokmod
+    global varccommits ordertok commitidx numcommits curview
+    global targetid targetrow
+
+    readcommit $id
+    set vid $v,$id
+    set cmitlisted($vid) 1
+    set children($vid) {}
+    set parents($vid) [list $p]
+    set a [newvarc $v $id]
+    set varcid($vid) $a
+    if {[string compare [lindex $varctok($v) $a] $vtokmod($v)] < 0} {
+	modify_arc $v $a
+    }
+    lappend varccommits($v,$a) $id
+    set vp $v,$p
+    if {[llength [lappend children($vp) $id]] > 1} {
+	set children($vp) [lsort -command [list vtokcmp $v] $children($vp)]
+	catch {unset ordertok}
+    }
+    fix_reversal $p $a $v
+    incr commitidx($v)
+    if {$v == $curview} {
+	set numcommits $commitidx($v)
+	setcanvscroll
+	if {[info exists targetid]} {
+	    if {![comes_before $targetid $p]} {
+		incr targetrow
+	    }
+	}
+    }
+}
+
+proc insertfakerow {id p} {
+    global varcid varccommits parents children cmitlisted
+    global commitidx varctok vtokmod targetid targetrow curview numcommits
+
+    set v $curview
+    set a $varcid($v,$p)
+    set i [lsearch -exact $varccommits($v,$a) $p]
+    if {$i < 0} {
+	puts "oops: insertfakerow can't find [shortids $p] on arc $a"
+	return
+    }
+    set children($v,$id) {}
+    set parents($v,$id) [list $p]
+    set varcid($v,$id) $a
+    lappend children($v,$p) $id
+    set cmitlisted($v,$id) 1
+    set numcommits [incr commitidx($v)]
+    # note we deliberately don't update varcstart($v) even if $i == 0
+    set varccommits($v,$a) [linsert $varccommits($v,$a) $i $id]
+    modify_arc $v $a $i
+    if {[info exists targetid]} {
+	if {![comes_before $targetid $p]} {
+	    incr targetrow
+	}
+    }
+    setcanvscroll
+    drawvisible
+}
+
+proc removefakerow {id} {
+    global varcid varccommits parents children commitidx
+    global varctok vtokmod cmitlisted currentid selectedline
+    global targetid curview numcommits
+
+    set v $curview
+    if {[llength $parents($v,$id)] != 1} {
+	puts "oops: removefakerow [shortids $id] has [llength $parents($v,$id)] parents"
+	return
+    }
+    set p [lindex $parents($v,$id) 0]
+    set a $varcid($v,$id)
+    set i [lsearch -exact $varccommits($v,$a) $id]
+    if {$i < 0} {
+	puts "oops: removefakerow can't find [shortids $id] on arc $a"
+	return
+    }
+    unset varcid($v,$id)
+    set varccommits($v,$a) [lreplace $varccommits($v,$a) $i $i]
+    unset parents($v,$id)
+    unset children($v,$id)
+    unset cmitlisted($v,$id)
+    set numcommits [incr commitidx($v) -1]
+    set j [lsearch -exact $children($v,$p) $id]
+    if {$j >= 0} {
+	set children($v,$p) [lreplace $children($v,$p) $j $j]
+    }
+    modify_arc $v $a $i
+    if {[info exist currentid] && $id eq $currentid} {
+	unset currentid
+	unset selectedline
+    }
+    if {[info exists targetid] && $targetid eq $id} {
+	set targetid $p
+    }
+    setcanvscroll
+    drawvisible
+}
+
+proc first_real_child {vp} {
+    global children nullid nullid2
+
+    foreach id $children($vp) {
+	if {$id ne $nullid && $id ne $nullid2} {
+	    return $id
+	}
+    }
+    return {}
+}
+
+proc last_real_child {vp} {
+    global children nullid nullid2
+
+    set kids $children($vp)
+    for {set i [llength $kids]} {[incr i -1] >= 0} {} {
+	set id [lindex $kids $i]
+	if {$id ne $nullid && $id ne $nullid2} {
+	    return $id
+	}
+    }
+    return {}
+}
+
+proc vtokcmp {v a b} {
+    global varctok varcid
+
+    return [string compare [lindex $varctok($v) $varcid($v,$a)] \
+		[lindex $varctok($v) $varcid($v,$b)]]
+}
+
+# This assumes that if lim is not given, the caller has checked that
+# arc a's token is less than $vtokmod($v)
+proc modify_arc {v a {lim {}}} {
+    global varctok vtokmod varcmod varcrow vupptr curview vrowmod varccommits
+
+    if {$lim ne {}} {
+	set c [string compare [lindex $varctok($v) $a] $vtokmod($v)]
+	if {$c > 0} return
+	if {$c == 0} {
+	    set r [lindex $varcrow($v) $a]
+	    if {$r ne {} && $vrowmod($v) <= $r + $lim} return
+	}
+    }
+    set vtokmod($v) [lindex $varctok($v) $a]
+    set varcmod($v) $a
+    if {$v == $curview} {
+	while {$a != 0 && [lindex $varcrow($v) $a] eq {}} {
+	    set a [lindex $vupptr($v) $a]
+	    set lim {}
+	}
+	set r 0
+	if {$a != 0} {
+	    if {$lim eq {}} {
+		set lim [llength $varccommits($v,$a)]
+	    }
+	    set r [expr {[lindex $varcrow($v) $a] + $lim}]
+	}
+	set vrowmod($v) $r
+	undolayout $r
+    }
+}
+
+proc update_arcrows {v} {
+    global vtokmod varcmod vrowmod varcrow commitidx currentid selectedline
+    global varcid vrownum varcorder varcix varccommits
+    global vupptr vdownptr vleftptr varctok
+    global displayorder parentlist curview cached_commitrow
+
+    if {$vrowmod($v) == $commitidx($v)} return
+    if {$v == $curview} {
+	if {[llength $displayorder] > $vrowmod($v)} {
+	    set displayorder [lrange $displayorder 0 [expr {$vrowmod($v) - 1}]]
+	    set parentlist [lrange $parentlist 0 [expr {$vrowmod($v) - 1}]]
+	}
+	catch {unset cached_commitrow}
+    }
+    set narctot [expr {[llength $varctok($v)] - 1}]
+    set a $varcmod($v)
+    while {$a != 0 && [lindex $varcix($v) $a] eq {}} {
+	# go up the tree until we find something that has a row number,
+	# or we get to a seed
+	set a [lindex $vupptr($v) $a]
+    }
+    if {$a == 0} {
+	set a [lindex $vdownptr($v) 0]
+	if {$a == 0} return
+	set vrownum($v) {0}
+	set varcorder($v) [list $a]
+	lset varcix($v) $a 0
+	lset varcrow($v) $a 0
+	set arcn 0
+	set row 0
+    } else {
+	set arcn [lindex $varcix($v) $a]
+	if {[llength $vrownum($v)] > $arcn + 1} {
+	    set vrownum($v) [lrange $vrownum($v) 0 $arcn]
+	    set varcorder($v) [lrange $varcorder($v) 0 $arcn]
+	}
+	set row [lindex $varcrow($v) $a]
+    }
+    while {1} {
+	set p $a
+	incr row [llength $varccommits($v,$a)]
+	# go down if possible
+	set b [lindex $vdownptr($v) $a]
+	if {$b == 0} {
+	    # if not, go left, or go up until we can go left
+	    while {$a != 0} {
+		set b [lindex $vleftptr($v) $a]
+		if {$b != 0} break
+		set a [lindex $vupptr($v) $a]
+	    }
+	    if {$a == 0} break
+	}
+	set a $b
+	incr arcn
+	lappend vrownum($v) $row
+	lappend varcorder($v) $a
+	lset varcix($v) $a $arcn
+	lset varcrow($v) $a $row
+    }
+    set vtokmod($v) [lindex $varctok($v) $p]
+    set varcmod($v) $p
+    set vrowmod($v) $row
+    if {[info exists currentid]} {
+	set selectedline [rowofcommit $currentid]
+    }
+}
+
+# Test whether view $v contains commit $id
+proc commitinview {id v} {
+    global varcid
+
+    return [info exists varcid($v,$id)]
+}
+
+# Return the row number for commit $id in the current view
+proc rowofcommit {id} {
+    global varcid varccommits varcrow curview cached_commitrow
+    global varctok vtokmod
+
+    set v $curview
+    if {![info exists varcid($v,$id)]} {
+	puts "oops rowofcommit no arc for [shortids $id]"
+	return {}
+    }
+    set a $varcid($v,$id)
+    if {[string compare [lindex $varctok($v) $a] $vtokmod($v)] >= 0} {
+	update_arcrows $v
+    }
+    if {[info exists cached_commitrow($id)]} {
+	return $cached_commitrow($id)
+    }
+    set i [lsearch -exact $varccommits($v,$a) $id]
+    if {$i < 0} {
+	puts "oops didn't find commit [shortids $id] in arc $a"
+	return {}
+    }
+    incr i [lindex $varcrow($v) $a]
+    set cached_commitrow($id) $i
+    return $i
+}
+
+# Returns 1 if a is on an earlier row than b, otherwise 0
+proc comes_before {a b} {
+    global varcid varctok curview
+
+    set v $curview
+    if {$a eq $b || ![info exists varcid($v,$a)] || \
+	    ![info exists varcid($v,$b)]} {
+	return 0
+    }
+    if {$varcid($v,$a) != $varcid($v,$b)} {
+	return [expr {[string compare [lindex $varctok($v) $varcid($v,$a)] \
+			   [lindex $varctok($v) $varcid($v,$b)]] < 0}]
+    }
+    return [expr {[rowofcommit $a] < [rowofcommit $b]}]
+}
+
+proc bsearch {l elt} {
+    if {[llength $l] == 0 || $elt <= [lindex $l 0]} {
+	return 0
+    }
+    set lo 0
+    set hi [llength $l]
+    while {$hi - $lo > 1} {
+	set mid [expr {int(($lo + $hi) / 2)}]
+	set t [lindex $l $mid]
+	if {$elt < $t} {
+	    set hi $mid
+	} elseif {$elt > $t} {
+	    set lo $mid
+	} else {
+	    return $mid
+	}
+    }
+    return $lo
+}
+
+# Make sure rows $start..$end-1 are valid in displayorder and parentlist
+proc make_disporder {start end} {
+    global vrownum curview commitidx displayorder parentlist
+    global varccommits varcorder parents vrowmod varcrow
+    global d_valid_start d_valid_end
+
+    if {$end > $vrowmod($curview)} {
+	update_arcrows $curview
+    }
+    set ai [bsearch $vrownum($curview) $start]
+    set start [lindex $vrownum($curview) $ai]
+    set narc [llength $vrownum($curview)]
+    for {set r $start} {$ai < $narc && $r < $end} {incr ai} {
+	set a [lindex $varcorder($curview) $ai]
+	set l [llength $displayorder]
+	set al [llength $varccommits($curview,$a)]
+	if {$l < $r + $al} {
+	    if {$l < $r} {
+		set pad [ntimes [expr {$r - $l}] {}]
+		set displayorder [concat $displayorder $pad]
+		set parentlist [concat $parentlist $pad]
+	    } elseif {$l > $r} {
+		set displayorder [lrange $displayorder 0 [expr {$r - 1}]]
+		set parentlist [lrange $parentlist 0 [expr {$r - 1}]]
+	    }
+	    foreach id $varccommits($curview,$a) {
+		lappend displayorder $id
+		lappend parentlist $parents($curview,$id)
+	    }
+	} elseif {[lindex $displayorder [expr {$r + $al - 1}]] eq {}} {
+	    set i $r
+	    foreach id $varccommits($curview,$a) {
+		lset displayorder $i $id
+		lset parentlist $i $parents($curview,$id)
+		incr i
+	    }
+	}
+	incr r $al
+    }
+}
+
+proc commitonrow {row} {
+    global displayorder
+
+    set id [lindex $displayorder $row]
+    if {$id eq {}} {
+	make_disporder $row [expr {$row + 1}]
+	set id [lindex $displayorder $row]
+    }
+    return $id
+}
+
+proc closevarcs {v} {
+    global varctok varccommits varcid parents children
+    global cmitlisted commitidx commitinterest vtokmod
+
+    set missing_parents 0
+    set scripts {}
+    set narcs [llength $varctok($v)]
+    for {set a 1} {$a < $narcs} {incr a} {
+	set id [lindex $varccommits($v,$a) end]
+	foreach p $parents($v,$id) {
+	    if {[info exists varcid($v,$p)]} continue
+	    # add p as a new commit
+	    incr missing_parents
+	    set cmitlisted($v,$p) 0
+	    set parents($v,$p) {}
+	    if {[llength $children($v,$p)] == 1 &&
+		[llength $parents($v,$id)] == 1} {
+		set b $a
+	    } else {
+		set b [newvarc $v $p]
+	    }
+	    set varcid($v,$p) $b
+	    if {[string compare [lindex $varctok($v) $b] $vtokmod($v)] < 0} {
+		modify_arc $v $b
+	    }
+	    lappend varccommits($v,$b) $p
+	    incr commitidx($v)
+	    if {[info exists commitinterest($p)]} {
+		foreach script $commitinterest($p) {
+		    lappend scripts [string map [list "%I" $p] $script]
+		}
+		unset commitinterest($id)
+	    }
+	}
+    }
+    if {$missing_parents > 0} {
+	foreach s $scripts {
+	    eval $s
+	}
+    }
+}
+
+# Use $rwid as a substitute for $id, i.e. reparent $id's children to $rwid
+# Assumes we already have an arc for $rwid.
+proc rewrite_commit {v id rwid} {
+    global children parents varcid varctok vtokmod varccommits
+
+    foreach ch $children($v,$id) {
+	# make $rwid be $ch's parent in place of $id
+	set i [lsearch -exact $parents($v,$ch) $id]
+	if {$i < 0} {
+	    puts "oops rewrite_commit didn't find $id in parent list for $ch"
+	}
+	set parents($v,$ch) [lreplace $parents($v,$ch) $i $i $rwid]
+	# add $ch to $rwid's children and sort the list if necessary
+	if {[llength [lappend children($v,$rwid) $ch]] > 1} {
+	    set children($v,$rwid) [lsort -command [list vtokcmp $v] \
+					$children($v,$rwid)]
+	}
+	# fix the graph after joining $id to $rwid
+	set a $varcid($v,$ch)
+	fix_reversal $rwid $a $v
+	# parentlist is wrong for the last element of arc $a
+	# even if displayorder is right, hence the 3rd arg here
+	modify_arc $v $a [expr {[llength $varccommits($v,$a)] - 1}]
+    }
+}
+
+proc getcommitlines {fd inst view updating}  {
+    global cmitlisted commitinterest leftover
+    global commitidx commitdata vdatemode
+    global parents children curview hlview
+    global idpending ordertok
+    global varccommits varcid varctok vtokmod vfilelimit
 
     set stuff [read $fd 500000]
     # git log doesn't terminate the last commit with a null...
-    if {$stuff == {} && $leftover($view) ne {} && [eof $fd]} {
+    if {$stuff == {} && $leftover($inst) ne {} && [eof $fd]} {
 	set stuff "\0"
     }
     if {$stuff == {}} {
 	if {![eof $fd]} {
 	    return 1
 	}
-	# Check if we have seen any ids listed as parents that haven't
-	# appeared in the list
-	foreach vid [array names idpending "$view,*"] {
-	    # should only get here if git log is buggy
-	    set id [lindex [split $vid ","] 1]
-	    set commitrow($vid) $commitidx($view)
-	    incr commitidx($view)
-	    if {$view == $curview} {
-		lappend parentlist {}
-		lappend displayorder $id
-		lappend commitlisted 0
-	    } else {
-		lappend vparentlist($view) {}
-		lappend vdisporder($view) $id
-		lappend vcmitlisted($view) 0
-	    }
+	global commfd viewcomplete viewactive viewname
+	global viewinstances
+	unset commfd($inst)
+	set i [lsearch -exact $viewinstances($view) $inst]
+	if {$i >= 0} {
+	    set viewinstances($view) [lreplace $viewinstances($view) $i $i]
 	}
-	set viewcomplete($view) 1
-	global viewname progresscoords
-	unset commfd($view)
-	notbusy $view
-	set progresscoords {0 0}
-	adjustprogress
 	# set it blocking so we wait for the process to terminate
 	fconfigure $fd -blocking 1
 	if {[catch {close $fd} err]} {
@@ -213,10 +1288,10 @@ proc getcommitlines {fd view}  {
 	    }
 	    if {[string range $err 0 4] == "usage"} {
 		set err "Gitk: error reading commits$fv:\
-			bad arguments to git rev-list."
+			bad arguments to git log."
 		if {$viewname($view) eq "Command line"} {
 		    append err \
-			"  (Note: arguments to gitk are passed to git rev-list\
+			"  (Note: arguments to gitk are passed to git log\
 			 to allow selection of commits to be displayed.)"
 		}
 	    } else {
@@ -224,23 +1299,31 @@ proc getcommitlines {fd view}  {
 	    }
 	    error_popup $err
 	}
+	if {[incr viewactive($view) -1] <= 0} {
+	    set viewcomplete($view) 1
+	    # Check if we have seen any ids listed as parents that haven't
+	    # appeared in the list
+	    closevarcs $view
+	    notbusy $view
+	}
 	if {$view == $curview} {
-	    run chewcommits $view
+	    run chewcommits
 	}
 	return 0
     }
     set start 0
     set gotsome 0
+    set scripts {}
     while 1 {
 	set i [string first "\0" $stuff $start]
 	if {$i < 0} {
-	    append leftover($view) [string range $stuff $start end]
+	    append leftover($inst) [string range $stuff $start end]
 	    break
 	}
 	if {$start == 0} {
-	    set cmit $leftover($view)
+	    set cmit $leftover($inst)
 	    append cmit [string range $stuff 0 [expr {$i - 1}]]
-	    set leftover($view) {}
+	    set leftover($inst) {}
 	} else {
 	    set cmit [string range $stuff $start [expr {$i - 1}]]
 	}
@@ -276,121 +1359,128 @@ proc getcommitlines {fd view}  {
 	    exit 1
 	}
 	set id [lindex $ids 0]
-	if {![info exists ordertok($view,$id)]} {
-	    set otok "o[strrep $vnextroot($view)]"
-	    incr vnextroot($view)
-	    set ordertok($view,$id) $otok
-	} else {
-	    set otok $ordertok($view,$id)
-	    unset idpending($view,$id)
+	set vid $view,$id
+
+	if {!$listed && $updating && ![info exists varcid($vid)] &&
+	    $vfilelimit($view) ne {}} {
+	    # git log doesn't rewrite parents for unlisted commits
+	    # when doing path limiting, so work around that here
+	    # by working out the rewritten parent with git rev-list
+	    # and if we already know about it, using the rewritten
+	    # parent as a substitute parent for $id's children.
+	    if {![catch {
+		set rwid [exec git rev-list --first-parent --max-count=1 \
+			      $id -- $vfilelimit($view)]
+	    }]} {
+		if {$rwid ne {} && [info exists varcid($view,$rwid)]} {
+		    # use $rwid in place of $id
+		    rewrite_commit $view $id $rwid
+		    continue
+		}
+	    }
+	}
+
+	set a 0
+	if {[info exists varcid($vid)]} {
+	    if {$cmitlisted($vid) || !$listed} continue
+	    set a $varcid($vid)
 	}
 	if {$listed} {
 	    set olds [lrange $ids 1 end]
-	    if {[llength $olds] == 1} {
-		set p [lindex $olds 0]
-		lappend children($view,$p) $id
-		if {![info exists ordertok($view,$p)]} {
-		    set ordertok($view,$p) $ordertok($view,$id)
-		    set idpending($view,$p) 1
-		}
-	    } else {
-		set i 0
-		foreach p $olds {
-		    if {$i == 0 || [lsearch -exact $olds $p] >= $i} {
-			lappend children($view,$p) $id
-		    }
-		    if {![info exists ordertok($view,$p)]} {
-			set ordertok($view,$p) "$otok[strrep $i]]"
-			set idpending($view,$p) 1
-		    }
-		    incr i
-		}
-	    }
 	} else {
 	    set olds {}
 	}
-	if {![info exists children($view,$id)]} {
-	    set children($view,$id) {}
-	}
 	set commitdata($id) [string range $cmit [expr {$j + 1}] end]
-	set commitrow($view,$id) $commitidx($view)
-	incr commitidx($view)
-	if {$view == $curview} {
-	    lappend parentlist $olds
-	    lappend displayorder $id
-	    lappend commitlisted $listed
-	} else {
-	    lappend vparentlist($view) $olds
-	    lappend vdisporder($view) $id
-	    lappend vcmitlisted($view) $listed
+	set cmitlisted($vid) $listed
+	set parents($vid) $olds
+	if {![info exists children($vid)]} {
+	    set children($vid) {}
+	} elseif {$a == 0 && [llength $children($vid)] == 1} {
+	    set k [lindex $children($vid) 0]
+	    if {[llength $parents($view,$k)] == 1 &&
+		(!$vdatemode($view) ||
+		 $varcid($view,$k) == [llength $varctok($view)] - 1)} {
+		set a $varcid($view,$k)
+	    }
+	}
+	if {$a == 0} {
+	    # new arc
+	    set a [newvarc $view $id]
+	}
+	if {[string compare [lindex $varctok($view) $a] $vtokmod($view)] < 0} {
+	    modify_arc $view $a
+	}
+	if {![info exists varcid($vid)]} {
+	    set varcid($vid) $a
+	    lappend varccommits($view,$a) $id
+	    incr commitidx($view)
+	}
+
+	set i 0
+	foreach p $olds {
+	    if {$i == 0 || [lsearch -exact $olds $p] >= $i} {
+		set vp $view,$p
+		if {[llength [lappend children($vp) $id]] > 1 &&
+		    [vtokcmp $view [lindex $children($vp) end-1] $id] > 0} {
+		    set children($vp) [lsort -command [list vtokcmp $view] \
+					   $children($vp)]
+		    catch {unset ordertok}
+		}
+		if {[info exists varcid($view,$p)]} {
+		    fix_reversal $p $a $view
+		}
+	    }
+	    incr i
 	}
+
 	if {[info exists commitinterest($id)]} {
 	    foreach script $commitinterest($id) {
-		eval [string map [list "%I" $id] $script]
+		lappend scripts [string map [list "%I" $id] $script]
 	    }
 	    unset commitinterest($id)
 	}
 	set gotsome 1
     }
     if {$gotsome} {
-	run chewcommits $view
+	global numcommits hlview
+
 	if {$view == $curview} {
-	    # update progress bar
-	    global progressdirn progresscoords proglastnc
-	    set inc [expr {($commitidx($view) - $proglastnc) * 0.0002}]
-	    set proglastnc $commitidx($view)
-	    set l [lindex $progresscoords 0]
-	    set r [lindex $progresscoords 1]
-	    if {$progressdirn} {
-		set r [expr {$r + $inc}]
-		if {$r >= 1.0} {
-		    set r 1.0
-		    set progressdirn 0
-		}
-		if {$r > 0.2} {
-		    set l [expr {$r - 0.2}]
-		}
-	    } else {
-		set l [expr {$l - $inc}]
-		if {$l <= 0.0} {
-		    set l 0.0
-		    set progressdirn 1
-		}
-		set r [expr {$l + 0.2}]
-	    }
-	    set progresscoords [list $l $r]
-	    adjustprogress
+	    set numcommits $commitidx($view)
+	    run chewcommits
+	}
+	if {[info exists hlview] && $view == $hlview} {
+	    # we never actually get here...
+	    run vhighlightmore
+	}
+	foreach s $scripts {
+	    eval $s
 	}
     }
     return 2
 }
 
-proc chewcommits {view} {
+proc chewcommits {} {
     global curview hlview viewcomplete
-    global selectedline pending_select
-
-    if {$view == $curview} {
-	layoutmore
-	if {$viewcomplete($view)} {
-	    global displayorder commitidx phase
-	    global numcommits startmsecs
-
-	    if {[info exists pending_select]} {
-		set row [first_real_row]
-		selectline $row 1
-	    }
-	    if {$commitidx($curview) > 0} {
-		#set ms [expr {[clock clicks -milliseconds] - $startmsecs}]
-		#puts "overall $ms ms for $numcommits commits"
-	    } else {
-		show_status [mc "No commits selected"]
-	    }
-	    notbusy layout
-	    set phase {}
+    global pending_select
+
+    layoutmore
+    if {$viewcomplete($curview)} {
+	global commitidx varctok
+	global numcommits startmsecs
+	global mainheadid nullid
+
+	if {[info exists pending_select]} {
+	    set row [first_real_row]
+	    selectline $row 1
+	}
+	if {$commitidx($curview) > 0} {
+	    #set ms [expr {[clock clicks -milliseconds] - $startmsecs}]
+	    #puts "overall $ms ms for $numcommits commits"
+	    #puts "[llength $varctok($view)] arcs, $commitidx($view) commits"
+	} else {
+	    show_status [mc "No commits selected"]
 	}
-    }
-    if {[info exists hlview] && $view == $hlview} {
-	vhighlightmore
+	notbusy layout
     }
     return 0
 }
@@ -400,38 +1490,6 @@ proc readcommit {id} {
     parsecommit $id $contents 0
 }
 
-proc updatecommits {} {
-    global viewdata curview phase displayorder ordertok idpending
-    global children commitrow selectedline thickerline showneartags
-    global isworktree
-
-    set isworktree [expr {[exec git rev-parse --is-inside-work-tree] == "true"}]
-
-    if {$phase ne {}} {
-	stop_rev_list
-	set phase {}
-    }
-    set n $curview
-    foreach id $displayorder {
-	catch {unset children($n,$id)}
-	catch {unset commitrow($n,$id)}
-	catch {unset ordertok($n,$id)}
-    }
-    foreach vid [array names idpending "$n,*"] {
-	unset idpending($vid)
-    }
-    set curview -1
-    catch {unset selectedline}
-    catch {unset thickerline}
-    catch {unset viewdata($n)}
-    readrefs
-    changedrefs
-    if {$showneartags} {
-	getallcommits
-    }
-    showview $n
-}
-
 proc parsecommit {id contents listed} {
     global commitinfo cdate
 
@@ -472,7 +1530,7 @@ proc parsecommit {id contents listed} {
 	set headline [string trimright [string range $headline 0 $i]]
     }
     if {!$listed} {
-	# git rev-list indents the comment by 4 spaces;
+	# git log indents the comment by 4 spaces;
 	# if we got this via git cat-file, add the indentation
 	set newcomment {}
 	foreach line [split $comment "\n"] {
@@ -558,10 +1616,10 @@ proc readrefs {} {
 
 # skip over fake commits
 proc first_real_row {} {
-    global nullid nullid2 displayorder numcommits
+    global nullid nullid2 numcommits
 
     for {set row 0} {$row < $numcommits} {incr row} {
-	set id [lindex $displayorder $row]
+	set id [commitonrow $row]
 	if {$id ne $nullid && $id ne $nullid2} {
 	    break
 	}
@@ -641,7 +1699,7 @@ proc setoptions {} {
 }
 
 proc makewindow {} {
-    global canv canv2 canv3 linespc charspc ctext cflist
+    global canv canv2 canv3 linespc charspc ctext cflist cscroll
     global tabstop
     global findtype findtypemenu findloc findstring fstring geometry
     global entries sha1entry sha1string sha1but
@@ -654,13 +1712,14 @@ proc makewindow {} {
     global bgcolor fgcolor bglist fglist diffcolors selectbgcolor
     global headctxmenu progresscanv progressitem progresscoords statusw
     global fprogitem fprogcoord lastprogupdate progupdatepending
-    global rprogitem rprogcoord
+    global rprogitem rprogcoord rownumsel numcommits
     global have_tk85
 
     menu .bar
     .bar add cascade -label [mc "File"] -menu .bar.file
     menu .bar.file
     .bar.file add command -label [mc "Update"] -command updatecommits
+    .bar.file add command -label [mc "Reload"] -command reloadcommits
     .bar.file add command -label [mc "Reread references"] -command rereadrefs
     .bar.file add command -label [mc "List references"] -command showrefs
     .bar.file add command -label [mc "Quit"] -command doquit
@@ -769,6 +1828,18 @@ proc makewindow {} {
 	-state disabled -width 26
     pack .tf.bar.rightbut -side left -fill y
 
+    label .tf.bar.rowlabel -text [mc "Row"]
+    set rownumsel {}
+    label .tf.bar.rownum -width 7 -font textfont -textvariable rownumsel \
+	-relief sunken -anchor e
+    label .tf.bar.rowlabel2 -text "/"
+    label .tf.bar.numcommits -width 7 -font textfont -textvariable numcommits \
+	-relief sunken -anchor e
+    pack .tf.bar.rowlabel .tf.bar.rownum .tf.bar.rowlabel2 .tf.bar.numcommits \
+	-side left
+    global selectedline
+    trace add variable selectedline {write unset} selectedline_change
+
     # Status label and progress bar
     set statusw .tf.bar.status
     label $statusw -width 15 -relief sunken
@@ -1016,7 +2087,7 @@ proc makewindow {} {
     bindkey k "selnextline 1"
     bindkey j "goback"
     bindkey l "goforw"
-    bindkey b "$ctext yview scroll -1 pages"
+    bindkey b prevfile
     bindkey d "$ctext yview scroll 18 units"
     bindkey u "$ctext yview scroll -18 units"
     bindkey / {dofind 1 1}
@@ -1088,6 +2159,8 @@ proc makewindow {} {
 	-command {flist_hl 0}
     $flist_menu add command -label [mc "Highlight this only"] \
 	-command {flist_hl 1}
+    $flist_menu add command -label [mc "External diff"] \
+        -command {external_diff}
 }
 
 # Windows sends all mouse wheel events to the current focused window, not
@@ -1108,6 +2181,17 @@ proc windows_mousewheel_redirector {W X Y D} {
     }
 }
 
+# Update row number label when selectedline changes
+proc selectedline_change {n1 n2 op} {
+    global selectedline rownumsel
+
+    if {$op eq "unset"} {
+	set rownumsel {}
+    } else {
+	set rownumsel [expr {$selectedline + 1}]
+    }
+}
+
 # mouse-2 makes all windows scan vertically, but only the one
 # the cursor is in scans horizontally
 proc canvscan {op w x y} {
@@ -1123,7 +2207,7 @@ proc canvscan {op w x y} {
 
 proc scrollcanv {cscroll f0 f1} {
     $cscroll set $f0 $f1
-    drawfrac $f0 $f1
+    drawvisible
     flushhighlights
 }
 
@@ -1192,7 +2276,7 @@ proc savestuff {w} {
     global viewname viewfiles viewargs viewargscmd viewperm nextviewnum
     global cmitmode wrapcomment datetimeformat limitdiffs
     global colors bgcolor fgcolor diffcolors diffcontext selectbgcolor
-    global autoselect
+    global autoselect extdifftool
 
     if {$stuffsaved} return
     if {![winfo viewable .]} return
@@ -1218,6 +2302,7 @@ proc savestuff {w} {
 	puts $f [list set diffcolors $diffcolors]
 	puts $f [list set diffcontext $diffcontext]
 	puts $f [list set selectbgcolor $selectbgcolor]
+	puts $f [list set extdifftool $extdifftool]
 
 	puts $f "set geometry(main) [wm geometry .]"
 	puts $f "set geometry(topwidth) [winfo width .tf]"
@@ -1318,7 +2403,7 @@ proc about {} {
     message $w.m -text [mc "
 Gitk - a commit viewer for git
 
-Copyright © 2005-2006 Paul Mackerras
+Copyright © 2005-2008 Paul Mackerras
 
 Use and redistribute under the terms of the GNU General Public License"] \
 	    -justify center -aspect 400 -border 2 -bg white -relief groove
@@ -1675,7 +2760,7 @@ image create bitmap reficon-o -background black -foreground "#ddddff" \
     -data $rectdata -maskdata $rectmask
 
 proc init_flist {first} {
-    global cflist cflist_top selectedline difffilestart
+    global cflist cflist_top difffilestart
 
     $cflist conf -state normal
     $cflist delete 0.0 end
@@ -1768,6 +2853,12 @@ proc pop_flist_menu {w X Y x y} {
 	set e [lindex $treediffs($diffids) [expr {$l-2}]]
     }
     set flist_menu_file $e
+    set xdiffstate "normal"
+    if {$cmitmode eq "tree"} {
+	set xdiffstate "disabled"
+    }
+    # Disable "External diff" item in tree mode
+    $flist_menu entryconf 2 -state $xdiffstate
     tk_popup $flist_menu $X $Y
 }
 
@@ -1783,6 +2874,113 @@ proc flist_hl {only} {
     set gdttype [mc "touching paths:"]
 }
 
+proc save_file_from_commit {filename output what} {
+    global nullfile
+
+    if {[catch {exec git show $filename -- > $output} err]} {
+	if {[string match "fatal: bad revision *" $err]} {
+	    return $nullfile
+	}
+	error_popup "Error getting \"$filename\" from $what: $err"
+	return {}
+    }
+    return $output
+}
+
+proc external_diff_get_one_file {diffid filename diffdir} {
+    global nullid nullid2 nullfile
+    global gitdir
+
+    if {$diffid == $nullid} {
+        set difffile [file join [file dirname $gitdir] $filename]
+	if {[file exists $difffile]} {
+	    return $difffile
+	}
+	return $nullfile
+    }
+    if {$diffid == $nullid2} {
+        set difffile [file join $diffdir "\[index\] [file tail $filename]"]
+        return [save_file_from_commit :$filename $difffile index]
+    }
+    set difffile [file join $diffdir "\[$diffid\] [file tail $filename]"]
+    return [save_file_from_commit $diffid:$filename $difffile \
+	       "revision $diffid"]
+}
+
+proc external_diff {} {
+    global gitktmpdir nullid nullid2
+    global flist_menu_file
+    global diffids
+    global diffnum
+    global gitdir extdifftool
+
+    if {[llength $diffids] == 1} {
+        # no reference commit given
+        set diffidto [lindex $diffids 0]
+        if {$diffidto eq $nullid} {
+            # diffing working copy with index
+            set diffidfrom $nullid2
+        } elseif {$diffidto eq $nullid2} {
+            # diffing index with HEAD
+            set diffidfrom "HEAD"
+        } else {
+            # use first parent commit
+            global parentlist selectedline
+            set diffidfrom [lindex $parentlist $selectedline 0]
+        }
+    } else {
+        set diffidfrom [lindex $diffids 0]
+        set diffidto [lindex $diffids 1]
+    }
+
+    # make sure that several diffs wont collide
+    if {![info exists gitktmpdir]} {
+	set gitktmpdir [file join [file dirname $gitdir] \
+			    [format ".gitk-tmp.%s" [pid]]]
+	if {[catch {file mkdir $gitktmpdir} err]} {
+	    error_popup "Error creating temporary directory $gitktmpdir: $err"
+	    unset gitktmpdir
+	    return
+	}
+	set diffnum 0
+    }
+    incr diffnum
+    set diffdir [file join $gitktmpdir $diffnum]
+    if {[catch {file mkdir $diffdir} err]} {
+	error_popup "Error creating temporary directory $diffdir: $err"
+	return
+    }
+
+    # gather files to diff
+    set difffromfile [external_diff_get_one_file $diffidfrom $flist_menu_file $diffdir]
+    set difftofile [external_diff_get_one_file $diffidto $flist_menu_file $diffdir]
+
+    if {$difffromfile ne {} && $difftofile ne {}} {
+        set cmd [concat | [shellsplit $extdifftool] \
+		     [list $difffromfile $difftofile]]
+        if {[catch {set fl [open $cmd r]} err]} {
+            file delete -force $diffdir
+            error_popup [mc "$extdifftool: command failed: $err"]
+        } else {
+            fconfigure $fl -blocking 0
+            filerun $fl [list delete_at_eof $fl $diffdir]
+        }
+    }
+}
+
+# delete $dir when we see eof on $f (presumably because the child has exited)
+proc delete_at_eof {f dir} {
+    while {[gets $f line] >= 0} {}
+    if {[eof $f]} {
+	if {[catch {close $f} err]} {
+	    error_popup "External diff viewer failed: $err"
+	}
+	file delete -force $dir
+	return 0
+    }
+    return 1
+}
+
 # Functions for adding and removing shell-type quoting
 
 proc shellquote {str} {
@@ -1925,7 +3123,7 @@ proc vieweditor {top n title} {
 	-variable newviewperm($n)
     grid $top.perm - -pady 5 -sticky w
     message $top.al -aspect 1000 \
-	-text [mc "Commits to include (arguments to git rev-list):"]
+	-text [mc "Commits to include (arguments to git log):"]
     grid $top.al - -sticky w -pady 5
     entry $top.args -width 50 -textvariable newviewargs($n) \
 	-background $bgcolor
@@ -2028,7 +3226,7 @@ proc newviewok {top n} {
 	    set viewargs($n) $newargs
 	    set viewargscmd($n) $newviewargscmd($n)
 	    if {$curview == $n} {
-		run updatecommits
+		run reloadcommits
 	    }
 	}
     }
@@ -2036,7 +3234,7 @@ proc newviewok {top n} {
 }
 
 proc delview {} {
-    global curview viewdata viewperm hlview selectedhlview
+    global curview viewperm hlview selectedhlview
 
     if {$curview == 0} return
     if {[info exists hlview] && $hlview == $curview} {
@@ -2044,7 +3242,6 @@ proc delview {} {
 	unset hlview
     }
     allviewmenus $curview delete
-    set viewdata($curview) {}
     set viewperm($curview) 0
     showview 0
 }
@@ -2058,48 +3255,28 @@ proc addviewmenu {n} {
     #	-command [list addvhighlight $n] -variable selectedhlview
 }
 
-proc flatten {var} {
-    global $var
-
-    set ret {}
-    foreach i [array names $var] {
-	lappend ret $i [set $var\($i\)]
-    }
-    return $ret
-}
-
-proc unflatten {var l} {
-    global $var
-
-    catch {unset $var}
-    foreach {i v} $l {
-	set $var\($i\) $v
-    }
-}
-
 proc showview {n} {
-    global curview viewdata viewfiles
+    global curview cached_commitrow ordertok
     global displayorder parentlist rowidlist rowisopt rowfinal
-    global colormap rowtextx commitrow nextcolor canvxmax
-    global numcommits commitlisted
+    global colormap rowtextx nextcolor canvxmax
+    global numcommits viewcomplete
     global selectedline currentid canv canvy0
     global treediffs
-    global pending_select phase
+    global pending_select mainheadid
     global commitidx
-    global commfd
-    global selectedview selectfirst
-    global vparentlist vdisporder vcmitlisted
+    global selectedview
     global hlview selectedhlview commitinterest
 
     if {$n == $curview} return
     set selid {}
+    set ymax [lindex [$canv cget -scrollregion] 3]
+    set span [$canv yview]
+    set ytop [expr {[lindex $span 0] * $ymax}]
+    set ybot [expr {[lindex $span 1] * $ymax}]
+    set yscreen [expr {($ybot - $ytop) / 2}]
     if {[info exists selectedline]} {
 	set selid $currentid
 	set y [yc $selectedline]
-	set ymax [lindex [$canv cget -scrollregion] 3]
-	set span [$canv yview]
-	set ytop [expr {[lindex $span 0] * $ymax}]
-	set ybot [expr {[lindex $span 1] * $ymax}]
 	if {$ytop < $y && $y < $ybot} {
 	    set yscreen [expr {$y - $ytop}]
 	}
@@ -2109,17 +3286,6 @@ proc showview {n} {
     }
     unselectline
     normalline
-    if {$curview >= 0} {
-	set vparentlist($curview) $parentlist
-	set vdisporder($curview) $displayorder
-	set vcmitlisted($curview) $commitlisted
-	if {$phase ne {} ||
-	    ![info exists viewdata($curview)] ||
-	    [lindex $viewdata($curview) 0] ne {}} {
-	    set viewdata($curview) \
-		[list $phase $rowidlist $rowisopt $rowfinal]
-	}
-    }
     catch {unset treediffs}
     clear_display
     if {[info exists hlview] && $hlview == $n} {
@@ -2127,6 +3293,8 @@ proc showview {n} {
 	set selectedhlview [mc "None"]
     }
     catch {unset commitinterest}
+    catch {unset cached_commitrow}
+    catch {unset ordertok}
 
     set curview $n
     set selectedview $n
@@ -2134,7 +3302,7 @@ proc showview {n} {
     .bar.view entryconf [mc "Delete view"] -state [expr {$n == 0? "disabled": "normal"}]
 
     run refill_reflist
-    if {![info exists viewdata($n)]} {
+    if {![info exists viewcomplete($n)]} {
 	if {$selid ne {}} {
 	    set pending_select $selid
 	}
@@ -2142,14 +3310,11 @@ proc showview {n} {
 	return
     }
 
-    set v $viewdata($n)
-    set phase [lindex $v 0]
-    set displayorder $vdisporder($n)
-    set parentlist $vparentlist($n)
-    set commitlisted $vcmitlisted($n)
-    set rowidlist [lindex $v 1]
-    set rowisopt [lindex $v 2]
-    set rowfinal [lindex $v 3]
+    set displayorder {}
+    set parentlist {}
+    set rowidlist {}
+    set rowisopt {}
+    set rowfinal {}
     set numcommits $commitidx($n)
 
     catch {unset colormap}
@@ -2161,9 +3326,8 @@ proc showview {n} {
     setcanvscroll
     set yf 0
     set row {}
-    set selectfirst 0
-    if {[info exists yscreen] && [info exists commitrow($n,$selid)]} {
-	set row $commitrow($n,$selid)
+    if {$selid ne {} && [commitinview $selid $n]} {
+	set row [rowofcommit $selid]
 	# try to get the selected row in the same position on the screen
 	set ymax [lindex [$canv cget -scrollregion] 3]
 	set ytop [expr {[yc $row] - $yscreen}]
@@ -2176,21 +3340,24 @@ proc showview {n} {
     drawvisible
     if {$row ne {}} {
 	selectline $row 0
-    } elseif {$selid ne {}} {
-	set pending_select $selid
+    } elseif {$mainheadid ne {} && [commitinview $mainheadid $curview]} {
+	selectline [rowofcommit $mainheadid] 1
+    } elseif {!$viewcomplete($n)} {
+	if {$selid ne {}} {
+	    set pending_select $selid
+	} else {
+	    set pending_select $mainheadid
+	}
     } else {
 	set row [first_real_row]
 	if {$row < $numcommits} {
 	    selectline $row 0
-	} else {
-	    set selectfirst 1
 	}
     }
-    if {$phase ne {}} {
-	if {$phase eq "getcommits"} {
+    if {!$viewcomplete($n)} {
+	if {$numcommits == 0} {
 	    show_status [mc "Reading commits..."]
 	}
-	run chewcommits $n
     } elseif {$numcommits == 0} {
 	show_status [mc "No commits selected"]
     }
@@ -2198,20 +3365,20 @@ proc showview {n} {
 
 # Stuff relating to the highlighting facility
 
-proc ishighlighted {row} {
+proc ishighlighted {id} {
     global vhighlights fhighlights nhighlights rhighlights
 
-    if {[info exists nhighlights($row)] && $nhighlights($row) > 0} {
-	return $nhighlights($row)
+    if {[info exists nhighlights($id)] && $nhighlights($id) > 0} {
+	return $nhighlights($id)
     }
-    if {[info exists vhighlights($row)] && $vhighlights($row) > 0} {
-	return $vhighlights($row)
+    if {[info exists vhighlights($id)] && $vhighlights($id) > 0} {
+	return $vhighlights($id)
     }
-    if {[info exists fhighlights($row)] && $fhighlights($row) > 0} {
-	return $fhighlights($row)
+    if {[info exists fhighlights($id)] && $fhighlights($id) > 0} {
+	return $fhighlights($id)
     }
-    if {[info exists rhighlights($row)] && $rhighlights($row) > 0} {
-	return $rhighlights($row)
+    if {[info exists rhighlights($id)] && $rhighlights($id) > 0} {
+	return $rhighlights($id)
     }
     return 0
 }
@@ -2249,7 +3416,7 @@ proc unbolden {} {
 
     set stillbold {}
     foreach row $boldrows {
-	if {![ishighlighted $row]} {
+	if {![ishighlighted [commitonrow $row]]} {
 	    bolden $row mainfont
 	} else {
 	    lappend stillbold $row
@@ -2259,17 +3426,13 @@ proc unbolden {} {
 }
 
 proc addvhighlight {n} {
-    global hlview curview viewdata vhl_done vhighlights commitidx
+    global hlview viewcomplete curview vhl_done commitidx
 
     if {[info exists hlview]} {
 	delvhighlight
     }
     set hlview $n
-    if {$n != $curview && ![info exists viewdata($n)]} {
-	set viewdata($n) [list getcommits {{}} 0 0 0]
-	set vparentlist($n) {}
-	set vdisporder($n) {}
-	set vcmitlisted($n) {}
+    if {$n != $curview && ![info exists viewcomplete($n)]} {
 	start_rev_list $n
     }
     set vhl_done $commitidx($hlview)
@@ -2288,43 +3451,38 @@ proc delvhighlight {} {
 }
 
 proc vhighlightmore {} {
-    global hlview vhl_done commitidx vhighlights
-    global displayorder vdisporder curview
+    global hlview vhl_done commitidx vhighlights curview
 
     set max $commitidx($hlview)
-    if {$hlview == $curview} {
-	set disp $displayorder
-    } else {
-	set disp $vdisporder($hlview)
-    }
     set vr [visiblerows]
     set r0 [lindex $vr 0]
     set r1 [lindex $vr 1]
     for {set i $vhl_done} {$i < $max} {incr i} {
-	set id [lindex $disp $i]
-	if {[info exists commitrow($curview,$id)]} {
-	    set row $commitrow($curview,$id)
+	set id [commitonrow $i $hlview]
+	if {[commitinview $id $curview]} {
+	    set row [rowofcommit $id]
 	    if {$r0 <= $row && $row <= $r1} {
 		if {![highlighted $row]} {
 		    bolden $row mainfontbold
 		}
-		set vhighlights($row) 1
+		set vhighlights($id) 1
 	    }
 	}
     }
     set vhl_done $max
+    return 0
 }
 
 proc askvhighlight {row id} {
-    global hlview vhighlights commitrow iddrawn
+    global hlview vhighlights iddrawn
 
-    if {[info exists commitrow($hlview,$id)]} {
-	if {[info exists iddrawn($id)] && ![ishighlighted $row]} {
+    if {[commitinview $id $hlview]} {
+	if {[info exists iddrawn($id)] && ![ishighlighted $id]} {
 	    bolden $row mainfontbold
 	}
-	set vhighlights($row) 1
+	set vhighlights($id) 1
     } else {
-	set vhighlights($row) 0
+	set vhighlights($id) 0
     }
 }
 
@@ -2462,12 +3620,12 @@ proc askfilehighlight {row id} {
     global filehighlight fhighlights fhl_list
 
     lappend fhl_list $id
-    set fhighlights($row) -1
+    set fhighlights($id) -1
     puts $filehighlight $id
 }
 
 proc readfhighlight {} {
-    global filehighlight fhighlights commitrow curview iddrawn
+    global filehighlight fhighlights curview iddrawn
     global fhl_list find_dirn
 
     if {![info exists filehighlight]} {
@@ -2480,18 +3638,16 @@ proc readfhighlight {} {
 	if {$i < 0} continue
 	for {set j 0} {$j < $i} {incr j} {
 	    set id [lindex $fhl_list $j]
-	    if {[info exists commitrow($curview,$id)]} {
-		set fhighlights($commitrow($curview,$id)) 0
-	    }
+	    set fhighlights($id) 0
 	}
 	set fhl_list [lrange $fhl_list [expr {$i+1}] end]
 	if {$line eq {}} continue
-	if {![info exists commitrow($curview,$line)]} continue
-	set row $commitrow($curview,$line)
-	if {[info exists iddrawn($line)] && ![ishighlighted $row]} {
+	if {![commitinview $line $curview]} continue
+	set row [rowofcommit $line]
+	if {[info exists iddrawn($line)] && ![ishighlighted $line]} {
 	    bolden $row mainfontbold
 	}
-	set fhighlights($row) 1
+	set fhighlights($line) 1
     }
     if {[eof $filehighlight]} {
 	# strange...
@@ -2540,7 +3696,7 @@ proc askfindhighlight {row id} {
 	}
     }
     if {$isbold && [info exists iddrawn($id)]} {
-	if {![ishighlighted $row]} {
+	if {![ishighlighted $id]} {
 	    bolden $row mainfontbold
 	    if {$isbold > 1} {
 		bolden_name $row mainfontbold
@@ -2550,7 +3706,7 @@ proc askfindhighlight {row id} {
 	    markrowmatches $row $id
 	}
     }
-    set nhighlights($row) $isbold
+    set nhighlights($id) $isbold
 }
 
 proc markrowmatches {row id} {
@@ -2588,7 +3744,7 @@ proc vrel_change {name ix op} {
 # prepare for testing whether commits are descendents or ancestors of a
 proc rhighlight_sel {a} {
     global descendent desc_todo ancestor anc_todo
-    global highlight_related rhighlights
+    global highlight_related
 
     catch {unset descendent}
     set desc_todo [list $a]
@@ -2608,16 +3764,16 @@ proc rhighlight_none {} {
 }
 
 proc is_descendent {a} {
-    global curview children commitrow descendent desc_todo
+    global curview children descendent desc_todo
 
     set v $curview
-    set la $commitrow($v,$a)
+    set la [rowofcommit $a]
     set todo $desc_todo
     set leftover {}
     set done 0
     for {set i 0} {$i < [llength $todo]} {incr i} {
 	set do [lindex $todo $i]
-	if {$commitrow($v,$do) < $la} {
+	if {[rowofcommit $do] < $la} {
 	    lappend leftover $do
 	    continue
 	}
@@ -2640,20 +3796,20 @@ proc is_descendent {a} {
 }
 
 proc is_ancestor {a} {
-    global curview parentlist commitrow ancestor anc_todo
+    global curview parents ancestor anc_todo
 
     set v $curview
-    set la $commitrow($v,$a)
+    set la [rowofcommit $a]
     set todo $anc_todo
     set leftover {}
     set done 0
     for {set i 0} {$i < [llength $todo]} {incr i} {
 	set do [lindex $todo $i]
-	if {![info exists commitrow($v,$do)] || $commitrow($v,$do) > $la} {
+	if {![commitinview $do $v] || [rowofcommit $do] > $la} {
 	    lappend leftover $do
 	    continue
 	}
-	foreach np [lindex $parentlist $commitrow($v,$do)] {
+	foreach np $parents($v,$do) {
 	    if {![info exists ancestor($np)]} {
 		set ancestor($np) 1
 		lappend todo $np
@@ -2695,11 +3851,11 @@ proc askrelhighlight {row id} {
 	}
     }
     if {[info exists iddrawn($id)]} {
-	if {$isbold && ![ishighlighted $row]} {
+	if {$isbold && ![ishighlighted $id]} {
 	    bolden $row mainfontbold
 	}
     }
-    set rhighlights($row) $isbold
+    set rhighlights($id) $isbold
 }
 
 # Graph layout functions
@@ -2730,40 +3886,81 @@ proc ntimes {n o} {
     return $ret
 }
 
+proc ordertoken {id} {
+    global ordertok curview varcid varcstart varctok curview parents children
+    global nullid nullid2
+
+    if {[info exists ordertok($id)]} {
+	return $ordertok($id)
+    }
+    set origid $id
+    set todo {}
+    while {1} {
+	if {[info exists varcid($curview,$id)]} {
+	    set a $varcid($curview,$id)
+	    set p [lindex $varcstart($curview) $a]
+	} else {
+	    set p [lindex $children($curview,$id) 0]
+	}
+	if {[info exists ordertok($p)]} {
+	    set tok $ordertok($p)
+	    break
+	}
+	set id [first_real_child $curview,$p]
+	if {$id eq {}} {
+	    # it's a root
+	    set tok [lindex $varctok($curview) $varcid($curview,$p)]
+	    break
+	}
+	if {[llength $parents($curview,$id)] == 1} {
+	    lappend todo [list $p {}]
+	} else {
+	    set j [lsearch -exact $parents($curview,$id) $p]
+	    if {$j < 0} {
+		puts "oops didn't find [shortids $p] in parents of [shortids $id]"
+	    }
+	    lappend todo [list $p [strrep $j]]
+	}
+    }
+    for {set i [llength $todo]} {[incr i -1] >= 0} {} {
+	set p [lindex $todo $i 0]
+	append tok [lindex $todo $i 1]
+	set ordertok($p) $tok
+    }
+    set ordertok($origid) $tok
+    return $tok
+}
+
 # Work out where id should go in idlist so that order-token
 # values increase from left to right
 proc idcol {idlist id {i 0}} {
-    global ordertok curview
-
-    set t $ordertok($curview,$id)
-    if {$i >= [llength $idlist] ||
-	$t < $ordertok($curview,[lindex $idlist $i])} {
+    set t [ordertoken $id]
+    if {$i < 0} {
+	set i 0
+    }
+    if {$i >= [llength $idlist] || $t < [ordertoken [lindex $idlist $i]]} {
 	if {$i > [llength $idlist]} {
 	    set i [llength $idlist]
 	}
-	while {[incr i -1] >= 0 &&
-	       $t < $ordertok($curview,[lindex $idlist $i])} {}
+	while {[incr i -1] >= 0 && $t < [ordertoken [lindex $idlist $i]]} {}
 	incr i
     } else {
-	if {$t > $ordertok($curview,[lindex $idlist $i])} {
+	if {$t > [ordertoken [lindex $idlist $i]]} {
 	    while {[incr i] < [llength $idlist] &&
-		   $t >= $ordertok($curview,[lindex $idlist $i])} {}
+		   $t >= [ordertoken [lindex $idlist $i]]} {}
 	}
     }
     return $i
 }
 
 proc initlayout {} {
-    global rowidlist rowisopt rowfinal displayorder commitlisted
+    global rowidlist rowisopt rowfinal displayorder parentlist
     global numcommits canvxmax canv
     global nextcolor
-    global parentlist
     global colormap rowtextx
-    global selectfirst
 
     set numcommits 0
     set displayorder {}
-    set commitlisted {}
     set parentlist {}
     set nextcolor 0
     set rowidlist {}
@@ -2772,16 +3969,19 @@ proc initlayout {} {
     set canvxmax [$canv cget -width]
     catch {unset colormap}
     catch {unset rowtextx}
-    set selectfirst 1
+    setcanvscroll
 }
 
 proc setcanvscroll {} {
     global canv canv2 canv3 numcommits linespc canvxmax canvy0
+    global lastscrollset lastscrollrows
 
     set ymax [expr {$canvy0 + ($numcommits - 0.5) * $linespc + 2}]
     $canv conf -scrollregion [list 0 0 $canvxmax $ymax]
     $canv2 conf -scrollregion [list 0 0 0 $ymax]
     $canv3 conf -scrollregion [list 0 0 0 $ymax]
+    set lastscrollset [clock clicks -milliseconds]
+    set lastscrollrows $numcommits
 }
 
 proc visiblerows {} {
@@ -2804,102 +4004,57 @@ proc visiblerows {} {
 }
 
 proc layoutmore {} {
-    global commitidx viewcomplete numcommits
-    global uparrowlen downarrowlen mingaplen curview
+    global commitidx viewcomplete curview
+    global numcommits pending_select selectedline curview
+    global lastscrollset lastscrollrows commitinterest
 
-    set show $commitidx($curview)
-    if {$show > $numcommits || $viewcomplete($curview)} {
-	showstuff $show $viewcomplete($curview)
-    }
-}
-
-proc showstuff {canshow last} {
-    global numcommits commitrow pending_select selectedline curview
-    global mainheadid displayorder selectfirst
-    global lastscrollset commitinterest
-
-    if {$numcommits == 0} {
-	global phase
-	set phase "incrdraw"
-	allcanvs delete all
-    }
-    set r0 $numcommits
-    set prev $numcommits
-    set numcommits $canshow
-    set t [clock clicks -milliseconds]
-    if {$prev < 100 || $last || $t - $lastscrollset > 500} {
-	set lastscrollset $t
+    if {$lastscrollrows < 100 || $viewcomplete($curview) ||
+	[clock clicks -milliseconds] - $lastscrollset > 500} {
 	setcanvscroll
     }
-    set rows [visiblerows]
-    set r1 [lindex $rows 1]
-    if {$r1 >= $canshow} {
-	set r1 [expr {$canshow - 1}]
-    }
-    if {$r0 <= $r1} {
-	drawcommits $r0 $r1
-    }
     if {[info exists pending_select] &&
-	[info exists commitrow($curview,$pending_select)] &&
-	$commitrow($curview,$pending_select) < $numcommits} {
-	selectline $commitrow($curview,$pending_select) 1
-    }
-    if {$selectfirst} {
-	if {[info exists selectedline] || [info exists pending_select]} {
-	    set selectfirst 0
-	} else {
-	    set l [first_real_row]
-	    selectline $l 1
-	    set selectfirst 0
-	}
+	[commitinview $pending_select $curview]} {
+	selectline [rowofcommit $pending_select] 1
     }
+    drawvisible
 }
 
 proc doshowlocalchanges {} {
-    global curview mainheadid phase commitrow
+    global curview mainheadid
 
-    if {[info exists commitrow($curview,$mainheadid)] &&
-	($phase eq {} || $commitrow($curview,$mainheadid) < $numcommits - 1)} {
+    if {[commitinview $mainheadid $curview]} {
 	dodiffindex
-    } elseif {$phase ne {}} {
-	lappend commitinterest($mainheadid) {}
+    } else {
+	lappend commitinterest($mainheadid) {dodiffindex}
     }
 }
 
 proc dohidelocalchanges {} {
-    global localfrow localirow lserial
+    global nullid nullid2 lserial curview
 
-    if {$localfrow >= 0} {
-	removerow $localfrow
-	set localfrow -1
-	if {$localirow > 0} {
-	    incr localirow -1
-	}
+    if {[commitinview $nullid $curview]} {
+	removefakerow $nullid
     }
-    if {$localirow >= 0} {
-	removerow $localirow
-	set localirow -1
+    if {[commitinview $nullid2 $curview]} {
+	removefakerow $nullid2
     }
     incr lserial
 }
 
 # spawn off a process to do git diff-index --cached HEAD
 proc dodiffindex {} {
-    global localirow localfrow lserial showlocalchanges
+    global lserial showlocalchanges
     global isworktree
 
     if {!$showlocalchanges || !$isworktree} return
     incr lserial
-    set localfrow -1
-    set localirow -1
     set fd [open "|git diff-index --cached HEAD" r]
     fconfigure $fd -blocking 0
     filerun $fd [list readdiffindex $fd $lserial]
 }
 
 proc readdiffindex {fd serial} {
-    global localirow commitrow mainheadid nullid2 curview
-    global commitinfo commitdata lserial
+    global mainheadid nullid nullid2 curview commitinfo commitdata lserial
 
     set isdiff 1
     if {[gets $fd line] < 0} {
@@ -2911,26 +4066,32 @@ proc readdiffindex {fd serial} {
     # we only need to see one line and we don't really care what it says...
     close $fd
 
-    # now see if there are any local changes not checked in to the index
-    if {$serial == $lserial} {
-	set fd [open "|git diff-files" r]
-	fconfigure $fd -blocking 0
-	filerun $fd [list readdifffiles $fd $serial]
+    if {$serial != $lserial} {
+	return 0
     }
 
-    if {$isdiff && $serial == $lserial && $localirow == -1} {
+    # now see if there are any local changes not checked in to the index
+    set fd [open "|git diff-files" r]
+    fconfigure $fd -blocking 0
+    filerun $fd [list readdifffiles $fd $serial]
+
+    if {$isdiff && ![commitinview $nullid2 $curview]} {
 	# add the line for the changes in the index to the graph
-	set localirow $commitrow($curview,$mainheadid)
 	set hl [mc "Local changes checked in to index but not committed"]
 	set commitinfo($nullid2) [list  $hl {} {} {} {} "    $hl\n"]
 	set commitdata($nullid2) "\n    $hl\n"
-	insertrow $localirow $nullid2
+	if {[commitinview $nullid $curview]} {
+	    removefakerow $nullid
+	}
+	insertfakerow $nullid2 $mainheadid
+    } elseif {!$isdiff && [commitinview $nullid2 $curview]} {
+	removefakerow $nullid2
     }
     return 0
 }
 
 proc readdifffiles {fd serial} {
-    global localirow localfrow commitrow mainheadid nullid curview
+    global mainheadid nullid nullid2 curview
     global commitinfo commitdata lserial
 
     set isdiff 1
@@ -2943,50 +4104,55 @@ proc readdifffiles {fd serial} {
     # we only need to see one line and we don't really care what it says...
     close $fd
 
-    if {$isdiff && $serial == $lserial && $localfrow == -1} {
+    if {$serial != $lserial} {
+	return 0
+    }
+
+    if {$isdiff && ![commitinview $nullid $curview]} {
 	# add the line for the local diff to the graph
-	if {$localirow >= 0} {
-	    set localfrow $localirow
-	    incr localirow
-	} else {
-	    set localfrow $commitrow($curview,$mainheadid)
-	}
 	set hl [mc "Local uncommitted changes, not checked in to index"]
 	set commitinfo($nullid) [list  $hl {} {} {} {} "    $hl\n"]
 	set commitdata($nullid) "\n    $hl\n"
-	insertrow $localfrow $nullid
+	if {[commitinview $nullid2 $curview]} {
+	    set p $nullid2
+	} else {
+	    set p $mainheadid
+	}
+	insertfakerow $nullid $p
+    } elseif {!$isdiff && [commitinview $nullid $curview]} {
+	removefakerow $nullid
     }
     return 0
 }
 
 proc nextuse {id row} {
-    global commitrow curview children
+    global curview children
 
     if {[info exists children($curview,$id)]} {
 	foreach kid $children($curview,$id) {
-	    if {![info exists commitrow($curview,$kid)]} {
+	    if {![commitinview $kid $curview]} {
 		return -1
 	    }
-	    if {$commitrow($curview,$kid) > $row} {
-		return $commitrow($curview,$kid)
+	    if {[rowofcommit $kid] > $row} {
+		return [rowofcommit $kid]
 	    }
 	}
     }
-    if {[info exists commitrow($curview,$id)]} {
-	return $commitrow($curview,$id)
+    if {[commitinview $id $curview]} {
+	return [rowofcommit $id]
     }
     return -1
 }
 
 proc prevuse {id row} {
-    global commitrow curview children
+    global curview children
 
     set ret -1
     if {[info exists children($curview,$id)]} {
 	foreach kid $children($curview,$id) {
-	    if {![info exists commitrow($curview,$kid)]} break
-	    if {$commitrow($curview,$kid) < $row} {
-		set ret $commitrow($curview,$kid)
+	    if {![commitinview $kid $curview]} break
+	    if {[rowofcommit $kid] < $row} {
+		set ret [rowofcommit $kid]
 	    }
 	}
     }
@@ -2995,7 +4161,7 @@ proc prevuse {id row} {
 
 proc make_idlist {row} {
     global displayorder parentlist uparrowlen downarrowlen mingaplen
-    global commitidx curview ordertok children commitrow
+    global commitidx curview children
 
     set r [expr {$row - $mingaplen - $downarrowlen - 1}]
     if {$r < 0} {
@@ -3009,6 +4175,7 @@ proc make_idlist {row} {
     if {$rb > $commitidx($curview)} {
 	set rb $commitidx($curview)
     }
+    make_disporder $r [expr {$rb + 1}]
     set ids {}
     for {} {$r < $ra} {incr r} {
 	set nextid [lindex $displayorder [expr {$r + 1}]]
@@ -3017,7 +4184,7 @@ proc make_idlist {row} {
 	    set rn [nextuse $p $r]
 	    if {$rn >= $row &&
 		$rn <= $r + $downarrowlen + $mingaplen + $uparrowlen} {
-		lappend ids [list $ordertok($curview,$p) $p]
+		lappend ids [list [ordertoken $p] $p]
 	    }
 	}
     }
@@ -3027,25 +4194,25 @@ proc make_idlist {row} {
 	    if {$p eq $nextid} continue
 	    set rn [nextuse $p $r]
 	    if {$rn < 0 || $rn >= $row} {
-		lappend ids [list $ordertok($curview,$p) $p]
+		lappend ids [list [ordertoken $p] $p]
 	    }
 	}
     }
     set id [lindex $displayorder $row]
-    lappend ids [list $ordertok($curview,$id) $id]
+    lappend ids [list [ordertoken $id] $id]
     while {$r < $rb} {
 	foreach p [lindex $parentlist $r] {
 	    set firstkid [lindex $children($curview,$p) 0]
-	    if {$commitrow($curview,$firstkid) < $row} {
-		lappend ids [list $ordertok($curview,$p) $p]
+	    if {[rowofcommit $firstkid] < $row} {
+		lappend ids [list [ordertoken $p] $p]
 	    }
 	}
 	incr r
 	set id [lindex $displayorder $r]
 	if {$id ne {}} {
 	    set firstkid [lindex $children($curview,$id) 0]
-	    if {$firstkid ne {} && $commitrow($curview,$firstkid) < $row} {
-		lappend ids [list $ordertok($curview,$id) $id]
+	    if {$firstkid ne {} && [rowofcommit $firstkid] < $row} {
+		lappend ids [list [ordertoken $id] $id]
 	    }
 	}
     }
@@ -3091,8 +4258,9 @@ proc layoutrows {row endrow} {
     global rowidlist rowisopt rowfinal displayorder
     global uparrowlen downarrowlen maxwidth mingaplen
     global children parentlist
-    global commitidx viewcomplete curview commitrow
+    global commitidx viewcomplete curview
 
+    make_disporder [expr {$row - 1}] [expr {$endrow + $uparrowlen}]
     set idlist {}
     if {$row > 0} {
 	set rm1 [expr {$row - 1}]
@@ -3148,7 +4316,7 @@ proc layoutrows {row endrow} {
 		foreach p [lindex $parentlist $r] {
 		    if {[lsearch -exact $idlist $p] >= 0} continue
 		    set fk [lindex $children($curview,$p) 0]
-		    if {$commitrow($curview,$fk) < $row} {
+		    if {[rowofcommit $fk] < $row} {
 			set x [idcol $idlist $p $x]
 			set idlist [linsert $idlist $x $p]
 		    }
@@ -3157,7 +4325,7 @@ proc layoutrows {row endrow} {
 		    set p [lindex $displayorder $r]
 		    if {[lsearch -exact $idlist $p] < 0} {
 			set fk [lindex $children($curview,$p) 0]
-			if {$fk ne {} && $commitrow($curview,$fk) < $row} {
+			if {$fk ne {} && [rowofcommit $fk] < $row} {
 			    set x [idcol $idlist $p $x]
 			    set idlist [linsert $idlist $x $p]
 			}
@@ -3372,7 +4540,7 @@ proc linewidth {id} {
 }
 
 proc rowranges {id} {
-    global commitrow curview children uparrowlen downarrowlen
+    global curview children uparrowlen downarrowlen
     global rowidlist
 
     set kids $children($curview,$id)
@@ -3382,13 +4550,13 @@ proc rowranges {id} {
     set ret {}
     lappend kids $id
     foreach child $kids {
-	if {![info exists commitrow($curview,$child)]} break
-	set row $commitrow($curview,$child)
+	if {![commitinview $child $curview]} break
+	set row [rowofcommit $child]
 	if {![info exists prev]} {
 	    lappend ret [expr {$row + 1}]
 	} else {
 	    if {$row <= $prevrow} {
-		puts "oops children out of order [shortids $id] $row < [shortids $prev] $prevrow"
+		puts "oops children of [shortids $id] out of order [shortids $child] $row <= [shortids $prev] $prevrow"
 	    }
 	    # see if the line extends the whole way from prevrow to row
 	    if {$row > $prevrow + $uparrowlen + $downarrowlen &&
@@ -3421,7 +4589,7 @@ proc rowranges {id} {
 	if {$child eq $id} {
 	    lappend ret $row
 	}
-	set prev $id
+	set prev $child
 	set prevrow $row
     }
     return $ret
@@ -3669,14 +4837,14 @@ proc drawlines {id} {
 }
 
 proc drawcmittext {id row col} {
-    global linespc canv canv2 canv3 canvy0 fgcolor curview
-    global commitlisted commitinfo rowidlist parentlist
+    global linespc canv canv2 canv3 fgcolor curview
+    global cmitlisted commitinfo rowidlist parentlist
     global rowtextx idpos idtags idheads idotherrefs
     global linehtag linentag linedtag selectedline
     global canvxmax boldrows boldnamerows fgcolor nullid nullid2
 
     # listed is 0 for boundary, 1 for normal, 2 for negative, 3 for left, 4 for right
-    set listed [lindex $commitlisted $row]
+    set listed $cmitlisted($curview,$id)
     if {$id eq $nullid} {
 	set ofill red
     } elseif {$id eq $nullid2} {
@@ -3732,7 +4900,7 @@ proc drawcmittext {id row col} {
     set date [formatdate $date]
     set font mainfont
     set nfont mainfont
-    set isbold [ishighlighted $row]
+    set isbold [ishighlighted $id]
     if {$isbold > 0} {
 	lappend boldrows $row
 	set font mainfontbold
@@ -3761,7 +4929,7 @@ proc drawcmittext {id row col} {
 proc drawcmitrow {row} {
     global displayorder rowidlist nrows_drawn
     global iddrawn markingmatches
-    global commitinfo parentlist numcommits
+    global commitinfo numcommits
     global filehighlight fhighlights findpattern nhighlights
     global hlview vhighlights
     global highlight_related rhighlights
@@ -3769,16 +4937,16 @@ proc drawcmitrow {row} {
     if {$row >= $numcommits} return
 
     set id [lindex $displayorder $row]
-    if {[info exists hlview] && ![info exists vhighlights($row)]} {
+    if {[info exists hlview] && ![info exists vhighlights($id)]} {
 	askvhighlight $row $id
     }
-    if {[info exists filehighlight] && ![info exists fhighlights($row)]} {
+    if {[info exists filehighlight] && ![info exists fhighlights($id)]} {
 	askfilehighlight $row $id
     }
-    if {$findpattern ne {} && ![info exists nhighlights($row)]} {
+    if {$findpattern ne {} && ![info exists nhighlights($id)]} {
 	askfindhighlight $row $id
     }
-    if {$highlight_related ne [mc "None"] && ![info exists rhighlights($row)]} {
+    if {$highlight_related ne [mc "None"] && ![info exists rhighlights($id)]} {
 	askrelhighlight $row $id
     }
     if {![info exists iddrawn($id)]} {
@@ -3881,23 +5049,79 @@ proc drawcommits {row {endrow {}}} {
     }
 }
 
-proc drawfrac {f0 f1} {
-    global canv linespc
+proc undolayout {row} {
+    global uparrowlen mingaplen downarrowlen
+    global rowidlist rowisopt rowfinal need_redisplay
+
+    set r [expr {$row - ($uparrowlen + $mingaplen + $downarrowlen)}]
+    if {$r < 0} {
+	set r 0
+    }
+    if {[llength $rowidlist] > $r} {
+	incr r -1
+	set rowidlist [lrange $rowidlist 0 $r]
+	set rowfinal [lrange $rowfinal 0 $r]
+	set rowisopt [lrange $rowisopt 0 $r]
+	set need_redisplay 1
+	run drawvisible
+    }
+}
 
+proc drawvisible {} {
+    global canv linespc curview vrowmod selectedline targetrow targetid
+    global need_redisplay cscroll numcommits
+
+    set fs [$canv yview]
     set ymax [lindex [$canv cget -scrollregion] 3]
-    if {$ymax eq {} || $ymax == 0} return
+    if {$ymax eq {} || $ymax == 0 || $numcommits == 0} return
+    set f0 [lindex $fs 0]
+    set f1 [lindex $fs 1]
     set y0 [expr {int($f0 * $ymax)}]
-    set row [expr {int(($y0 - 3) / $linespc) - 1}]
     set y1 [expr {int($f1 * $ymax)}]
+
+    if {[info exists targetid]} {
+	if {[commitinview $targetid $curview]} {
+	    set r [rowofcommit $targetid]
+	    if {$r != $targetrow} {
+		# Fix up the scrollregion and change the scrolling position
+		# now that our target row has moved.
+		set diff [expr {($r - $targetrow) * $linespc}]
+		set targetrow $r
+		setcanvscroll
+		set ymax [lindex [$canv cget -scrollregion] 3]
+		incr y0 $diff
+		incr y1 $diff
+		set f0 [expr {$y0 / $ymax}]
+		set f1 [expr {$y1 / $ymax}]
+		allcanvs yview moveto $f0
+		$cscroll set $f0 $f1
+		set need_redisplay 1
+	    }
+	} else {
+	    unset targetid
+	}
+    }
+
+    set row [expr {int(($y0 - 3) / $linespc) - 1}]
     set endrow [expr {int(($y1 - 3) / $linespc) + 1}]
+    if {$endrow >= $vrowmod($curview)} {
+	update_arcrows $curview
+    }
+    if {[info exists selectedline] &&
+	$row <= $selectedline && $selectedline <= $endrow} {
+	set targetrow $selectedline
+    } elseif {[info exists targetid]} {
+	set targetrow [expr {int(($row + $endrow) / 2)}]
+    }
+    if {[info exists targetrow]} {
+	if {$targetrow >= $numcommits} {
+	    set targetrow [expr {$numcommits - 1}]
+	}
+	set targetid [commitonrow $targetrow]
+    }
     drawcommits $row $endrow
 }
 
-proc drawvisible {} {
-    global canv
-    eval drawfrac [$canv yview]
-}
-
 proc clear_display {} {
     global iddrawn linesegs need_redisplay nrows_drawn
     global vhighlights fhighlights nhighlights rhighlights
@@ -3950,7 +5174,7 @@ proc findcrossings {id} {
 
 proc assigncolor {id} {
     global colormap colors nextcolor
-    global commitrow parentlist children children curview
+    global parents children children curview
 
     if {[info exists colormap($id)]} return
     set ncolors [llength $colors]
@@ -3962,7 +5186,7 @@ proc assigncolor {id} {
     if {[llength $kids] == 1} {
 	set child [lindex $kids 0]
 	if {[info exists colormap($child)]
-	    && [llength [lindex $parentlist $commitrow($curview,$child)]] == 1} {
+	    && [llength $parents($curview,$child)] == 1} {
 	    set colormap($id) $colormap($child)
 	    return
 	}
@@ -3990,7 +5214,7 @@ proc assigncolor {id} {
 		&& [lsearch -exact $badcolors $colormap($child)] < 0} {
 		lappend badcolors $colormap($child)
 	    }
-	    foreach p [lindex $parentlist $commitrow($curview,$child)] {
+	    foreach p $parents($curview,$child) {
 		if {[info exists colormap($p)]
 		    && [lsearch -exact $badcolors $colormap($p)] < 0} {
 		    lappend badcolors $colormap($p)
@@ -4023,7 +5247,7 @@ proc bindline {t id} {
 proc drawtags {id x xt y1} {
     global idtags idheads idotherrefs mainhead
     global linespc lthickness
-    global canv commitrow rowtextx curview fgcolor bgcolor
+    global canv rowtextx curview fgcolor bgcolor
 
     set marks {}
     set ntags 0
@@ -4073,7 +5297,7 @@ proc drawtags {id x xt y1} {
 		       $xr $yt $xr $yb $xl $yb $x [expr {$yb - $delta}] \
 		       -width 1 -outline black -fill yellow -tags tag.$id]
 	    $canv bind $t <1> [list showtag $tag 1]
-	    set rowtextx($commitrow($curview,$id)) [expr {$xr + $linespc}]
+	    set rowtextx([rowofcommit $id]) [expr {$xr + $linespc}]
 	} else {
 	    # draw a head or other ref
 	    if {[incr nheads -1] >= 0} {
@@ -4127,103 +5351,6 @@ proc show_status {msg} {
 	-tags text -fill $fgcolor
 }
 
-# Insert a new commit as the child of the commit on row $row.
-# The new commit will be displayed on row $row and the commits
-# on that row and below will move down one row.
-proc insertrow {row newcmit} {
-    global displayorder parentlist commitlisted children
-    global commitrow curview rowidlist rowisopt rowfinal numcommits
-    global numcommits
-    global selectedline commitidx ordertok
-
-    if {$row >= $numcommits} {
-	puts "oops, inserting new row $row but only have $numcommits rows"
-	return
-    }
-    set p [lindex $displayorder $row]
-    set displayorder [linsert $displayorder $row $newcmit]
-    set parentlist [linsert $parentlist $row $p]
-    set kids $children($curview,$p)
-    lappend kids $newcmit
-    set children($curview,$p) $kids
-    set children($curview,$newcmit) {}
-    set commitlisted [linsert $commitlisted $row 1]
-    set l [llength $displayorder]
-    for {set r $row} {$r < $l} {incr r} {
-	set id [lindex $displayorder $r]
-	set commitrow($curview,$id) $r
-    }
-    incr commitidx($curview)
-    set ordertok($curview,$newcmit) $ordertok($curview,$p)
-
-    if {$row < [llength $rowidlist]} {
-	set idlist [lindex $rowidlist $row]
-	if {$idlist ne {}} {
-	    if {[llength $kids] == 1} {
-		set col [lsearch -exact $idlist $p]
-		lset idlist $col $newcmit
-	    } else {
-		set col [llength $idlist]
-		lappend idlist $newcmit
-	    }
-	}
-	set rowidlist [linsert $rowidlist $row $idlist]
-	set rowisopt [linsert $rowisopt $row 0]
-	set rowfinal [linsert $rowfinal $row [lindex $rowfinal $row]]
-    }
-
-    incr numcommits
-
-    if {[info exists selectedline] && $selectedline >= $row} {
-	incr selectedline
-    }
-    redisplay
-}
-
-# Remove a commit that was inserted with insertrow on row $row.
-proc removerow {row} {
-    global displayorder parentlist commitlisted children
-    global commitrow curview rowidlist rowisopt rowfinal numcommits
-    global numcommits
-    global linesegends selectedline commitidx
-
-    if {$row >= $numcommits} {
-	puts "oops, removing row $row but only have $numcommits rows"
-	return
-    }
-    set rp1 [expr {$row + 1}]
-    set id [lindex $displayorder $row]
-    set p [lindex $parentlist $row]
-    set displayorder [lreplace $displayorder $row $row]
-    set parentlist [lreplace $parentlist $row $row]
-    set commitlisted [lreplace $commitlisted $row $row]
-    set kids $children($curview,$p)
-    set i [lsearch -exact $kids $id]
-    if {$i >= 0} {
-	set kids [lreplace $kids $i $i]
-	set children($curview,$p) $kids
-    }
-    set l [llength $displayorder]
-    for {set r $row} {$r < $l} {incr r} {
-	set id [lindex $displayorder $r]
-	set commitrow($curview,$id) $r
-    }
-    incr commitidx($curview) -1
-
-    if {$row < [llength $rowidlist]} {
-	set rowidlist [lreplace $rowidlist $row $row]
-	set rowisopt [lreplace $rowisopt $row $row]
-	set rowfinal [lreplace $rowfinal $row $row]
-    }
-
-    incr numcommits -1
-
-    if {[info exists selectedline] && $selectedline > $row} {
-	incr selectedline -1
-    }
-    redisplay
-}
-
 # Don't change the text pane cursor if it is currently the hand cursor,
 # showing that we are over a sha1 ID link.
 proc settextcursor {c} {
@@ -4326,9 +5453,9 @@ proc stopfinding {} {
 
 proc findmore {} {
     global commitdata commitinfo numcommits findpattern findloc
-    global findstartline findcurline displayorder
+    global findstartline findcurline findallowwrap
     global find_dirn gdttype fhighlights fprogcoord
-    global findallowwrap
+    global curview varcorder vrownum varccommits vrowmod
 
     if {![info exists find_dirn]} {
 	return 0
@@ -4364,14 +5491,31 @@ proc findmore {} {
 	set n 500
 	set moretodo 1
     }
+    if {$l + ($find_dirn > 0? $n: 1) > $vrowmod($curview)} {
+	update_arcrows $curview
+    }
     set found 0
     set domore 1
+    set ai [bsearch $vrownum($curview) $l]
+    set a [lindex $varcorder($curview) $ai]
+    set arow [lindex $vrownum($curview) $ai]
+    set ids [lindex $varccommits($curview,$a)]
+    set arowend [expr {$arow + [llength $ids]}]
     if {$gdttype eq [mc "containing:"]} {
 	for {} {$n > 0} {incr n -1; incr l $find_dirn} {
-	    set id [lindex $displayorder $l]
+	    if {$l < $arow || $l >= $arowend} {
+		incr ai $find_dirn
+		set a [lindex $varcorder($curview) $ai]
+		set arow [lindex $vrownum($curview) $ai]
+		set ids [lindex $varccommits($curview,$a)]
+		set arowend [expr {$arow + [llength $ids]}]
+	    }
+	    set id [lindex $ids [expr {$l - $arow}]]
 	    # shouldn't happen unless git log doesn't give all the commits...
-	    if {![info exists commitdata($id)]} continue
-	    if {![doesmatch $commitdata($id)]} continue
+	    if {![info exists commitdata($id)] ||
+		![doesmatch $commitdata($id)]} {
+		continue
+	    }
 	    if {![info exists commitinfo($id)]} {
 		getcommit $id
 	    }
@@ -4387,16 +5531,27 @@ proc findmore {} {
 	}
     } else {
 	for {} {$n > 0} {incr n -1; incr l $find_dirn} {
-	    set id [lindex $displayorder $l]
-	    if {![info exists fhighlights($l)]} {
+	    if {$l < $arow || $l >= $arowend} {
+		incr ai $find_dirn
+		set a [lindex $varcorder($curview) $ai]
+		set arow [lindex $vrownum($curview) $ai]
+		set ids [lindex $varccommits($curview,$a)]
+		set arowend [expr {$arow + [llength $ids]}]
+	    }
+	    set id [lindex $ids [expr {$l - $arow}]]
+	    if {![info exists fhighlights($id)]} {
+		# this sets fhighlights($id) to -1
 		askfilehighlight $l $id
+	    }
+	    if {$fhighlights($id) > 0} {
+		set found $domore
+		break
+	    }
+	    if {$fhighlights($id) < 0} {
 		if {$domore} {
 		    set domore 0
 		    set findcurline [expr {$l - $find_dirn}]
 		}
-	    } elseif {$fhighlights($l)} {
-		set found $domore
-		break
 	    }
 	}
     }
@@ -4490,7 +5645,9 @@ proc selcanvline {w x y} {
 	set l 0
     }
     if {$w eq $canv} {
-	if {![info exists rowtextx($l)] || $x < $rowtextx($l)} return
+	set xmax [lindex [$canv cget -scrollregion] 2]
+	set xleft [expr {[lindex [$canv xview] 0] * $xmax}]
+	if {![info exists rowtextx($l)] || $xleft + $x < $rowtextx($l)} return
     }
     unmarkmatches
     selectline $l 1
@@ -4511,7 +5668,7 @@ proc commit_descriptor {p} {
 # append some text to the ctext widget, and make any SHA1 ID
 # that we know about be a clickable link.
 proc appendwithlinks {text tags} {
-    global ctext commitrow linknum curview pendinglinks
+    global ctext linknum curview pendinglinks
 
     set start [$ctext index "end - 1c"]
     $ctext insert end $text $tags
@@ -4529,11 +5686,11 @@ proc appendwithlinks {text tags} {
 }
 
 proc setlink {id lk} {
-    global curview commitrow ctext pendinglinks commitinterest
+    global curview ctext pendinglinks commitinterest
 
-    if {[info exists commitrow($curview,$id)]} {
+    if {[commitinview $id $curview]} {
 	$ctext tag conf $lk -foreground blue -underline 1
-	$ctext tag bind $lk <1> [list selectline $commitrow($curview,$id) 1]
+	$ctext tag bind $lk <1> [list selectline [rowofcommit $id] 1]
 	$ctext tag bind $lk <Enter> {linkcursor %W 1}
 	$ctext tag bind $lk <Leave> {linkcursor %W -1}
     } else {
@@ -4584,7 +5741,7 @@ proc viewnextline {dir} {
 # add a list of tag or branch names at position pos
 # returns the number of names inserted
 proc appendrefs {pos ids var} {
-    global ctext commitrow linknum curview $var maxrefs
+    global ctext linknum curview $var maxrefs
 
     if {[catch {$ctext index $pos}]} {
 	return 0
@@ -4687,12 +5844,12 @@ proc make_secsel {l} {
 
 proc selectline {l isnew} {
     global canv ctext commitinfo selectedline
-    global displayorder
-    global canvy0 linespc parentlist children curview
+    global canvy0 linespc parents children curview
     global currentid sha1entry
     global commentend idtags linknum
     global mergemax numcommits pending_select
     global cmitmode showneartags allcommits
+    global targetrow targetid lastscrollrows
     global autoselect
 
     catch {unset pending_select}
@@ -4701,6 +5858,15 @@ proc selectline {l isnew} {
     unsel_reflist
     stopfinding
     if {$l < 0 || $l >= $numcommits} return
+    set id [commitonrow $l]
+    set targetid $id
+    set targetrow $l
+    set selectedline $l
+    set currentid $id
+    if {$lastscrollrows < $numcommits} {
+	setcanvscroll
+    }
+
     set y [expr {$canvy0 + $l * $linespc}]
     set ymax [lindex [$canv cget -scrollregion] 3]
     set ytop [expr {$y - $linespc - 1}]
@@ -4740,13 +5906,9 @@ proc selectline {l isnew} {
     make_secsel $l
 
     if {$isnew} {
-	addtohistory [list selectline $l 0]
+	addtohistory [list selbyid $id]
     }
 
-    set selectedline $l
-
-    set id [lindex $displayorder $l]
-    set currentid $id
     $sha1entry delete 0 end
     $sha1entry insert 0 $id
     if {$autoselect} {
@@ -4758,6 +5920,9 @@ proc selectline {l isnew} {
     $ctext conf -state normal
     clear_ctext
     set linknum 0
+    if {![info exists commitinfo($id)]} {
+	getcommit $id
+    }
     set info $commitinfo($id)
     set date [formatdate [lindex $info 2]]
     $ctext insert end "[mc "Author"]: [lindex $info 1]  $date\n"
@@ -4772,7 +5937,7 @@ proc selectline {l isnew} {
     }
 
     set headers {}
-    set olds [lindex $parentlist $l]
+    set olds $parents($curview,$id)
     if {[llength $olds] > 1} {
 	set np 0
 	foreach p $olds {
@@ -4830,7 +5995,7 @@ proc selectline {l isnew} {
     } elseif {[llength $olds] <= 1} {
 	startdiff $id
     } else {
-	mergediff $id $l
+	mergediff $id
     }
 }
 
@@ -4992,11 +6157,12 @@ proc gettreeline {gtf id} {
 	if {$diffids eq $nullid} {
 	    set fname $line
 	} else {
-	    if {$diffids ne $nullid2 && [lindex $line 1] ne "blob"} continue
 	    set i [string first "\t" $line]
 	    if {$i < 0} continue
-	    set sha1 [lindex $line 2]
 	    set fname [string range $line [expr {$i+1}] end]
+	    set line [string range $line 0 [expr {$i-1}]]
+	    if {$diffids ne $nullid2 && [lindex $line 1] ne "blob"} continue
+	    set sha1 [lindex $line 2]
 	    if {[string index $fname 0] eq "\""} {
 		set fname [lindex $fname 0]
 	    }
@@ -5075,19 +6241,19 @@ proc getblobline {bf id} {
     return [expr {$nl >= 1000? 2: 1}]
 }
 
-proc mergediff {id l} {
+proc mergediff {id} {
     global diffmergeid mdifffd
     global diffids
+    global parents
     global diffcontext
-    global parentlist
-    global limitdiffs viewfiles curview
+    global limitdiffs vfilelimit curview
 
     set diffmergeid $id
     set diffids $id
     # this doesn't seem to actually affect anything...
     set cmd [concat | git diff-tree --no-commit-id --cc -U$diffcontext $id]
-    if {$limitdiffs && $viewfiles($curview) ne {}} {
-	set cmd [concat $cmd -- $viewfiles($curview)]
+    if {$limitdiffs && $vfilelimit($curview) ne {}} {
+	set cmd [concat $cmd -- $vfilelimit($curview)]
     }
     if {[catch {set mdf [open $cmd r]} err]} {
 	error_popup "[mc "Error getting merge diffs:"] $err"
@@ -5095,7 +6261,7 @@ proc mergediff {id l} {
     }
     fconfigure $mdf -blocking 0
     set mdifffd($id) $mdf
-    set np [llength [lindex $parentlist $l]]
+    set np [llength $parents($curview,$id)]
     settabs $np
     filerun $mdf [list getmergediffline $mdf $id $np]
 }
@@ -5265,7 +6431,7 @@ proc gettreediffs {ids} {
 
 proc gettreediffline {gdtf ids} {
     global treediff treediffs treepending diffids diffmergeid
-    global cmitmode viewfiles curview limitdiffs
+    global cmitmode vfilelimit curview limitdiffs
 
     set nr 0
     while {[incr nr] <= 1000 && [gets $gdtf line] >= 0} {
@@ -5282,10 +6448,10 @@ proc gettreediffline {gdtf ids} {
 	return [expr {$nr >= 1000? 2: 1}]
     }
     close $gdtf
-    if {$limitdiffs && $viewfiles($curview) ne {}} {
+    if {$limitdiffs && $vfilelimit($curview) ne {}} {
 	set flist {}
 	foreach f $treediff {
-	    if {[path_filter $viewfiles($curview) $f]} {
+	    if {[path_filter $vfilelimit($curview) $f]} {
 		lappend flist $f
 	    }
 	}
@@ -5331,14 +6497,14 @@ proc getblobdiffs {ids} {
     global diffinhdr treediffs
     global diffcontext
     global ignorespace
-    global limitdiffs viewfiles curview
+    global limitdiffs vfilelimit curview
 
     set cmd [diffcmd $ids "-p -C --no-commit-id -U$diffcontext"]
     if {$ignorespace} {
 	append cmd " -w"
     }
-    if {$limitdiffs && $viewfiles($curview) ne {}} {
-	set cmd [concat $cmd -- $viewfiles($curview)]
+    if {$limitdiffs && $vfilelimit($curview) ne {}} {
+	set cmd [concat $cmd -- $vfilelimit($curview)]
     }
     if {[catch {set bdf [open $cmd r]} err]} {
 	puts "error getting diffs: $err"
@@ -5478,26 +6644,44 @@ proc changediffdisp {} {
     $ctext tag conf d1 -elide [lindex $diffelide 1]
 }
 
+proc highlightfile {loc cline} {
+    global ctext cflist cflist_top
+
+    $ctext yview $loc
+    $cflist tag remove highlight $cflist_top.0 "$cflist_top.0 lineend"
+    $cflist tag add highlight $cline.0 "$cline.0 lineend"
+    $cflist see $cline.0
+    set cflist_top $cline
+}
+
 proc prevfile {} {
-    global difffilestart ctext
-    set prev [lindex $difffilestart 0]
+    global difffilestart ctext cmitmode
+
+    if {$cmitmode eq "tree"} return
+    set prev 0.0
+    set prevline 1
     set here [$ctext index @0,0]
     foreach loc $difffilestart {
 	if {[$ctext compare $loc >= $here]} {
-	    $ctext yview $prev
+	    highlightfile $prev $prevline
 	    return
 	}
 	set prev $loc
+	incr prevline
     }
-    $ctext yview $prev
+    highlightfile $prev $prevline
 }
 
 proc nextfile {} {
-    global difffilestart ctext
+    global difffilestart ctext cmitmode
+
+    if {$cmitmode eq "tree"} return
     set here [$ctext index @0,0]
+    set line 1
     foreach loc $difffilestart {
+	incr line
 	if {[$ctext compare $loc > $here]} {
-	    $ctext yview $loc
+	    highlightfile $loc $line
 	    return
 	}
     }
@@ -5731,7 +6915,7 @@ proc fontname {f} {
 }
 
 proc incrfont {inc} {
-    global mainfont textfont ctext canv phase cflist showrefstop
+    global mainfont textfont ctext canv cflist showrefstop
     global stopped entries fontattr
 
     unmarkmatches
@@ -5782,8 +6966,7 @@ proc sha1change {n1 n2 op} {
 }
 
 proc gotocommit {} {
-    global sha1string currentid commitrow tagids headids
-    global displayorder numcommits curview
+    global sha1string tagids headids curview varcid
 
     if {$sha1string == {}
 	|| ([info exists currentid] && $sha1string == $currentid)} return
@@ -5794,23 +6977,18 @@ proc gotocommit {} {
     } else {
 	set id [string tolower $sha1string]
 	if {[regexp {^[0-9a-f]{4,39}$} $id]} {
-	    set matches {}
-	    foreach i $displayorder {
-		if {[string match $id* $i]} {
-		    lappend matches $i
-		}
-	    }
+	    set matches [array names varcid "$curview,$id*"]
 	    if {$matches ne {}} {
 		if {[llength $matches] > 1} {
 		    error_popup [mc "Short SHA1 id %s is ambiguous" $id]
 		    return
 		}
-		set id [lindex $matches 0]
+		set id [lindex [split [lindex $matches 0] ","] 1]
 	    }
 	}
     }
-    if {[info exists commitrow($curview,$id)]} {
-	selectline $commitrow($curview,$id) 1
+    if {[commitinview $id $curview]} {
+	selectline [rowofcommit $id] 1
 	return
     }
     if {[regexp {^[0-9a-fA-F]{4,}$} $sha1string]} {
@@ -5919,7 +7097,7 @@ proc arrowjump {id n y} {
 }
 
 proc lineclick {x y id isnew} {
-    global ctext commitinfo children canv thickerline curview commitrow
+    global ctext commitinfo children canv thickerline curview
 
     if {![info exists commitinfo($id)] && ![getcommit $id]} return
     unmarkmatches
@@ -5987,9 +7165,9 @@ proc normalline {} {
 }
 
 proc selbyid {id} {
-    global commitrow curview
-    if {[info exists commitrow($curview,$id)]} {
-	selectline $commitrow($curview,$id) 1
+    global curview
+    if {[commitinview $id $curview]} {
+	selectline [rowofcommit $id] 1
     }
 }
 
@@ -6002,20 +7180,24 @@ proc mstime {} {
 }
 
 proc rowmenu {x y id} {
-    global rowctxmenu commitrow selectedline rowmenuid curview
+    global rowctxmenu selectedline rowmenuid curview
     global nullid nullid2 fakerowmenu mainhead
 
     stopfinding
     set rowmenuid $id
     if {![info exists selectedline]
-	|| $commitrow($curview,$id) eq $selectedline} {
+	|| [rowofcommit $id] eq $selectedline} {
 	set state disabled
     } else {
 	set state normal
     }
     if {$id ne $nullid && $id ne $nullid2} {
 	set menu $rowctxmenu
-	$menu entryconfigure 7 -label [mc "Reset %s branch to here" $mainhead]
+	if {$mainhead ne {}} {
+	    $menu entryconfigure 7 -label [mc "Reset %s branch to here" $mainhead]
+	} else {
+	    $menu entryconfigure 7 -label [mc "Detached head: can't reset" $mainhead] -state disabled
+	}
     } else {
 	set menu $fakerowmenu
     }
@@ -6026,15 +7208,15 @@ proc rowmenu {x y id} {
 }
 
 proc diffvssel {dirn} {
-    global rowmenuid selectedline displayorder
+    global rowmenuid selectedline
 
     if {![info exists selectedline]} return
     if {$dirn} {
-	set oldid [lindex $displayorder $selectedline]
+	set oldid [commitonrow $selectedline]
 	set newid $rowmenuid
     } else {
 	set oldid $rowmenuid
-	set newid [lindex $displayorder $selectedline]
+	set newid [commitonrow $selectedline]
     }
     addtohistory [list doseldiff $oldid $newid]
     doseldiff $oldid $newid
@@ -6212,24 +7394,24 @@ proc domktag {} {
 }
 
 proc redrawtags {id} {
-    global canv linehtag commitrow idpos selectedline curview
+    global canv linehtag idpos currentid curview
     global canvxmax iddrawn
 
-    if {![info exists commitrow($curview,$id)]} return
+    if {![commitinview $id $curview]} return
     if {![info exists iddrawn($id)]} return
-    drawcommits $commitrow($curview,$id)
+    set row [rowofcommit $id]
     $canv delete tag.$id
     set xt [eval drawtags $id $idpos($id)]
-    $canv coords $linehtag($commitrow($curview,$id)) $xt [lindex $idpos($id) 2]
-    set text [$canv itemcget $linehtag($commitrow($curview,$id)) -text]
-    set xr [expr {$xt + [font measure mainfont $text]}]
+    $canv coords $linehtag($row) $xt [lindex $idpos($id) 2]
+    set text [$canv itemcget $linehtag($row) -text]
+    set font [$canv itemcget $linehtag($row) -font]
+    set xr [expr {$xt + [font measure $font $text]}]
     if {$xr > $canvxmax} {
 	set canvxmax $xr
 	setcanvscroll
     }
-    if {[info exists selectedline]
-	&& $selectedline == $commitrow($curview,$id)} {
-	selectline $selectedline 0
+    if {[info exists currentid] && $currentid == $id} {
+	make_secsel $row
     }
 }
 
@@ -6355,8 +7537,8 @@ proc mkbrgo {top} {
 }
 
 proc cherrypick {} {
-    global rowmenuid curview commitrow
-    global mainhead
+    global rowmenuid curview
+    global mainhead mainheadid
 
     set oldhead [exec git rev-parse HEAD]
     set dheads [descheads $rowmenuid]
@@ -6382,20 +7564,22 @@ proc cherrypick {} {
 	return
     }
     addnewchild $newhead $oldhead
-    if {[info exists commitrow($curview,$oldhead)]} {
-	insertrow $commitrow($curview,$oldhead) $newhead
+    if {[commitinview $oldhead $curview]} {
+	insertrow $newhead $oldhead $curview
 	if {$mainhead ne {}} {
 	    movehead $newhead $mainhead
 	    movedhead $newhead $mainhead
+	    set mainheadid $newhead
 	}
 	redrawtags $oldhead
 	redrawtags $newhead
+	selbyid $newhead
     }
     notbusy cherrypick
 }
 
 proc resethead {} {
-    global mainheadid mainhead rowmenuid confirm_ok resettype
+    global mainhead rowmenuid confirm_ok resettype
 
     set confirm_ok 0
     set w ".confirmreset"
@@ -6428,12 +7612,13 @@ proc resethead {} {
     tkwait window $w
     if {!$confirm_ok} return
     if {[catch {set fd [open \
-	    [list | sh -c "git reset --$resettype $rowmenuid 2>&1"] r]} err]} {
+	    [list | git reset --$resettype $rowmenuid 2>@1] r]} err]} {
 	error_popup $err
     } else {
 	dohidelocalchanges
 	filerun $fd [list readresetstat $fd]
 	nowbusy reset [mc "Resetting"]
+	selbyid $rowmenuid
     }
 }
 
@@ -6489,24 +7674,46 @@ proc cobranch {} {
     global showlocalchanges mainheadid
 
     # check the tree is clean first??
-    set oldmainhead $mainhead
     nowbusy checkout [mc "Checking out"]
     update
     dohidelocalchanges
     if {[catch {
-	exec git checkout -q $headmenuhead
+	set fd [open [list | git checkout $headmenuhead 2>@1] r]
     } err]} {
 	notbusy checkout
 	error_popup $err
+	if {$showlocalchanges} {
+	    dodiffindex
+	}
     } else {
-	notbusy checkout
-	set mainhead $headmenuhead
-	set mainheadid $headmenuid
-	if {[info exists headids($oldmainhead)]} {
-	    redrawtags $headids($oldmainhead)
+	filerun $fd [list readcheckoutstat $fd $headmenuhead $headmenuid]
+    }
+}
+
+proc readcheckoutstat {fd newhead newheadid} {
+    global mainhead mainheadid headids showlocalchanges progresscoords
+
+    if {[gets $fd line] >= 0} {
+	if {[regexp {([0-9]+)% \(([0-9]+)/([0-9]+)\)} $line match p m n]} {
+	    set progresscoords [list 0 [expr {1.0 * $m / $n}]]
+	    adjustprogress
 	}
-	redrawtags $headmenuid
+	return 1
+    }
+    set progresscoords {0 0}
+    adjustprogress
+    notbusy checkout
+    if {[catch {close $fd} err]} {
+	error_popup $err
     }
+    set oldmainhead $mainhead
+    set mainhead $newhead
+    set mainheadid $newheadid
+    if {[info exists headids($oldmainhead)]} {
+	redrawtags $headids($oldmainhead)
+    }
+    redrawtags $newheadid
+    selbyid $newheadid
     if {$showlocalchanges} {
 	dodiffindex
     }
@@ -6620,13 +7827,13 @@ proc reflistfilter_change {n1 n2 op} {
 
 proc refill_reflist {} {
     global reflist reflistfilter showrefstop headids tagids otherrefids
-    global commitrow curview commitinterest
+    global curview commitinterest
 
     if {![info exists showrefstop] || ![winfo exists $showrefstop]} return
     set refs {}
     foreach n [array names headids] {
 	if {[string match $reflistfilter $n]} {
-	    if {[info exists commitrow($curview,$headids($n))]} {
+	    if {[commitinview $headids($n) $curview]} {
 		lappend refs [list $n H]
 	    } else {
 		set commitinterest($headids($n)) {run refill_reflist}
@@ -6635,7 +7842,7 @@ proc refill_reflist {} {
     }
     foreach n [array names tagids] {
 	if {[string match $reflistfilter $n]} {
-	    if {[info exists commitrow($curview,$tagids($n))]} {
+	    if {[commitinview $tagids($n) $curview]} {
 		lappend refs [list $n T]
 	    } else {
 		set commitinterest($tagids($n)) {run refill_reflist}
@@ -6644,7 +7851,7 @@ proc refill_reflist {} {
     }
     foreach n [array names otherrefids] {
 	if {[string match $reflistfilter $n]} {
-	    if {[info exists commitrow($curview,$otherrefids($n))]} {
+	    if {[commitinview $otherrefids($n) $curview]} {
 		lappend refs [list $n o]
 	    } else {
 		set commitinterest($otherrefids($n)) {run refill_reflist}
@@ -7788,7 +8995,7 @@ proc changedrefs {} {
 }
 
 proc rereadrefs {} {
-    global idtags idheads idotherrefs mainhead
+    global idtags idheads idotherrefs mainheadid
 
     set refids [concat [array names idtags] \
 		    [array names idheads] [array names idotherrefs]]
@@ -7797,7 +9004,7 @@ proc rereadrefs {} {
 	    set ref($id) [listrefs $id]
 	}
     }
-    set oldmainhead $mainhead
+    set oldmainhead $mainheadid
     readrefs
     changedrefs
     set refids [lsort -unique [concat $refids [array names idtags] \
@@ -7805,8 +9012,8 @@ proc rereadrefs {} {
     foreach id $refids {
 	set v [listrefs $id]
 	if {![info exists ref($id)] || $ref($id) != $v ||
-	    ($id eq $oldmainhead && $id ne $mainhead) ||
-	    ($id eq $mainhead && $id ne $oldmainhead)} {
+	    ($id eq $oldmainhead && $id ne $mainheadid) ||
+	    ($id eq $mainheadid && $id ne $oldmainhead)} {
 	    redrawtags $id
 	}
     }
@@ -7858,9 +9065,15 @@ proc showtag {tag isnew} {
 
 proc doquit {} {
     global stopped
+    global gitktmpdir
+
     set stopped 100
     savestuff .
     destroy .
+
+    if {[info exists gitktmpdir]} {
+	catch {file delete -force $gitktmpdir}
+    }
 }
 
 proc mkfontdisp {font top which} {
@@ -7989,7 +9202,7 @@ proc doprefs {} {
     global maxwidth maxgraphpct
     global oldprefs prefstop showneartags showlocalchanges
     global bgcolor fgcolor ctext diffcolors selectbgcolor
-    global tabstop limitdiffs autoselect
+    global tabstop limitdiffs autoselect extdifftool
 
     set top .gitkprefs
     set prefstop $top
@@ -8041,6 +9254,15 @@ proc doprefs {} {
     pack $top.ldiff.b $top.ldiff.l -side left
     grid x $top.ldiff -sticky w
 
+    entry $top.extdifft -textvariable extdifftool
+    frame $top.extdifff
+    label $top.extdifff.l -text [mc "External diff tool" ] -font optionfont \
+	-padx 10
+    button $top.extdifff.b -text [mc "Choose..."] -font optionfont \
+	-command choose_extdiff
+    pack $top.extdifff.l $top.extdifff.b -side left
+    grid x $top.extdifff $top.extdifft -sticky w
+
     label $top.cdisp -text [mc "Colors: press to choose"]
     grid $top.cdisp - -sticky w -pady 10
     label $top.bg -padx 40 -relief sunk -background $bgcolor
@@ -8088,6 +9310,15 @@ proc doprefs {} {
     bind $top <Visibility> "focus $top.buts.ok"
 }
 
+proc choose_extdiff {} {
+    global extdifftool
+
+    set prog [tk_getOpenFile -title "External diff tool" -multiple false]
+    if {$prog ne {}} {
+	set extdifftool $prog
+    }
+}
+
 proc choosecolor {v vi w x cmd} {
     global $v
 
@@ -8479,7 +9710,6 @@ if {[catch {package require Tk 8.4} err]} {
 }
 
 # defaults...
-set datemode 0
 set wrcomcmd "git diff-tree --stdin -p --pretty"
 
 set gitencoding {}
@@ -8516,6 +9746,8 @@ set limitdiffs 1
 set datetimeformat "%Y-%m-%d %H:%M:%S"
 set autoselect 1
 
+set extdifftool "meld"
+
 set colors {green red blue magenta darkgrey brown orange}
 set bgcolor white
 set fgcolor black
@@ -8570,7 +9802,6 @@ if {![file isdirectory $gitdir]} {
     exit 1
 }
 
-set mergeonly 0
 set revtreeargs {}
 set cmdline_files {}
 set i 0
@@ -8578,11 +9809,6 @@ set revtreeargscmd {}
 foreach arg $argv {
     switch -glob -- $arg {
 	"" { }
-	"-d" { set datemode 1 }
-	"--merge" {
-	    set mergeonly 1
-	    lappend revtreeargs $arg
-	}
 	"--" {
 	    set cmdline_files [lrange $argv [expr {$i + 1}] end]
 	    break
@@ -8598,7 +9824,7 @@ foreach arg $argv {
 }
 
 if {$i >= [llength $argv] && $revtreeargs ne {}} {
-    # no -- on command line, but some arguments (other than -d)
+    # no -- on command line, but some arguments (other than --argscmd)
     if {[catch {
 	set f [eval exec git rev-parse --no-revs --no-flags $revtreeargs]
 	set cmdline_files [split $f "\n"]
@@ -8626,42 +9852,9 @@ if {$i >= [llength $argv] && $revtreeargs ne {}} {
     }
 }
 
-if {$mergeonly} {
-    # find the list of unmerged files
-    set mlist {}
-    set nr_unmerged 0
-    if {[catch {
-	set fd [open "| git ls-files -u" r]
-    } err]} {
-	show_error {} . "[mc "Couldn't get list of unmerged files:"] $err"
-	exit 1
-    }
-    while {[gets $fd line] >= 0} {
-	set i [string first "\t" $line]
-	if {$i < 0} continue
-	set fname [string range $line [expr {$i+1}] end]
-	if {[lsearch -exact $mlist $fname] >= 0} continue
-	incr nr_unmerged
-	if {$cmdline_files eq {} || [path_filter $cmdline_files $fname]} {
-	    lappend mlist $fname
-	}
-    }
-    catch {close $fd}
-    if {$mlist eq {}} {
-	if {$nr_unmerged == 0} {
-	    show_error {} . [mc "No files selected: --merge specified but\
-			     no files are unmerged."]
-	} else {
-	    show_error {} . [mc "No files selected: --merge specified but\
-			     no unmerged files are within file limit."]
-	}
-	exit 1
-    }
-    set cmdline_files $mlist
-}
-
 set nullid "0000000000000000000000000000000000000000"
 set nullid2 "0000000000000000000000000000000000000001"
+set nullfile "/dev/null"
 
 set have_tk85 [expr {[package vcompare $tk_version "8.5"] >= 0}]
 
@@ -8693,12 +9886,12 @@ set viewperm(0) 0
 set viewargs(0) {}
 set viewargscmd(0) {}
 
+set numcommits 0
+set loginstance 0
 set cmdlineok 0
 set stopped 0
 set stuffsaved 0
 set patchnum 0
-set localirow -1
-set localfrow -1
 set lserial 0
 set isworktree [expr {[exec git rev-parse --is-inside-work-tree] == "true"}]
 setcoords
@@ -8718,6 +9911,7 @@ if {$cmdline_files ne {} || $revtreeargs ne {} || $revtreeargscmd ne {}} {
     set viewargs(1) $revtreeargs
     set viewargscmd(1) $revtreeargscmd
     set viewperm(1) 0
+    set vdatemode(1) 0
     addviewmenu 1
     .bar.view entryconf [mc "Edit view..."] -state normal
     .bar.view entryconf [mc "Delete view"] -state normal
diff --git a/gitk-git/gitk-git/po/es.po b/gitk-git/gitk-git/po/es.po
new file mode 100644
index 0000000000..2cb1486247
--- /dev/null
+++ b/gitk-git/gitk-git/po/es.po
@@ -0,0 +1,890 @@
+# Translation of gitk
+# Copyright (C) 2005-2008 Santiago Gala
+# This file is distributed under the same license as the gitk package.
+# Santiago Gala <santiago.gala@gmail.com>, 2008.
+#
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: gitk\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2008-03-13 17:29+0100\n"
+"PO-Revision-Date: 2008-03-25 11:20+0100\n"
+"Last-Translator: Santiago Gala <santiago.gala@gmail.com>\n"
+"Language-Team: Spanish\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: gitk:111
+msgid "Error executing git rev-list:"
+msgstr "Error al ejecutar git rev-list:"
+
+#: gitk:124
+msgid "Reading"
+msgstr "Leyendo"
+
+#: gitk:151 gitk:2191
+msgid "Reading commits..."
+msgstr "Leyendo revisiones..."
+
+#: gitk:275
+msgid "Can't parse git log output:"
+msgstr "Error analizando la salida de git log:"
+
+#: gitk:386 gitk:2195
+msgid "No commits selected"
+msgstr "No se seleccionaron revisiones"
+
+#: gitk:500
+msgid "No commit information available"
+msgstr "Falta información sobre las revisiones"
+
+#: gitk:599 gitk:621 gitk:1955 gitk:6423 gitk:7923 gitk:8082
+msgid "OK"
+msgstr "Aceptar"
+
+#: gitk:623 gitk:1956 gitk:6107 gitk:6178 gitk:6275 gitk:6321 gitk:6425
+#: gitk:7924 gitk:8083
+msgid "Cancel"
+msgstr "Cancelar"
+
+#: gitk:661
+msgid "File"
+msgstr "Archivo"
+
+#: gitk:663
+msgid "Update"
+msgstr "Actualizar"
+
+#: gitk:664
+msgid "Reread references"
+msgstr "Releer referencias"
+
+#: gitk:665
+msgid "List references"
+msgstr "Lista de referencias"
+
+#: gitk:666
+msgid "Quit"
+msgstr "Salir"
+
+#: gitk:668
+msgid "Edit"
+msgstr "Editar"
+
+#: gitk:669
+msgid "Preferences"
+msgstr "Preferencias"
+
+#: gitk:672 gitk:1892
+msgid "View"
+msgstr "Vista"
+
+#: gitk:673
+msgid "New view..."
+msgstr "Nueva vista..."
+
+#: gitk:674 gitk:2133 gitk:8722
+msgid "Edit view..."
+msgstr "Modificar vista..."
+
+#: gitk:676 gitk:2134 gitk:8723
+msgid "Delete view"
+msgstr "Eliminar vista"
+
+#: gitk:678
+msgid "All files"
+msgstr "Todos los archivos"
+
+#: gitk:682
+msgid "Help"
+msgstr "Ayuda"
+
+#: gitk:683 gitk:1317
+msgid "About gitk"
+msgstr "Acerca de gitk"
+
+#: gitk:684
+msgid "Key bindings"
+msgstr "Combinaciones de teclas"
+
+#: gitk:741
+msgid "SHA1 ID: "
+msgstr "SHA1 ID: "
+
+#: gitk:791
+msgid "Find"
+msgstr "Buscar"
+
+#: gitk:792
+msgid "next"
+msgstr "<<"
+
+#: gitk:793
+msgid "prev"
+msgstr ">>"
+
+#: gitk:794
+msgid "commit"
+msgstr "revisión"
+
+#: gitk:797 gitk:799 gitk:2356 gitk:2379 gitk:2403 gitk:4306 gitk:4369
+msgid "containing:"
+msgstr "que contiene:"
+
+#: gitk:800 gitk:1778 gitk:1783 gitk:2431
+msgid "touching paths:"
+msgstr "que modifica la ruta:"
+
+#: gitk:801 gitk:2436
+msgid "adding/removing string:"
+msgstr "que añade/elimina cadena:"
+
+#: gitk:810 gitk:812
+msgid "Exact"
+msgstr "Exacto"
+
+#: gitk:812 gitk:2514 gitk:4274
+msgid "IgnCase"
+msgstr "NoMayús"
+
+#: gitk:812 gitk:2405 gitk:2512 gitk:4270
+msgid "Regexp"
+msgstr "Regex"
+
+#: gitk:814 gitk:815 gitk:2533 gitk:2563 gitk:2570 gitk:4380 gitk:4436
+msgid "All fields"
+msgstr "Todos los campos"
+
+#: gitk:815 gitk:2531 gitk:2563 gitk:4336
+msgid "Headline"
+msgstr "Título"
+
+#: gitk:816 gitk:2531 gitk:4336 gitk:4436 gitk:4827
+msgid "Comments"
+msgstr "Comentarios"
+
+#: gitk:816 gitk:2531 gitk:2535 gitk:2570 gitk:4336 gitk:4763 gitk:5956
+#: gitk:5971
+msgid "Author"
+msgstr "Autor"
+
+#: gitk:816 gitk:2531 gitk:4336 gitk:4765
+msgid "Committer"
+msgstr ""
+
+#: gitk:845
+msgid "Search"
+msgstr "Buscar"
+
+#: gitk:852
+msgid "Diff"
+msgstr "Diferencia"
+
+#: gitk:854
+msgid "Old version"
+msgstr "Versión antigua"
+
+#: gitk:856
+msgid "New version"
+msgstr "Versión nueva"
+
+#: gitk:858
+msgid "Lines of context"
+msgstr "Líneas de contexto"
+
+#: gitk:868
+msgid "Ignore space change"
+msgstr "Ignora cambios de espaciado"
+
+#: gitk:926
+msgid "Patch"
+msgstr "Parche"
+
+#: gitk:928
+msgid "Tree"
+msgstr "Árbol"
+
+#: gitk:1053 gitk:1068 gitk:6022
+msgid "Diff this -> selected"
+msgstr "Diferencia de esta -> seleccionada"
+
+#: gitk:1055 gitk:1070 gitk:6023
+msgid "Diff selected -> this"
+msgstr "Diferencia de seleccionada -> esta"
+
+#: gitk:1057 gitk:1072 gitk:6024
+msgid "Make patch"
+msgstr "Crear patch"
+
+#: gitk:1058 gitk:6162
+msgid "Create tag"
+msgstr "Crear etiqueta"
+
+#: gitk:1059 gitk:6255
+msgid "Write commit to file"
+msgstr "Escribir revisiones a archivo"
+
+#: gitk:1060 gitk:6309
+msgid "Create new branch"
+msgstr "Crear nueva rama"
+
+#: gitk:1061
+msgid "Cherry-pick this commit"
+msgstr "Añadir esta revisión a la rama actual (cherry-pick)"
+
+#: gitk:1063
+msgid "Reset HEAD branch to here"
+msgstr "Traer la rama HEAD aquí"
+
+#: gitk:1079
+msgid "Check out this branch"
+msgstr "Cambiar a esta rama"
+
+#: gitk:1081
+msgid "Remove this branch"
+msgstr "Eliminar esta rama"
+
+#: gitk:1087
+msgid "Highlight this too"
+msgstr "Seleccionar también"
+
+#: gitk:1089
+msgid "Highlight this only"
+msgstr "Seleccionar sólo"
+
+#: gitk:1318
+msgid ""
+"\n"
+"Gitk - a commit viewer for git\n"
+"\n"
+"Copyright © 2005-2006 Paul Mackerras\n"
+"\n"
+"Use and redistribute under the terms of the GNU General Public License"
+msgstr ""
+"\n"
+"Gitk - un visualizador de revisiones para git\n"
+"\n"
+"Copyright © 2005-2006 Paul Mackerras\n"
+"\n"
+"Uso y redistribución permitidos según los términos de la Licencia Pública General de "
+"GNU (GNU GPL)"
+
+#: gitk:1326 gitk:1387 gitk:6581
+msgid "Close"
+msgstr "Cerrar"
+
+#: gitk:1345
+msgid "Gitk key bindings"
+msgstr "Combinaciones de tecla de Gitk"
+
+#: gitk:1347
+msgid "Gitk key bindings:"
+msgstr "Combinaciones de tecla de Gitk:"
+
+#: gitk:1349
+#, tcl-format
+msgid "<%s-Q>\t\tQuit"
+msgstr "<%s-Q>\t\tSalir"
+
+#: gitk:1350
+msgid "<Home>\t\tMove to first commit"
+msgstr "<Home>\t\tIr a la primera revisión"
+
+#: gitk:1351
+msgid "<End>\t\tMove to last commit"
+msgstr "<End>\t\tIr a la última revisión"
+
+#: gitk:1352
+msgid "<Up>, p, i\tMove up one commit"
+msgstr "<Up>, p, i\tSubir una revisión"
+
+#: gitk:1353
+msgid "<Down>, n, k\tMove down one commit"
+msgstr "<Down>, n, k\tBajar una revisión"
+
+#: gitk:1354
+msgid "<Left>, z, j\tGo back in history list"
+msgstr "<Left>, z, j\tRetroceder en la historia"
+
+#: gitk:1355
+msgid "<Right>, x, l\tGo forward in history list"
+msgstr "<Right>, x, l\tAvanzar en la historia"
+
+#: gitk:1356
+msgid "<PageUp>\tMove up one page in commit list"
+msgstr "<PageUp>\tSubir una página en la lista de revisiones"
+
+#: gitk:1357
+msgid "<PageDown>\tMove down one page in commit list"
+msgstr "<PageDown>\tBajar una página en la lista de revisiones"
+
+#: gitk:1358
+#, tcl-format
+msgid "<%s-Home>\tScroll to top of commit list"
+msgstr "<%s-Home>\tDesplazarse al inicio de la lista de revisiones"
+
+#: gitk:1359
+#, tcl-format
+msgid "<%s-End>\tScroll to bottom of commit list"
+msgstr "<%s-End>\tDesplazarse al final de la lista de revisiones"
+
+#: gitk:1360
+#, tcl-format
+msgid "<%s-Up>\tScroll commit list up one line"
+msgstr "<%s-Up>\tDesplazar una línea hacia arriba la lista de revisiones"
+
+#: gitk:1361
+#, tcl-format
+msgid "<%s-Down>\tScroll commit list down one line"
+msgstr "<%s-Down>\tDesplazar una línea hacia abajo la lista de revisiones"
+
+#: gitk:1362
+#, tcl-format
+msgid "<%s-PageUp>\tScroll commit list up one page"
+msgstr "<%s-PageUp>\tDesplazar una página hacia arriba la lista de revisiones"
+
+#: gitk:1363
+#, tcl-format
+msgid "<%s-PageDown>\tScroll commit list down one page"
+msgstr "<%s-PageDown>\tDesplazar una página hacia abajo la lista de revisiones"
+
+#: gitk:1364
+msgid "<Shift-Up>\tFind backwards (upwards, later commits)"
+msgstr "<Shift-Up>\tBuscar hacia atrás (arriba, revisiones siguientes)"
+
+#: gitk:1365
+msgid "<Shift-Down>\tFind forwards (downwards, earlier commits)"
+msgstr "<Shift-Down>\tBuscar hacia adelante (abajo, revisiones anteriores)"
+
+#: gitk:1366
+msgid "<Delete>, b\tScroll diff view up one page"
+msgstr "<Delete>, b\tDesplaza hacia arriba una página la vista de diferencias"
+
+#: gitk:1367
+msgid "<Backspace>\tScroll diff view up one page"
+msgstr "<Backspace>\tDesplaza hacia arriba una página la vista de diferencias"
+
+#: gitk:1368
+msgid "<Space>\t\tScroll diff view down one page"
+msgstr "<Space>\t\tDesplaza hacia abajo una página la vista de diferencias"
+
+#: gitk:1369
+msgid "u\t\tScroll diff view up 18 lines"
+msgstr "u\t\tDesplaza hacia arriba 18 líneas la vista de diferencias"
+
+#: gitk:1370
+msgid "d\t\tScroll diff view down 18 lines"
+msgstr "d\t\tDesplaza hacia abajo 18 líneas la vista de diferencias"
+
+#: gitk:1371
+#, tcl-format
+msgid "<%s-F>\t\tFind"
+msgstr "<%s-F>\t\tBuscar"
+
+#: gitk:1372
+#, tcl-format
+msgid "<%s-G>\t\tMove to next find hit"
+msgstr "<%s-G>\t\tBuscar el siguiente"
+
+#: gitk:1373
+msgid "<Return>\tMove to next find hit"
+msgstr "<Return>\tBuscar el siguiente"
+
+#: gitk:1374
+msgid "/\t\tMove to next find hit, or redo find"
+msgstr "/\t\tBuscar el siguiente, o reiniciar la búsqueda"
+
+#: gitk:1375
+msgid "?\t\tMove to previous find hit"
+msgstr "?\t\tBuscar el anterior"
+
+#: gitk:1376
+msgid "f\t\tScroll diff view to next file"
+msgstr "f\t\tDesplazar la vista de diferencias al archivo siguiente"
+
+#: gitk:1377
+#, tcl-format
+msgid "<%s-S>\t\tSearch for next hit in diff view"
+msgstr "<%s-S>\t\tBuscar siguiente en la vista de diferencias"
+
+#: gitk:1378
+#, tcl-format
+msgid "<%s-R>\t\tSearch for previous hit in diff view"
+msgstr "<%s-R>\t\tBuscar anterior en la vista de diferencias"
+
+#: gitk:1379
+#, tcl-format
+msgid "<%s-KP+>\tIncrease font size"
+msgstr "<%s-KP+>\tAumentar tamaño del texto"
+
+#: gitk:1380
+#, tcl-format
+msgid "<%s-plus>\tIncrease font size"
+msgstr "<%s-plus>\tAumentar tamaño del texto"
+
+#: gitk:1381
+#, tcl-format
+msgid "<%s-KP->\tDecrease font size"
+msgstr "<%s-KP->\tDisminuir tamaño del texto"
+
+#: gitk:1382
+#, tcl-format
+msgid "<%s-minus>\tDecrease font size"
+msgstr "<%s-minus>\tDisminuir tamaño del texto"
+
+#: gitk:1383
+msgid "<F5>\t\tUpdate"
+msgstr "<F5>\t\tActualizar"
+
+#: gitk:1896
+msgid "Gitk view definition"
+msgstr "Definición de vistas de Gitk"
+
+#: gitk:1921
+msgid "Name"
+msgstr "Nombre"
+
+#: gitk:1924
+msgid "Remember this view"
+msgstr "Recordar esta vista"
+
+#: gitk:1928
+msgid "Commits to include (arguments to git rev-list):"
+msgstr "Revisiones a incluir (argumentos a git rev-list):"
+
+#: gitk:1935
+msgid "Command to generate more commits to include:"
+msgstr "Comando que genera más revisiones a incluir:"
+
+#: gitk:1942
+msgid "Enter files and directories to include, one per line:"
+msgstr "Introducir archivos y directorios a incluir, uno por línea:"
+
+#: gitk:1989
+msgid "Error in commit selection arguments:"
+msgstr "Error en los argumentos de selección de las revisiones:"
+
+#: gitk:2043 gitk:2127 gitk:2583 gitk:2597 gitk:3781 gitk:8688 gitk:8689
+msgid "None"
+msgstr "Ninguno"
+
+#: gitk:2531 gitk:4336 gitk:5958 gitk:5973
+msgid "Date"
+msgstr "Fecha"
+
+#: gitk:2531 gitk:4336
+msgid "CDate"
+msgstr "Fecha de creación"
+
+#: gitk:2680 gitk:2685
+msgid "Descendant"
+msgstr "Descendiente"
+
+#: gitk:2681
+msgid "Not descendant"
+msgstr "No descendiente"
+
+#: gitk:2688 gitk:2693
+msgid "Ancestor"
+msgstr "Antepasado"
+
+#: gitk:2689
+msgid "Not ancestor"
+msgstr "No antepasado"
+
+#: gitk:2924
+msgid "Local changes checked in to index but not committed"
+msgstr "Cambios locales añadidos al índice pero sin completar revisión"
+
+#: gitk:2954
+msgid "Local uncommitted changes, not checked in to index"
+msgstr "Cambios locales sin añadir al índice"
+
+#: gitk:4305
+msgid "Searching"
+msgstr "Buscando"
+
+#: gitk:4767
+msgid "Tags:"
+msgstr "Etiquetas:"
+
+#: gitk:4784 gitk:4790 gitk:5951
+msgid "Parent"
+msgstr "Padre"
+
+#: gitk:4795
+msgid "Child"
+msgstr "Hija"
+
+#: gitk:4804
+msgid "Branch"
+msgstr "Rama"
+
+#: gitk:4807
+msgid "Follows"
+msgstr "Sigue-a"
+
+#: gitk:4810
+msgid "Precedes"
+msgstr "Precede-a"
+
+#: gitk:5093
+msgid "Error getting merge diffs:"
+msgstr "Error al leer las diferencias de fusión:"
+
+#: gitk:5778
+msgid "Goto:"
+msgstr "Ir a:"
+
+#: gitk:5780
+msgid "SHA1 ID:"
+msgstr "SHA1 ID:"
+
+#: gitk:5805
+#, tcl-format
+msgid "Short SHA1 id %s is ambiguous"
+msgstr "La id SHA1 abreviada %s es ambigua"
+
+#: gitk:5817
+#, tcl-format
+msgid "SHA1 id %s is not known"
+msgstr "La id SHA1 %s es desconocida"
+
+#: gitk:5819
+#, tcl-format
+msgid "Tag/Head %s is not known"
+msgstr "La etiqueta/rama %s es deconocida"
+
+#: gitk:5961
+msgid "Children"
+msgstr "Hijas"
+
+#: gitk:6018
+#, tcl-format
+msgid "Reset %s branch to here"
+msgstr "Poner la rama %s en esta revisión"
+
+#: gitk:6049
+msgid "Top"
+msgstr "Origen"
+
+#: gitk:6050
+msgid "From"
+msgstr "De"
+
+#: gitk:6055
+msgid "To"
+msgstr "A"
+
+#: gitk:6078
+msgid "Generate patch"
+msgstr "Generar parche"
+
+#: gitk:6080
+msgid "From:"
+msgstr "De:"
+
+#: gitk:6089
+msgid "To:"
+msgstr "Para:"
+
+#: gitk:6098
+msgid "Reverse"
+msgstr "Invertir"
+
+#: gitk:6100 gitk:6269
+msgid "Output file:"
+msgstr "Escribir a archivo:"
+
+#: gitk:6106
+msgid "Generate"
+msgstr "Generar"
+
+#: gitk:6142
+msgid "Error creating patch:"
+msgstr "Error en la creación del parche:"
+
+#: gitk:6164 gitk:6257 gitk:6311
+msgid "ID:"
+msgstr "ID:"
+
+#: gitk:6173
+msgid "Tag name:"
+msgstr "Nombre de etiqueta:"
+
+#: gitk:6177 gitk:6320
+msgid "Create"
+msgstr "Crear"
+
+#: gitk:6192
+msgid "No tag name specified"
+msgstr "No se ha especificado etiqueta"
+
+#: gitk:6196
+#, tcl-format
+msgid "Tag \"%s\" already exists"
+msgstr "La etiqueta \"%s\" ya existe"
+
+#: gitk:6202
+msgid "Error creating tag:"
+msgstr "Error al crear la etiqueta:"
+
+#: gitk:6266
+msgid "Command:"
+msgstr "Comando:"
+
+#: gitk:6274
+msgid "Write"
+msgstr "Escribir"
+
+#: gitk:6290
+msgid "Error writing commit:"
+msgstr "Error al escribir revisión:"
+
+#: gitk:6316
+msgid "Name:"
+msgstr "Nombre:"
+
+#: gitk:6335
+msgid "Please specify a name for the new branch"
+msgstr "Especifique un nombre para la nueva rama"
+
+#: gitk:6364
+#, tcl-format
+msgid "Commit %s is already included in branch %s -- really re-apply it?"
+msgstr "La revisión %s ya está incluida en la rama %s -- ¿Volver a aplicarla?"
+
+#: gitk:6369
+msgid "Cherry-picking"
+msgstr "Eligiendo revisiones (cherry-picking)"
+
+#: gitk:6381
+msgid "No changes committed"
+msgstr "No se han guardado cambios"
+
+#: gitk:6404
+msgid "Confirm reset"
+msgstr "Confirmar git reset"
+
+#: gitk:6406
+#, tcl-format
+msgid "Reset branch %s to %s?"
+msgstr "¿Reponer la rama %s a %s?"
+
+#: gitk:6410
+msgid "Reset type:"
+msgstr "Tipo de reposición:"
+
+#: gitk:6414
+msgid "Soft: Leave working tree and index untouched"
+msgstr "Suave: No altera la copia de trabajo ni el índice"
+
+#: gitk:6417
+msgid "Mixed: Leave working tree untouched, reset index"
+msgstr "Mixta: Actualiza el índice, no altera la copia de trabajo"
+
+#: gitk:6420
+msgid ""
+"Hard: Reset working tree and index\n"
+"(discard ALL local changes)"
+msgstr ""
+"Dura: Actualiza el índice y la copia de trabajo\n"
+"(abandona TODAS las modificaciones locales)"
+
+#: gitk:6436
+msgid "Resetting"
+msgstr "Reponiendo"
+
+#: gitk:6493
+msgid "Checking out"
+msgstr "Creando copia de trabajo"
+
+#: gitk:6523
+msgid "Cannot delete the currently checked-out branch"
+msgstr "No se puede borrar la rama actual"
+
+#: gitk:6529
+#, tcl-format
+msgid ""
+"The commits on branch %s aren't on any other branch.\n"
+"Really delete branch %s?"
+msgstr ""
+"Las revisiones de la rama %s no están presentes en otras ramas.\n"
+"¿Borrar la rama %s?"
+
+#: gitk:6560
+#, tcl-format
+msgid "Tags and heads: %s"
+msgstr "Etiquetas y ramas: %s"
+
+#: gitk:6574
+msgid "Filter"
+msgstr "Filtro"
+
+#: gitk:6868
+msgid ""
+"Error reading commit topology information; branch and preceding/following "
+"tag information will be incomplete."
+msgstr ""
+"Error al leer la topología de revisiones: la información sobre "
+"las ramas y etiquetas precedentes y siguientes será incompleta."
+
+#: gitk:7852
+msgid "Tag"
+msgstr "Etiqueta"
+
+#: gitk:7852
+msgid "Id"
+msgstr "Id"
+
+#: gitk:7892
+msgid "Gitk font chooser"
+msgstr "Selector de tipografías gitk"
+
+#: gitk:7909
+msgid "B"
+msgstr "B"
+
+#: gitk:7912
+msgid "I"
+msgstr "I"
+
+#: gitk:8005
+msgid "Gitk preferences"
+msgstr "Preferencias de gitk"
+
+#: gitk:8006
+msgid "Commit list display options"
+msgstr "Opciones de visualización de la lista de revisiones"
+
+#: gitk:8009
+msgid "Maximum graph width (lines)"
+msgstr "Ancho máximo del gráfico (en líneas)"
+
+#: gitk:8013
+#, tcl-format
+msgid "Maximum graph width (% of pane)"
+msgstr "Ancho máximo del gráfico (en % del panel)"
+
+#: gitk:8018
+msgid "Show local changes"
+msgstr "Mostrar cambios locales"
+
+#: gitk:8023
+msgid "Auto-select SHA1"
+msgstr "Seleccionar automáticamente SHA1 hash"
+
+#: gitk:8028
+msgid "Diff display options"
+msgstr "Opciones de visualización de diferencias"
+
+#: gitk:8030
+msgid "Tab spacing"
+msgstr "Espaciado de tabulador"
+
+#: gitk:8034
+msgid "Display nearby tags"
+msgstr "Mostrar etiquetas cercanas"
+
+#: gitk:8039
+msgid "Limit diffs to listed paths"
+msgstr "Limitar las diferencias a las rutas seleccionadas"
+
+#: gitk:8044
+msgid "Colors: press to choose"
+msgstr "Colores: pulse para seleccionar"
+
+#: gitk:8047
+msgid "Background"
+msgstr "Fondo"
+
+#: gitk:8051
+msgid "Foreground"
+msgstr "Primer plano"
+
+#: gitk:8055
+msgid "Diff: old lines"
+msgstr "Diff: líneas viejas"
+
+#: gitk:8060
+msgid "Diff: new lines"
+msgstr "Diff: líneas nuevas"
+
+#: gitk:8065
+msgid "Diff: hunk header"
+msgstr "Diff: cabecera de fragmento"
+
+#: gitk:8071
+msgid "Select bg"
+msgstr "Color de fondo de la selección"
+
+#: gitk:8075
+msgid "Fonts: press to choose"
+msgstr "Tipografías: pulse para elegir"
+
+#: gitk:8077
+msgid "Main font"
+msgstr "Tipografía principal"
+
+#: gitk:8078
+msgid "Diff display font"
+msgstr "Tipografía para diferencias"
+
+#: gitk:8079
+msgid "User interface font"
+msgstr "Tipografía para interfaz de usuario"
+
+#: gitk:8095
+#, tcl-format
+msgid "Gitk: choose color for %s"
+msgstr "Gitk: elegir color para %s"
+
+#: gitk:8476
+msgid ""
+"Sorry, gitk cannot run with this version of Tcl/Tk.\n"
+" Gitk requires at least Tcl/Tk 8.4."
+msgstr ""
+"Esta versión de Tcl/Tk es demasiado antigua.\n"
+" Gitk requiere Tcl/Tk versión 8.4 o superior."
+
+#: gitk:8565
+msgid "Cannot find a git repository here."
+msgstr "No hay un repositorio git aquí."
+
+#: gitk:8569
+#, tcl-format
+msgid "Cannot find the git directory \"%s\"."
+msgstr "No hay directorio git \"%s\"."
+
+#: gitk:8612
+#, tcl-format
+msgid "Ambiguous argument '%s': both revision and filename"
+msgstr "Argumento ambiguo: '%s' es tanto una revisión como un nombre de archivo"
+
+#: gitk:8624
+msgid "Bad arguments to gitk:"
+msgstr "Argumentos incorrectos a Gitk:"
+
+#: gitk:8636
+msgid "Couldn't get list of unmerged files:"
+msgstr "Imposible obtener la lista de archivos pendientes de fusión:"
+
+#: gitk:8652
+msgid "No files selected: --merge specified but no files are unmerged."
+msgstr ""
+"No hay archivos seleccionados: se seleccionó la opción --merge pero no hay "
+"archivos pendientes de fusión."
+
+#: gitk:8655
+msgid ""
+"No files selected: --merge specified but no unmerged files are within file "
+"limit."
+msgstr ""
+"No hay archivos seleccionados: se seleccionó la opción --merge pero los archivos "
+"especificados no necesitan fusión."
+
+#: gitk:8716
+msgid "Command line"
+msgstr "Línea de comandos"
diff --git a/gitk-git/po/de.po b/gitk-git/po/de.po
index 5ee2fca8b2..b9867bf8e0 100644
--- a/gitk-git/po/de.po
+++ b/gitk-git/po/de.po
@@ -7,249 +7,253 @@ msgid ""
 msgstr ""
 "Project-Id-Version: git-gui\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-01-09 22:20+0100\n"
-"PO-Revision-Date: 2008-01-09 22:21+0100\n"
+"POT-Creation-Date: 2008-05-01 11:54+0200\n"
+"PO-Revision-Date: 2008-05-02 21:12+0200\n"
 "Last-Translator: Christian Stimming <stimming@tuhh.de>\n"
 "Language-Team: German\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: gitk:101
+#: gitk:111
 msgid "Error executing git rev-list:"
 msgstr "Fehler beim Ausführen von git-rev-list:"
 
-#: gitk:114
+#: gitk:124
 msgid "Reading"
 msgstr "Lesen"
 
-#: gitk:141 gitk:2143
+#: gitk:151 gitk:2191
 msgid "Reading commits..."
 msgstr "Versionen lesen..."
 
-#: gitk:264
+#: gitk:275
 msgid "Can't parse git log output:"
-msgstr "Git log Ausgabe kann nicht erkannt werden:"
+msgstr "Ausgabe von git-log kann nicht erkannt werden:"
 
-#: gitk:375 gitk:2147
+#: gitk:386 gitk:2195
 msgid "No commits selected"
 msgstr "Keine Versionen ausgewählt."
 
-#: gitk:486
+#: gitk:500
 msgid "No commit information available"
 msgstr "Keine Versionsinformation verfügbar"
 
-#: gitk:585 gitk:607 gitk:1908 gitk:6366 gitk:7866 gitk:8020
+#: gitk:599 gitk:621 gitk:1955 gitk:6424 gitk:7924 gitk:8083
 msgid "OK"
 msgstr "Ok"
 
-#: gitk:609 gitk:1909 gitk:6046 gitk:6117 gitk:6218 gitk:6264 gitk:6368
-#: gitk:7867 gitk:8021
+#: gitk:623 gitk:1956 gitk:6108 gitk:6179 gitk:6276 gitk:6322 gitk:6426
+#: gitk:7925 gitk:8084
 msgid "Cancel"
 msgstr "Abbrechen"
 
-#: gitk:646
+#: gitk:661
 msgid "File"
 msgstr "Datei"
 
-#: gitk:648
+#: gitk:663
 msgid "Update"
 msgstr "Aktualisieren"
 
-#: gitk:649
+#: gitk:664
 msgid "Reread references"
 msgstr "Zweige neu laden"
 
-#: gitk:650
+#: gitk:665
 msgid "List references"
-msgstr "Zweige auflisten"
+msgstr "Zweige/Markierungen auflisten"
 
-#: gitk:651
+#: gitk:666
 msgid "Quit"
 msgstr "Beenden"
 
-#: gitk:653
+#: gitk:668
 msgid "Edit"
 msgstr "Bearbeiten"
 
-#: gitk:654
+#: gitk:669
 msgid "Preferences"
 msgstr "Einstellungen"
 
-#: gitk:657
+#: gitk:672 gitk:1892
 msgid "View"
 msgstr "Ansicht"
 
-#: gitk:658
+#: gitk:673
 msgid "New view..."
 msgstr "Neue Ansicht..."
 
-#: gitk:659 gitk:2085 gitk:8651
+#: gitk:674 gitk:2133 gitk:8723
 msgid "Edit view..."
 msgstr "Ansicht bearbeiten..."
 
-#: gitk:661 gitk:2086 gitk:8652
+#: gitk:676 gitk:2134 gitk:8724
 msgid "Delete view"
 msgstr "Ansicht löschen"
 
-#: gitk:663
+#: gitk:678
 msgid "All files"
 msgstr "Alle Dateien"
 
-#: gitk:667
+#: gitk:682
 msgid "Help"
 msgstr "Hilfe"
 
-#: gitk:668 gitk:1280
+#: gitk:683 gitk:1317
 msgid "About gitk"
 msgstr "Über gitk"
 
-#: gitk:669
+#: gitk:684
 msgid "Key bindings"
 msgstr "Tastenkürzel"
 
-#: gitk:726
+#: gitk:741
 msgid "SHA1 ID: "
 msgstr "SHA1:"
 
-#: gitk:776
+#: gitk:791
 msgid "Find"
 msgstr "Suche"
 
-#: gitk:777
+#: gitk:792
 msgid "next"
 msgstr "nächste"
 
-#: gitk:778
+#: gitk:793
 msgid "prev"
 msgstr "vorige"
 
-#: gitk:779
+#: gitk:794
 msgid "commit"
 msgstr "Version"
 
-#: gitk:782 gitk:784 gitk:2308 gitk:2331 gitk:2355 gitk:4257 gitk:4320
+#: gitk:797 gitk:799 gitk:2356 gitk:2379 gitk:2403 gitk:4306 gitk:4369
 msgid "containing:"
 msgstr "enthaltend:"
 
-#: gitk:785 gitk:1741 gitk:1746 gitk:2383
+#: gitk:800 gitk:1778 gitk:1783 gitk:2431
 msgid "touching paths:"
 msgstr "Pfad betreffend:"
 
-#: gitk:786 gitk:2388
+#: gitk:801 gitk:2436
 msgid "adding/removing string:"
-msgstr "String dazu/löschen:"
+msgstr "Zeichenkette ändernd:"
 
-#: gitk:795 gitk:797
+#: gitk:810 gitk:812
 msgid "Exact"
 msgstr "Exakt"
 
-#: gitk:797 gitk:2466 gitk:4225
+#: gitk:812 gitk:2514 gitk:4274
 msgid "IgnCase"
 msgstr "Kein Groß/Klein"
 
-#: gitk:797 gitk:2357 gitk:2464 gitk:4221
+#: gitk:812 gitk:2405 gitk:2512 gitk:4270
 msgid "Regexp"
 msgstr "Regexp"
 
-#: gitk:799 gitk:800 gitk:2485 gitk:2515 gitk:2522 gitk:4331 gitk:4387
+#: gitk:814 gitk:815 gitk:2533 gitk:2563 gitk:2570 gitk:4380 gitk:4436
 msgid "All fields"
 msgstr "Alle Felder"
 
-#: gitk:800 gitk:2483 gitk:2515 gitk:4287
+#: gitk:815 gitk:2531 gitk:2563 gitk:4336
 msgid "Headline"
 msgstr "Überschrift"
 
-#: gitk:801 gitk:2483 gitk:4287 gitk:4387 gitk:4775
+#: gitk:816 gitk:2531 gitk:4336 gitk:4436 gitk:4827
 msgid "Comments"
 msgstr "Beschreibung"
 
-#: gitk:801 gitk:2483 gitk:2487 gitk:2522 gitk:4287 gitk:4711 gitk:5895
-#: gitk:5910
+#: gitk:816 gitk:2531 gitk:2535 gitk:2570 gitk:4336 gitk:4763 gitk:5957
+#: gitk:5972
 msgid "Author"
 msgstr "Autor"
 
-#: gitk:801 gitk:2483 gitk:4287 gitk:4713
+#: gitk:816 gitk:2531 gitk:4336 gitk:4765
 msgid "Committer"
 msgstr "Eintragender"
 
-#: gitk:829
+#: gitk:845
 msgid "Search"
 msgstr "Suche"
 
-#: gitk:836
+#: gitk:852
 msgid "Diff"
 msgstr "Vergleich"
 
-#: gitk:838
+#: gitk:854
 msgid "Old version"
 msgstr "Alte Version"
 
-#: gitk:840
+#: gitk:856
 msgid "New version"
 msgstr "Neue Version"
 
-#: gitk:842
+#: gitk:858
 msgid "Lines of context"
 msgstr "Kontextzeilen"
 
-#: gitk:900
+#: gitk:868
+msgid "Ignore space change"
+msgstr "Leerzeichenänderungen ignorieren"
+
+#: gitk:926
 msgid "Patch"
 msgstr "Patch"
 
-#: gitk:902
+#: gitk:928
 msgid "Tree"
 msgstr "Baum"
 
-#: gitk:1018 gitk:1033 gitk:5961
+#: gitk:1053 gitk:1068 gitk:6023
 msgid "Diff this -> selected"
 msgstr "Vergleich diese -> gewählte"
 
-#: gitk:1020 gitk:1035 gitk:5962
+#: gitk:1055 gitk:1070 gitk:6024
 msgid "Diff selected -> this"
 msgstr "Vergleich gewählte -> diese"
 
-#: gitk:1022 gitk:1037 gitk:5963
+#: gitk:1057 gitk:1072 gitk:6025
 msgid "Make patch"
 msgstr "Patch erstellen"
 
-#: gitk:1023 gitk:6101
+#: gitk:1058 gitk:6163
 msgid "Create tag"
 msgstr "Markierung erstellen"
 
-#: gitk:1024 gitk:6198
+#: gitk:1059 gitk:6256
 msgid "Write commit to file"
 msgstr "Version in Datei schreiben"
 
-#: gitk:1025 gitk:6252
+#: gitk:1060 gitk:6310
 msgid "Create new branch"
 msgstr "Neuen Zweig erstellen"
 
-#: gitk:1026
+#: gitk:1061
 msgid "Cherry-pick this commit"
 msgstr "Diese Version pflücken"
 
-#: gitk:1028
+#: gitk:1063
 msgid "Reset HEAD branch to here"
 msgstr "HEAD-Zweig auf diese Version zurücksetzen"
 
-#: gitk:1044
+#: gitk:1079
 msgid "Check out this branch"
 msgstr "Auf diesen Zweig umstellen"
 
-#: gitk:1046
+#: gitk:1081
 msgid "Remove this branch"
 msgstr "Zweig löschen"
 
-#: gitk:1052
+#: gitk:1087
 msgid "Highlight this too"
 msgstr "Diesen auch hervorheben"
 
-#: gitk:1054
+#: gitk:1089
 msgid "Highlight this only"
 msgstr "Nur diesen hervorheben"
 
-#: gitk:1281
+#: gitk:1318
 msgid ""
 "\n"
 "Gitk - a commit viewer for git\n"
@@ -267,262 +271,425 @@ msgstr ""
 "License\n"
 "        "
 
-#: gitk:1289 gitk:1350 gitk:6524
+#: gitk:1326 gitk:1387 gitk:6582
 msgid "Close"
 msgstr "Schließen"
 
-#: gitk:1308
+#: gitk:1345
 msgid "Gitk key bindings"
 msgstr "Gitk Tastaturbelegung"
 
-#: gitk:1858
+#: gitk:1347
+msgid "Gitk key bindings:"
+msgstr "Gitk Tastaturbelegung:"
+
+#: gitk:1349
+#, tcl-format
+msgid "<%s-Q>\t\tQuit"
+msgstr "<%s-Q>\t\tBeenden"
+
+#: gitk:1350
+msgid "<Home>\t\tMove to first commit"
+msgstr "<Pos1>\t\tZur neuesten Version springen"
+
+#: gitk:1351
+msgid "<End>\t\tMove to last commit"
+msgstr "<Ende>\t\tZur ältesten Version springen"
+
+#: gitk:1352
+msgid "<Up>, p, i\tMove up one commit"
+msgstr "<Hoch>, p, i\tNächste neuere Version"
+
+#: gitk:1353
+msgid "<Down>, n, k\tMove down one commit"
+msgstr "<Runter>, n, k\tNächste ältere Version"
+
+#: gitk:1354
+msgid "<Left>, z, j\tGo back in history list"
+msgstr "<Links>, z, j\tEine Version zurückgehen"
+
+#: gitk:1355
+msgid "<Right>, x, l\tGo forward in history list"
+msgstr "<Rechts>, x, l\tEine Version weitergehen"
+
+#: gitk:1356
+msgid "<PageUp>\tMove up one page in commit list"
+msgstr "<BildHoch>\tEine Seite nach oben blättern"
+
+#: gitk:1357
+msgid "<PageDown>\tMove down one page in commit list"
+msgstr "<BildRunter>\tEine Seite nach unten blättern"
+
+#: gitk:1358
+#, tcl-format
+msgid "<%s-Home>\tScroll to top of commit list"
+msgstr "<%s-Pos1>\tZum oberen Ende der Versionsliste blättern"
+
+#: gitk:1359
+#, tcl-format
+msgid "<%s-End>\tScroll to bottom of commit list"
+msgstr "<%s-Ende>\tZum unteren Ende der Versionsliste blättern"
+
+#: gitk:1360
+#, tcl-format
+msgid "<%s-Up>\tScroll commit list up one line"
+msgstr "<%s-Hoch>\tVersionsliste eine Zeile nach oben blättern"
+
+#: gitk:1361
+#, tcl-format
+msgid "<%s-Down>\tScroll commit list down one line"
+msgstr "<%s-Runter>\tVersionsliste eine Zeile nach unten blättern"
+
+#: gitk:1362
+#, tcl-format
+msgid "<%s-PageUp>\tScroll commit list up one page"
+msgstr "<%s-BildHoch>\tVersionsliste eine Seite hoch blättern"
+
+#: gitk:1363
+#, tcl-format
+msgid "<%s-PageDown>\tScroll commit list down one page"
+msgstr "<%s-BildRunter>\tVersionsliste eine Seite nach unten blättern"
+
+#: gitk:1364
+msgid "<Shift-Up>\tFind backwards (upwards, later commits)"
+msgstr "<Umschalt-Hoch>\tRückwärts suchen (nach oben; neuere Versionen)"
+
+#: gitk:1365
+msgid "<Shift-Down>\tFind forwards (downwards, earlier commits)"
+msgstr "<Umschalt-Runter> Suchen (nach unten; ältere Versionen)"
+
+#: gitk:1366
+msgid "<Delete>, b\tScroll diff view up one page"
+msgstr "<Entf>, b\t\tVergleich eine Seite nach oben blättern"
+
+#: gitk:1367
+msgid "<Backspace>\tScroll diff view up one page"
+msgstr "<Löschtaste>\tVergleich eine Seite nach oben blättern"
+
+#: gitk:1368
+msgid "<Space>\t\tScroll diff view down one page"
+msgstr "<Leertaste>\tVergleich eine Seite nach unten blättern"
+
+#: gitk:1369
+msgid "u\t\tScroll diff view up 18 lines"
+msgstr "u\t\tVergleich um 18 Zeilen nach oben (»up«) blättern"
+
+#: gitk:1370
+msgid "d\t\tScroll diff view down 18 lines"
+msgstr "d\t\tVergleich um 18 Zeilen nach unten (»down«) blättern"
+
+#: gitk:1371
+#, tcl-format
+msgid "<%s-F>\t\tFind"
+msgstr "<%s-F>\t\tSuchen"
+
+#: gitk:1372
+#, tcl-format
+msgid "<%s-G>\t\tMove to next find hit"
+msgstr "<%s-G>\t\tWeitersuchen"
+
+#: gitk:1373
+msgid "<Return>\tMove to next find hit"
+msgstr "<Eingabetaste>\tWeitersuchen"
+
+#: gitk:1374
+msgid "/\t\tMove to next find hit, or redo find"
+msgstr "/\t\tWeitersuchen oder neue Suche beginnen"
+
+#: gitk:1375
+msgid "?\t\tMove to previous find hit"
+msgstr "?\t\tRückwärts weitersuchen"
+
+#: gitk:1376
+msgid "f\t\tScroll diff view to next file"
+msgstr "f\t\tVergleich zur nächsten Datei (»file«) blättern"
+
+#: gitk:1377
+#, tcl-format
+msgid "<%s-S>\t\tSearch for next hit in diff view"
+msgstr "<%s-S>\t\tWeitersuchen im Vergleich"
+
+#: gitk:1378
+#, tcl-format
+msgid "<%s-R>\t\tSearch for previous hit in diff view"
+msgstr "<%s-R>\t\tRückwärts weitersuchen im Vergleich"
+
+#: gitk:1379
+#, tcl-format
+msgid "<%s-KP+>\tIncrease font size"
+msgstr "<%s-Nummerblock-Plus>\tSchriftgröße vergrößern"
+
+#: gitk:1380
+#, tcl-format
+msgid "<%s-plus>\tIncrease font size"
+msgstr "<%s-Plus>\tSchriftgröße vergrößern"
+
+#: gitk:1381
+#, tcl-format
+msgid "<%s-KP->\tDecrease font size"
+msgstr "<%s-Nummernblock-> Schriftgröße verkleinern"
+
+#: gitk:1382
+#, tcl-format
+msgid "<%s-minus>\tDecrease font size"
+msgstr "<%s-Minus>\tSchriftgröße verkleinern"
+
+#: gitk:1383
+msgid "<F5>\t\tUpdate"
+msgstr "<F5>\t\tAktualisieren"
+
+#: gitk:1896
 msgid "Gitk view definition"
 msgstr "Gitk Ansichten"
 
-#: gitk:1882
+#: gitk:1921
 msgid "Name"
 msgstr "Name"
 
-#: gitk:1885
+#: gitk:1924
 msgid "Remember this view"
 msgstr "Diese Ansicht speichern"
 
-#: gitk:1889
+#: gitk:1928
 msgid "Commits to include (arguments to git rev-list):"
 msgstr "Versionen anzeigen (Argumente von git-rev-list):"
 
-#: gitk:1895
+#: gitk:1935
+msgid "Command to generate more commits to include:"
+msgstr "Versionsliste durch folgendes Kommando erzeugen lassen:"
+
+#: gitk:1942
 msgid "Enter files and directories to include, one per line:"
 msgstr "Folgende Dateien und Verzeichnisse anzeigen (eine pro Zeile):"
 
-#: gitk:1942
+#: gitk:1989
 msgid "Error in commit selection arguments:"
 msgstr "Fehler in den ausgewählten Versionen:"
 
-#: gitk:1993 gitk:2079 gitk:2535 gitk:2549 gitk:3732 gitk:8620 gitk:8621
+#: gitk:2043 gitk:2127 gitk:2583 gitk:2597 gitk:3781 gitk:8689 gitk:8690
 msgid "None"
 msgstr "Keine"
 
-#: gitk:2483 gitk:4287 gitk:5897 gitk:5912
+#: gitk:2531 gitk:4336 gitk:5959 gitk:5974
 msgid "Date"
 msgstr "Datum"
 
-#: gitk:2483 gitk:4287
+#: gitk:2531 gitk:4336
 msgid "CDate"
 msgstr "Eintragedatum"
 
-#: gitk:2632 gitk:2637
+#: gitk:2680 gitk:2685
 msgid "Descendant"
 msgstr "Abkömmling"
 
-#: gitk:2633
+#: gitk:2681
 msgid "Not descendant"
 msgstr "Nicht Abkömmling"
 
-#: gitk:2640 gitk:2645
+#: gitk:2688 gitk:2693
 msgid "Ancestor"
 msgstr "Vorgänger"
 
-#: gitk:2641
+#: gitk:2689
 msgid "Not ancestor"
 msgstr "Nicht Vorgänger"
 
-#: gitk:2875
+#: gitk:2924
 msgid "Local changes checked in to index but not committed"
 msgstr "Lokale Änderungen bereitgestellt, aber nicht eingetragen"
 
-#: gitk:2905
+#: gitk:2954
 msgid "Local uncommitted changes, not checked in to index"
 msgstr "Lokale Änderungen, nicht bereitgestellt"
 
-#: gitk:4256
+#: gitk:4305
 msgid "Searching"
 msgstr "Suchen"
 
-#: gitk:4715
+#: gitk:4767
 msgid "Tags:"
 msgstr "Markierungen:"
 
-#: gitk:4732 gitk:4738 gitk:5890
+#: gitk:4784 gitk:4790 gitk:5952
 msgid "Parent"
 msgstr "Eltern"
 
-#: gitk:4743
+#: gitk:4795
 msgid "Child"
 msgstr "Kind"
 
-#: gitk:4752
+#: gitk:4804
 msgid "Branch"
 msgstr "Zweig"
 
-#: gitk:4755
+#: gitk:4807
 msgid "Follows"
 msgstr "Folgt auf"
 
-#: gitk:4758
+#: gitk:4810
 msgid "Precedes"
 msgstr "Vorgänger von"
 
-#: gitk:5040
+#: gitk:5094
 msgid "Error getting merge diffs:"
 msgstr "Fehler beim Laden des Vergleichs:"
 
-#: gitk:5717
+#: gitk:5779
 msgid "Goto:"
 msgstr "Gehe zu:"
 
-#: gitk:5719
+#: gitk:5781
 msgid "SHA1 ID:"
-msgstr "SHA1 Kennung:"
+msgstr "SHA1-Hashwert:"
 
-#: gitk:5744
+#: gitk:5806
 #, tcl-format
 msgid "Short SHA1 id %s is ambiguous"
-msgstr "Kurze SHA1-Kennung »%s« ist mehrdeutig"
+msgstr "Kurzer SHA1-Hashwert »%s« ist mehrdeutig"
 
-#: gitk:5756
+#: gitk:5818
 #, tcl-format
 msgid "SHA1 id %s is not known"
-msgstr "SHA1-Kennung »%s« unbekannt"
+msgstr "SHA1-Hashwert »%s« unbekannt"
 
-#: gitk:5758
+#: gitk:5820
 #, tcl-format
 msgid "Tag/Head %s is not known"
 msgstr "Markierung/Zweig »%s« ist unbekannt"
 
-#: gitk:5900
+#: gitk:5962
 msgid "Children"
 msgstr "Kinder"
 
-#: gitk:5957
+#: gitk:6019
 #, tcl-format
 msgid "Reset %s branch to here"
 msgstr "Zweig »%s« hierher zurücksetzen"
 
-#: gitk:5988
+#: gitk:6050
 msgid "Top"
 msgstr "Oben"
 
-#: gitk:5989
+#: gitk:6051
 msgid "From"
 msgstr "Von"
 
-#: gitk:5994
+#: gitk:6056
 msgid "To"
 msgstr "bis"
 
-#: gitk:6017
+#: gitk:6079
 msgid "Generate patch"
 msgstr "Patch erstellen"
 
-#: gitk:6019
+#: gitk:6081
 msgid "From:"
 msgstr "Von:"
 
-#: gitk:6028
+#: gitk:6090
 msgid "To:"
 msgstr "bis:"
 
-#: gitk:6037
+#: gitk:6099
 msgid "Reverse"
 msgstr "Umgekehrt"
 
-#: gitk:6039 gitk:6212
+#: gitk:6101 gitk:6270
 msgid "Output file:"
 msgstr "Ausgabedatei:"
 
-#: gitk:6045
+#: gitk:6107
 msgid "Generate"
 msgstr "Erzeugen"
 
-#: gitk:6081
+#: gitk:6143
 msgid "Error creating patch:"
 msgstr "Fehler beim Patch erzeugen:"
 
-#: gitk:6103 gitk:6200 gitk:6254
+#: gitk:6165 gitk:6258 gitk:6312
 msgid "ID:"
 msgstr "ID:"
 
-#: gitk:6112
+#: gitk:6174
 msgid "Tag name:"
 msgstr "Markierungsname:"
 
-#: gitk:6116 gitk:6263
+#: gitk:6178 gitk:6321
 msgid "Create"
 msgstr "Erstellen"
 
-#: gitk:6131
+#: gitk:6193
 msgid "No tag name specified"
 msgstr "Kein Markierungsname angegeben"
 
-#: gitk:6135
+#: gitk:6197
 #, tcl-format
 msgid "Tag \"%s\" already exists"
 msgstr "Markierung »%s« existiert bereits."
 
-#: gitk:6145
+#: gitk:6203
 msgid "Error creating tag:"
 msgstr "Fehler bei Markierung erstellen:"
 
-#: gitk:6209
+#: gitk:6267
 msgid "Command:"
 msgstr "Kommando:"
 
-#: gitk:6217
+#: gitk:6275
 msgid "Write"
 msgstr "Schreiben"
 
-#: gitk:6233
+#: gitk:6291
 msgid "Error writing commit:"
-msgstr "Fehler beim Version eintragen:"
+msgstr "Fehler beim Schreiben der Version:"
 
-#: gitk:6259
+#: gitk:6317
 msgid "Name:"
 msgstr "Name:"
 
-#: gitk:6278
+#: gitk:6336
 msgid "Please specify a name for the new branch"
 msgstr "Bitte geben Sie einen Namen für den neuen Zweig an."
 
-#: gitk:6307
+#: gitk:6365
 #, tcl-format
 msgid "Commit %s is already included in branch %s -- really re-apply it?"
 msgstr ""
 "Version »%s« ist bereits im Zweig »%s« enthalten -- trotzdem erneut "
 "eintragen?"
 
-#: gitk:6312
+#: gitk:6370
 msgid "Cherry-picking"
 msgstr "Version pflücken"
 
-#: gitk:6324
+#: gitk:6382
 msgid "No changes committed"
 msgstr "Keine Änderungen eingetragen"
 
-#: gitk:6347
+#: gitk:6405
 msgid "Confirm reset"
 msgstr "Zurücksetzen bestätigen"
 
-#: gitk:6349
+#: gitk:6407
 #, tcl-format
 msgid "Reset branch %s to %s?"
 msgstr "Zweig »%s« auf »%s« zurücksetzen?"
 
-#: gitk:6353
+#: gitk:6411
 msgid "Reset type:"
 msgstr "Art des Zurücksetzens:"
 
-#: gitk:6357
+#: gitk:6415
 msgid "Soft: Leave working tree and index untouched"
 msgstr "Harmlos: Arbeitskopie und Bereitstellung unverändert"
 
-#: gitk:6360
+#: gitk:6418
 msgid "Mixed: Leave working tree untouched, reset index"
 msgstr ""
 "Gemischt: Arbeitskopie unverändert,\n"
 "Bereitstellung zurückgesetzt"
 
-#: gitk:6363
+#: gitk:6421
 msgid ""
 "Hard: Reset working tree and index\n"
 "(discard ALL local changes)"
@@ -530,21 +697,21 @@ msgstr ""
 "Hart: Arbeitskopie und Bereitstellung\n"
 "(Alle lokalen Änderungen werden gelöscht)"
 
-#: gitk:6379
+#: gitk:6437
 msgid "Resetting"
 msgstr "Zurücksetzen"
 
-#: gitk:6436
+#: gitk:6494
 msgid "Checking out"
 msgstr "Umstellen"
 
-#: gitk:6466
+#: gitk:6524
 msgid "Cannot delete the currently checked-out branch"
 msgstr ""
 "Der Zweig, auf den die Arbeitskopie momentan umgestellt ist, kann nicht "
 "gelöscht werden."
 
-#: gitk:6472
+#: gitk:6530
 #, tcl-format
 msgid ""
 "The commits on branch %s aren't on any other branch.\n"
@@ -553,16 +720,16 @@ msgstr ""
 "Die Versionen auf Zweig »%s« existieren auf keinem anderen Zweig.\n"
 "Zweig »%s« trotzdem löschen?"
 
-#: gitk:6503
+#: gitk:6561
 #, tcl-format
 msgid "Tags and heads: %s"
 msgstr "Markierungen und Zweige: %s"
 
-#: gitk:6517
+#: gitk:6575
 msgid "Filter"
 msgstr "Filtern"
 
-#: gitk:6811
+#: gitk:6869
 msgid ""
 "Error reading commit topology information; branch and preceding/following "
 "tag information will be incomplete."
@@ -570,113 +737,117 @@ msgstr ""
 "Fehler beim Lesen der Strukturinformationen; Zweige und Vorgänger/Nachfolger "
 "Informationen werden unvollständig sein."
 
-#: gitk:7795
+#: gitk:7853
 msgid "Tag"
 msgstr "Markierung"
 
-#: gitk:7795
+#: gitk:7853
 msgid "Id"
 msgstr "Id"
 
-#: gitk:7835
+#: gitk:7893
 msgid "Gitk font chooser"
 msgstr "Gitk Schriften wählen"
 
-#: gitk:7852
+#: gitk:7910
 msgid "B"
 msgstr "F"
 
-#: gitk:7855
+#: gitk:7913
 msgid "I"
 msgstr "K"
 
-#: gitk:7948
+#: gitk:8006
 msgid "Gitk preferences"
 msgstr "Gitk Einstellungen"
 
-#: gitk:7949
+#: gitk:8007
 msgid "Commit list display options"
 msgstr "Anzeige Versionsliste"
 
-#: gitk:7952
+#: gitk:8010
 msgid "Maximum graph width (lines)"
 msgstr "Maximale Graphenbreite (Zeilen)"
 
-#: gitk:7956
+#: gitk:8014
 #, tcl-format
 msgid "Maximum graph width (% of pane)"
 msgstr "Maximale Graphenbreite (% des Fensters)"
 
-#: gitk:7961
+#: gitk:8019
 msgid "Show local changes"
 msgstr "Lokale Änderungen anzeigen"
 
-#: gitk:7966
+#: gitk:8024
+msgid "Auto-select SHA1"
+msgstr "SHA1-Hashwert automatisch markieren"
+
+#: gitk:8029
 msgid "Diff display options"
 msgstr "Anzeige Vergleich"
 
-#: gitk:7968
+#: gitk:8031
 msgid "Tab spacing"
 msgstr "Tabulatorbreite"
 
-#: gitk:7972
+#: gitk:8035
 msgid "Display nearby tags"
 msgstr "Naheliegende Überschriften anzeigen"
 
-#: gitk:7977
+#: gitk:8040
 msgid "Limit diffs to listed paths"
 msgstr "Vergleich nur für angezeigte Pfade"
 
-#: gitk:7982
+#: gitk:8045
 msgid "Colors: press to choose"
 msgstr "Farben: Klicken zum Wählen"
 
-#: gitk:7985
+#: gitk:8048
 msgid "Background"
-msgstr "Vordergrund"
+msgstr "Hintergrund"
 
-#: gitk:7989
+#: gitk:8052
 msgid "Foreground"
-msgstr "Hintergrund"
+msgstr "Vordergrund"
 
-#: gitk:7993
+#: gitk:8056
 msgid "Diff: old lines"
 msgstr "Vergleich: Alte Zeilen"
 
-#: gitk:7998
+#: gitk:8061
 msgid "Diff: new lines"
 msgstr "Vergleich: Neue Zeilen"
 
-#: gitk:8003
+#: gitk:8066
 msgid "Diff: hunk header"
 msgstr "Vergleich: Änderungstitel"
 
-#: gitk:8009
+#: gitk:8072
 msgid "Select bg"
 msgstr "Hintergrundfarbe Auswählen"
 
-#: gitk:8013
+#: gitk:8076
 msgid "Fonts: press to choose"
 msgstr "Schriftart: Klicken zum Wählen"
 
-#: gitk:8015
+#: gitk:8078
 msgid "Main font"
 msgstr "Programmschriftart"
 
-#: gitk:8016
+#: gitk:8079
 msgid "Diff display font"
 msgstr "Vergleich"
 
-#: gitk:8017
+#: gitk:8080
 msgid "User interface font"
 msgstr "Beschriftungen"
 
-#: gitk:8033
+#: gitk:8096
 #, tcl-format
 msgid "Gitk: choose color for %s"
 msgstr "Gitk: Farbe wählen für %s"
 
-#: gitk:8414
+#: gitk:8477
 msgid ""
 "Sorry, gitk cannot run with this version of Tcl/Tk.\n"
 " Gitk requires at least Tcl/Tk 8.4."
@@ -684,35 +855,33 @@ msgstr ""
 "Gitk läuft nicht mit dieser Version von Tcl/Tk.\n"
 "Gitk benötigt mindestens Tcl/Tk 8.4."
 
-#: gitk:8501
+#: gitk:8566
 msgid "Cannot find a git repository here."
 msgstr "Kein Git-Projektarchiv gefunden."
 
-#: gitk:8505
+#: gitk:8570
 #, tcl-format
 msgid "Cannot find the git directory \"%s\"."
 msgstr "Git-Verzeichnis »%s« wurde nicht gefunden."
 
-#: gitk:8544
+#: gitk:8613
 #, tcl-format
 msgid "Ambiguous argument '%s': both revision and filename"
 msgstr "Mehrdeutige Angabe »%s«: Sowohl Version als auch Dateiname existiert."
 
-#: gitk:8556
+#: gitk:8625
 msgid "Bad arguments to gitk:"
 msgstr "Falsche Kommandozeilen-Parameter für gitk:"
 
-#: gitk:8568
+#: gitk:8637
 msgid "Couldn't get list of unmerged files:"
 msgstr "Liste der nicht-zusammengeführten Dateien nicht gefunden:"
 
-#: gitk:8584
+#: gitk:8653
 msgid "No files selected: --merge specified but no files are unmerged."
-msgstr ""
-"Keine Dateien ausgewähle: --merge angegeben, es existieren aber keine nicht-"
-"zusammengeführten Dateien."
+msgstr "Keine Dateien ausgewählt: --merge angegeben, es existieren aber keine nicht-zusammengeführten Dateien."
 
-#: gitk:8587
+#: gitk:8656
 msgid ""
 "No files selected: --merge specified but no unmerged files are within file "
 "limit."
@@ -720,6 +889,6 @@ msgstr ""
 "Keine Dateien ausgewähle: --merge angegeben, aber keine nicht-"
 "zusammengeführten Dateien sind in der Dateiauswahl."
 
-#: gitk:8646
+#: gitk:8717
 msgid "Command line"
 msgstr "Kommandozeile"
diff --git a/gitk-git/po/sv.po b/gitk-git/po/sv.po
new file mode 100644
index 0000000000..f6b080df4c
--- /dev/null
+++ b/gitk-git/po/sv.po
@@ -0,0 +1,887 @@
+# Swedish translation for gitk
+# Copyright (C) 2005-2008 Paul Mackerras
+# This file is distributed under the same license as the gitk package.
+#
+# Peter Karlsson <peter@softwolves.pp.se>, 2008.
+msgid ""
+msgstr ""
+"Project-Id-Version: sv\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2008-03-14 15:03+0100\n"
+"PO-Revision-Date: 2008-03-14 16:06CET-1\n"
+"Last-Translator: Peter Karlsson <peter@softwolves.pp.se>\n"
+"Language-Team: Swedish <sv@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit"
+
+#: gitk:111
+msgid "Error executing git rev-list:"
+msgstr "Fel vid körning av git rev-list:"
+
+#: gitk:124
+msgid "Reading"
+msgstr "Läser"
+
+#: gitk:151 gitk:2191
+msgid "Reading commits..."
+msgstr "Läser incheckningar..."
+
+#: gitk:275
+msgid "Can't parse git log output:"
+msgstr "Kan inte tolka utdata från git log:"
+
+#: gitk:386 gitk:2195
+msgid "No commits selected"
+msgstr "Inga incheckningar markerade"
+
+#: gitk:500
+msgid "No commit information available"
+msgstr "Ingen incheckningsinformation är tillgänglig"
+
+#: gitk:599 gitk:621 gitk:1955 gitk:6423 gitk:7923 gitk:8082
+msgid "OK"
+msgstr "OK"
+
+#: gitk:623 gitk:1956 gitk:6107 gitk:6178 gitk:6275 gitk:6321 gitk:6425
+#: gitk:7924 gitk:8083
+msgid "Cancel"
+msgstr "Avbryt"
+
+#: gitk:661
+msgid "File"
+msgstr "Arkiv"
+
+#: gitk:663
+msgid "Update"
+msgstr "Uppdatera"
+
+#: gitk:664
+msgid "Reread references"
+msgstr "Läs om referenser"
+
+#: gitk:665
+msgid "List references"
+msgstr "Visa referenser"
+
+#: gitk:666
+msgid "Quit"
+msgstr "Avsluta"
+
+#: gitk:668
+msgid "Edit"
+msgstr "Redigera"
+
+#: gitk:669
+msgid "Preferences"
+msgstr "Inställningar"
+
+#: gitk:672 gitk:1892
+msgid "View"
+msgstr "Visa"
+
+#: gitk:673
+msgid "New view..."
+msgstr "Ny vy..."
+
+#: gitk:674 gitk:2133 gitk:8722
+msgid "Edit view..."
+msgstr "Ändra vy..."
+
+#: gitk:676 gitk:2134 gitk:8723
+msgid "Delete view"
+msgstr "Ta bort vy"
+
+#: gitk:678
+msgid "All files"
+msgstr "Alla filer"
+
+#: gitk:682
+msgid "Help"
+msgstr "Hjälp"
+
+#: gitk:683 gitk:1317
+msgid "About gitk"
+msgstr "Om gitk"
+
+#: gitk:684
+msgid "Key bindings"
+msgstr "Tangentbordsbindningar"
+
+#: gitk:741
+msgid "SHA1 ID: "
+msgstr "SHA1-id: "
+
+#: gitk:791
+msgid "Find"
+msgstr "Sök"
+
+#: gitk:792
+msgid "next"
+msgstr "nästa"
+
+#: gitk:793
+msgid "prev"
+msgstr "föreg"
+
+#: gitk:794
+msgid "commit"
+msgstr "incheckning"
+
+#: gitk:797 gitk:799 gitk:2356 gitk:2379 gitk:2403 gitk:4306 gitk:4369
+msgid "containing:"
+msgstr "som innehåller:"
+
+#: gitk:800 gitk:1778 gitk:1783 gitk:2431
+msgid "touching paths:"
+msgstr "som rör sökväg:"
+
+#: gitk:801 gitk:2436
+msgid "adding/removing string:"
+msgstr "som lägger/till tar bort sträng:"
+
+#: gitk:810 gitk:812
+msgid "Exact"
+msgstr "Exakt"
+
+#: gitk:812 gitk:2514 gitk:4274
+msgid "IgnCase"
+msgstr "IgnVersaler"
+
+#: gitk:812 gitk:2405 gitk:2512 gitk:4270
+msgid "Regexp"
+msgstr "Reg.uttr."
+
+#: gitk:814 gitk:815 gitk:2533 gitk:2563 gitk:2570 gitk:4380 gitk:4436
+msgid "All fields"
+msgstr "Alla fält"
+
+#: gitk:815 gitk:2531 gitk:2563 gitk:4336
+msgid "Headline"
+msgstr "Rubrik"
+
+#: gitk:816 gitk:2531 gitk:4336 gitk:4436 gitk:4827
+msgid "Comments"
+msgstr "Kommentarer"
+
+#: gitk:816 gitk:2531 gitk:2535 gitk:2570 gitk:4336 gitk:4763 gitk:5956
+#: gitk:5971
+msgid "Author"
+msgstr "Författare"
+
+#: gitk:816 gitk:2531 gitk:4336 gitk:4765
+msgid "Committer"
+msgstr "Incheckare"
+
+#: gitk:845
+msgid "Search"
+msgstr "Sök"
+
+#: gitk:852
+msgid "Diff"
+msgstr "Diff"
+
+#: gitk:854
+msgid "Old version"
+msgstr "Gammal version"
+
+#: gitk:856
+msgid "New version"
+msgstr "Ny version"
+
+#: gitk:858
+msgid "Lines of context"
+msgstr "Rader sammanhang"
+
+#: gitk:868
+msgid "Ignore space change"
+msgstr "Ignorera ändringar i blanksteg"
+
+#: gitk:926
+msgid "Patch"
+msgstr "Patch"
+
+#: gitk:928
+msgid "Tree"
+msgstr "Träd"
+
+#: gitk:1053 gitk:1068 gitk:6022
+msgid "Diff this -> selected"
+msgstr "Diff denna -> markerad"
+
+#: gitk:1055 gitk:1070 gitk:6023
+msgid "Diff selected -> this"
+msgstr "Diff markerad -> denna"
+
+#: gitk:1057 gitk:1072 gitk:6024
+msgid "Make patch"
+msgstr "Skapa patch"
+
+#: gitk:1058 gitk:6162
+msgid "Create tag"
+msgstr "Skapa tagg"
+
+#: gitk:1059 gitk:6255
+msgid "Write commit to file"
+msgstr "Skriv incheckning till fil"
+
+#: gitk:1060 gitk:6309
+msgid "Create new branch"
+msgstr "Skapa ny gren"
+
+#: gitk:1061
+msgid "Cherry-pick this commit"
+msgstr "Plocka denna incheckning"
+
+#: gitk:1063
+msgid "Reset HEAD branch to here"
+msgstr "Återställ HEAD-grenen hit"
+
+#: gitk:1079
+msgid "Check out this branch"
+msgstr "Checka ut denna gren"
+
+#: gitk:1081
+msgid "Remove this branch"
+msgstr "Ta bort denna gren"
+
+#: gitk:1087
+msgid "Highlight this too"
+msgstr "Markera även detta"
+
+#: gitk:1089
+msgid "Highlight this only"
+msgstr "Markera bara detta"
+
+#: gitk:1318
+msgid ""
+"\n"
+"Gitk - a commit viewer for git\n"
+"\n"
+"Copyright © 2005-2006 Paul Mackerras\n"
+"\n"
+"Use and redistribute under the terms of the GNU General Public License"
+msgstr ""
+"\n"
+"Gitk - en incheckningsvisare för git\n"
+"\n"
+"Copyright © 2005-2006 Paul Mackerras\n"
+"\n"
+"Använd och vidareförmedla enligt villkoren i GNU General Public License"
+
+#: gitk:1326 gitk:1387 gitk:6581
+msgid "Close"
+msgstr "Stäng"
+
+#: gitk:1345
+msgid "Gitk key bindings"
+msgstr "Tangentbordsbindningar för Gitk"
+
+#: gitk:1347
+msgid "Gitk key bindings:"
+msgstr "Tangentbordsbindningar för Gitk:"
+
+#: gitk:1349
+#, tcl-format
+msgid "<%s-Q>\t\tQuit"
+msgstr "<%s-Q>\t\tAvsluta"
+
+#: gitk:1350
+msgid "<Home>\t\tMove to first commit"
+msgstr "<Home>\t\tGå till första incheckning"
+
+#: gitk:1351
+msgid "<End>\t\tMove to last commit"
+msgstr "<End>\t\tGå till sista incheckning"
+
+#: gitk:1352
+msgid "<Up>, p, i\tMove up one commit"
+msgstr "<Upp>, p, i\tGå en incheckning upp"
+
+#: gitk:1353
+msgid "<Down>, n, k\tMove down one commit"
+msgstr "<Ned>, n, k\tGå en incheckning ned"
+
+#: gitk:1354
+msgid "<Left>, z, j\tGo back in history list"
+msgstr "<Vänster>, z, j\tGå bakåt i historiken"
+
+#: gitk:1355
+msgid "<Right>, x, l\tGo forward in history list"
+msgstr "<Höger>, x, l\tGå framåt i historiken"
+
+#: gitk:1356
+msgid "<PageUp>\tMove up one page in commit list"
+msgstr "<PageUp>\tGå upp en sida i incheckningslistan"
+
+#: gitk:1357
+msgid "<PageDown>\tMove down one page in commit list"
+msgstr "<PageDown>\tGå ned en sida i incheckningslistan"
+
+#: gitk:1358
+#, tcl-format
+msgid "<%s-Home>\tScroll to top of commit list"
+msgstr "<%s-Home>\tRulla till början av incheckningslistan"
+
+#: gitk:1359
+#, tcl-format
+msgid "<%s-End>\tScroll to bottom of commit list"
+msgstr "<%s-End>\tRulla till slutet av incheckningslistan"
+
+#: gitk:1360
+#, tcl-format
+msgid "<%s-Up>\tScroll commit list up one line"
+msgstr "<%s-Upp>\tRulla incheckningslistan upp ett steg"
+
+#: gitk:1361
+#, tcl-format
+msgid "<%s-Down>\tScroll commit list down one line"
+msgstr "<%s-Ned>\tRulla incheckningslistan ned ett steg"
+
+#: gitk:1362
+#, tcl-format
+msgid "<%s-PageUp>\tScroll commit list up one page"
+msgstr "<%s-PageUp>\tRulla incheckningslistan upp en sida"
+
+#: gitk:1363
+#, tcl-format
+msgid "<%s-PageDown>\tScroll commit list down one page"
+msgstr "<%s-PageDown>\tRulla incheckningslistan ned en sida"
+
+#: gitk:1364
+msgid "<Shift-Up>\tFind backwards (upwards, later commits)"
+msgstr "<Skift-Upp>\tSök bakåt (uppåt, senare incheckningar)"
+
+#: gitk:1365
+msgid "<Shift-Down>\tFind forwards (downwards, earlier commits)"
+msgstr "<Skift-Ned>\tSök framåt (nedåt, tidigare incheckningar)"
+
+#: gitk:1366
+msgid "<Delete>, b\tScroll diff view up one page"
+msgstr "<Delete>, b\tRulla diffvisningen upp en sida"
+
+#: gitk:1367
+msgid "<Backspace>\tScroll diff view up one page"
+msgstr "<Baksteg>\tRulla diffvisningen upp en sida"
+
+#: gitk:1368
+msgid "<Space>\t\tScroll diff view down one page"
+msgstr "<Blanksteg>\tRulla diffvisningen ned en sida"
+
+#: gitk:1369
+msgid "u\t\tScroll diff view up 18 lines"
+msgstr "u\t\tRulla diffvisningen upp 18 rader"
+
+#: gitk:1370
+msgid "d\t\tScroll diff view down 18 lines"
+msgstr "d\t\tRulla diffvisningen ned 18 rader"
+
+#: gitk:1371
+#, tcl-format
+msgid "<%s-F>\t\tFind"
+msgstr "<%s-F>\t\tSök"
+
+#: gitk:1372
+#, tcl-format
+msgid "<%s-G>\t\tMove to next find hit"
+msgstr "<%s-G>\t\tGå till nästa sökträff"
+
+#: gitk:1373
+msgid "<Return>\tMove to next find hit"
+msgstr "<Return>\t\tGå till nästa sökträff"
+
+#: gitk:1374
+msgid "/\t\tMove to next find hit, or redo find"
+msgstr "/\t\tGå till nästa sökträff, eller sök på nytt"
+
+#: gitk:1375
+msgid "?\t\tMove to previous find hit"
+msgstr "?\t\tGå till föregående sökträff"
+
+#: gitk:1376
+msgid "f\t\tScroll diff view to next file"
+msgstr "f\t\tRulla diffvisningen till nästa fil"
+
+#: gitk:1377
+#, tcl-format
+msgid "<%s-S>\t\tSearch for next hit in diff view"
+msgstr "<%s-S>\t\tGå till nästa sökträff i diffvisningen"
+
+#: gitk:1378
+#, tcl-format
+msgid "<%s-R>\t\tSearch for previous hit in diff view"
+msgstr "<%s-R>\t\tGå till föregående sökträff i diffvisningen"
+
+#: gitk:1379
+#, tcl-format
+msgid "<%s-KP+>\tIncrease font size"
+msgstr "<%s-Num+>\tÖka teckenstorlek"
+
+#: gitk:1380
+#, tcl-format
+msgid "<%s-plus>\tIncrease font size"
+msgstr "<%s-plus>\tÖka teckenstorlek"
+
+#: gitk:1381
+#, tcl-format
+msgid "<%s-KP->\tDecrease font size"
+msgstr "<%s-Num->\tMinska teckenstorlek"
+
+#: gitk:1382
+#, tcl-format
+msgid "<%s-minus>\tDecrease font size"
+msgstr "<%s-minus>\tMinska teckenstorlek"
+
+#: gitk:1383
+msgid "<F5>\t\tUpdate"
+msgstr "<F5>\t\tUppdatera"
+
+#: gitk:1896
+msgid "Gitk view definition"
+msgstr "Definition av Gitk-vy"
+
+#: gitk:1921
+msgid "Name"
+msgstr "Namn"
+
+#: gitk:1924
+msgid "Remember this view"
+msgstr "Spara denna vy"
+
+#: gitk:1928
+msgid "Commits to include (arguments to git rev-list):"
+msgstr "Incheckningar att ta med (argument till git rev-list):"
+
+#: gitk:1935
+msgid "Command to generate more commits to include:"
+msgstr "Kommando för att generera fler incheckningar att ta med:"
+
+#: gitk:1942
+msgid "Enter files and directories to include, one per line:"
+msgstr "Ange filer och kataloger att ta med, en per rad:"
+
+#: gitk:1989
+msgid "Error in commit selection arguments:"
+msgstr "Fel i argument för val av incheckningar:"
+
+#: gitk:2043 gitk:2127 gitk:2583 gitk:2597 gitk:3781 gitk:8688 gitk:8689
+msgid "None"
+msgstr "Inget"
+
+#: gitk:2531 gitk:4336 gitk:5958 gitk:5973
+msgid "Date"
+msgstr "Datum"
+
+#: gitk:2531 gitk:4336
+msgid "CDate"
+msgstr "Skapat datum"
+
+#: gitk:2680 gitk:2685
+msgid "Descendant"
+msgstr "Avkomling"
+
+#: gitk:2681
+msgid "Not descendant"
+msgstr "Inte avkomling"
+
+#: gitk:2688 gitk:2693
+msgid "Ancestor"
+msgstr "Förfader"
+
+#: gitk:2689
+msgid "Not ancestor"
+msgstr "Inte förfader"
+
+#: gitk:2924
+msgid "Local changes checked in to index but not committed"
+msgstr "Lokala ändringar sparade i indexet men inte incheckade"
+
+#: gitk:2954
+msgid "Local uncommitted changes, not checked in to index"
+msgstr "Lokala ändringar, ej sparade i indexet"
+
+#: gitk:4305
+msgid "Searching"
+msgstr "Söker"
+
+#: gitk:4767
+msgid "Tags:"
+msgstr "Taggar:"
+
+#: gitk:4784 gitk:4790 gitk:5951
+msgid "Parent"
+msgstr "Förälder"
+
+#: gitk:4795
+msgid "Child"
+msgstr "Barn"
+
+#: gitk:4804
+msgid "Branch"
+msgstr "Gren"
+
+#: gitk:4807
+msgid "Follows"
+msgstr "Följer"
+
+#: gitk:4810
+msgid "Precedes"
+msgstr "Föregår"
+
+#: gitk:5093
+msgid "Error getting merge diffs:"
+msgstr "Fel vid hämtning av sammanslagningsdiff:"
+
+#: gitk:5778
+msgid "Goto:"
+msgstr "Gå till:"
+
+#: gitk:5780
+msgid "SHA1 ID:"
+msgstr "SHA1-id:"
+
+#: gitk:5805
+#, tcl-format
+msgid "Short SHA1 id %s is ambiguous"
+msgstr "Förkortat SHA1-id %s är tvetydigt"
+
+#: gitk:5817
+#, tcl-format
+msgid "SHA1 id %s is not known"
+msgstr "SHA-id:t %s är inte känt"
+
+#: gitk:5819
+#, tcl-format
+msgid "Tag/Head %s is not known"
+msgstr "Tagg/huvud %s är okänt"
+
+#: gitk:5961
+msgid "Children"
+msgstr "Barn"
+
+#: gitk:6018
+#, tcl-format
+msgid "Reset %s branch to here"
+msgstr "Återställ grenen %s hit"
+
+#: gitk:6049
+msgid "Top"
+msgstr "Topp"
+
+#: gitk:6050
+msgid "From"
+msgstr "Från"
+
+#: gitk:6055
+msgid "To"
+msgstr "Till"
+
+#: gitk:6078
+msgid "Generate patch"
+msgstr "Generera patch"
+
+#: gitk:6080
+msgid "From:"
+msgstr "Från:"
+
+#: gitk:6089
+msgid "To:"
+msgstr "Till:"
+
+#: gitk:6098
+msgid "Reverse"
+msgstr "Vänd"
+
+#: gitk:6100 gitk:6269
+msgid "Output file:"
+msgstr "Utdatafil:"
+
+#: gitk:6106
+msgid "Generate"
+msgstr "Generera"
+
+#: gitk:6142
+msgid "Error creating patch:"
+msgstr "Fel vid generering av patch:"
+
+#: gitk:6164 gitk:6257 gitk:6311
+msgid "ID:"
+msgstr "Id:"
+
+#: gitk:6173
+msgid "Tag name:"
+msgstr "Taggnamn:"
+
+#: gitk:6177 gitk:6320
+msgid "Create"
+msgstr "Skapa"
+
+#: gitk:6192
+msgid "No tag name specified"
+msgstr "Inget taggnamn angavs"
+
+#: gitk:6196
+#, tcl-format
+msgid "Tag \"%s\" already exists"
+msgstr "Taggen \"%s\" finns redan"
+
+#: gitk:6202
+msgid "Error creating tag:"
+msgstr "Fel vid skapande av tagg:"
+
+#: gitk:6266
+msgid "Command:"
+msgstr "Kommando:"
+
+#: gitk:6274
+msgid "Write"
+msgstr "Skriv"
+
+#: gitk:6290
+msgid "Error writing commit:"
+msgstr "Fel vid skrivning av incheckning:"
+
+#: gitk:6316
+msgid "Name:"
+msgstr "Namn:"
+
+#: gitk:6335
+msgid "Please specify a name for the new branch"
+msgstr "Ange ett namn för den nya grenen"
+
+#: gitk:6364
+#, tcl-format
+msgid "Commit %s is already included in branch %s -- really re-apply it?"
+msgstr "Incheckningen %s finns redan på grenen %s -- skall den verkligen appliceras på nytt?"
+
+#: gitk:6369
+msgid "Cherry-picking"
+msgstr "Plockar"
+
+#: gitk:6381
+msgid "No changes committed"
+msgstr "Inga ändringar incheckade"
+
+#: gitk:6404
+msgid "Confirm reset"
+msgstr "Bekräfta återställning"
+
+#: gitk:6406
+#, tcl-format
+msgid "Reset branch %s to %s?"
+msgstr "Återställa grenen %s till %s?"
+
+#: gitk:6410
+msgid "Reset type:"
+msgstr "Typ av återställning:"
+
+#: gitk:6414
+msgid "Soft: Leave working tree and index untouched"
+msgstr "Mjuk: Rör inte utcheckning och index"
+
+#: gitk:6417
+msgid "Mixed: Leave working tree untouched, reset index"
+msgstr "Blandad: Rör inte utcheckning, återställ index"
+
+#: gitk:6420
+msgid ""
+"Hard: Reset working tree and index\n"
+"(discard ALL local changes)"
+msgstr ""
+"Hård: Återställ utcheckning och index\n"
+"(förkastar ALLA lokala ändringar)"
+
+#: gitk:6436
+msgid "Resetting"
+msgstr "Återställer"
+
+#: gitk:6493
+msgid "Checking out"
+msgstr "Checkar ut"
+
+#: gitk:6523
+msgid "Cannot delete the currently checked-out branch"
+msgstr "Kan inte ta bort den just nu utcheckade grenen"
+
+#: gitk:6529
+#, tcl-format
+msgid ""
+"The commits on branch %s aren't on any other branch.\n"
+"Really delete branch %s?"
+msgstr ""
+"Incheckningarna på grenen %s existerar inte på någon annan gren.\n"
+"Vill du verkligen ta bort grenen %s?"
+
+#: gitk:6560
+#, tcl-format
+msgid "Tags and heads: %s"
+msgstr "Taggar och huvuden: %s"
+
+#: gitk:6574
+msgid "Filter"
+msgstr "Filter"
+
+#: gitk:6868
+msgid ""
+"Error reading commit topology information; branch and preceding/following "
+"tag information will be incomplete."
+msgstr ""
+"Fel vid läsning av information om incheckningstopologi; information om "
+"grenar och föregående/senare taggar kommer inte vara komplett."
+
+#: gitk:7852
+msgid "Tag"
+msgstr "Tagg"
+
+#: gitk:7852
+msgid "Id"
+msgstr "Id"
+
+#: gitk:7892
+msgid "Gitk font chooser"
+msgstr "Teckensnittsväljare för Gitk"
+
+#: gitk:7909
+msgid "B"
+msgstr "F"
+
+#: gitk:7912
+msgid "I"
+msgstr "K"
+
+#: gitk:8005
+msgid "Gitk preferences"
+msgstr "Inställningar för Gitk"
+
+#: gitk:8006
+msgid "Commit list display options"
+msgstr "Alternativ för incheckningslistvy"
+
+#: gitk:8009
+msgid "Maximum graph width (lines)"
+msgstr "Maximal grafbredd (rader)"
+
+#: gitk:8013
+#, tcl-format
+msgid "Maximum graph width (% of pane)"
+msgstr "Maximal grafbredd (% av ruta)"
+
+#: gitk:8018
+msgid "Show local changes"
+msgstr "Visa lokala ändringar"
+
+#: gitk:8023
+msgid "Auto-select SHA1"
+msgstr "Välj SHA1 automatiskt"
+
+#: gitk:8028
+msgid "Diff display options"
+msgstr "Alternativ för diffvy"
+
+#: gitk:8030
+msgid "Tab spacing"
+msgstr "Blanksteg för tabulatortecken"
+
+#: gitk:8034
+msgid "Display nearby tags"
+msgstr "Visa närliggande taggar"
+
+#: gitk:8039
+msgid "Limit diffs to listed paths"
+msgstr "Begränsa diff till listade sökvägar"
+
+#: gitk:8044
+msgid "Colors: press to choose"
+msgstr "Färger: tryck för att välja"
+
+#: gitk:8047
+msgid "Background"
+msgstr "Bakgrund"
+
+#: gitk:8051
+msgid "Foreground"
+msgstr "Förgrund"
+
+#: gitk:8055
+msgid "Diff: old lines"
+msgstr "Diff: gamla rader"
+
+#: gitk:8060
+msgid "Diff: new lines"
+msgstr "Diff: nya rader"
+
+#: gitk:8065
+msgid "Diff: hunk header"
+msgstr "Diff: delhuvud"
+
+#: gitk:8071
+msgid "Select bg"
+msgstr "Markerad bakgrund"
+
+#: gitk:8075
+msgid "Fonts: press to choose"
+msgstr "Teckensnitt: tryck för att välja"
+
+#: gitk:8077
+msgid "Main font"
+msgstr "Huvudteckensnitt"
+
+#: gitk:8078
+msgid "Diff display font"
+msgstr "Teckensnitt för diffvisning"
+
+#: gitk:8079
+msgid "User interface font"
+msgstr "Teckensnitt för användargränssnitt"
+
+#: gitk:8095
+#, tcl-format
+msgid "Gitk: choose color for %s"
+msgstr "Gitk: välj färg för %s"
+
+#: gitk:8476
+msgid ""
+"Sorry, gitk cannot run with this version of Tcl/Tk.\n"
+" Gitk requires at least Tcl/Tk 8.4."
+msgstr ""
+"Gitk kan tyvärr inte köra med denna version av Tcl/Tk.\n"
+" Gitk kräver åtminstone Tcl/Tk 8.4."
+
+#: gitk:8565
+msgid "Cannot find a git repository here."
+msgstr "Hittar inget gitk-arkiv här."
+
+#: gitk:8569
+#, tcl-format
+msgid "Cannot find the git directory \"%s\"."
+msgstr "Hittar inte git-katalogen \"%s\"."
+
+#: gitk:8612
+#, tcl-format
+msgid "Ambiguous argument '%s': both revision and filename"
+msgstr "Tvetydigt argument \"%s\": både revision och filnamn"
+
+#: gitk:8624
+msgid "Bad arguments to gitk:"
+msgstr "Felaktiga argument till gitk:"
+
+#: gitk:8636
+msgid "Couldn't get list of unmerged files:"
+msgstr "Kunde inta hämta lista över ej sammanslagna filer:"
+
+#: gitk:8652
+msgid "No files selected: --merge specified but no files are unmerged."
+msgstr "Inga filer valdes: --merge angavs men det finns inga filer som inte har slagits samman."
+
+#: gitk:8655
+msgid ""
+"No files selected: --merge specified but no unmerged files are within file "
+"limit."
+msgstr ""
+"Inga filer valdes: --merge angavs men det finns inga filer inom "
+"filbegränsningen."
+
+#: gitk:8716
+msgid "Command line"
+msgstr "Kommandorad"
+