从提交树中提取与代码更改相关的提交
Extract commits related to code changes from commit tree
现在我可以使用 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 文件相关的更改。
If that is possible, how do we get the list of modified files?
啊,现在你问对了问题! Git,当然不会在每次commit时存储修改文件的列表。相反,每个提交代表整个存储库在某个时间点的状态。为了找到被修改的文件,您需要将一次提交中包含的文件与上一次提交进行比较。
对于 repo.walk()
返回的每个提交,tree
属性引用关联的 Tree
对象(它本身是代表文件和目录的 TreeEntry
对象的列表包含在那个特定的 Tree
).
一个 Tree
对象有一个 diff_to_tree()
方法可以用来将它与另一个 Tree
对象进行比较。这个 returns 一个 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,看起来几乎相同。希望这就足够了
给你开始了。
这主要是将重写为
- 当前pygit2API
- Python3
它还修复了迭代逻辑中的一个缺陷:当遍历修订范围 (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 (f'Files changed in {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(f'(was {patch.delta.old_file.path})'.)
print()
现在我可以使用 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 文件相关的更改。
If that is possible, how do we get the list of modified files?
啊,现在你问对了问题! Git,当然不会在每次commit时存储修改文件的列表。相反,每个提交代表整个存储库在某个时间点的状态。为了找到被修改的文件,您需要将一次提交中包含的文件与上一次提交进行比较。
对于 repo.walk()
返回的每个提交,tree
属性引用关联的 Tree
对象(它本身是代表文件和目录的 TreeEntry
对象的列表包含在那个特定的 Tree
).
一个 Tree
对象有一个 diff_to_tree()
方法可以用来将它与另一个 Tree
对象进行比较。这个 returns 一个 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,看起来几乎相同。希望这就足够了 给你开始了。
这主要是将
- 当前pygit2API
- Python3
它还修复了迭代逻辑中的一个缺陷:当遍历修订范围 (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 (f'Files changed in {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(f'(was {patch.delta.old_file.path})'.)
print()