gpt4 book ai didi

git - 从 git 历史中删除除某些文件夹以外的所有文件夹

转载 作者:太空狗 更新时间:2023-10-29 12:43:31 25 4
gpt4 key购买 nike

我有一个复杂的 git 存储库,我想从中删除所有 文件和历史记录,除了两个文件夹,比方说:

foo/a
bar/x/y

虽然 git filter-branch --subdirectory-filter 会让我选择一个文件夹,并将其设为新的根目录,但它似乎没有给我任何选择两个目录的选项,并且保留他们的位置。

git filter-branch --tree-filter--index-filter 似乎可以让我遍历历史上的每个提交,我可以在其中使用 git rm 在不需要的文件夹上。

我似乎找不到任何有效的方法来让这些命令只保留我想要的两个文件夹,同时清除其他所有内容

谢谢!

最佳答案

你是对的:树过滤器或索引过滤器将是使用 git filter-branch 执行此操作的方法。

树过滤器更简单,但速度更慢(很容易慢 10 到 100 倍)。树过滤器的工作方式是您提供的命令在一个临时目录中运行,该目录包含所有且仅包含原始(现在正在复制)提交中存在的文件。您的命令留下的任何文件都保留在复制的提交中。您的命令在临时目录中创建的任何文件也在复制的提交中。 (您可以在临时目录中创建或删除目录,这两种方式都没有效果,因为 Git 只存储文件。)因此,要删除除 A 和 B 之外的所有内容,请编写一个命令来删除所有文件在 A 或 B 之外的其他地方:

find . -name A -prune -o -name B -prune -o -print0 | xargs -0 rm

例如。

索引过滤器更难,但速度更快,因为 Git 不必将所有文件复制到文件树中,然后重新扫描文件树以构建新索引,以复制原始提交。相反,它仅提供一个索引,然后您可以使用 git rm -rf --cached --ignore-unmatchgit update-index 等命令对其进行操作对于最一般的情况。但是,现在您拥有的唯一工具是 Git 中用于操作索引的工具。没有花哨的 Unix find 命令。

当然,您有 git ls-files,它会读取索引的当前内容。因此,您可以使用您喜欢的任何语言编写程序(我会在这里首先使用 Python,可能,其他人可能会从 Perl 开始),本质上是这样的:

for (all files in the index)
if (file name starts with 'A/' or 'B/')
do nothing
else
add to removal list
invoke "git rm --cached" on paths in removal list

如果您愿意相信没有文件名具有嵌入的换行符,则可以在常规 shell 中完成上述操作:

git ls-files | IFS=$'\n' while read path; do
case "$path" in A/*|B/*) continue;; esac
git rm --cached "$path"
done

效率不是很高(每个路径一个 git rm --cached!)但应该作为 --index-filter “开箱即用”地工作。

(未经测试,但可能有效并且应该更有效:通过 grep -v 管道输出 git ls-files 以删除所需的文件,然后管道 grep 输出到 git update-index --force-remove --stdin。这仍然假定路径名中没有换行符。)

关于git - 从 git 历史中删除除某些文件夹以外的所有文件夹,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42834812/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com