在macOS上使用树过滤器和sed从Git提交中删除敏感数据



我试着阅读了多篇关于sed以及如何从已经提交的文件中删除密钥的文章。我正在试用这个

git filter-branch --tree-filter 
"sed -i '' 's/my_sensitive_data/<your-api-key>/' ./app/src/main/java/com/demo/Test.kt"

我一直得到sed ./app/src/main/java/com/demo/Test.kt: No such file or directory。但如果我用同样的命令

sed -i '' 's/my_sensitive_data/<your-api-key>/' ./app/src/main/java/com/demo/Test.kt

在我运行git filter-branch命令的目录中,sed命令确实适当地替换了它。

我正在运行macOS catalina并使用ZSH。我在这里可能做错了什么?

使用git filter-branch,Git在每次提交时都会运行过滤器1也就是说,树过滤器:

  • 检查提交(在临时目录中)
  • 运行指定的命令(在该临时目录中);以及
  • 根据该命令留下的内容构建替换提交

filter branch命令对要复制的每个提交重复此操作。(过滤分支就是这样做的:它复制提交。原始文件仍然存在。)

您的一些提交具有该文件;CCD_ 7命令将对这些提交起作用。您的一些提交缺少文件,在这种情况下sed命令将失败。git filter-branch将该故障视为筛选命令的非零退出状态,导致git filter-branch本身停止,无法执行所需的筛选。

解决方案是避免在文件不存在时完全运行此sed命令。有两种方法可以做到这一点(请参见脚注1),但最简单的是首先将命令修改为检查。代替:

sed -i '' 's/my_sensitive_data/<your-api-key>/' ./app/src/main/java/com/demo/Test.kt

你会使用:

if [ -f app/src/main/java/com/demo/Test.kt ]; then
sed -i '' 's/my_sensitive_data/<your-api-key>/' app/src/main/java/com/demo/Test.kt
fi

注意:如果将其压缩为一行,则至少需要再加一个分号。我省略了它(也去掉了./,因为它是多余的),以使行更适合发布目的。


1从技术上讲,它只在您告诉它的提交上运行过滤器,这可能比每次提交的更少。将访问的提交是通过正引用显式或隐式命名的提交,不包括通过负引用显式或隐含命名的提交。这句话里有很多行话,值得一试:

  • 阳性指称是一种前面没有否定的指称,也不用于否定指称的任何特殊句法方法。这方面的简单示例包括feature(分支名称)、v2.1(标记名称)和a1234567(缩写的提交哈希)。

  • 否定引用是在否定之前的引用,或用于否定的语法:^feature^v2.1^a1234567。对于否定语法的一个简单示例,请考虑master..feature:这完全等同于编写feature ^master

  • 短语显式或隐式指的是Git正在遍历提交图。有关这意味着什么的正确教程,请参阅Think Like(a)Git。

命令行中提到的所有正引用都会导致Git遍历提交图,标记要复制的提交。所有的负引用都会导致Git遍历图形,取消标记提交。如果您将该过程视为";先标记,然后取消标记";您会得到正确的结果:只有标记为的提交才会被复制和过滤。如果您将其视为";先取消标记";,则";在";阶段必须尊重所有较早的";取消标记";。(Git实际上是以一种复杂的交错方式进行的,这样它总是能得到正确的结果,但比简单的两遍算法做得更快。)

那些分支名称的正引用会导致名称被记住。然后,Git将所有标记的提交按适当的顺序排列——根据复制过程的需要进行拓扑排序——并开始复制。在复制时,它构建了一个从旧哈希ID到新哈希ID的映射。在复制过程结束时,对于这些保存的分支名称中的每一个,Git都会强制名称指向新的哈希ID而不是旧的哈希ID,过滤现在就完成了。

因此,如果有一个简单(或复杂!)的范围表达式,让Git只枚举需要复制和筛选的提交,你可以使用它,而不是在过滤器中进行测试。例如,假设敏感数据是专门在提交badf00d中引入的,其父级是cafedad:因此,所有好的提交都可以从cafedad访问,而所有

坏的一些在

cafedad之前提交,可能还有cafedad本身,缺少Test.kt文件,因此sed将在这些文件上失败。在这种情况下:

git filter-branch <filter-specifiers> -- cafedad..master

这将起到关键作用,因为这将复制和筛选限制为只有(a)具有文件和(b)需要编辑的提交。

最新更新