# Git-Historie durchsuchen ## Kurzfassung `rg` durchsucht normalerweise den aktuellen Dateistand. Auch mit `--hidden --no-ignore` wird die eigentliche Git-Historie nicht zuverlässig durchsucht: Die historischen Objekte liegen unter `.git/objects` komprimiert und über ihre Hashes organisiert. Für die Git-Historie verwendet man je nach Fragestellung `git log`, `git grep` und `git rev-list`. ## Änderungen mit `git log` finden ### Exakte Zeichenfolge: `-S` Mit `-S` findet man Commits, in denen sich die Anzahl einer exakten Zeichenfolge geändert hat — also typischerweise, wenn eine Zeichenfolge hinzugefügt oder entfernt wurde: ```bash git log --all -S'example_endpoint' --oneline ``` Die zugehörigen Änderungen anzeigen: ```bash git log --all -S'example_endpoint' -p ``` ### Regulärer Ausdruck: `-G` Mit `-G` sucht Git in hinzugefügten und entfernten Zeilen nach einem regulären Ausdruck: ```bash git log --all -G'example[_-]endpoint' --oneline ``` Mit Patch-Ausgabe: ```bash git log --all -G'example[_-]endpoint' -p ``` `--all` bezieht alle Commits ein, die von lokalen Branches, Remote-Tracking- Branches und Tags erreichbar sind. ## Vollständige historische Dateistände durchsuchen `git log -S` und `git log -G` suchen nach Änderungen. Wenn stattdessen jeder vollständige Dateistand durchsucht werden soll, kann man `git grep` mit `git rev-list` kombinieren: ```bash git rev-list --all | while read commit; do git grep -n -E 'example[_-]endpoint' "$commit" -- && echo "Found in $commit" done ``` Die Ausgabe enthält die Commit-ID, die betroffene Datei und die Zeilennummer. Einen einzelnen historischen Dateistand kann man direkt durchsuchen: ```bash git grep -n -E 'example[_-]endpoint' ``` Ein Commit kann beispielsweise ein vollständiger Hash, ein Branch-Name oder ein Tag sein: ```bash git grep -n -E 'example[_-]endpoint' HEAD~10 git grep -n -E 'example[_-]endpoint' v1.2.0 ``` ## Reflog und nicht mehr erreichbare Commits `--all` findet nur Commits, die noch über Referenzen erreichbar sind. Kürzlich gelöschte Branches können zusätzlich über die Reflogs gefunden werden: ```bash git log --all --reflog -G'example[_-]endpoint' --oneline ``` Falls ein Commit weder über Branches, Tags noch Reflogs erreichbar ist, kann Git ihn eventuell noch als unerreichbares Objekt kennen: ```bash git fsck --full --no-reflogs --unreachable ``` Nur unerreichbare Commits durchsuchen: ```bash git fsck --full --no-reflogs --unreachable | awk '$2 == "commit" { print $3 }' | while read commit; do git grep -n -E 'example[_-]endpoint' "$commit" -- && echo "Found in $commit" done ``` Das funktioniert nur, solange die Objekte noch nicht durch Garbage Collection entfernt wurden. Bei einem Shallow Clone kann außerdem die ältere Historie lokal fehlen. ## `rg` und `.git` Der Befehl: ```bash rg --hidden --no-ignore '/example[\_\-]endpoint' ``` durchsucht den aktuellen Dateibaum einschließlich normalerweise versteckter Dateien. Er durchsucht jedoch nicht sinnvoll die komprimierten historischen Git-Objekte unter `.git/objects`. Für den regulären Ausdruck genügt normalerweise: ```text example[_-]endpoint ``` Der führende `/` ist ein wörtliches Zeichen und sollte nur verwendet werden, wenn tatsächlich ein Slash vor `example` gesucht werden soll. Die Backslashes vor `_` und `-` sind hier ebenfalls nicht erforderlich. Für die Suche im aktuellen Dateistand siehe [[Linux/ripgrep_guide]]. Für Informationen darüber, warum alte Historie fehlen oder umgeschrieben worden kann, siehe [[Git-History-Truncation]].