# Git History Manipulation (13.01.2025)
Einer der grössten Vorteile von Git als Versionsverwaltungs-System ist die Historie. Keine Änderung geht je verloren und es kann immer zu einem früheren Zeitpunkt gewechselt werden.
Es kommt jedoch auch vor, dass man die Historie abändern möchte. Sei es weil man aus Versehen ein Secret oder eine fehlerhafte Änderung veröffentlicht hat oder ob man sich einfach auf dem falschen Branch bewegt hat. In diesem Blog werden wir uns die verschiedenen Möglichkeiten ansehen, um die Git Historie manuell zu verändern.
## Revert[^1]
Der sauberste Weg, um Änderungen rückgängig zu machen, ist über einen Revert. Die Idee liegt darin, dass nicht eine Änderung gelöscht wird, sondern lediglich rückgängig gemacht wird.
Wie aus dieser einfachen Erklärung ersichtlich ist, Ändern wir die Historie damit also nicht. Stattdessen machen wir einen Commit rückgängig, was in einem neuen Commit abgelegt wird. Diese Strategie lohnt sich also nicht, wenn eine Änderung ganz gelöscht werden sollte. Stattdessen ist sie dann hilfreich, wenn eine Änderung fehlerhaft ist und für eine einfache Lösung einfach rückgängig gemacht werden sollte.
Um einen Revert auszuführen müssen wir den `revert` Befehl nutzen:
```bash
git revert <hash>
```
Der Hash hierbei ist die ID des Commits in der Historie. Diese kann mit folgendem Befehl eingesehen werden:
```bash
git log
```
## Reset[^2]
Ein weiterer Weg ist ein sogenannte Reset. Anders als ein Revert machen wir jedoch nicht die Änderungen eines Commits rückgängig, sondern setzten den Stand unseres Branches zu einem bestimmten Commit zurück.
Für einen Reset haben wir wieder den gleichen Aufbau von Befehl:
```bash
git reset <hash>
```
Hierbei ist zu beachten, dass die Änderungen nicht direkt rückgängig gemacht werden, es werden nur die Commits entfernt ohne die Änderungen zu löschen. Einen ganzen Reset ist auch möglich, dafür müssen wir jedoch noch die `--hard` Flag mitgeben:
```bash
git reset <hash> --hard
```
Dann wird unser Head auf diesen Commit zurückgesetzt und alle anschliessenden Änderungen gelöscht.
## Reflog[^3]
Die Bisherigen Strategien sind hilfreich um falsche Commits rückgängig zu machen. Es kommt jedoch auch vor, dass man eine solche Änderung rückgängig machen will. Hat man beispielsweise einen Hard Reset durchgeführt und merkt, dass dies ein Fehler war, dann können wir diese Änderung mit dem Reflog wiederherstellen.
Den Reflog kann man sich wie eine Zeitmaschine vorstellen. In den normalen Gut Logs werden nur die commits gespeichert. Wenn man mit Reset jedoch einen Commit löscht, wird dieser dort nicht mehr aufgeführt. Der Reflog speichert jedoch alle Änderungen des Heads. Wir können also alle Bewegungen innerhalb des Repos wieder rekuperieren.
Mit folgendem Befehl können wir alle Aktionen in unserem Repo einsehen:
```bash
git reflog
```
Anschliessend können wir auf einen früheren Zeitpunkt in unserem Repo wechseln mit:
```bash
git reset HEAD@{index}
```
Hierbei wird index mit dem Wert, welcher im Reflog angegeben wird, ersetzt.
Ein solcher Reset macht keine Commits rückgängig, sondern eine Bewegung unseres Heads. Der Head ist unsere Position innerhalb des Repos. Wir können mit dem Reflog also gelöschte commits aber auch beispielsweise einen gelöschten Branch wieder zurückholen.
## Fazit
Wir haben uns verschiedene Strategien angeschaut um die Historie eines Git Repositories zu verändern. Alle die Fälle adressieren ein anderes Szenario und alle sind auf ihre eigene Weise vorteilhaft. Es ist jedoch wichtig, alle Strategien zu kennen um in den richtigen Situationen auch möglichst vorteilhaft zu reagieren, ohne, dass unnötig Daten verloren gehen.
Wenn man einen Fehler gemacht hat und sich nicht mehr genau an die Befehle erinnert, ist [Oh sh\*t, Git](https://ohshitgit.com/) eine sehr gute Ressource.
[^1]: vgl. git-revert, in: Git Documentation, 13.01.2025, https://git-scm.com/docs/git-revert
[^2]: vgl. git-reset, in; Git Documentation, 13.01.2025, https://git-scm.com/docs/git-reset
[^3]: vgl. git-reflog, in: Git Documentation, 13.01.2025, https://git-scm.com/docs/git-reflog