¿Cómo replace una cadena en el historial completo de Git?

Tengo una de mis passwords en pocos files en mi repo de Git. ¿Hay alguna forma de replace esta contraseña con alguna otra cadena en toda la historia de forma automática para que no quede rastro de ella? Idealmente, si pudiera escribir cadenas simples de recepción de scripts bash para search y replace por y haciendo todo el trabajo en sí, algo como:

./replaceStringInWholeGitHistory.sh "my_password" "xxxxxxxx" 

Editar: esta pregunta no está duplicada, porque estoy preguntando sobre replace cadenas sin eliminar files completos.

Primero, encuentre todos los files que podrían contener la contraseña. Supongamos que la contraseña es abc123 y la twig es master . Es posible que deba excluir aquellos files que tienen abc123 solo como una cadena normal.

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

Luego reemplace "abc123" por "******". Supongamos que uno de los files es foo/bar.txt .

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

Finalmente, fuerce al master inserción al repository remoto si existe.

 git push origin -f master:master 

Hice una testing simple y funcionó, pero no estoy seguro de si está bien con tu caso. Debe tratar con todos los files de todas las twigs. En cuanto a las tags, puede que tenga que eliminar todas las antiguas y crear nuevas.

Al principio me gustaría agradecer a ElpieKay , quien publicó las funciones principales de mis soluciones, que solo he automatizado.

Entonces, finalmente tengo el guión que quería tener. Lo dividí en pedazos que dependen el uno del otro y pueden servir como guiones independientes. Se parece a esto:

censorStringsInWholeGitHistory.sh:

 #!/bin/bash #arguments are strings to censore for string in "$@" do echo "" echo "================ Censoring string "$string": ================" ~/replaceStringInWholeGitHistory.sh "$string" "********" done 

uso:

 ~/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 

uso:

 ~/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 

uso:

 ~/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 

uso:

 ~/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 -is/$2/$3/g $1;fi" 

uso:

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

Tengo todas esas secuencias de commands ubicadas en mi carpeta de inicio, lo que es necesario para el correcto funcionamiento en esta versión. No estoy seguro de que sea la mejor opción, pero por ahora no puedo encontrar una mejor. Por supuesto, cada script debe ser ejecutable, lo que podemos lograr con chmod +x ~/myscript.sh .

Probablemente mi script no sea óptimo, para grandes reposes se procesará por mucho time, pero funciona 🙂

Y, al final, podemos impulsar nuestro repository censurado a cualquier control remoto con:

 git push <remote> -f --all 

Edición: pista importante de ElpieKay:

No olvides eliminar y volver a crear las tags que has pulsado. Aún apuntan a las confirmaciones anteriores que pueden contener su contraseña.

Tal vez voy a mejorar mi script en el futuro para hacer esto automáticamente.