gitpython и git diff

Я хочу получить только разницу файла, измененного из репозитория git. Прямо сейчас я использую gitpython для фактического получения объектов фиксации и файлов изменений git, но я хочу провести анализ зависимостей только для измененных частей файла. Есть ли способ получить git diff от git python? Или мне придется сравнивать каждый из файлов, читая строку за строкой?


person user1816561    schedule 19.11.2013    source источник


Ответы (6)


Вы можете использовать GitPython с командой git «diff», просто нужно использовать объект «дерево» каждой фиксации или ветки, для которой вы хотите увидеть различия, например:

repo = Repo('/git/repository')
t = repo.head.commit.tree
repo.git.diff(t)

Это напечатает «все» различия для всех файлов, включенных в эту фиксацию, поэтому, если вы хотите каждый из них, вы должны перебирать их.

С фактической веткой это:

repo.git.diff('HEAD~1')

Надеюсь, что это поможет, с уважением.

person Cairo    schedule 27.04.2014
comment
Как узнать diff между tree и head~1. У них есть сходство, но у последнего больше различий. Кажется, что последний включает разницу с последним коммитом. - person Timo; 17.07.2021

Если вы хотите получить доступ к содержимому diff, попробуйте следующее:

repo = git.Repo(repo_root.as_posix())
commit_dev = repo.commit("dev")
commit_origin_dev = repo.commit("origin/dev")
diff_index = commit_origin_dev.diff(commit_dev)

for diff_item in diff_index.iter_change_type('M'):
    print("A blob:\n{}".format(diff_item.a_blob.data_stream.read().decode('utf-8')))
    print("B blob:\n{}".format(diff_item.b_blob.data_stream.read().decode('utf-8'))) 

Это распечатает содержимое каждого файла.

person D. A.    schedule 01.09.2017
comment
Превосходно. Это способ сделать это с помощью GitPython API, а не напрямую делегировать Git CLI, как это делает Cairo answer. - person Michael; 12.12.2018

Как вы заметили, Git не хранит различия. Имея два больших двоичных объекта (до и после изменения), вы можете использовать модуль Python difflib. для сравнения данных.

person Greg Hewgill    schedule 19.11.2013
comment
Репозиторий, над которым я работаю, имеет только одну основную ветку. Если я пытаюсь получить два больших двоичных объекта, как мне получить второй для сравнения с предыдущим изменением? - person user1816561; 19.11.2013
comment
Извините, еще вопрос. Таким образом, помимо попыток получить как a blob, так и b blob и понять, что это такое, действительно ли эти blob дадут мне измененное содержимое файла? - person user1816561; 19.11.2013
comment
@user1816561 user1816561, если вы имеете в виду два больших двоичных объекта, как в diff вашего рабочего дерева, по сравнению с самой последней фиксацией, вы должны использовать repo.head.commit.diff(None) - person Addison Klinke; 25.02.2021
comment
Это python3 версия ссылки. - person Timo; 17.07.2021

Вместо этого я предлагаю вам использовать PyDriller (внутренне использует GitPython) . Гораздо проще в использовании:

for commit in RepositoryMining("path_to_repo").traverse_commits():
    for modified_file in commit.modifications: # here you have the list of modified files
        print(modified_file.diff)
        # etc...

Вы также можете проанализировать один коммит, выполнив:

for commit in RepositoryMining("path_to_repo", single="123213")
person Davide Spadini    schedule 08.02.2019

Если вы хотите выполнить git diff для файла между двумя фиксациями, это можно сделать следующим образом:

import git

repo = git.Repo()
path_to_a_file = "diff_this_file_across_commits.txt"

commits_touching_path = list(repo.iter_commits(paths=path))

print repo.git.diff(commits_touching_path[0], commits_touching_path[1], path_to_a_file)

Это покажет вам различия между двумя последними коммитами, которые были сделаны для указанного вами файла.

Надеюсь, это помогло.

person Nikola Đuza    schedule 13.09.2016

Я не уверен, что вы получили то, что искали!

Вот как вы это делаете

import git
repo = git.Repo("path/of/repo/")

# the below gives us all commits
repo.commits()

# take the first and last commit

a_commit = repo.commits()[0]
b_commit = repo.commits()[1]

# now get the diff
repo.diff(a_commit,b_commit)

Ваше здоровье.

person Ciasto piekarz    schedule 07.03.2014
comment
Этот код не работает. AttributeError: 'Repo' object has no attribute 'diff' и AttributeError: 'Repo' object has no attribute 'commits' - person firelynx; 16.08.2018