Search code examples
gitversion-controlgit-blame

How to copy lines by preserving authors


I have a file with a lot of lines and want to refactor it, by splitting it across multiple files. By simply copy/pasting I will loose history of committed lines and their authors when git blameing. Is there any way to copy/paste those lines and preserve their authors?


Solution

  • Git does not record the author (or committer) of a specific line of code.

    What Git does—all that it does—is record a complete snapshot, paired with a set of metadata: author name/email/date, committer name/email/date, parent commit.

    Various tools, such as git log, git show, git diff, and git annotate (or git blame), use the recorded data in various ways. The git blame code in particular will compare each commit against its parent. If some line(s) were added or changed in this particular commit, it will assign the commit's author to the entire line(s) and report the result.

    This means it's easy to get the tool to assign some particular set of changed line(s) to some particular author: make a commit with that name set as the author.

    This also means it's easy to accidentally change every line of a file (e.g., by changing line-terminator characters from LF-only to CRLF or vice versa) and "acquire authorship" of every line of that file. But all this means is that when you are using git blame, you need to know how to work the tool: you need to be aware of its limitations.

    Some—I include myself in this group—would argue that if you move code around for refactoring, you should "take ownership" of the moved lines. The original author may have written the original code, but not in that form. The line for i in expr, for instance, means something very different in two different functions and/or files. If you move a big enough chunk, maybe the code retains its "real meaning", and ... maybe not. Git will keep the original author of the original lines in their original place, and anyone who understands git blame will not just look at the new refactored code, but continue to follow the code back through history to find its original author, pre-refactor.

    Still, if you want to split "author" and "committer", Git gives you a (per-commit) way to do that.