如何在整个Git历史记录中替换字符串? [英] How to replace a string in a whole Git history?

查看:62
本文介绍了如何在整个Git历史记录中替换字符串?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Git存储库中的几个文件中提交了我的密码之一.是否有某种方法可以在整个历史记录中自动用其他字符串替换此密码,以便没有痕迹?理想情况下,如果我可以编写简单的bash脚本来接收字符串以查找并替换并自己完成整个工作,例如:

I have one of my passwords commited in probably few files in my Git repo. Is there some way to replace this password with some other string in whole history automatically so that there is no trace of it? Ideally if I could write simple bash script receiving strings to find and replace by and doing whole work itself, something like:

./replaceStringInWholeGitHistory.sh "my_password" "xxxxxxxx"

此问题与

this question is not a duplicate of that one, because I am asking about replacing strings without removing whole files.

推荐答案

在一开始,我要感谢 ElpieKay ,他发布了我的解决方案的核心功能,而这些功能只是我自动完成的.

At the beginning I'd like to thank ElpieKay, who posted core functions of my solutions, which I've only automatized.

所以,最后我有了想要的脚本.我将其分为相互依赖的部分,它们可以用作独立的脚本.看起来像这样:

So, finally I have script I wanted to have. I divided it into pieces which depend on each other and can serve as independent scripts. It looks like this:

#!/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"

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" "********"

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" "********"

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

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来实现.

I have all those scripts located in my home folder, what is necessary for proper working in this version. I'm not sure that's the best option, but for now I cannot find better one. Of course every script has to be executable, what we can achieve with chmod +x ~/myscript.sh.

我的脚本可能不是最佳的,对于大型仓库而言,它会处理很长时间,但是可以正常工作:)

Probably my script is not optimal, for big repos it will process very long, but it works :)

最后,我们可以使用以下命令将经过审查的存储库推送到任何远程服务器:

And, at the very end, we can push our censored repo to any remote with:

git push <remote> -f --all

ElpieKay的重要提示:

important hint from ElpieKay:

不要忘记删除并重新创建您推送的标签.他们 仍指向可能包含您密码的旧提交.

Don't forget to delete and recreate tags that you have pushed. They are still pointing to the old commits that may contain your password.

也许将来我会改进脚本以自动执行此操作.

Maybe I'll improve my script in future to do this automatically.

这篇关于如何在整个Git历史记录中替换字符串?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆