如何替换整个Git历史中的字符串?

v8wbuo2f  于 2023-06-20  发布在  Git
关注(0)|答案(3)|浏览(109)

我有一个密码在我的Git存储库中的几个文件中提交。有没有什么方法可以在整个历史记录中自动用其他字符串替换这个密码,这样就不会有任何痕迹了?理想情况下,如果我可以编写简单的bash脚本,接收字符串来查找和替换,并完成整个工作本身,类似于:

./replaceStringInWholeGitHistory.sh "my_password" "xxxxxxxx"

***编辑:这个问题不是that one的重复,因为我问的是在不删除整个文件的情况下替换字符串。

sqyvllje

sqyvllje1#

git filter-repo --replace-text

Git 2.25 man git-filter-branch已经明确推荐使用git filter-repo而不是git filter-tree,所以我们开始吧。
安装https://superuser.com/questions/1563034/how-do-you-install-git-filter-repo/1589985#1589985

python3 -m pip install --user git-filter-repo

然后用途:

echo 'my_password==>xxxxxxxx' > replace.txt
git filter-repo --replace-text replace.txt

或者与Bash魔法相当:

git filter-repo --replace-text <(echo 'my_password==>xxxxxxxx')

使用以下简单的测试存储库进行测试:https://github.com/cirosantilli/test-git-filter-repository和替换字符串:

d1==>asdf
d2==>qwer

上面的行为在默认情况下对所有分支(如此侵入!!!),要仅对选定的分支执行操作,请使用用途:git filter-repo: can it be used on a specific branch?例如:

--refs HEAD
--refs refs/heads/master

并且只对指定的提交范围执行操作,您可以:如何使用git filter-repo只修改一个提交范围,而不是整个分支历史?

--refs HEAD~2..master
--refs HEAD~2..HEAD

选件--replace-text的文档位于:https://github.com/newren/git-filter-repo/blob/7b3e714b94a6e5b9f478cb981c7f560ef3f36506/Documentation/git-filter-repo.txt#L155
--replace-text<expressions_file>::
包含表达式的文件,如果找到这些表达式,将替换它们。默认情况下,每个表达式都被视为文本,但支持regex:glob:前缀。您可以使用==>和一些替换文本结束该行,以选择除默认***REMOVED***之外的替换选项。
如何在单个文件中替换:git-filter-repo replace text by expression in a single file
当然,一旦你公开推送了一个密码,就为时已晚,你将不得不更改密码,所以在这种情况下,我甚至不会费心更换:从Git历史中删除敏感文件及其提交
标签:How to substitute text from files in git history?
在git-filter-repo ac 039 ecc 095 d上测试。

ffx8fchx

ffx8fchx2#

首先,找到所有可能包含密码的文件。假设密码是abc123,分支是master。您可能需要排除那些仅将abc123作为普通字符串的文件。

git log -S "abc123" master --name-only --pretty=format: | sort -u

然后将“abc123”替换为“******”。假设其中一个文件是foo/bar.txt

git filter-branch --tree-filter "if [ -f foo/bar.txt ];then sed -i s/abc123/******/g foo/bar.txt;fi"

最后,强制将master推送到远程存储库(如果存在)。

git push origin -f master:master

我做了一个简单的测试,它的工作,但我不知道如果它的好你的情况。您需要处理所有分支的所有文件。至于标签,您可能必须删除所有旧的,并创建新的。

pxq42qpu

pxq42qpu3#

首先,我要感谢ElpieKay,他发布了我的解决方案的核心功能,我只是将其自动化。
最后,我终于有了我想要的剧本。我把它分成几个部分,它们相互依赖,可以作为独立的脚本。它看起来像这样:

www.example.com censorStringsInWholeGitHistory.sh:

#!/bin/bash
#arguments are strings to censore

for string in "$@"
do
  echo ""
  echo "================ Censoring string "$string": ================"
  ~/replaceStringInWholeGitHistory.sh "$string" "********"
done

用法:

~/censorStringsInWholeGitHistory.sh "my_password1" "my_password2" "some_f_word"

www.example.com replaceStringInWholeGitHistory.sh:

#!/bin/bash
# $1 - string to find
# $2 - string to replace with

for branch in $(git branch | cut -c 3-); do
  echo ""
  echo ">>> Replacing strings in branch $branch:"
  echo ""
  ~/replaceStringInBranch.sh "$branch" "$1" "$2"
done

用法:

~/replaceStringInWholeGitHistory.sh "my_password" "********"

www.example.com replaceStringInBranch.sh:

#!/bin/bash
# $1 - branch
# $2 - string to find
# $3 - string to replace with

git checkout $1
for file in $(~/findFilesContainingStringInBranch.sh "$2"); do
  echo "          Filtering file $file:"
  ~/changeStringsInFileInCurrentBranch.sh "$file" "$2" "$3"
done

用法:

~/replaceStringInBranch.sh master "my_password" "********"

www.example.com findFilesContainingStringInBranch.sh:

#!/bin/bash

# $1 - string to find
# $2 - branch name or nothing (current branch in that case)

git log -S "$1" $2 --name-only --pretty=format: -- | sort -u

用法:

~/findFilesContainingStringInBranch.sh "my_password" master

www.example.com changeStringsInFileInCurrentBranch.sh:

#!/bin/bash

# $1 - file name
# $2 - string to find
# $3 - string to replace

git filter-branch -f --tree-filter "if [ -f $1 ];then sed -i s/$2/$3/g $1;fi"

用法:

~/changeStringsInFileInCurrentBranch.sh "abc.txt" "my_password" "********"

我有所有这些脚本位于我的主文件夹中,什么是必要的,在这个版本中正常工作。我不确定这是最好的选择,但现在我找不到更好的。当然,每个脚本都必须是可执行的,我们可以用chmod +x ~/myscript.sh来实现。
可能我的脚本不是最佳的,对于大型repo它将处理很长时间,但它工作:)
而且,在最后,我们可以将我们的审查存储库推送到任何远程:

git push <remote> -f --all
    • 编辑:**ElpieKay的重要提示:

不要忘记删除和重新创建您推送的标签。他们仍然指向可能包含您的密码的旧提交。
也许我会在将来改进我的脚本来自动完成这一点。

相关问题