karol selak
Tengo una de mis contraseñas confirmadas en probablemente algunos archivos en mi repositorio de Git. ¿Hay alguna forma de reemplazar esta contraseña con alguna otra cadena en todo el historial automáticamente para que no quede rastro de ella? Idealmente, si pudiera escribir un script bash simple que reciba cadenas para buscar y reemplazar y hacer todo el trabajo por sí mismo, algo como:
./replaceStringInWholeGitHistory.sh "my_password" "xxxxxxxx"
Editar: esta pregunta no es un duplicado de esa, porque estoy preguntando sobre el reemplazo de cadenas sin eliminar archivos completos.
elpiekay
Primero, busque todos los archivos que puedan contener la contraseña. Supongamos que la contraseña es abc123
y la rama es master
. Es posible que deba excluir aquellos archivos que tienen abc123
sólo como una cadena normal.
git log -S "abc123" master --name-only --pretty=format: | sort -u
Luego reemplace “abc123” con “******”. Supongamos que uno de los archivos es foo/bar.txt
.
git filter-branch --tree-filter "if [ -f foo/bar.txt ];then sed -i s/abc123/******/g foo/bar.txt;fi"
Finalmente, forzar el empuje master
al repositorio remoto si existe.
git push origin -f master:master
Hice una prueba simple y funcionó, pero no estoy seguro si está bien con su caso. Debe manejar todos los archivos de todas las sucursales. En cuanto a las etiquetas, es posible que deba eliminar todas las antiguas y crear otras nuevas.
-
Hm, está bien, funciona para la rama real, pero al tener más, probablemente tendré que hacer eso para cada una de ellas.
-Karol Selak
26 oct 2017 a las 10:40
-
Tengo un problema con sucursales diferentes a master. cuando intento
git log -S "abc123" test --name-only --pretty=format: | sort -u
me sale error:fatal: ambiguous argument 'test': both revision and filename
. ¿Puedo evitarlo de alguna manera?-Karol Selak
6 de noviembre de 2017 a las 17:05
-
@KarolSelak el error dice que tienes un árbitro llamado
test
y también un archivo llamadotest
. Es un conflicto de nombres. Si esperas que Git interpretetest
como referencia, luego usegit log -S "abc123" test --name-only --pretty=format: -- | sort -u
. Si se interpreta como un archivo, utilicegit log -S "abc123" --name-only --pretty=format: -- test | sort -u
. Si necesitas ambos, entoncesgit log -S "abc123" test --name-only --pretty=format: -- test | sort -u
. Hay espacios alrededor del--
. Ver git-scm.com/docs/gitcli#_descripción para más.– Elpie Kay
6 de noviembre de 2017 a las 22:57
-
Muchas gracias, finalmente he escrito lo que necesito, pero eso es principalmente tu mérito. Espero que la solución final sirva a otros durante mucho tiempo 🙂
-Karol Selak
7 de noviembre de 2017 a las 12:47
-
@KarolSelak Me alegro de que ayude =). No olvide eliminar y volver a crear las etiquetas que ha enviado. Todavía están apuntando a las confirmaciones antiguas que pueden contener su contraseña.
– Elpie Kay
7 de noviembre de 2017 a las 13:08
Ciro Santilli OurBigBook.com
git filter-repo --replace-text
Git 2.25 man git-filter-branch
ya recomienda claramente usar git filter-repo
en vez de git filter-tree
así que, aquí vamos.
Instalar https://superuser.com/questions/1563034/how-do-you-install-git-filter-repo/1589985#1589985
python3 -m pip install --user git-filter-repo
y luego usa:
echo 'my_password==>xxxxxxxx' > replace.txt
git filter-repo --replace-text replace.txt
o equivalente con Bash magic:
git filter-repo --replace-text <(echo 'my_password==>xxxxxxxx')
Probado con este repositorio de prueba simple: https://github.com/cirosantilli/test-git-filter-repositorio y cadenas de reemplazo:
d1==>asdf
d2==>qwer
Lo anterior actúa en todas las ramas de forma predeterminada (¡¡tan invasivo!), Para actuar solo en las ramas seleccionadas, use: git filter-repo: ¿se puede usar en una rama específica? p.ej:
--refs HEAD
--refs refs/heads/master
La opción --replace-text
opción está documentada en: https://github.com/newren/git-filter-repo/blob/7b3e714b94a6e5b9f478cb981c7f560ef3f36506/Documentation/git-filter-repo.txt#L155
–replace-text
:: Un archivo con expresiones que, si se encuentran, serán reemplazadas. Por defecto, cada expresión se trata como texto literal, pero
regex:
yglob:
Se admiten prefijos. Puede terminar la línea con==>
y algún texto de reemplazo para elegir una opción de reemplazo que no sea la predeterminada de***REMOVED***
.
Por supuesto, una vez que haya enviado una contraseña públicamente, siempre es demasiado tarde y tendrá que cambiar la contraseña, por lo que ni siquiera me molestaría en reemplazar en este caso: Eliminar archivos confidenciales y sus confirmaciones del historial de Git
Relacionado: ¿Cómo sustituir el texto de los archivos en el historial de git?
Probado en git-filter-repo ac039ecc095d.
karol selak
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 partes que dependen unas de otras 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"
reemplazarStringInWholeGitHistory.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" "********"
reemplazarStringInBranch.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 -i s/$2/$3/g $1;fi"
uso:
~/changeStringsInFileInCurrentBranch.sh "abc.txt" "my_password" "********"
Tengo todos esos scripts ubicados en mi carpeta de inicio, lo que es necesario para que funcione correctamente 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 tiene que ser ejecutable, lo que podemos lograr con chmod +x ~/myscript.sh
.
Probablemente mi secuencia de comandos no sea óptima, para repositorios grandes se procesará por mucho tiempo, pero funciona 🙂
Y, al final, podemos enviar nuestro repositorio censurado a cualquier control remoto con:
git push <remote> -f --all
Editar: pista importante de ElpieKay:
No olvide eliminar y volver a crear las etiquetas que ha enviado. Todavía están apuntando a las confirmaciones antiguas que pueden contener su contraseña.
Tal vez mejore mi script en el futuro para hacer esto automáticamente.
-
¿Estos scripts realmente funcionan? No pude hacer que funcionaran: sed: -e expression #1, char 7: falló el filtro del árbol de comandos `s’ sin terminar:
– hora del Este
29 de abril de 2020 a las 21:42
-
Sí, lo acabo de comprobar y ahora me funciona. Aunque uso Git v2.17.1, no estoy seguro de qué pasa con las versiones más nuevas. Y uso Ubuntu.
-Karol Selak
29 de abril de 2020 a las 22:02
-
¿Es el problema por casualidad que la cadena sed realmente debería escaparse? No veo cómo podría funcionar esto si contiene espacios, barras o similar
– hora del Este
29 de abril de 2020 a las 23:14
-
No sé, mi respuesta se basa en la de ElpieKay (stackoverflow.com/a/46951323/3668967), así que tal vez él pueda ayudarte.
-Karol Selak
1 de mayo de 2020 a las 15:27
Se puede hacer. ¿Ha publicado su repositorio en un servidor remoto (github, gitlab, otro…)? ¿Hay otra persona que trabaje con él?
– Techniv
26 de octubre de 2017 a las 9:42
Posible duplicado de Eliminar archivos confidenciales y sus confirmaciones del historial de Git
– kowsky
26 de octubre de 2017 a las 9:44
Para ser estrictos, esta es la cuenta de nuestra empresa, pocas personas tienen acceso a ella y usamos el repositorio interno de GitHub en nuestro propio servidor. Pero, en general, por ahora se confía en todas las personas que tienen acceso al repositorio.
-Karol Selak
26 de octubre de 2017 a las 9:46