views:

117

answers:

2

I'm about to move a ton of files around in an existing project. Before I do this, I'd like to have a firm grasp on some techniques used to analyze code that has a multi-file history.

How can I use git to ask: "where did this line of code come from?" when the content has moved through multiple files in it's life time?

I know git doesn't track renames explicitly (for good reason) so it seems like I should be able to ask this, I'm just not sure how. If there are method's to visualize this that'd be great to know too.

+1  A: 

git blame is what you would use to ask "where did this line of code come from?". I don't know if it handles renames. Probably does.

Nicolás
git blame isn't good for detecting line moves (especially when refactoring the code). I mean if one dev wrote the line, then next dev moved the line up or down for some reason - git blame will show the latter.
Eimantas
+2  A: 

I would recommend looking at three tools in the git toolbox. The first one is blame, which is very much the same as it is in cvs. It shows you which commit last touched each line in a file. If you want to look see what was there before, you can take the commit that touched the line and look at the previous commit.

git show <sha1_of_interesting_commit>^ -- file/path

You can repeat the blame to see what happened before that.

git blame <sha1_of_interesting_commit>^ -- file/path

The second tool is using --follow to track files past renames.

git log --follow -- file/path

The third - and possibly the most useful tool - is the pickaxe option to log. This searches history for changes the removed, introduced or changed lines that include a given bit of text. This is especially useful for tracking things like function names. It may be new in a file in a particular commit, but did it come from a different source file? Was a call to it added at the same time, or before it moved?

git log -S"Interesting_Function"

If you are using a patch or stat option (e.g. -p or --stat) the output will be restricted to those files whose changes actually involved the search string unless you also use --pickaxe-all where the whole change is displayed.

Combined with git grep to show where all the current occurrences of a string are, pickaxe is an extremely useful history mining tool.

Charles Bailey