How to use git blame in GitPython?

Question:

I’m trying to use the GitPython module in my script… and I can’t. That’s not very documented : GitPython Blame

I think I’m not so far, because the normally git blame I want to reproduce is the follow : git blame -L127,+1 ../../core/src/filepath.cpp -e

Here is my script :

from git import *
    repo = Repo("C:\Path\to\my\repos\")
    assert not repo.bare
    # log_line = open("lineDeb.txt")
    # for line in log_line:
    repo.git.blame(L='127,+1' '../../core/src/filepath.cpp', e=True)

The two lines commented are for the final goal to git blame on each number line in my "lineDeb.txt" file.

I’ve the following ouput :

...
git.exc.GitCommandError: 'git blame -L127,+1../../core/src/filepath.cpp -e' returned with exit code 129
stderr: 'usage: git blame [options] [rev-opts] [rev] [--] file
...

The goal is to get the email of the line committer…

Asked By: Algorys

||

Answers:

for commit, lines in repo.blame('HEAD', filepath):
    print("%s changed these lines: %s" % (commit, lines))

The commit is the one that changed the given lines, in order of appearance in the file. Thus, if your would write all lines into a file, your would have the file at filepath at revision HEAD.

If you are looking for only a specific line, and as there are no options that you could currently pass to the blame subcommand, you would have to count to the line yourself.

ln = 127 # lines start at 0 here
tlc = 0

for commit, lines in repo.blame('HEAD', filepath):
    if tlc <= ln < (tlc + len(lines)):
         print(commit)
    tlc += len(lines)

This is less optimal than passing the respective -L option to git blame, but should do the job.

If it turns out to be too slow, you could consider making a PR that adds **kwargs to Repo.blame to pass on to git blame.

Answered By: Byron

If you’re blaming a large number of lines you might find this higher performance:

blame = []
cmd = 'cd {path};git blame {fname}'.format(
            path=repo_path,
            fname=rootpath + fname)
with os.popen(cmd) as process:
   blame = process.readlines()

print blame[line_number]
Answered By: user3323999
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.