Git tree-filter 在提交时运行 python 脚本
Posted
技术标签:
【中文标题】Git tree-filter 在提交时运行 python 脚本【英文标题】:Git tree-filter run python script on commits 【发布时间】:2014-05-09 12:28:30 【问题描述】:我之前在#git
上被问过这个问题,但由于它相当重要,我会在这里发布。我想在 repo 上运行 filter-branch
以使用 python 脚本在数百次提交中修改(数千个)文件。我在 repo 目录中使用以下命令调用 clean.py
脚本:
git filter-branch -f --tree-filter '(cd ../cleaner/ && python clean.py --path=files/*/*/**)'
Clean.py 看起来像这样,会修改路径中的所有文件(即files/*/*/**
):
from os import environ as environment
import argparse, yaml
import logging
from cleaner import Cleaner
parser = argparse.ArgumentParser()
parser.add_argument("--path", help="path to run cleaner on", type=str)
args = parser.parse_args()
# logging.basicConfig(level=logging.DEBUG)
with open("config.yml") as sets:
config = yaml.load(sets)
path = args.path
if not path:
path = config["cleaner"]["general_pattern"]
cleaner = Cleaner(config["cleaner"])
print "Cleaning path: " + str(path)
cleaner.clean(path, True)
运行命令后,终端输出如下:
$ python deploy.py --verbose
INFO:root:Checked out master branch
INFO:root:Running command:
'git filter-branch -f --tree-filter '(cd C:/Users/Graeme/Documents/programming/clean-cdn/clean-jsdelivr/ && python clean.py --path=files/*/*/**)' -d "../tmp"' in ../jsdelivr
Rewrite 298ec3a2ca5877a25ebd40aeb815d7b5a5f33a7e (1/1535)
Cleaning path: files/*/*/**
C:\Program Files (x86)\git/libexec/git-core\git-filter-branch: line 343: ../commit: No such file or directory
C:\Program Files (x86)\git/libexec/git-core\git-filter-branch: line 346: ../map/298ec3a2ca5877a25ebd40aeb815d7b5a5f33a7e
: No such file or directory
could not write rewritten commit
rm: cannot remove `/c/Users/Graeme/Documents/programming/clean-cdn/tmp/revs': Permission denied
rm: cannot remove directory `/c/Users/Graeme/Documents/programming/clean-cdn/tmp': Directory not empty
python 脚本成功执行并正确修改了文件,但 filter-branch
没有完成修复提交。 似乎存在权限问题,但我无法获得在它周围以提升的权限运行。我已经尝试使用 git v1.8 和 v1.9 在 win7、win8 和 ubuntu 上运行过滤器分支。编辑该脚本在 Centros 上与 git1.7.1
一样工作 p>
目标是在files/*/*/**
中的内容与数据库同步后减小 CDN 存储库的大小(接近 1GB)。The source code of the projectTarget repo for the rewrite
【问题讨论】:
git --version
的输出是什么?
您能澄清一下您要清理的存储库是什么吗?是github.com/jsdelivr/jsdelivr(当前包大小~284MB)吗?
@michas 我试过在v1.9.0
、v1.8.5
和1.8.3
上运行它。是的,这是正确的回购罗伯托
【参考方案1】:
您遇到的权限问题很有趣——您是在存储库的本地副本(即您可以完全访问文件系统的地方)还是在远程服务器上执行此操作?
阅读您的 python 代码,您似乎正在尝试删除每个大小超过一定大小的文件,而不是 .INI 文件,我没听错吗?
如果是这样,请问您是否考虑过The BFG Repo-Cleaner?显然,您可以通过编写自己的代码(我知道我有)学到很多关于 Git 的知识,但我认为 BFG 可能是为您的需求量身定制的 - 并且会比任何基于 git-filter-branch
的方法更快。
在您的情况下,您可能希望使用如下命令运行它:
$ java -jar bfg.jar --strip-blobs-bigger-than 100K my-repo.git
这会删除所有大于 100K、不在您最新提交中的 blob。
我在jsdelivr repo 上快速运行了这个,并在the cleaned repo 中将包大小从 284M 减少到 138M。 BFG 清理步骤耗时不到 5 秒,随后的 git gc --prune=now --aggressive
不到 2 分钟。
全面披露:我是 BFG Repo-Cleaner 的作者。
【讨论】:
此外,我们当前的文件也不是神圣的 - 有没有让您的工具命中所有提交到HEAD
再神圣:--no-blob-protection 是你(可怕的)朋友!
好吧整洁 - 看起来很有希望。无论如何要指定***REMOVED***
文本,您的项目是否支持全局路径?
谢谢,上下文很好!将 BFG 更改为零文件 (github.com/rtyley/bfg-repo-cleaner/blob/ed21bed/bfg-library/src/… ) 并不难,但从阅读问题 347 来看,我认为这对您尝试做的事情的精神并不重要 - 替换文件称为“文件名”我认为 .REMOVED.git-id' 会很好。总的来说,我不确定 /frequent/ 历史重写是否对 jsdelivr 项目有好处 - 是否会让提交拉取请求的人感到困惑?
关于字节大小 - 我刚刚削减了 BFG 的 v1.11.3 版本,支持按单字节文件大小过滤文件!几小时内将在repo1.maven.org/maven2/com/madgag/bfg 上显示。【参考方案2】:
您不应将cd
转移到另一个目录,因为git-filter-branch
script 将使用相对路径来访问文件。
【讨论】:
脚本在其相对目录中加载一些.yml
文件,过滤器分支在repos 路径的上下文中执行命令。 AFAIK 无法设置 cwd
路径【参考方案3】:
考虑使用BFG。它使用起来更快更简单。
【讨论】:
以上是关于Git tree-filter 在提交时运行 python 脚本的主要内容,如果未能解决你的问题,请参考以下文章