git - 通过 git filter-branch 调用时反直觉的 git rm --cached 标志行为(追溯 .gitignore)
问题描述
问题
通过--cached
运行时标志有什么区别?git rm
git filter-branch --index-filter
git filter-branch --index-filter 'git rm --cached *.ext'
git filter-branch --index-filter 'git rm *.ext'
问题
当我运行时git rm --cached *.ext
,所有*.ext
文件都未跟踪但未从工作目录中删除(--cached
据我所知,这是 flag 的目的)
但是,当我尝试追溯运行该命令时
git filter-branch --index-filter 'git rm --cached *.ext'
所有历史*.ext
文件都未跟踪,现有*.ext
文件已从工作目录中删除。
为什么?
没有有什么区别--cached
理论
由于该命令在所有提交上运行,每次运行都没有“工作目录”,因此它还将 HEAD/当前工作目录视为没有工作目录的独立提交。
解决方案
你的理论大部分是正确的,只是在最后有点偏离。 git filter-branch
不使用标准索引,也不使用您的工作树。当它调用您的每个过滤器时,它会在一个临时目录中运行,该目录在文件系统中的位置取决于您是否提供了一个选项。1 由于没有可用的工作树,所有索引过滤器操作都应使用. 2 Filter-branch 还在临时目录中创建一个临时索引。这个临时索引在过滤的每一步都存在:它用于提取索引过滤器的提交,然后在索引过滤器修改它后进行新的提交。-d directory
git rm
--cached
完成所有过滤操作后,最后几个步骤filter-branch
是:
更新所有要修改的引用:过滤的分支和任何标签(如果您使用
--tag-name-filter
. 例如,之前master
可能已经确定了提交a123456...
。b789abc...
如果现在应该使用新提交而不是a123456
,Git 必须重写refs/heads/master
,以便它现在识别提交b789abc...
。如果您在非裸存储库中(filter-branch可用于裸存储库),则实际上
git checkout
是新提交而不是旧提交。这会更新您的索引和工作树,以便您的索引和工作树保持“干净”。3 实际操作是git read-tree
:if [ "$(is_bare_repository)" = false ]; then git read-tree -u -m HEAD || exit fi
正是这最后一步,即有效签出,删除了您的*.ext
文件。
您当前的索引将它们显示为tracked,它们是;它们在您当前的commit中,即 (say) a123456...
。您的新目标提交b789abc...
缺少*.ext
文件,因为您使用--index-filter
. 所以要从当前提交移动到新提交,正确的操作是删除文件。
要解决问题:
在使用该选项运行filter-branch 命令git rm --cached '*.ext'
之前--index-filter
运行,然后提交。这样,您当前的提交(将不再是a123456...
)将没有文件,并且您的索引将没有文件,因此它们将只是当前提交和新提交中的未跟踪文件,并且不会受到影响.
1 Filter-branch$tempdir
从您的-d
选项或默认设置开始,即.git-rewrite
. 然后它创建$tempdir/t
,$tempdir
如果需要也创建;将位置更改为其中;并将 Git 工作树设置为.
. 除非您使用该选项或在任何过滤器中尝试以某种方式操作当前目录,否则此$tempdir/t
目录将保持为空。--tree-filter
2没有--cached
,git rm
会尝试从 中删除文件$GIT_WORK_TREE
,即$tempdir/t
. Filter-branch 自己的状态文件../
来自这里,即 in $tempdir
,因此它们通常应该是安全的,但是尝试删除无论如何都不应该存在的东西仍然不是一个好主意:如果没有别的,那就是浪费计算时间。使用--cached
甚至git rm
不会尝试它。
3这里的“干净”是一种定义模糊的状态,无论如何您都可能认识它。如果需要,精确的定义在 中git-sh-setup.sh
,特别是在函数中require_clean_work_tree
。如果在非裸存储库上运行,Filter-branch 在开始过滤之前调用它。
推荐阅读
- c++ - 自定义条件范围互斥锁
- r - 如何将列表转换为数据框
- python - 如何使用python删除位图图像蒙版中的小岛补丁?
- clojure - clojure 宏中的文本替换功能,如 C 的 #define
- sockets - 如何从 Dart 中的 Future 返回套接字数据?
- unit-testing - Symfony 4. 允许获取私有服务的特殊容器
- php - php中两个数组的区别
- javascript - 如果未在承诺中验证重定向和 setState
- python - 在 PyTorch 中沿矩阵的对角线绑定所有值
- python - 如何修复:(TypeError:'str' object is not callable)