我使用以下命令通过git filter-branch
清理我的存储库,以删除一些文件夹:
git filter-branch --force --index-filter 'git rm -r --cached --ignore-unmatch folder' \
--prune-empty --tag-name-filter cat -- --all
在此之后,我还有一些仅与已删除文件相关的提交。是否有办法清理这些内容,即删除不再历史记录中的文件上的提交?
我使用以下命令通过git filter-branch
清理我的存储库,以删除一些文件夹:
git filter-branch --force --index-filter 'git rm -r --cached --ignore-unmatch folder' \
--prune-empty --tag-name-filter cat -- --all
在此之后,我还有一些仅与已删除文件相关的提交。是否有办法清理这些内容,即删除不再历史记录中的文件上的提交?
如果确实存在这种情况,您可以使用--prune-empty
运行一个除了这些提交无其他作用的第二个filter-branch命令来丢弃它们。
之后,我仍然有一些提交只与已删除的文件相关。
这应该很少见,因为您已经包含了:
--prune-empty
这个命令会指示filter-branch
忽略任何与其父提交相同的简单(非合并)提交。
有可能您有一些合并提交,将两个在其输入点上完全相同的分支合并在一起,但是这些提交不能被删除,因为它们合并了在其输入点上完全相同的分支。
比如说,在过滤之前,我们有以下分支结构:
B--C
/ \
...--o--A M--o--...
\ /
D--E
提交记录 M
是一个合并记录,必须保留(因此已经保留),但是假设在过滤后 A
对比 B
折叠掉了,而且 C
对比 B
(或对比 A
)也由于相同的原因折叠掉了,那么就会得到:
...--o--A'-----M'-o--...
\ /
D'-E'
A'
确实可以是A
,但这涵盖了更一般的情况)。在这里,M
确实仍然需要保持逻辑结构,即使在最初删除文件时可以进行快进。
更有趣的情况是D
和E
本身消失了,因为现在M
仍然存在于过滤分支过程中,并且仍然具有两个父级,但是两个父级都映射到提交A'
本身。我不确定在没有查看的情况下会发生什么:filter-branch是否可以使用A'
作为M'
的两个父级之一进行合并提交?如果它尝试这样做,git commit-tree
会将提交M'
写为普通的非合并提交吗?测试结果是否定的:
$ mkdir mtest
$ cd mtest
$ git init
Initialized empty Git repository in ...
$ echo test commit-tree > README
$ git add README
$ git commit -m initial
[master (root-commit) 1db1f76] initial
1 file changed, 1 insertion(+)
create mode 100644 README
$ echo log msg | git commit-tree -p HEAD -p HEAD HEAD^{tree}
error: duplicate parent 1db1f76a4e7217d5198c0f178464b7a087e94078 ignored
44f91061b7bd08c39a4dc9e8ebb1f4f7c588ea9e
看起来,一个天真的filter-branch
会尝试创建M'
并将其作为单亲提交:
...--o--A'-M'-o--...
其中M'
和A'
没有差异。不过,filter-branch代码对此进行了检查:
for parent in $parents; do
for reparent in $(map "$parent"); do
case "$parentstr " in
*" -p $reparent "*)
;;
*)
parentstr="$parentstr -p $reparent"
;;
esac
done
done
git filter-branch --prune-empty
,但提交记录仍然存在。我使用 git show
进行了检查,发现这些提交记录只包含在第一个 git filter-branch
中已删除的文件上所做的更改。 - Holtgit show
和合并提交:Git 默认会显示合并差异,有意省略文件以使差异更有用。添加 -m
以使 Git 对每个父提交进行差异比较。(如果它们不是合并提交,我不确定这里发生了什么。) - torekgit show -m COMMIT_ID
,并且得到了相同的输出。 - Holtgit log
返回的提交,这些不是已更新的吗? - Holt我在此页面的第6步找到了答案:https://github.com/epics-modules/motor/wiki/Creating-a-standalone-driver-module
git filter-branch --prune-empty --parent-filter 'sed "s/-p //g" | xargs -r git show-branch --independent | sed "s/\</-p /g"'