# Commits rückgängig machen: reset vs. revert 🔄

Du hast also einen oder mehrere Commits gemacht, die du loswerden möchtest – vielleicht war ein Fehler dabei, oder du hast dich in eine falsche Richtung entwickelt. Git bietet dafür zwei grundlegend verschiedene Strategien: **Reset** und **Revert**. Welche du wählen solltest, hängt entscheidend davon ab, ob du die Commits **bereits gepusht** hast oder nicht.

---

## Das Grundprinzip verstehen

Bevor wir in die Details gehen, hier die Kernfrage, die du dir immer stellen solltest:

> **Haben andere Menschen (oder ich selbst auf einem anderen Gerät) bereits Zugriff auf diese Commits?**

Diese Frage bestimmt, welchen Weg du gehen solltest:

```mermaid
flowchart TD
    A["Commit rueckgaengig machen?"] --> B{"Bereits gepusht?"}
    B -->|Nein| C["git reset\nHistorie umschreiben"]
    B -->|Ja| D["git revert\nNeuen Commit erstellen"]
    
    C --> E["Commits verschwinden\naus der Historie"]
    D --> F["Alter Commit bleibt,\nwird durch neuen rueckgaengig gemacht"]
    
    style C fill:#90EE90,color:#000000
    style D fill:#87CEEB,color:#000000
```

---

## Methode 1: `git reset` – die Historie umschreiben ✂️

Mit `reset` **entfernst** du Commits aus deiner lokalen Historie, als hätten sie nie existiert. Das ist sauber und elegant – aber nur, solange niemand sonst diese Commits bereits hat.

### Die drei Varianten von Reset

Git reset gibt es in drei „Härtegraden", die bestimmen, was mit deinen Änderungen passiert:

1. **`--soft`** – der sanfte Reset
   
   Die Commits werden entfernt, aber alle Änderungen bleiben in der **Staging Area** erhalten. Du kannst sie direkt neu committen (z. B. mit einer besseren Nachricht oder anders aufgeteilt).
   
   ```bash
   git reset --soft HEAD~1    # Letzten Commit entfernen, Änderungen bleiben staged
   ```

2. **`--mixed`** (Standard) – der mittlere Weg
   
   Die Commits werden entfernt, die Änderungen landen im **Working Directory** (also nicht mehr staged, aber noch vorhanden). Du kannst entscheiden, was du davon behalten möchtest.
   
   ```bash
   git reset HEAD~1           # Letzten Commit entfernen, Änderungen im Working Directory
   git reset --mixed HEAD~1   # Identisch zur Zeile darüber
   ```

3. **`--hard`** – der radikale Reset ⚠️
   
   Die Commits werden entfernt **und** alle Änderungen werden **unwiderruflich gelöscht**. Hier ist Vorsicht geboten!
   
   ```bash
   git reset --hard HEAD~1    # Letzten Commit UND alle Änderungen komplett löschen
   ```

### Was bedeutet `HEAD~1`?

- `HEAD` zeigt auf deinen aktuellen Commit
- `HEAD~1` bedeutet „ein Commit vor HEAD"
- `HEAD~3` würde drei Commits zurückgehen
- Du kannst auch einen konkreten Commit-Hash angeben: `git reset --soft abc1234`

### Reset in PhpStorm durchführen

1. Öffne das **Git-Log** (unten im Git-Tab)
2. Finde den Commit, zu dem du **zurückkehren** möchtest (also den letzten „guten" Commit)
3. **Rechtsklick** auf diesen Commit
4. Wähle **Reset Current Branch to Here...**
5. Im Dialog wählst du zwischen **Soft**, **Mixed** oder **Hard**

> 💡 **Tipp:** In PhpStorm siehst du direkt eine Erklärung zu jeder Option, was sehr hilfreich ist.

---

## Methode 2: `git revert` – sicher rückgängig machen 🛡️

Mit `revert` erstellst du einen **neuen Commit**, der die Änderungen eines früheren Commits rückgängig macht. Die ursprünglichen Commits bleiben in der Historie erhalten – es wird nur ein „Gegengift" hinzugefügt.

### Warum Revert statt Reset bei gepushten Commits?

Wenn du Commits gepusht hast und dann mit `reset` deine lokale Historie umschreibst, entsteht ein Problem: Dein lokales Repository und das Remote-Repository haben dann **unterschiedliche Historien**. Git wird sich weigern, deinen Push zu akzeptieren, und du müsstest einen **Force Push** machen – was die Historie für alle anderen zerstört, die vielleicht schon mit diesen Commits arbeiten.

`revert` vermeidet dieses Problem elegant:

```mermaid
flowchart LR
    subgraph "Nach Reset - GEFÄHRLICH"
        A1["Commit A"] --> A2["Commit B"] --> A3["Commit C"]
        A1 -.->|"reset"| A4["Commit C\nverschwunden"]
    end
    
    subgraph "Nach Revert - SICHER"
        B1["Commit A"] --> B2["Commit B"] --> B3["Commit C"] --> B4["Revert C\nmacht C rueckgaengig"]
    end
```

### Revert im Terminal

```bash
# Den letzten Commit rückgängig machen
git revert HEAD

# Einen bestimmten Commit rückgängig machen (per Hash)
git revert abc1234

# Mehrere Commits auf einmal revert (ältester..neuester)
git revert abc1234..def5678
```

Nach dem Revert öffnet sich normalerweise ein Editor für die Commit-Nachricht. Git schlägt automatisch etwas wie „Revert ‚Feature XY hinzugefügt'" vor, was du anpassen oder übernehmen kannst.

### Revert in PhpStorm durchführen

1. Öffne das **Git-Log**
2. Finde den Commit, den du rückgängig machen möchtest
3. **Rechtsklick** auf den Commit
4. Wähle **Revert Commit**
5. PhpStorm erstellt automatisch einen neuen Commit, der die Änderungen umkehrt

---

## Wann welche Methode? – Die Entscheidungshilfe

| Situation | Empfohlene Methode | Begründung |
|-----------|-------------------|------------|
| Commit noch nicht gepusht, du möchtest neu committen | `reset --soft` | Änderungen bleiben staged, du kannst sie direkt verbessern |
| Commit noch nicht gepusht, du möchtest alles überdenken | `reset --mixed` | Änderungen im Working Directory, du wählst neu aus |
| Commit noch nicht gepusht, Änderungen sollen weg | `reset --hard` | Schnell und sauber, aber **unwiderruflich** |
| Commit **bereits gepusht** | `revert` | Sicher, keine Probleme mit Remote |
| Alte Commits mitten in der Historie korrigieren | `revert` | Historie bleibt intakt |
| Gemeinsames Projekt mit anderen | **Immer `revert`** | Teamkollegen werden es dir danken |

---

## Der Sonderfall: Force Push ⚠️

Falls du **trotzdem** nach einem Reset pushen möchtest (weil du z. B. allein am Projekt arbeitest und sicher bist, dass niemand sonst betroffen ist), kannst du einen **Force Push** machen:

```bash
git push --force
# oder etwas sicherer:
git push --force-with-lease
```

In **PhpStorm** findest du diese Option im Push-Dialog unter **Force Push**.

> ⚠️ **Wichtig:** Force Push überschreibt die Remote-Historie unwiderruflich. Nutze das nur, wenn du **absolut sicher** bist, dass niemand anderes mit diesen Commits arbeitet. In Team-Projekten ist Force Push auf den Main-Branch oft sogar verboten.

Die Option `--force-with-lease` ist etwas sicherer: Sie verweigert den Push, falls jemand anderes in der Zwischenzeit gepusht hat.

---

## Praktisches Beispiel: Der typische „Oh nein"-Moment

**Szenario:** Du hast gerade einen Commit gemacht und gepusht, der versehentlich Debug-Code enthält.

1. **Prüfen, was passiert ist:**
   
   Schau im Git-Log, welcher Commit das Problem verursacht hat (notiere dir den Hash, z. B. `a1b2c3d`).

2. **Revert durchführen:**
   ```bash
   git revert a1b2c3d
   ```
   
   Oder in PhpStorm: Rechtsklick auf den Commit → **Revert Commit**

3. **Den Revert-Commit pushen:**
   ```bash
   git push
   ```

4. **Fertig!** Die Debug-Änderungen sind rückgängig gemacht, und die Historie zeigt transparent, was passiert ist.

---

## Zusammenfassung 📋

- **`reset`** schreibt die Historie um – ideal für lokale Commits, die noch niemand gesehen hat
- **`revert`** erstellt einen neuen „Rückgängig-Commit" – sicher für bereits gepushte Commits
- **Faustregel:** Sobald ein Commit gepusht wurde, nutze `revert`
- **Force Push** nur im Notfall und nur bei Solo-Projekten
- PhpStorm bietet für beide Methoden komfortable Menüoptionen im Git-Log