Friday, July 24, 2009

Git grep and navigate

I use Eclipse for my java project work. It has a decent search, but it is not all that fast, however what it does do is let you see what files have the search string and click on a list to get to a file of interest. I don't like using the mouse, but I need to be able to search for various strings and then view them in context to navigate the code.

Enter git grep. Git grep turns out to be a much faster alternative than even grep. What is nice about git grep is that it avoids searching through any non-git files (like the .git subdirectory). Also it is 10% faster than regular grep because if the way git compresses files. The uncompression and reading of the git files is actually faster than opening every file inode, so it can get that speedup. The problem with a simple grep is that after greping, typically you need to look at the context of the line. Grep has options for adding a few context lines, but I might need 10 lines of context for some specific lines and that can get hard to read. However, if I could use some curses interface to explore the files then it would be ok.

Enter vim. I found that Vim has a way of exploring a filename with a specified line number by typing gF (woohoo). So I tried

git grep -n "somesearchstring" > output.txt
vim output.txt

the -n on grep gives you the line numbers. I would rather have this as one-line command. So I tried

git grep -n "somesearchstring" | vim -

This bring up the grep list, but when you hit gF to go to a particular file vim wants you to save the file first, which is lame because these are just temporary files, I'm only using them for the moment.

So I wrote this alias for doing what I want

alias z="tee /tmp/blah; vim /tmp/blah"

This will save the output to a tmp file and open that tmp file.

So finally, my command is now

git grep -n "somesearchstring" | z

and up pops my vim editor where I can go to each file line of interest with gF and come back with ctrl-o. By the time Eclipse finishes it's search, I can already have found what I want on the command line, and no mousing.

Note: this can be further simplified by a bash function in your .bashrc

function gg { git grep -n '$1' | z; };

so that it becomes

gg "somesearchstring"


Bart Trojanowski said...

I love 'git grep' and I love using it from vim. But I prefer to use the :GitGrep command.

Check out my patches to git-vim on github...

Some of the cooler uses:

:git grep foo
... will open a quick fix window with the search results

,gg (in normal mode)
... will use the current search string and run :git grep on it. I often use it right after *, that is *,gg to do a git grep on the work under the cursor.

rado said...

Thanks Bart, the git-vim plugin works well for me.