现在,我可以使用pygit2库遍历github存储库的提交树。我收到了存储库中每个文件更改的所有提交。这意味着我正在对存储库中扩展名为.rtf的文本文件进行更改。如何过滤掉仅与代码更改相关的提交?我不希望这些更改与文本文档有关。
感谢任何帮助或指示。感谢。
last = repo[repo.head.target]
t0=last
f = open(outputFile,'w')
print t0.hex
for commit in repo.walk(last.id):
if t0.hex == commit.hex:
continue
print commit.hex
out=repo.diff(t0,commit)
f.write(out.patch)
t0=commit;
作为输出的一部分,我得到了rtf文件以及以下内容的区别:
diff --git a/archived-output/NEW/action-core[best].rtf b/archived-output/NEW/action-core[best].rtf
deleted file mode 100644
index 56cdec6..0000000
--- a/archived-output/NEW/action-core[best].rtf
+++ /dev/null
@@ -1,8935 +0,0 @@
-{\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff31507\deff0\stshfdbch31506\stshfloch31506\stshfhich31506\stshfbi31507\deflang1033\deflangfe1033\themelang1033\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f1\fbidi \fswiss\fcharset0\fprq2{\*\panose 020b0604020202020204}Arial;}
-{\f2\fbidi \fmodern\fcharset0\fprq1{\*\panose 02070309020205020404}Courier New;}{\f3\fbidi \froman\fcharset2\fprq2{\*\panose 05050102010706020507}Symbol;}
要么必须从树中过滤提交,要么我必须过滤输出。我正在考虑是否可以通过在遍历树时删除相应的提交来删除与rtf文件相关的更改。
答案 0 :(得分:1)
啊,现在你问的是正确的问题!当然,Git不会在每次提交中存储已修改文件的列表。相反,每个提交代表某个特定时间点的整个存储库的状态。为了找到修改过的文件,您需要将一次提交中包含的文件与之前的提交进行比较。如果可以的话,我们如何获得修改过的文件列表?
对于repo.walk()
返回的每个提交,tree
属性引用关联的Tree
对象(它本身是表示包含在其中的文件和目录的TreeEntry
个对象的列表。特别是Tree
)。
Tree
对象具有diff_to_tree()
方法,可用于将其与另一个Tree
对象进行比较。这将返回一个Diff
对象,该对象充当Patch
个对象列表的迭代器。每个Patch
对象引用正在比较的两个Tree
之间的单个文件中的更改。
Patch
对象确实是所有这一切的关键,因为这就是方法
我们确定哪些文件已被修改。
以下代码演示了这一点。对于每个提交,它将打印 新文件,已修改文件或已删除文件的列表:
import stat
import pygit2
repo = pygit2.Repository('.')
prev = None
for cur in repo.walk(repo.head.target):
if prev is not None:
print prev.id
diff = cur.tree.diff_to_tree(prev.tree)
for patch in diff:
print patch.status, ':', patch.new_file_path,
if patch.new_file_path != patch.old_file_path:
print '(was %s)' % patch.old_file_path,
print
if cur.parents:
prev = cur
cur = cur.parents[0]
如果我们针对a sample repository运行此操作,我们可以查看 前几次提交的输出:
c285a21e013892ee7601a53df16942cdcbd39fe6
D : fragments/configure-flannel.sh
A : fragments/flannel-config.service.yaml
A : fragments/write-flannel-config.sh
M : kubecluster.yaml
b06de8f2f366204aa1327491fff91574e68cd4ec
M : fragments/enable-services-master.sh
M : fragments/enable-services-minion.sh
c265ddedac7162c103672022633a574ea03edf6f
M : fragments/configure-flannel.sh
88a8bd0eefd45880451f4daffd47f0e592f5a62b
A : fragments/configure-docker-storage.sh
M : fragments/write-heat-params.yaml
M : kubenode.yaml
并将其与git log --oneline --name-status
的输出进行比较:
c285a21 configure flannel via systemd unit
D fragments/configure-flannel.sh
A fragments/flannel-config.service.yaml
A fragments/write-flannel-config.sh
M kubecluster.yaml
b06de8f call daemon-reload before starting services
M fragments/enable-services-master.sh
M fragments/enable-services-minion.sh
c265dde fix json syntax problem
M fragments/configure-flannel.sh
88a8bd0 configure cinder volume for docker storage
A fragments/configure-docker-storage.sh
M fragments/write-heat-params.yaml
M kubenode.yaml
...... aaaand,看起来几乎相同。希望这已经足够了 你开始了。
答案 1 :(得分:0)
这主要是将larsks's excellent answer重写为
它还修复了迭代逻辑中的一个缺陷:当遍历修订范围(a..b)时,原始代码可能会错过将最后一个修订与其父版本进行区分的功能。
以下近似命令
git log --name-status --pretty="format:Files changed in %h" origin/devel..master
在larsks提供的示例存储库中。
但是,我无法跟踪文件重命名。这被打印为删除和添加。永远不会到达打印重命名的代码行。
import pygit2
repo = pygit2.Repository('.')
# Show files changed between origin/devel and current HEAD
devel = repo.revparse_single('origin/devel')
walker = repo.walk(repo.head.target)
walker.hide(devel.id)
for cur in walker:
if cur.parents:
print ("Files changed in {}".format(cur.short_id))
prev = cur.parents[0]
diff = prev.tree.diff_to_tree(cur.tree)
for patch in diff:
print(patch.delta.status_char(), ':', patch.delta.new_file.path)
if patch.delta.new_file.path != patch.delta.old_file.path:
print('(was {})'.format(patch.delta.old_file.path))
print()