# Push-Konflikte: Wenn GitHub „ahead" ist 🚧

Du möchtest deine lokalen Commits auf GitHub pushen, aber Git verweigert das mit einer Fehlermeldung. Das passiert, wenn das Remote-Repository **neuere Commits enthält**, die du lokal noch nicht hast. Diese Situation ist völlig normal und gehört zum Git-Alltag – besonders wenn du an mehreren Geräten arbeitest oder mit anderen zusammenarbeitest.

---

## Warum lehnt Git den Push ab?

Git hat eine wichtige Schutzfunktion: Es verhindert, dass du versehentlich Änderungen auf dem Server **überschreibst**, die du noch gar nicht gesehen hast. Wenn das Remote-Repository Commits enthält, die in deiner lokalen Historie fehlen, sagt Git sinngemäß:

> „Stopp! Auf dem Server gibt es neuere Änderungen. Hol dir die erst, bevor du deine eigenen hochlädst."

Die typische Fehlermeldung sieht ungefähr so aus:

```
! [rejected]        main -> main (fetch first)
error: failed to push some refs to 'github.com:username/repo.git'
hint: Updates were rejected because the remote contains work that you do not
hint: have locally. This is usually caused by another repository pushing to
hint: the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
```

Das folgende Diagramm zeigt, wie diese Situation entsteht:

```mermaid
flowchart TB
    subgraph LOCAL["💻 Dein lokaler Stand"]
        L1["Commit A"] --> L2["Commit B"] --> L3["Commit C\n- deine neue Arbeit"]
    end
    
    subgraph REMOTE["☁️ GitHub-Stand"]
        R1["Commit A"] --> R2["Commit B"] --> R3["Commit X\n- andere Aenderung"]
    end
    
    L3 -.->|"Push verweigert!"| R3
```

Du bist bei **Commit C**, aber GitHub hat in der Zwischenzeit **Commit X** bekommen. Git weiß nicht, wie es diese beiden zusammenbringen soll, ohne dass du es ihm sagst.

---

## Die Lösung: Erst Pull, dann Push

Der Standard-Workflow in dieser Situation ist einfach:

1. **Hole die Remote-Änderungen** mit `git pull`
2. **Löse eventuelle Konflikte** (falls dieselben Stellen geändert wurden)
3. **Pushe dann erneut** deine kombinierten Änderungen

### In PhpStorm durchführen

1. **Pull durchführen**
   
   Gehe zu **Git → Pull** (oder drücke `Ctrl+T` bzw. `Cmd+T` auf macOS). PhpStorm zeigt dir ein Dialogfenster, in dem du den Remote-Branch auswählen kannst – normalerweise ist das schon korrekt voreingestellt.

2. **Ergebnis prüfen**
   
   Nach dem Pull gibt es drei mögliche Szenarien:
   
   - **Alles automatisch zusammengeführt:** Git konnte die Änderungen problemlos kombinieren. Du siehst eine Erfolgsmeldung und kannst direkt pushen.
   - **Merge-Commit erstellt:** Wenn die Änderungen in unterschiedlichen Dateien oder an unterschiedlichen Stellen waren, erstellt Git automatisch einen „Merge-Commit", der beide Historien zusammenführt.
   - **Konflikte aufgetreten:** Wenn dieselben Zeilen in derselben Datei geändert wurden, musst du manuell entscheiden, welche Version gilt (siehe unten).

3. **Push erneut versuchen**
   
   Nach erfolgreichem Pull gehst du zu **Git → Push** (oder `Ctrl+Shift+K` bzw. `Cmd+Shift+K`). Jetzt sollte der Push funktionieren.

---

## Was passiert beim Pull genau?

Hinter den Kulissen macht `git pull` eigentlich **zwei Dinge**:

```mermaid
flowchart LR
    A["git pull"] --> B["git fetch\n- Aenderungen herunterladen"]
    B --> C["git merge\n- Aenderungen integrieren"]
```

- **Fetch:** Lädt die neuen Commits vom Server herunter, ohne sie direkt in deinen Branch zu integrieren.
- **Merge:** Führt die heruntergeladenen Commits mit deinem lokalen Branch zusammen.

Nach einem erfolgreichen Pull sieht deine Historie so aus:

```mermaid
flowchart TB
    A["Commit A"] --> B["Commit B"]
    B --> C["Commit C\n- deine Arbeit"]
    B --> X["Commit X\n- andere Aenderung"]
    C --> M["Merge-Commit\n- beide zusammengefuehrt"]
    X --> M
```

---

## Wenn Konflikte auftreten

Falls du und die andere Änderung (oder du selbst vom anderen Computer) **dieselben Codezeilen** bearbeitet habt, kann Git nicht automatisch entscheiden, welche Version richtig ist. PhpStorm zeigt dir dann den **Merge-Dialog**:

1. **Konflikt-Benachrichtigung**
   
   PhpStorm meldet, dass Konflikte aufgetreten sind und fragt, ob du sie lösen möchtest. Klicke auf **Merge** oder **Resolve**.

2. **Drei-Spalten-Editor nutzen**
   
   Du siehst drei Spalten nebeneinander:
   
   - **Links:** Deine lokale Version
   - **Rechts:** Die Version von GitHub
   - **Mitte:** Das Ergebnis, das du erstellen möchtest
   
   Mit den Pfeiltasten (`>>` und `<<`) oder durch direktes Bearbeiten in der Mitte kannst du entscheiden, welche Änderungen übernommen werden.

3. **Konflikt als gelöst markieren**
   
   Sobald du fertig bist, klickst du auf **Apply**. PhpStorm markiert den Konflikt als gelöst.

4. **Merge-Commit abschließen**
   
   Nachdem alle Konflikte gelöst sind, fordert PhpStorm dich auf, den Merge-Commit abzuschließen. Bestätige dies, und dann kannst du pushen.

---

## Alternative: Rebase statt Merge

Neben dem klassischen Merge gibt es noch eine andere Strategie namens **Rebase**. Dabei werden deine lokalen Commits so umgeschrieben, als hättest du sie *nach* den Remote-Änderungen gemacht. Das ergibt eine **lineare Historie** ohne Merge-Commits:

```mermaid
flowchart LR
    A["Commit A"] --> B["Commit B"] --> X["Commit X\n- von GitHub"] --> C2["Commit C\n- deine Arbeit, neu aufgesetzt"]
```

### Rebase in PhpStorm aktivieren

1. Gehe zu **Git → Pull**
2. Im Pull-Dialog aktiviere die Option **Rebase** (statt Merge)
3. Führe den Pull durch

Oder du stellst es als Standard ein unter **Settings → Version Control → Git → Update Method → Rebase**.

### Wann Rebase, wann Merge?

| Situation | Empfehlung |
|-----------|------------|
| Du arbeitest allein oder an einem Feature-Branch | **Rebase** – für eine saubere, lineare Historie |
| Mehrere Personen arbeiten am selben Branch | **Merge** – sicherer, da keine Historie umgeschrieben wird |
| Du hast den Branch bereits gepusht und andere arbeiten damit | **Merge** – Rebase würde deren Arbeit durcheinanderbringen |
| Du bist unsicher | **Merge** – es ist die sichere Standardoption |

---

## Tipps zur Vermeidung dieser Situation

Auch wenn die Lösung nicht schwer ist, kannst du dir das Leben leichter machen:

- **Regelmäßig pullen:** Bevor du anfängst zu arbeiten, ziehe dir erst die neuesten Änderungen. Das reduziert die Wahrscheinlichkeit von Konflikten.
- **Häufig pushen:** Je öfter du deine Änderungen hochlädst, desto kleiner sind die Unterschiede zwischen lokal und remote.
- **Kommunikation im Team:** Wenn mehrere Personen an denselben Dateien arbeiten, sprecht euch ab, wer wann welche Bereiche bearbeitet.
- **Feature-Branches nutzen:** Arbeite in separaten Branches statt direkt auf `main`. So vermeidest du Konflikte mit anderen, bis du bewusst mergst.

---

## Zusammenfassung

| Problem | Lösung |
|---------|--------|
| Push wird abgelehnt wegen neuerer Remote-Commits | `git pull` durchführen, dann erneut pushen |
| Pull führt zu Konflikten | Konflikte in PhpStorm mit dem Drei-Spalten-Editor lösen |
| Du möchtest eine lineare Historie | Rebase statt Merge beim Pull verwenden |

Der Ablauf ist also immer: **Pull → (Konflikte lösen) → Push**. Mit etwas Routine wird das schnell zur Gewohnheit, und du wirst sehen, dass diese Situationen viel weniger beängstigend sind, als sie anfangs wirken. 😊