The "Show origin of this line" context menu command on a line in a patch in gitk is by far my most frequently used way of navigating back in history. It's so much faster than git gui blame. Now, I wish it were available right from my text editor, showing me the origin of the line under the cursor when working with code. In fact, it is; I have been using this feature in a roughly hacked way for a couple of months now, and I don't want to miss it any more. Most of my co-workers are jealous when they see it. I'd like to get it into gitk for real now, and I need some guidance on the best way to implement it. I can see two ways: 1) Add an option like '--show-origin=foo.cpp:25'. This would run "git blame" on the given line in the working copy, and highlight the result. 2) Add an option like '--select-file=foo.cpp:25'. This would be used in combination with the existing --select-commit option to simply highlight a given line in the patch (so the caller needs to do the initial git blame himself). There are pros and cons to both. 1) is certainly easier to use from a text editor scripter's point of view (a simple one-liner in most cases), whereas 2) probably needs a glue script to run the initial git blame. On the other hand, that glue script could also take care of restricting the history to a week or so forward from the target commit, which makes gitk load much faster. Also, 2) could be used from git gui blame's "Show history context" command, which currently only selects the commit but can't highlight the line. So I think I'd lean towards option 2). Below is the prototype that I have been using; not sure how buggy it is. If we go this route, one question would be whether we want to ship the glue script too, and how. Any opinions? -Stefan >From 80acb168ef13a55521e9b821450800450660769d Mon Sep 17 00:00:00 2001 From: Stefan Haller <stefan@xxxxxxxxxxxxxxxx> Date: Thu, 18 Jul 2013 18:55:11 +0200 Subject: [PATCH] gitk: Add options --select-file and --select-line These can be used in combination with --select-commit to jump to a given line in a patch. This can be useful for scripting your text editor to bring up gitk showing you the place in the history that last modified the line you are on. For example, given this little glue script, saved as "show_line_in_gitk.rb" somewhere in your path: #!/usr/bin/env ruby if ARGV.length != 2 puts "Usage: #{$0} <file> <line>" exit 1 end file, line = ARGV blame_output = `git blame -p -L#{line},+1 "#{file}"` exit 1 if $?.exitstatus != 0 blame_output_lines = blame_output.split("\n") commit, line = blame_output_lines[0].split file = blame_output_lines.grep(/^filename /)[0][9..-1] date = blame_output_lines.grep(/^committer-time /)[0][15..-1] datestr = Time.at(date.to_i + 60 * 60 * 24 * 7).to_s system "gitk --before='#{datestr}' \ --select-commit=#{commit} \ --select-file='#{file}' \ --select-line=#{line} &" you could add this function to your .vimrc: function! ShowLineInGitk() execute "!show_line_in_gitk.rb " . expand("%p") . " " . line(".") endfunction and map it to a key. --- gitk | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/gitk b/gitk index 5cd00d8..318a484 100755 --- a/gitk +++ b/gitk @@ -464,12 +464,17 @@ proc stop_rev_list {view} { } proc reset_pending_select {selid} { - global pending_select mainheadid selectheadid + global pending_select pending_select_file pending_select_line + global mainheadid selectheadid selectfile select_line if {$selid ne {}} { set pending_select $selid } elseif {$selectheadid ne {}} { set pending_select $selectheadid + if {$selectfile ne {}} { + set pending_select_file $selectfile + set pending_select_line $select_line + } } else { set pending_select $mainheadid } @@ -1597,6 +1602,17 @@ proc getcommitlines {fd inst view updating} { return 2 } +proc select_pending_line {} { + global pending_select pending_select_file pending_select_line + + if {[info exists pending_select_file]} { + selectline [rowofcommit $pending_select] 1 \ + [list $pending_select_file $pending_select_line] + } else { + selectline [rowofcommit $pending_select] 1 + } +} + proc chewcommits {} { global curview hlview viewcomplete global pending_select @@ -1611,7 +1627,7 @@ proc chewcommits {} { reset_pending_select {} if {[commitinview $pending_select $curview]} { - selectline [rowofcommit $pending_select] 1 + select_pending_line } else { set row [first_real_row] selectline $row 1 @@ -5083,7 +5099,7 @@ proc layoutmore {} { if {[info exists pending_select] && [commitinview $pending_select $curview]} { update - selectline [rowofcommit $pending_select] 1 + select_pending_line } drawvisible } @@ -7082,6 +7098,8 @@ proc selectline {l isnew {desired_loc {}}} { global autoselect autosellen jump_to_here catch {unset pending_select} + catch {unset pending_select_file} + catch {unset pending_select_line} $canv delete hover normalline unsel_reflist @@ -11940,6 +11958,8 @@ if {[catch {set gitdir [exec git rev-parse --git-dir]}]} { set selecthead {} set selectheadid {} +set selectfile {} +set select_line {} set revtreeargs {} set cmdline_files {} @@ -11955,6 +11975,12 @@ foreach arg $argv { "--select-commit=*" { set selecthead [string range $arg 16 end] } + "--select-file=*" { + set selectfile [string range $arg 14 end] + } + "--select-line=*" { + set select_line [string range $arg 14 end] + } "--argscmd=*" { set revtreeargscmd [string range $arg 10 end] } -- 1.8.3.2.747.g15edaa9 -- Stefan Haller Berlin, Germany http://www.haller-berlin.de/ -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html