# Git & GitHub meistern: Vom ersten Commit zum professionellen Workflow mit Windows 11 und PhpStorm

Ein umfassender Praxiskurs für Git und GitHub unter Windows 11 und in PhpStorm. Das Buch führt von Versionskontroll-Grundlagen über Branching, Teamwork und Automatisierung bis zu Git-Interna, Sicherheit, Administration, Fehlersuche und professionellen Enterprise-Workflows.

# Versionskontrolle und Git verstehen

Dieses Kapitel erklärt, warum Versionskontrolle unverzichtbar ist und welche Probleme Git löst. Du lernst Snapshots, Repositories, Commits, Arbeitsstände und verteilte Systeme kennen und grenzt Git von GitHub sowie von zentralen Werkzeugen wie Subversion verständlich ab.

# Warum Software versioniert wird

## Lernziele

Nach dieser Lektion kannst du erklären,

- warum Softwareprojekte eine nachvollziehbare Historie benötigen,
- welche Risiken ohne Versionskontrolle entstehen,
- warum Kopien wie `projekt_final_neu_wirklichfinal` keine verlässliche Lösung sind,
- wie Versionierung Zusammenarbeit, Qualität und Sicherheit unterstützt,
- weshalb Git nicht nur für große Teams, sondern auch für Einzelentwickler wertvoll ist.

---

## Software verändert sich ständig

Software ist kein statisches Dokument. Schon ein kleines Projekt entwickelt sich fortlaufend weiter:

- Funktionen kommen hinzu.
- Fehler werden korrigiert.
- Abhängigkeiten werden aktualisiert.
- Konfigurationen ändern sich.
- Dateien werden umbenannt, verschoben oder gelöscht.
- Anforderungen ändern sich nach Gesprächen mit Kunden, dem Team oder dem Fachbereich.

Eine einzelne Datei kann dabei dutzende oder hunderte Änderungen durchlaufen. Bei einem PHP-Projekt betrifft das häufig nicht nur den Anwendungscode, sondern auch Tests, Composer-Konfiguration, Datenbankmigrationen, Dokumentation und CI-Konfiguration.

Die entscheidende Frage lautet daher nicht, *ob* sich ein Projekt verändert, sondern:

> **Wie lässt sich nachvollziehen, was sich wann, warum und durch wen verändert hat?**

Genau dafür wird Software versioniert.

---

## Das Problem ohne Versionskontrolle

Stell dir vor, du entwickelst eine kleine PHP-Anwendung für eine Terminverwaltung. Zu Beginn existiert nur eine Datei:

```text
terminverwaltung/
└── index.php
```

Im Laufe der Zeit ergänzt du Validierungen, einen Datenbankzugriff und ein Login. Vor einer riskanten Änderung erstellst du vorsichtshalber eine Kopie des gesamten Ordners:

```text
terminverwaltung/
terminverwaltung_backup/
terminverwaltung_backup_neu/
terminverwaltung_final/
terminverwaltung_final2/
terminverwaltung_final_wirklich/
```

Dieses Vorgehen wirkt zunächst sicher, führt aber schnell zu Problemen.

### Unklare Bedeutung von Kopien

An den Ordnernamen ist kaum zu erkennen:

- Welche Version läuft produktiv?
- Welche Kopie enthält den letzten funktionierenden Stand?
- Welche Änderung wurde zwischen `final` und `final2` vorgenommen?
- Welche Version enthält den Fehler?
- Darf ein alter Ordner gelöscht werden?

Der Dateiname oder Ordnername wird zur improvisierten Versionshistorie. Diese Historie ist jedoch unvollständig, fehleranfällig und schwer durchsuchbar.

### Änderungen gehen verloren

Wenn du eine Funktion umbaust und später feststellst, dass die frühere Variante besser war, brauchst du den alten Zustand. Ohne Versionskontrolle musst du hoffen, dass eine passende Sicherheitskopie existiert.

Fehlt sie, bleibt nur:

- Änderungen mühsam zurückbauen,
- Code aus Erinnerungen rekonstruieren,
- Dateien vergleichen,
- oder Arbeit erneut erledigen.

### Zusammenarbeit überschreibt Arbeit

Arbeiten zwei Personen gleichzeitig an derselben Datei, entsteht ein besonders gefährliches Szenario:

1. Anna bearbeitet `UserService.php`.
2. Ben bearbeitet ebenfalls `UserService.php`.
3. Anna speichert ihre Datei.
4. Ben speichert später seine Datei über Annas Version.

Je nach Arbeitsweise kann Annas Änderung vollständig verschwinden. Selbst wenn beide vorher Kopien angelegt haben, ist später oft unklar, welche Teile aus welcher Datei übernommen werden müssen.

### Fehler sind schwer einzugrenzen

Ein Fehler wird am Montag entdeckt. Am Freitag funktionierte noch alles. Inzwischen gab es viele Änderungen.

Ohne Historie ist die Fehlersuche mühsam:

- Welche Dateien wurden seit Freitag verändert?
- Welche konkrete Zeile war die Ursache?
- Wer kennt die fachliche Entscheidung hinter der Änderung?
- Lässt sich der funktionierende Zustand kurzfristig wiederherstellen?

Ohne belastbare Antworten steigt der Zeitaufwand – und das Risiko, beim Reparieren neue Fehler einzubauen.

---

## Versionierung schafft eine überprüfbare Projektgeschichte

Versionskontrolle speichert nicht einfach nur Dateikopien. Sie hält eine **Geschichte bewusst festgehaltener Projektzustände** fest.

Ein solcher gespeicherter Zustand wird in Git später *Commit* genannt. Ein Commit dokumentiert typischerweise:

- welche Dateien geändert wurden,
- welche Inhalte sich geändert haben,
- wann die Änderung gespeichert wurde,
- wer sie erstellt hat,
- und warum sie vorgenommen wurde.

Statt vieler unklarer Projektordner entsteht eine nachvollziehbare Abfolge:

```text
Projektbeginn
    ↓
Grundstruktur angelegt
    ↓
Benutzerregistrierung ergänzt
    ↓
Passwortvalidierung korrigiert
    ↓
Tests für Login hinzugefügt
    ↓
Sicherheitslücke geschlossen
```

Die Historie wird damit zu einem technischen Gedächtnis des Projekts.

---

## Die zentralen Gründe für Versionskontrolle

### Änderungen nachvollziehen

Eine gute Projektgeschichte beantwortet wichtige Fragen schnell:

- Was wurde verändert?
- Wann wurde es verändert?
- Wer hat es verändert?
- Warum wurde es verändert?
- Zu welchem Ticket, Issue oder Fehlerbericht gehört die Änderung?

Ein Commit kann beispielsweise die Nachricht tragen:

```text
Fix: Passwort-Hash vor dem Speichern erzeugen
```

Diese Nachricht ist wesentlich hilfreicher als eine Ordnerkopie namens `backup_17`.

> **Grundsatz:** Eine Änderung ohne nachvollziehbaren Zweck wird später teuer – spätestens bei Wartung, Fehlersuche oder Review.

---

### Frühere Zustände wiederherstellen

Nicht jede Änderung ist erfolgreich. Ein neues Feature kann Fehler verursachen, eine Konfigurationsänderung kann den Build beschädigen oder ein Refactoring kann unerwartete Seiteneffekte haben.

Versionskontrolle ermöglicht es, gezielt zu einem früheren Zustand zurückzukehren oder einzelne ältere Dateiversionen wiederherzustellen.

Das bedeutet nicht, dass man sorglos arbeiten sollte. Es bedeutet aber, dass experimentelles Arbeiten kontrollierbar wird:

- Du kannst eine Idee ausprobieren.
- Du kannst Änderungen vergleichen.
- Du kannst einen Fehler isolieren.
- Du kannst einen funktionierenden Stand wiederherstellen.
- Du kannst eine falsche Entscheidung transparent korrigieren.

Damit wird das Projekt widerstandsfähiger gegenüber menschlichen Fehlern.

---

### Parallel arbeiten

In professionellen Projekten arbeiten mehrere Personen gleichzeitig:

- Entwicklerinnen und Entwickler implementieren Features.
- Tester prüfen Fehlerkorrekturen.
- DevOps-Teams ändern Deployment-Konfigurationen.
- Technische Redaktionen aktualisieren Dokumentation.
- Sicherheitsverantwortliche prüfen Abhängigkeiten und Richtlinien.

Versionskontrolle koordiniert diese parallele Arbeit. Sie erkennt, wenn Änderungen unabhängig voneinander kombiniert werden können, und macht sichtbar, wenn zwei Personen denselben Bereich unterschiedlich verändert haben.

Solche Überschneidungen heißen später **Konflikte**. Ein Konflikt ist keine Beschädigung des Projekts, sondern ein Hinweis:

> Git kann nicht zuverlässig entscheiden, welche von zwei konkurrierenden Änderungen fachlich richtig ist.

Menschen treffen diese Entscheidung bewusst. Das ist deutlich sicherer, als Änderungen unbemerkt zu überschreiben.

---

### Fehler schneller finden

Eine Projektgeschichte hilft nicht nur beim Zurücksetzen. Sie ist auch ein Diagnosewerkzeug.

Angenommen, eine API-Anfrage liefert seit kurzem falsche Daten. Mit einer Historie kannst du untersuchen:

1. Wann trat der Fehler erstmals auf?
2. Welche Änderungen wurden kurz davor integriert?
3. Welche Datei oder Funktion wurde verändert?
4. Welche Person kennt den fachlichen Hintergrund?
5. Welcher Commit führte die fehlerhafte Änderung ein?

Git bietet dafür später Funktionen wie Log-Ansichten, Diffs, Dateihistorien und `git bisect`. Sie helfen dabei, Fehler systematisch einzugrenzen, statt nur Vermutungen anzustellen.

---

### Code-Reviews ermöglichen

Bevor eine Änderung in den Hauptzweig eines Projekts gelangt, sollte sie oft von einer anderen Person geprüft werden. Dieser Prozess heißt **Code Review**.

Ein Review funktioniert nur, wenn klar erkennbar ist:

- Welche Änderung wird vorgeschlagen?
- Welche Dateien sind betroffen?
- Was war das Ziel?
- Welche Tests wurden ergänzt oder ausgeführt?
- Welche Auswirkungen sind zu erwarten?

Versionskontrolle liefert dafür eine präzise Änderungsmenge. Statt ein gesamtes Projekt manuell zu vergleichen, prüfen Reviewer gezielt die Unterschiede zwischen zwei definierten Ständen.

Das verbessert nicht nur die Codequalität. Reviews fördern auch Wissenstransfer, gemeinsame Standards und frühzeitige Sicherheitsprüfungen.

---

### Releases reproduzierbar machen

Software wird häufig in klaren Versionen veröffentlicht, etwa als `1.0.0`, `1.1.0` oder `2.0.0`.

Ohne Versionskontrolle ist es schwierig, sicher zu beantworten:

- Welcher Quellcode wurde für Version `1.4.2` ausgeliefert?
- Welche Konfiguration gehörte zu diesem Release?
- Welche Fehlerkorrektungen sind darin enthalten?
- Kann derselbe Stand erneut gebaut werden?
- Lässt sich ein Hotfix auf genau dieser Basis entwickeln?

Mit Versionierung kann ein Release eindeutig an einen bestimmten Projektzustand gebunden werden. Später werden dafür Git-Tags verwendet.

Das ist besonders wichtig, wenn eine ältere Produktversion weiterhin gewartet werden muss.

---

### Wissen dauerhaft im Projekt festhalten

Teams verändern sich. Personen wechseln Aufgaben, verlassen ein Unternehmen oder erinnern sich nach Monaten nicht mehr an jede Entscheidung.

Eine gute Historie ergänzt Dokumentation. Sie kann beispielsweise zeigen:

- warum eine Validierung absichtlich streng ist,
- weshalb eine Abhängigkeit aktualisiert wurde,
- warum eine scheinbar unnötige Sonderbehandlung existiert,
- welches Issue einen Fehler beschrieben hat,
- welche Sicherheitslücke geschlossen wurde.

Natürlich ersetzt eine Commit-Nachricht keine vollständige Architektur- oder Fachkonzeptdokumentation. Sie hält aber den Zusammenhang zwischen einer konkreten Codeänderung und ihrer Entscheidung fest.

---

## Versionskontrolle ist mehr als ein Backup

Backups und Versionskontrolle haben unterschiedliche Aufgaben.

| Aspekt | Backup | Versionskontrolle |
|---|---|---|
| Hauptziel | Datenverlust verhindern | Änderungen nachvollziehbar verwalten |
| Typischer Umfang | Gesamter Datenbestand | Projektdateien und ihre Historie |
| Zeitpunkt | Meist automatisch oder periodisch | Bewusst bei fachlich sinnvollen Änderungen |
| Vergleich einzelner Änderungen | Oft umständlich | Zentrale Funktion |
| Zusammenarbeit | Nicht dafür ausgelegt | Zentrale Funktion |
| Rückkehr zu einer bestimmten Änderung | Häufig schwierig | Gezielt möglich |
| Dokumentation des Zwecks | Meist nicht vorhanden | Commit-Nachrichten und Referenzen |

Ein Backup schützt beispielsweise vor einem defekten Datenträger, Ransomware oder versehentlich gelöschten Daten. Git schützt nicht zuverlässig vor allen diesen Risiken, insbesondere nicht allein auf einem einzelnen Computer.

Umgekehrt beantwortet ein Backup normalerweise nicht die Frage:

> „Welche Zeilen wurden geändert, als die Passwortvalidierung angepasst wurde?“

Die professionelle Praxis lautet deshalb:

> **Versionskontrolle und Backups ergänzen einander – keines ersetzt das andere.**

---

## Ein Beispiel aus dem PHP-Alltag

Nehmen wir an, eine Methode zur E-Mail-Prüfung wird geändert.

**Vorher:**

```php
function isValidEmail(string $email): bool
{
    return str_contains($email, '@');
}
```

**Nachher:**

```php
function isValidEmail(string $email): bool
{
    return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
}
```

Ohne Versionskontrolle ist später nur sichtbar, wie die Datei *jetzt* aussieht. Der frühere Ansatz, der Zeitpunkt der Änderung und die Motivation gehen verloren.

Mit Versionskontrolle kann die Änderung als eigener Commit festgehalten werden:

```text
Fix: E-Mail-Adressen mit PHP-Filter validieren
```

Zusätzlich können Tests im selben Commit dokumentieren, welche Fälle berücksichtigt wurden. Später lässt sich eindeutig nachvollziehen:

- welche Implementierung ersetzt wurde,
- warum die Änderung erfolgte,
- welche Dateien dazugehören,
- und ob die Änderung mit einem Bug-Report verknüpft war.

---

## Versionierung unterstützt kleine und große Projekte

Ein verbreiteter Irrtum lautet:

> „Git brauche ich erst, wenn mehrere Personen am Projekt arbeiten.“

Tatsächlich profitieren Einzelentwickler besonders früh von Versionierung.

### Für Einzelentwickler

Git hilft dir,

- Experimente sicher auszuprobieren,
- Änderungen in kleinen Schritten festzuhalten,
- Fehler auf frühere Änderungen zurückzuführen,
- zwischen mehreren Aufgaben zu wechseln,
- ältere Zustände wiederzufinden,
- und ein Portfolio mit nachvollziehbarer Entwicklung zu pflegen.

### Für Teams

Zusätzlich unterstützt Git,

- parallele Feature-Entwicklung,
- Pull Requests und Code Reviews,
- geregelte Freigaben,
- Release-Management,
- CI-Prüfungen,
- Branch-Schutz,
- und eine gemeinsame, transparente Projektgeschichte.

Der Einstieg lohnt sich daher bereits beim ersten ernsthaften Projekt.

---

## Was genau sollte versioniert werden?

Grundsätzlich gehören Dateien in die Versionskontrolle, wenn sie nötig sind, um das Projekt zu verstehen, zu entwickeln, zu testen oder reproduzierbar zu bauen.

Für ein PHP-Projekt sind das häufig:

```text
src/
tests/
config/
public/
composer.json
composer.lock
phpunit.xml
README.md
.github/
```

Nicht versioniert werden sollten typischerweise Dateien, die lokal erzeugt werden, vertrauliche Daten enthalten oder sich jederzeit reproduzieren lassen, beispielsweise:

```text
vendor/
.idea/workspace.xml
.env
var/cache/
var/log/
```

Welche Dateien ignoriert werden sollen, hängt vom Projekt ab. Die Regeln dafür werden später mit `.gitignore` systematisch behandelt.

Wichtig ist zunächst das Prinzip:

> **Versioniere den gemeinsamen, nachvollziehbaren Projektzustand – nicht persönliche Arbeitsreste oder geheime Zugangsdaten.**

---

## Gute Versionierung beginnt mit kleinen, sinnvollen Schritten

Versionskontrolle entfaltet ihren größten Nutzen, wenn Änderungen klar abgegrenzt werden.

Ungünstig wäre ein riesiger Sammel-Commit wie:

```text
Diverse Änderungen
```

Darin könnten sich gleichzeitig befinden:

- ein neues Feature,
- eine Fehlerkorrektur,
- Formatierungsänderungen,
- aktualisierte Abhängigkeiten,
- und eine versehentlich eingecheckte Konfigurationsdatei.

Besser sind kleine, logisch zusammenhängende Schritte:

```text
Feat: Terminvalidierung ergänzen
Test: Ungültige Endzeiten abdecken
Fix: Zeitzone beim Speichern berücksichtigen
Docs: API-Beispiel für Terminanlage ergänzen
```

Dadurch wird die Historie lesbar, überprüfbar und leichter rückgängig zu machen.

---

## Git als Werkzeug für diese Aufgabe

Git ist ein verteiltes Versionskontrollsystem. Es speichert die Projektgeschichte lokal auf deinem Computer und kann sie mit anderen Repositories austauschen, etwa über GitHub.

Dabei ist Git nicht einfach ein Cloud-Speicher und auch nicht nur ein Werkzeug für Befehlszeilenprofis. Es bildet die Grundlage für viele alltägliche Entwicklungsabläufe:

- lokale Änderungen sicher festhalten,
- neue Entwicklungszweige erstellen,
- Änderungen anderer abrufen,
- Pull Requests prüfen,
- Releases markieren,
- und Fehler bis zu ihrer Ursache zurückverfolgen.

PhpStorm stellt viele dieser Funktionen grafisch bereit. Dennoch ist es wichtig, die zugrunde liegenden Konzepte zu verstehen. Dann kannst du sicher entscheiden, welche Aktion sinnvoll ist – unabhängig davon, ob du die IDE oder die Kommandozeile verwendest.

---

## Merksätze

- **Softwareentwicklung ist Veränderung.** Ohne Historie werden Veränderungen schnell unübersichtlich.
- **Versionskontrolle beantwortet Fragen.** Was, wann, wer und warum sind zentrale Informationen.
- **Git ist kein Ersatz für Backups.** Beide Schutzmechanismen werden benötigt.
- **Auch Einzelentwickler profitieren.** Git macht Experimente, Korrekturen und Fehlersuche sicherer.
- **Kleine, zusammenhängende Änderungen erzeugen eine wertvolle Historie.**
- **Versionskontrolle macht Zusammenarbeit kontrollierbar, nicht automatisch konfliktfrei.**
- **Ein Commit ist ein bewusst dokumentierter Projektzustand**, nicht bloß ein beliebiger Speichervorgang.

---

## Selbstcheck

Prüfe dein Verständnis mit diesen Fragen:

1. Warum sind Ordnerkopien mit Namen wie `projekt_final2` keine zuverlässige Versionsstrategie?
2. Welche Fragen sollte eine gute Projektgeschichte beantworten können?
3. Worin unterscheidet sich Versionskontrolle von einem Backup?
4. Warum ist Git auch bei einem Solo-Projekt sinnvoll?
5. Weshalb sollten unabhängige Änderungen nicht in einem einzigen großen Commit zusammengefasst werden?
6. Welche Arten von Dateien gehören in einem PHP-Projekt normalerweise *nicht* ins Repository?

Im nächsten Abschnitt wird betrachtet, wie Änderungen, Versionen und Projektgeschichte konkret zusammenhängen.

# Änderungen, Versionen und Projektgeschichte

## Änderungen sind die Rohstoffe der Entwicklung

Software entsteht nicht in einem einzigen Schritt. Sie entwickelt sich fortlaufend:

- Eine Funktion wird ergänzt.
- Ein Fehler wird korrigiert.
- Eine Abhängigkeit wird aktualisiert.
- Eine Konfiguration wird angepasst.
- Dokumentation wird verbessert.
- Code wird umstrukturiert, ohne sein Verhalten zu ändern.

Jede dieser Anpassungen ist eine **Änderung**. Für sich genommen kann sie klein sein; über Wochen, Monate und Jahre bilden Änderungen jedoch die Geschichte eines Projekts.

Ohne Versionskontrolle bleibt diese Geschichte meist unsichtbar. Dateien werden überschrieben, Kopien angelegt oder Änderungen nur mündlich kommuniziert. Das funktioniert kurzzeitig, wird aber schnell unsicher.

Stell dir vor, eine Datei `Calculator.php` wird geändert:

```php
public function add(int $a, int $b): int
{
    return $a + $b;
}
```

Später ergänzt jemand eine Eingabeprüfung:

```php
public function add(int $a, int $b): int
{
    if ($a < 0 || $b < 0) {
        throw new InvalidArgumentException('Negative Werte sind nicht erlaubt.');
    }

    return $a + $b;
}
```

Die zweite Variante ist nicht einfach „die Datei“. Sie ist eine *neue Fassung* derselben Datei. Für ein einzelnes Beispiel ist der Unterschied offensichtlich. In einem Projekt mit hunderten Dateien, mehreren Entwicklerinnen und Entwicklern und vielen parallelen Aufgaben ist er ohne Werkzeug kaum zuverlässig nachzuvollziehen.

---

## Was eine Version bedeutet

Eine **Version** ist ein eindeutig nachvollziehbarer Zustand eines Projekts zu einem bestimmten Zeitpunkt.

Dabei geht es nicht nur um eine einzelne Datei. Eine Version kann den gemeinsamen Zustand vieler Bestandteile beschreiben:

- PHP-Quellcode,
- Tests,
- Composer-Konfiguration,
- Dokumentation,
- Konfigurationsdateien,
- CI-Workflows,
- Datenbankschemata,
- Build-Skripte.

Eine Version beantwortet Fragen wie:

- Welcher Code war letzte Woche produktiv?
- Wann wurde dieser Fehler eingeführt?
- Welche Dateien gehörten zu Version `2.1.0`?
- Welche Änderung hat ein Verhalten verändert?
- Wer hat diese Anpassung vorgenommen und warum?
- Wie kann ein früherer funktionierender Stand wiederhergestellt werden?

Eine Versionsnummer wie `1.4.2` ist dabei eine **fachliche Kennzeichnung**, etwa für ein Release. Git selbst verwaltet dagegen technische Zustände über Commits und eindeutige Kennungen. Auf diesen Unterschied wird der Kurs später noch detailliert eingehen.

> **Wichtig:** Eine Version ist nicht zwingend eine veröffentlichte Produktversion. Auch jeder kleine, lokale Entwicklungsschritt kann eine nachvollziehbare Version sein.

---

## Von Dateikopien zur echten Projektgeschichte

Ohne Versionskontrolle sieht die Entwicklung eines Projekts oft ungefähr so aus:

```text
projekt/
├── index.php
├── index_alt.php
├── index_neu.php
├── index_final.php
├── index_final_final.php
└── index_final_wirklich_final.php
```

Oder es entstehen Ordner wie:

```text
shopprojekt/
├── backup/
├── backup_neu/
├── backup_vor_update/
├── stand_vom_freitag/
└── produktiv_final/
```

Diese Methode hat erkennbare Nachteile:

1. **Unklare Herkunft**  
   Es ist nicht mehr klar, welche Kopie die richtige ist.

2. **Keine Begründung**  
   Dateinamen erklären selten, *warum* etwas geändert wurde.

3. **Schwierige Vergleiche**  
   Unterschiede zwischen zwei Ordnern oder Dateien müssen mühsam gesucht werden.

4. **Keine sichere Zusammenarbeit**  
   Mehrere Personen überschreiben leicht gegenseitig ihre Änderungen.

5. **Unvollständige Sicherung**  
   Häufig werden nur einzelne Dateien kopiert. Zusammenhängende Änderungen fehlen dann.

6. **Keine saubere Rückkehr**  
   Ein alter Stand kann vielleicht gefunden werden, aber nicht zuverlässig wiederhergestellt werden.

Git ersetzt diese unstrukturierten Kopien durch eine präzise Projektgeschichte. Statt Dateien mit Zusätzen wie `_alt` oder `_neu` zu speichern, hält Git fest:

- *welche* Dateien geändert wurden,
- *was* sich darin geändert hat,
- *wann* die Änderung gespeichert wurde,
- *wer* sie erstellt hat,
- *warum* sie vorgenommen wurde,
- und *auf welchem vorherigen Stand* sie aufbaut.

---

## Änderungen als nachvollziehbare Einheiten

In professionellen Projekten wird nicht jede Tastatureingabe sofort als dauerhafte Version gespeichert. Stattdessen fasst man logisch zusammenhängende Änderungen zu einer Einheit zusammen.

Ein Beispiel: Für eine neue Passwortprüfung könnten diese Änderungen zusammengehören:

- `PasswordValidator.php` wird ergänzt,
- passende Unit-Tests werden erstellt,
- eine Fehlermeldung wird dokumentiert,
- eine Konfiguration wird angepasst.

Diese gemeinsame Änderung sollte später als *eine nachvollziehbare Einheit* sichtbar sein. In Git heißt eine solche gespeicherte Einheit **Commit**.

Eine passende Beschreibung könnte lauten:

```text
feat(auth): Passwortlänge validieren
```

Nicht hilfreich wären dagegen Nachrichten wie:

```text
Update
```

```text
Änderungen
```

```text
Fix
```

Die Qualität einer Projektgeschichte hängt wesentlich davon ab, ob Änderungen sinnvoll zusammengefasst und verständlich beschrieben werden.

### Gute Änderungseinheit

Eine gute Änderungseinheit beantwortet idealerweise eine konkrete Frage:

> „Was wurde mit diesem Schritt erreicht?“

Beispiele:

- „E-Mail-Adresse bei der Registrierung validieren“
- „Fehlerhafte Berechnung der Mehrwertsteuer korrigieren“
- „PHPUnit auf Version 11 aktualisieren“
- „README um lokale Installationsschritte ergänzen“
- „Nicht verwendete Legacy-Klasse entfernen“

### Zu große Änderungseinheit

Folgende Mischung ist problematisch:

```text
Neue Login-Funktion, CSS-Anpassungen, Composer-Update,
Tippfehlerkorrekturen und Datenbank-Migration
```

Diese Änderung enthält mehrere unabhängige Themen. Wenn später ein Fehler in der Login-Funktion auftritt, möchte man nicht gleichzeitig CSS-Anpassungen oder ein Abhängigkeitsupdate zurücknehmen müssen.

### Zu kleine Änderungseinheit

Auch das Gegenteil kann unpraktisch sein:

```text
Leerzeile in Datei A ergänzt
```

```text
Leerzeile in Datei B ergänzt
```

```text
Leerzeile in Datei C ergänzt
```

Nicht jede minimale Änderung braucht einen eigenen Commit. Entscheidend ist, dass die Historie fachlich verständlich bleibt.

---

## Projektgeschichte als Kette von Entscheidungen

Eine Projektgeschichte ist mehr als eine Liste technischer Dateiunterschiede. Sie dokumentiert Entscheidungen.

Angenommen, ein Projekt entwickelt sich in diesen Schritten:

```text
A  Projektgrundstruktur anlegen
B  Composer-Abhängigkeiten hinzufügen
C  Benutzerregistrierung implementieren
D  E-Mail-Validierung ergänzen
E  Validierungsfehler korrigieren
F  Version 1.0.0 veröffentlichen
```

Diese Abfolge erklärt nicht nur, *dass* sich Dateien verändert haben. Sie zeigt auch, wie das Projekt zu seinem aktuellen Zustand gelangt ist.

Vereinfacht kann man die Entwicklung als Kette darstellen:

```text
A ── B ── C ── D ── E ── F
```

Jeder Schritt baut auf einem vorherigen Stand auf. Die aktuelle Version enthält also die Ergebnisse aller vorherigen Schritte.

Das ist ein wichtiges Denkmodell:

> Die Projektgeschichte ist keine Ansammlung zufälliger Sicherungskopien, sondern eine Folge bewusst gespeicherter Zustände und Entscheidungen.

Später können sich solche Entwicklungslinien aufteilen und wieder zusammengeführt werden. Git verwendet dafür **Branches** und **Merges**. Zunächst genügt die Vorstellung einer linearen Geschichte.

---

## Momentaufnahme und Änderung unterscheiden

Im Alltag sprechen Teams oft davon, „eine Änderung zu speichern“. Git arbeitet intern jedoch vor allem mit **Momentaufnahmen** des Projektzustands.

Bei einem Commit hält Git fest, wie die verfolgten Dateien zu diesem Zeitpunkt aussehen. Der Commit verweist außerdem auf seinen Vorgänger. Dadurch kann Git Unterschiede zwischen Zuständen berechnen.

Vereinfacht:

```text
Commit A: Grundstruktur
Commit B: Grundstruktur + Composer-Dateien
Commit C: Grundstruktur + Composer-Dateien + Registrierung
```

Git muss nicht für jede Version eine vollständige Ordnerkopie neben die vorherige legen. Es speichert Inhalte effizient und organisiert sie so, dass frühere Zustände weiterhin erreichbar bleiben.

Für die praktische Arbeit ist zunächst diese Formulierung hilfreich:

- Eine **Änderung** beschreibt, was du bearbeitet hast.
- Ein **Commit** speichert einen nachvollziehbaren Projektzustand.
- Die **Historie** verbindet diese Zustände miteinander.

---

## Warum die Geschichte im Alltag wichtig ist

Eine gute Historie hilft nicht nur bei großen Problemen. Sie ist ein tägliches Arbeitswerkzeug.

### Fehlerursachen finden

Ein Test schlägt plötzlich fehl. Nun stellt sich die Frage:

> „Seit wann ist dieses Verhalten vorhanden?“

Mit der Historie kannst du prüfen:

- Welche Änderungen wurden zuletzt vorgenommen?
- Welche Datei wurde verändert?
- In welchem Commit wurde die betreffende Zeile eingeführt?
- Welche Begründung stand in der Commit-Nachricht?

Statt zu raten, untersuchst du konkrete Informationen.

### Frühere Zustände vergleichen

Vielleicht funktioniert ein Formular in der aktuellen Version nicht mehr, in der Vorversion aber schon. Dann vergleichst du beide Stände.

Beispielhaft:

```text
Version vorher: Formular sendet Daten korrekt
Version aktuell: Validierung verhindert das Absenden
```

Ein Vergleich zeigt, welche Codezeilen zwischen diesen Zuständen verändert wurden.

### Änderungen gezielt zurücknehmen

Nicht jede Änderung soll dauerhaft bleiben. Vielleicht wurde eine Funktion falsch umgesetzt oder ein Update verursacht Probleme.

Ohne Versionskontrolle müsstest du alte Dateien suchen und manuell zurückkopieren. Mit Git kannst du gezielt feststellen:

- welcher Commit problematisch ist,
- welche Dateien er verändert hat,
- und wie die Änderung kontrolliert zurückgenommen werden kann.

### Wissen im Team erhalten

Menschen wechseln Projekte, vergessen Details oder sind im Urlaub. Eine verständliche Historie bewahrt Kontext.

Statt jemanden fragen zu müssen, warum ein ungewöhnlicher Codeabschnitt existiert, kann die Historie Hinweise liefern:

```text
fix(api): Timeout für langsame Zahlungsanbieter erhöhen
```

Vielleicht wurde diese Anpassung wegen eines konkreten Produktionsproblems vorgenommen. Eine gute Commit-Nachricht, ein verknüpftes Issue oder ein Pull Request machen diese Entscheidung später nachvollziehbar.

### Releases reproduzieren

Wenn ein Kunde einen Fehler in Version `1.8.0` meldet, muss das Team genau diesen Stand untersuchen können — nicht nur die heutige, bereits weiterentwickelte Variante.

Versionskontrolle ermöglicht es, ältere Stände gezielt zu prüfen, Tests auszuführen und bei Bedarf eine Korrektur auf dieser Basis zu entwickeln.

---

## Die Zeitachse eines kleinen Projekts

Ein einfaches PHP-Projekt könnte sich so entwickeln:

```text
1. Projektstruktur erstellen
2. Composer konfigurieren
3. Erste Klasse schreiben
4. Tests hinzufügen
5. Fehler korrigieren
6. Dokumentation ergänzen
7. Release veröffentlichen
```

Als Historie könnte das aussehen:

```text
a1b2c3d  Projektstruktur anlegen
b2c3d4e  Composer und Autoloading konfigurieren
c3d4e5f  Preisberechnung implementieren
d4e5f6a  Tests für Preisberechnung ergänzen
e5f6a7b  Rundungsfehler bei Mehrwertsteuer korrigieren
f6a7b8c  README um Installationsanleitung erweitern
g7b8c9d  Release 1.0.0 vorbereiten
```

Die Zeichenfolgen am Anfang stehen beispielhaft für Commit-IDs. Git verwendet sie, um jeden gespeicherten Zustand eindeutig zu identifizieren.

An dieser Liste lässt sich bereits viel ablesen:

- Die Preisberechnung wurde *vor* den Tests implementiert.
- Danach wurde ein Rundungsfehler entdeckt und behoben.
- Die Dokumentation wurde erst später ergänzt.
- Das Release baut auf allen vorherigen Änderungen auf.

Eine solche Historie ist wesentlich wertvoller als ein Ordner mit dem Namen `projekt_neu_final`.

---

## Änderungen haben Kontext

Eine Zeile Code allein erklärt selten genug. Der Kontext einer Änderung ist oft mindestens genauso wichtig wie der technische Unterschied.

Betrachte diese Änderung:

```php
private const TAX_RATE = 0.19;
```

Wird daraus später:

```php
private const TAX_RATE = 0.20;
```

ist der technische Unterschied klein. Die entscheidende Frage lautet aber:

> Warum wurde der Wert geändert?

Mögliche Antworten:

- Eine gesetzliche Änderung tritt zu einem bestimmten Datum in Kraft.
- Der Wert war bisher fehlerhaft.
- Die Konstante wird nur in einer Testumgebung verwendet.
- Eine neue Konfiguration ersetzt den festen Wert.

Versionskontrolle kann diesen Kontext über Commit-Nachrichten, Issues, Pull Requests und Reviews festhalten. Git speichert primär die technische Historie; Plattformen wie GitHub ergänzen sie um Diskussionen, Aufgaben und Freigaben.

---

## Die Projektgeschichte ist kein Ersatz für Kommunikation

Eine Commit-Historie ist wertvoll, aber sie ersetzt nicht alles.

Sie kann dokumentieren:

- was geändert wurde,
- wann es geschah,
- wer die Änderung gespeichert hat,
- welche Nachricht dazu hinterlegt wurde.

Sie kann jedoch nicht automatisch alle fachlichen Hintergründe erfassen. Wichtige Architekturentscheidungen, Sicherheitsannahmen oder Produktentscheidungen gehören häufig zusätzlich in:

- Issues,
- Pull-Request-Beschreibungen,
- Architekturentscheidungsprotokolle,
- technische Dokumentation,
- Ticketsysteme,
- das Projekt-README.

Eine gute Praxis ist daher:

1. **Commits klein und verständlich halten.**
2. **Commit-Nachrichten konkret formulieren.**
3. **Größere Entscheidungen dokumentieren.**
4. **Zusammenhänge zwischen Code, Issue und Pull Request verknüpfen.**

---

## Eine Geschichte darf nicht beliebig sein

Nicht jede Projektgeschichte ist automatisch gut, nur weil Git verwendet wird. Auch ein Git-Repository kann unübersichtlich werden.

Typische Warnzeichen sind:

- Commit-Nachrichten wie „WIP“, „Test“, „Änderung“ oder „asdf“,
- riesige Commits mit vielen unabhängigen Themen,
- fehlende Tests bei funktionalen Änderungen,
- Zugangsdaten oder generierte Dateien in der Historie,
- unklare oder widersprüchliche Branch-Namen,
- häufiges Überschreiben bereits veröffentlichter Historie.

Ein Ziel professioneller Versionskontrolle lautet deshalb:

> Die Historie soll nicht nur vollständig, sondern auch verständlich, überprüfbar und sicher sein.

Das bedeutet nicht, dass jeder Commit perfekt sein muss. Gerade beim Lernen oder bei lokaler Experimentierarbeit entstehen unfertige Zwischenstände. Vor einer gemeinsamen Veröffentlichung können diese jedoch oft sinnvoll geordnet, zusammengefasst oder dokumentiert werden.

---

## Praktisches Denkmodell: Fragen an jede Änderung

Bevor du eine Änderung dauerhaft speicherst, helfen diese Fragen:

1. **Was habe ich geändert?**  
   Beschreibe die technische oder fachliche Wirkung klar.

2. **Warum war die Änderung nötig?**  
   Gibt es einen Fehler, ein Ticket, eine Anforderung oder eine Entscheidung?

3. **Gehört alles in einen gemeinsamen Schritt?**  
   Oder lassen sich unabhängige Änderungen trennen?

4. **Ist der neue Zustand funktionsfähig?**  
   Wurden Tests ausgeführt oder zumindest die Auswirkungen geprüft?

5. **Kann eine andere Person die Änderung später verstehen?**  
   Reicht die Commit-Nachricht aus, oder braucht es zusätzliche Dokumentation?

6. **Kann die Änderung bei Bedarf isoliert rückgängig gemacht werden?**  
   Kleine, klar abgegrenzte Commits erleichtern das erheblich.

Diese Fragen machen aus „Dateien speichern“ eine professionelle, nachvollziehbare Arbeitsweise.

---

## Git und die unveränderliche Vergangenheit

Ein zentraler Vorteil von Git ist, dass frühere Commits normalerweise nicht einfach überschrieben werden. Neue Arbeit baut auf bestehenden Zuständen auf.

Wenn du heute einen Commit erstellst, bleibt der vorherige Zustand weiterhin Teil der Historie:

```text
Vorheriger Stand ── Neue Änderung ── Aktueller Stand
```

Dadurch kannst du:

- frühere Versionen untersuchen,
- Änderungen vergleichen,
- ältere Stände wiederherstellen,
- Fehler zeitlich eingrenzen,
- Releases dauerhaft markieren.

Später wirst du lernen, dass Git-Historien unter bestimmten Umständen umgeschrieben werden können, etwa mit `git rebase` oder speziellen Bereinigungswerkzeugen. Das sind jedoch bewusste, teilweise riskante Operationen — insbesondere bei bereits mit anderen geteilten Commits.

Für den Einstieg gilt:

> Neue Arbeit wird als neuer nachvollziehbarer Schritt ergänzt, nicht durch das unkontrollierte Überschreiben alter Arbeit ersetzt.

---

## Zusammenfassung

Änderungen bilden die Grundlage jeder Softwareentwicklung. Versionskontrolle macht aus diesen Änderungen eine zuverlässige Projektgeschichte.

Die wichtigsten Begriffe:

- **Änderung:** Eine Anpassung an Dateien oder Projektinhalten.
- **Version:** Ein nachvollziehbarer Zustand des gesamten Projekts zu einem bestimmten Zeitpunkt.
- **Commit:** Eine in Git gespeicherte, beschriebene Momentaufnahme eines Projektzustands.
- **Historie:** Die geordnete Verbindung aller Commits und damit die Entwicklungsgeschichte des Projekts.

Eine gute Projektgeschichte hilft dir dabei,

- Fehler schneller zu verstehen,
- ältere Stände sicher wiederzufinden,
- Änderungen gezielt zurückzunehmen,
- Releases reproduzierbar zu machen,
- und Wissen im Team langfristig zu bewahren.

Im nächsten Schritt wird deutlich, wie unterschiedliche Systeme diese Geschichte organisieren: zentral auf einem Server oder verteilt auf die Rechner aller Beteiligten.

# Zentrale und verteilte Versionskontrolle

## Lernziele

Nach diesem Abschnitt kannst du:

- zentrale und verteilte Versionskontrollsysteme unterscheiden,
- den grundlegenden Ablauf beider Modelle erklären,
- Vorteile, Grenzen und Risiken beider Ansätze bewerten,
- einordnen, warum Git als *verteiltes* Versionskontrollsystem konzipiert ist,
- verstehen, weshalb GitHub trotz seiner zentralen Rolle nicht aus Git ein zentrales System macht.

---

## Zwei grundlegende Modelle

Versionskontrollsysteme organisieren Änderungen an Dateien und machen die Entwicklungsgeschichte nachvollziehbar. Dabei haben sich zwei grundlegende Architekturmodelle etabliert:

1. **Zentrale Versionskontrolle**: Es gibt ein maßgebliches Repository auf einem Server.
2. **Verteilte Versionskontrolle**: Jede lokale Kopie enthält grundsätzlich die vollständige Repository-Historie.

Der entscheidende Unterschied betrifft nicht nur den Speicherort der Daten. Er verändert auch, **wann** Teams miteinander kommunizieren müssen, wie sie offline arbeiten können, wie sicher ihre Historie ist und welche Arbeitsabläufe sinnvoll sind.

---

## Zentrale Versionskontrolle

Bei einem zentralen Versionskontrollsystem liegt die vollständige Projektgeschichte auf einem zentralen Server. Entwicklerinnen und Entwickler laden Dateien daraus herunter, bearbeiten sie lokal und übertragen ihre Änderungen wieder zurück auf den Server.

Typische zentrale Systeme sind:

- Subversion, meist über den Befehl `svn`
- Perforce
- Team Foundation Version Control, kurz TFVC
- ältere Systeme wie CVS

### Grundprinzip

Die Arbeitskopie auf dem lokalen Computer enthält in der Regel die aktuelle Version der Dateien, aber nicht zwingend die vollständige Historie aller Versionen. Der Server ist die zentrale Wahrheit über den Projektzustand.

```text
Entwicklerin A ──┐
                 ├── Zentraler Versionskontrollserver
Entwickler B ────┤
                 │
Entwickler C ────┘
```

Ein typischer Ablauf sieht so aus:

1. Änderungen vom Server abrufen.
2. Dateien lokal bearbeiten.
3. Vor dem Hochladen prüfen, ob andere Personen Änderungen veröffentlicht haben.
4. Eigene Änderungen an den zentralen Server senden.
5. Der Server speichert die neue offizielle Revision.

### Typischer zentraler Workflow

```text
Server aktualisieren
        ↓
Dateien bearbeiten
        ↓
Änderungen übertragen
        ↓
Server enthält die neue Projektversion
```

In Subversion wären die zentralen Aktionen beispielsweise:

```bash
svn update
svn commit -m "Validierung für E-Mail-Adresse ergänzt"
```

Die exakte Syntax ist hier weniger wichtig als das Denkmodell: Ohne Verbindung zum Server sind viele zentrale Aktionen nicht möglich.

---

## Vorteile zentraler Systeme

Zentrale Versionskontrolle kann gerade in klar geregelten Umgebungen sinnvoll sein.

### Ein eindeutig zentraler Projektstand

Es gibt einen klaren Ort, an dem sich die offizielle Historie befindet. Teams müssen nicht entscheiden, welches Repository maßgeblich ist: Der zentrale Server ist es per Definition.

Das vereinfacht manche organisatorischen Prozesse:

- Berechtigungen werden zentral verwaltet.
- Backups konzentrieren sich auf einen Server.
- Regeln für Änderungen lassen sich zentral erzwingen.
- Der aktuelle Projektstand ist an einer Stelle sichtbar.

### Einfaches mentales Modell

Für Einsteigerinnen und Einsteiger wirkt das Modell häufig intuitiv:

> „Ich lade die aktuelle Version herunter, ändere etwas und speichere es wieder auf dem Server.“

Die Abläufe ähneln der Arbeit mit einer gemeinsam genutzten Dateiablage, auch wenn Versionskontrolle deutlich leistungsfähiger ist.

### Serverseitige Kontrolle

Unternehmen mit strengen Vorgaben können zentrale Serverregeln nutzen, etwa:

- verpflichtende Prüfungen vor einem Commit,
- zentrale Zugriffsrechte,
- Audit-Protokolle,
- verbindliche Dateisperren für bestimmte Dateitypen.

Besonders bei großen Binärdateien oder Dateien, die sich kaum sinnvoll zusammenführen lassen, können Sperrmechanismen nützlich sein. Beispielsweise soll nicht gleichzeitig an derselben Photoshop-Datei gearbeitet werden.

---

## Grenzen zentraler Systeme

Die Einfachheit des Modells bringt Abhängigkeiten mit sich.

### Abhängigkeit vom Server

Ist der zentrale Server nicht erreichbar, sind zentrale Funktionen eingeschränkt oder unmöglich. Das kann passieren durch:

- Netzwerkprobleme,
- Wartungsarbeiten,
- VPN-Ausfälle,
- einen Serverausfall,
- fehlende Internetverbindung auf Reisen.

Lokale Änderungen sind zwar häufig weiterhin möglich, aber das Übertragen, Abrufen und oft auch das komfortable Anzeigen der Historie hängt vom Server ab.

### Eingeschränkte Offline-Arbeit

In einem zentralen System kann ein Commit direkt eine Serveroperation sein. Ohne Netzwerk lässt sich die Änderung daher nicht als vollwertiger, gemeinsamer Versionsstand speichern.

Das führt oft dazu, dass Entwicklerinnen und Entwickler größere Änderungspakete sammeln und später gesammelt übertragen. Große Pakete sind aber schwieriger zu prüfen, zu testen und bei Problemen zurückzunehmen.

### Zentraler Ausfallpunkt

Der Server ist ein sogenannter *Single Point of Failure*: Fällt er aus und existiert kein funktionierendes Backup, ist die Projektgeschichte gefährdet.

Ein zentraler Server kann selbstverständlich professionell gesichert werden. Dennoch bleibt seine Verfügbarkeit für den täglichen Arbeitsablauf entscheidend.

### Branches können teuer sein

Bei einigen älteren zentralen Systemen sind Branches technisch oder organisatorisch schwergewichtiger. Teams vermeiden sie dann häufig und arbeiten lange auf gemeinsamen Entwicklungszweigen.

Das erhöht die Wahrscheinlichkeit, dass parallele Änderungen miteinander kollidieren.

> **Merksatz:** In zentralen Systemen ist Zusammenarbeit oft stärker an den gemeinsamen Server und dessen Verfügbarkeit gebunden.

---

## Verteilte Versionskontrolle

Ein verteiltes Versionskontrollsystem speichert die vollständige Projektgeschichte nicht nur auf einem Server, sondern auch lokal bei den Beteiligten.

Git ist das bekannteste verteilte Versionskontrollsystem. Weitere Beispiele sind Mercurial und Fossil.

Wenn du ein Git-Repository klonst, erhältst du nicht bloß die aktuell sichtbaren Dateien. Du erhältst normalerweise auch:

- die Commit-Historie,
- Branches und Tags,
- die Git-Objekte,
- lokale Referenzen,
- die Informationen, die Git für Vergleiche, Branches und viele Wiederherstellungen benötigt.

```text
Lokales Repository A  ←→  Gemeinsames Remote-Repository  ←→  Lokales Repository B
        ↕                            ↕                             ↕
 vollständige Historie         vollständige Historie         vollständige Historie
```

Das Wort *verteilt* bedeutet nicht, dass es keinen zentralen Server geben darf. Es bedeutet vielmehr:

> Jedes vollständige Git-Repository ist grundsätzlich eine eigenständige Kopie der Projektgeschichte.

---

## Das lokale Repository als vollwertige Kopie

Ein Git-Repository besteht aus mehr als dem Projektordner mit den sichtbaren Dateien. Im versteckten Verzeichnis `.git` verwaltet Git unter anderem:

- Commits,
- Branch-Referenzen,
- Tags,
- die Staging Area,
- Konfiguration,
- lokale Bewegungsprotokolle, die Reflogs.

Beim Klonen eines Repositorys entsteht daher eine lokale, funktionsfähige Datenbasis.

```text
Projektordner
├── src
├── tests
├── composer.json
└── .git
    ├── objects
    ├── refs
    ├── HEAD
    ├── index
    └── config
```

Die Details dieser Dateien und Verzeichnisse werden in späteren Kapiteln vertieft. Für den Moment genügt dieses Verständnis:

- Die sichtbaren Projektdateien bilden dein **Arbeitsverzeichnis**.
- Das `.git`-Verzeichnis enthält die **lokale Versionsdatenbank**.

---

## Lokale Commits ohne Netzwerk

Ein entscheidender Vorteil von Git ist, dass ein Commit lokal erstellt wird. Dafür ist weder GitHub noch ein Unternehmensserver erforderlich.

```bash
git add src/EmailValidator.php
git commit -m "Validierung für E-Mail-Adresse ergänzen"
```

Dieser Commit wird zunächst nur im lokalen Repository gespeichert.

Erst mit einem Push überträgst du ihn in ein anderes Repository, beispielsweise zu GitHub:

```bash
git push origin main
```

Die Begriffe beschreiben unterschiedliche Vorgänge:

| Aktion | Bedeutung |
|---|---|
| `git commit` | Speichert einen neuen Versionsstand **lokal** |
| `git push` | Überträgt lokale Commits in ein entferntes Repository |
| `git fetch` | Lädt Informationen und Commits aus einem entfernten Repository herunter |
| `git pull` | Ruft Änderungen ab und integriert sie in den aktuellen lokalen Branch |

Diese Trennung ist ein Kernmerkmal verteilter Versionskontrolle.

---

## Typischer Git-Workflow

Ein einfacher Git-Workflow kann so aussehen:

```text
Dateien lokal ändern
        ↓
Änderungen auswählen und vormerken
        ↓
Lokalen Commit erstellen
        ↓
Tests lokal ausführen
        ↓
Commit zu GitHub oder einem anderen Remote pushen
```

Als Befehlsfolge:

```bash
git status
git add src/EmailValidator.php
git commit -m "Validierung für E-Mail-Adresse ergänzen"
git push
```

Zwischen `git commit` und `git push` können Sekunden, Stunden oder auch Tage liegen. Ob das sinnvoll ist, hängt vom Teamworkflow ab. Technisch ist es möglich, weil der Commit bereits lokal existiert.

---

## Remote-Repositorys sind nicht „der Git-Server“

In der Praxis verwenden Teams oft ein gemeinsames Remote-Repository als Koordinationspunkt. Das kann bei GitHub, GitLab, Bitbucket oder auf einem eigenen Server liegen.

```text
Laptop von Lea ─────┐
                    ├── GitHub-Repository
Laptop von Omar ────┤
                    │
Build-Server ───────┘
```

Dieses GitHub-Repository ist für das Team häufig die **gemeinsame Referenz**. Es ist aber technisch nicht das einzige Repository, das die Historie enthält.

Auch Leas und Omars lokale Repositories enthalten eine vollständige Historie. GitHub ergänzt Git um Funktionen für Zusammenarbeit und Plattformbetrieb, zum Beispiel:

- Pull Requests,
- Code Reviews,
- Issues,
- Rechteverwaltung,
- GitHub Actions,
- Releases,
- Sicherheitsprüfungen.

GitHub ist damit für viele Teams organisatorisch zentral, Git selbst bleibt jedoch ein verteiltes System.

> **Wichtig:** „Wir arbeiten mit GitHub“ bedeutet nicht, dass Git zentralisiert wäre. GitHub ist ein Remote und eine Kollaborationsplattform für Git-Repositories.

---

## Mehrere Remotes verwenden

Ein Git-Repository kann mit mehreren entfernten Repositories verbunden sein. Das ist ein deutlicher Ausdruck der verteilten Architektur.

Ein Open-Source-Beitrag kann beispielsweise so organisiert sein:

```text
Lokales Repository
       │
       ├── origin   → eigener Fork auf GitHub
       │
       └── upstream → ursprüngliches Projekt auf GitHub
```

Die zugehörigen Remote-Namen sind frei wählbar. `origin` ist nur eine Konvention, die Git beim Klonen automatisch verwendet.

```bash
git remote -v
```

Eine mögliche Ausgabe:

```text
origin    git@github.com:beispielkonto/mein-fork.git (fetch)
origin    git@github.com:beispielkonto/mein-fork.git (push)
upstream  git@github.com:organisation/originalprojekt.git (fetch)
upstream  git@github.com:organisation/originalprojekt.git (push)
```

Du kannst also Änderungen aus einem Repository abrufen und in ein anderes veröffentlichen. Git schreibt keine einzige zentrale Instanz vor.

---

## Vergleich der Modelle

| Aspekt | Zentrale Versionskontrolle | Verteilte Versionskontrolle mit Git |
|---|---|---|
| Maßgebliche Historie | Liegt primär auf einem zentralen Server | Liegt in vollständigen lokalen Repository-Kopien und optionalen Remotes |
| Commit | Häufig direkt auf dem Server | Zunächst lokal |
| Offline-Arbeit | Oft eingeschränkt | Für Commits, Branches, Logs und Diffs weitgehend möglich |
| Serverausfall | Kann den gesamten Workflow blockieren | Lokale Arbeit und Historienanalyse bleiben möglich |
| Branches | Je nach System eher aufwendig | Sehr leichtgewichtig und schnell |
| Zusammenarbeit | Stark auf zentralen Server ausgerichtet | Über Push, Fetch und frei wählbare Remotes |
| Datensicherung | Zentraler Server ist besonders kritisch | Mehrere vollständige Kopien können zusätzliche Redundanz schaffen |
| Zugriffssteuerung | Typischerweise zentral | Meist über Remotes, Plattformen und Serverregeln organisiert |

Die Tabelle beschreibt Tendenzen. Moderne zentrale Systeme können Offline-Funktionen anbieten, und ein Git-Team kann seinen Workflow stark um ein einziges GitHub-Repository herum organisieren. Die grundlegende Architektur bleibt dennoch verschieden.

---

## Verteilung bedeutet nicht automatisch Sicherheit

Es wäre falsch zu behaupten, dass Git automatisch ein Backup-Konzept ersetzt. Mehrere lokale Kopien können zwar helfen, doch sie sind nicht automatisch zuverlässig gesichert.

Beispiele für Risiken:

- Niemand außer einer Person hat die neuesten lokalen Commits.
- Ein Laptop wird beschädigt oder geht verloren.
- Ein lokaler Branch wird gelöscht.
- Ein Commit wird nie zu einem Remote gepusht.
- Ein zentraler GitHub-Account wird falsch konfiguriert oder kompromittiert.

Ein professionelles Team sorgt deshalb dafür, dass wichtige Arbeit regelmäßig auf ein geeignetes Remote übertragen wird und dass dieses Remote zusätzlich abgesichert ist.

> **Praxisregel:** Ein lokaler Commit schützt vor vielen Fehlern im Arbeitsverzeichnis. Ein gepushter Commit schützt zusätzlich vor dem Verlust eines einzelnen Computers. Ein getestetes Backup schützt vor weitergehenden Ausfällen.

---

## Warum Git trotzdem oft „zentral“ wirkt

Ein GitHub-Workflow fühlt sich für viele Teams zentral an:

1. Ein Repository auf GitHub wird erstellt.
2. Alle Teammitglieder klonen dieses Repository.
3. Feature-Branches werden dorthin gepusht.
4. Pull Requests werden dort geprüft.
5. Der Hauptbranch wird dort geschützt.
6. CI-Prüfungen laufen dort.

Das ist keine Schwäche oder ein Widerspruch. Git erlaubt eine zentrale *Zusammenarbeitsstruktur*, ohne seine verteilte Natur aufzugeben.

Man kann es so unterscheiden:

| Ebene | Zentral oder verteilt? |
|---|---|
| Git-Datenmodell | Verteilt |
| Lokale Git-Repositories | Eigenständig und vollständig |
| GitHub als Teamplattform | Häufig zentraler Koordinationspunkt |
| Teamregeln und Branch-Schutz | Zentral organisiert |
| Commits, Branches und Diffs auf dem Laptop | Lokal verfügbar |

Diese Kombination ist einer der Gründe für Gits Erfolg: Teams erhalten lokale Geschwindigkeit und Flexibilität, können ihre Zusammenarbeit aber trotzdem klar über GitHub organisieren.

---

## Ein konkretes Alltagsszenario

Stell dir vor, du arbeitest im Zug ohne Internetverbindung an einem PHP-Projekt.

Mit Git kannst du weiterhin:

```bash
git status
git diff
git switch feature/email-validation
git add src/EmailValidator.php
git commit -m "Fehlermeldung für ungültige Domain verbessern"
git log --oneline
```

Du kannst also Änderungen prüfen, Branches wechseln, Commits erstellen und die Historie untersuchen.

Sobald wieder eine Verbindung besteht, veröffentlichst du die bereits vorhandenen Commits:

```bash
git push origin feature/email-validation
```

Danach kann GitHub einen Pull Request anbieten oder du erstellst ihn selbst über die Website beziehungsweise PhpStorm.

In einem strikt zentralen System wäre der lokale Arbeitsschritt vergleichbar möglich, aber die vollständige Versionsverwaltung und insbesondere der Commit könnten stärker von der Erreichbarkeit des Servers abhängen.

---

## Auswirkungen auf Branching und Experimente

Weil lokale Branches in Git sehr günstig erzeugt werden können, eignet sich Git gut für kurze, isolierte Experimente.

```bash
git switch -c experiment/neue-validierungsregel
```

Du kannst dort eine Idee umsetzen, testen und später entscheiden:

- Die Änderungen sind sinnvoll: Branch weiterentwickeln oder zusammenführen.
- Die Änderungen sind nicht sinnvoll: Branch löschen.
- Die Idee ist noch offen: Branch lokal behalten.

```bash
git switch main
git branch -D experiment/neue-validierungsregel
```

Solange du keinen Push ausführst, bleibt dieser Branch vollständig lokal. Er beeinflusst weder GitHub noch andere Teammitglieder.

Dieses Verhalten fördert kleine, risikoarme Experimente und klar abgegrenzte Änderungen.

---

## Häufige Missverständnisse

### „GitHub speichert meine Commits automatisch“

Nein. Ein lokaler Commit wird nicht automatisch zu GitHub übertragen.

Nach diesem Befehl:

```bash
git commit -m "Formularvalidierung verbessern"
```

existiert der Commit zunächst nur lokal. Erst ein Push veröffentlicht ihn im Remote:

```bash
git push
```

### „Ein Git-Repository braucht immer GitHub“

Nein. Git funktioniert vollständig ohne GitHub.

Du kannst ein lokales Repository anlegen und verwenden:

```bash
git init
```

GitHub wird erst relevant, wenn du ein Remote für Zusammenarbeit, Sicherung, Veröffentlichung oder Automatisierung verwenden möchtest.

### „Verteilt heißt, dass jede Person alles veröffentlichen darf“

Nein. Die technische Architektur und die Berechtigungen sind verschiedene Dinge.

Git erlaubt lokale Commits und lokale Branches ohne zentrale Freigabe. Ein GitHub-Repository kann aber genau festlegen:

- Wer pushen darf,
- welche Branches geschützt sind,
- ob Pull-Request-Reviews nötig sind,
- welche Prüfungen erfolgreich sein müssen,
- wer Releases erstellen darf.

### „Lokale Commits sind unwichtig, weil nur GitHub zählt“

Lokale Commits sind sehr wichtig. Sie strukturieren deine Arbeit, ermöglichen sichere Experimente und bilden die Grundlage für jeden späteren Push. GitHub erhält keine magischen Änderungen, sondern die Commits, die du lokal erstellt hast.

---

## Entscheidungshilfe: Welches Modell passt wann?

In der Praxis entscheidet man selten ausschließlich aufgrund der Architektur. Anforderungen an Teams, Infrastruktur, Sicherheit und bestehende Werkzeuge spielen ebenfalls eine Rolle.

**Zentrale Versionskontrolle** kann passend sein, wenn:

- ein bestehendes Unternehmen stark auf ein zentrales System ausgerichtet ist,
- sehr spezielle Sperr- und Dateiverwaltungsprozesse benötigt werden,
- große Binärdateien und exklusive Bearbeitung im Vordergrund stehen,
- ein vorhandenes System nicht kurzfristig migriert werden kann.

**Verteilte Versionskontrolle mit Git** ist besonders geeignet, wenn:

- Teams häufig mit Branches arbeiten,
- Entwicklerinnen und Entwickler auch offline produktiv sein sollen,
- kleine, lokale Commits erwünscht sind,
- Pull Requests und automatisierte Prüfungen etabliert werden sollen,
- Open-Source-Zusammenarbeit oder Forks relevant sind,
- moderne Plattformen wie GitHub, GitLab oder Bitbucket genutzt werden.

Für die meisten Softwareprojekte ist Git heute der verbreitete Standard. Das liegt nicht nur an GitHub, sondern vor allem an Gits leistungsfähigem lokalen Datenmodell, seinen günstigen Branches und seiner flexiblen Zusammenarbeit über Remotes.

---

## Merkpunkte

- Ein **zentrales** Versionskontrollsystem speichert die maßgebliche Historie primär auf einem Server.
- Ein **verteiltes** System wie Git gibt jeder vollständigen lokalen Repository-Kopie die Projektgeschichte mit.
- In Git ist ein Commit zunächst **lokal**; `git push` veröffentlicht ihn in einem Remote.
- GitHub ist ein wichtiger zentraler Koordinationspunkt, macht Git aber nicht zu einem zentralen Versionskontrollsystem.
- Verteilte Repositories bieten Redundanz, ersetzen aber kein bewusstes Backup- und Push-Konzept.
- Die Fähigkeit, lokal zu committen, zu vergleichen, zu verzweigen und Historie zu lesen, ist ein zentraler Vorteil von Git.

---

## Selbsttest

1. Worin besteht der wichtigste architektonische Unterschied zwischen zentraler und verteilter Versionskontrolle?
2. Warum kannst du mit Git ohne Internet einen Commit erstellen?
3. Was ist der Unterschied zwischen `git commit` und `git push`?
4. Weshalb bleibt Git ein verteiltes System, obwohl ein Team GitHub als gemeinsamen Mittelpunkt verwendet?
5. Warum ist ein lokaler Commit allein noch keine ausreichende Datensicherung?
6. Nenne eine Situation, in der lokale Branches besonders hilfreich sind.

# Git als Snapshot-System

## Die zentrale Idee: Git speichert Zustände, nicht nur Änderungen

Viele Versionskontrollsysteme werden zunächst als eine Folge von Änderungen verstanden:

> „In Version 2 wurden drei Zeilen ergänzt, in Version 3 eine Datei umbenannt.“

Git kann Änderungen selbstverständlich anzeigen und übertragen. Intern basiert sein Modell aber auf einer anderen, äußerst wichtigen Idee:

> **Ein Commit repräsentiert einen vollständigen Snapshot des Projektzustands zu einem bestimmten Zeitpunkt.**

Ein Snapshot ist wie eine Momentaufnahme des gesamten Repository-Inhalts. Er beschreibt, welche Dateien und Verzeichnisse zu diesem Zeitpunkt existieren und welche Inhalte sie haben.

Statt gedanklich nur zu fragen:

> „Welche Zeilen haben sich seit gestern geändert?“

kannst du bei Git fragen:

> „Wie sah das gesamte Projekt bei diesem Commit aus?“

Dieses Denkmodell erleichtert später das Verständnis von Branches, Merges, Rebase, Wiederherstellung und Konflikten erheblich.

---

## Was ein Snapshot enthält

Ein Git-Commit verweist auf einen bestimmten Zustand des Projektverzeichnisses. Dieser Zustand umfasst insbesondere:

- Dateien und ihre Inhalte
- Verzeichnisse und ihre Struktur
- Dateinamen und Pfade
- Informationen über ausführbare Dateien
- den oder die Vorgänger-Commits
- Autor, Committer, Zeitstempel und Commit-Nachricht

Angenommen, ein kleines PHP-Projekt enthält zunächst diese Dateien:

```text
projekt/
├── composer.json
├── src/
│   └── Greeting.php
└── tests/
    └── GreetingTest.php
```

Nach dem ersten Commit speichert Git einen Snapshot genau dieses Zustands.

Später ergänzt du eine README-Datei:

```text
projekt/
├── README.md
├── composer.json
├── src/
│   └── Greeting.php
└── tests/
    └── GreetingTest.php
```

Der nächste Commit beschreibt diesen *neuen vollständigen Zustand*. Er sagt vereinfacht:

> „Zu diesem Zeitpunkt bestand das Projekt aus README.md, composer.json, src/Greeting.php und tests/GreetingTest.php — jeweils mit genau diesen Inhalten.“

Git speichert also nicht bloß die Aussage „README.md wurde hinzugefügt“. Diese Änderung lässt sich aus dem Vergleich zweier Snapshots ableiten.

---

## Git zeigt Änderungen durch den Vergleich von Snapshots

Wenn du diesen Befehl ausführst:

```bash
git diff
```

zeigt Git dir Unterschiede zwischen Zuständen an. Das bedeutet jedoch nicht, dass Git einen Commit zwingend als klassische Liste einzelner Textänderungen speichert.

Git vergleicht beispielsweise:

- den Zustand im Arbeitsverzeichnis mit dem Index,
- den Index mit dem letzten Commit,
- zwei beliebige Commits,
- zwei Branches,
- oder zwei Versionstags.

Beispiel:

```bash
git diff HEAD~1 HEAD
```

Dieser Befehl vergleicht den vorletzten Commit mit dem aktuellen Commit. Git berechnet daraus, welche Dateien hinzugefügt, entfernt oder verändert wurden.

Die sichtbare Änderung könnte so aussehen:

```diff
+ # Mein PHP-Projekt
+
+ Ein kleines Beispielprojekt für Git.
```

Das ist eine *Darstellung des Unterschieds*. Das zugrunde liegende Modell bleibt: Git kennt zwei vollständige Zustände und vergleicht sie.

---

## Ein Commit ist kein vollständiges Dateikopie-Archiv

Die Formulierung „vollständiger Snapshot“ kann einen falschen Eindruck erzeugen: Git kopiert nicht bei jedem Commit blind jede Datei erneut auf die Festplatte.

Das wäre bei größeren Projekten ineffizient.

Stattdessen speichert Git Inhalte objektbasiert:

- Unveränderte Dateiinhalte werden wiederverwendet.
- Nur neue oder geänderte Inhalte benötigen neue Objekte.
- Verzeichnisstrukturen werden ebenfalls als Objekte gespeichert.
- Commits verweisen auf diese unveränderlichen Objekte.

Wenn sich nur `README.md` ändert, muss Git nicht erneut eine Kopie von `src/Greeting.php` speichern. Der neue Snapshot verweist einfach wieder auf den bereits bekannten Inhalt dieser Datei.

**Denkmodell:** Jeder Commit beschreibt einen vollständigen Zustand, aber Git speichert gleiche Inhalte nur einmal.

Das verbindet Verständlichkeit mit hoher Effizienz.

---

## Beispiel: Drei Zustände eines Projekts

Stell dir diese Entwicklung vor.

### Commit A: Projekt anlegen

```text
composer.json
src/Greeting.php
```

`src/Greeting.php`:

```php
<?php

declare(strict_types=1);

final class Greeting
{
    public function message(): string
    {
        return 'Hallo';
    }
}
```

### Commit B: Test ergänzen

```text
composer.json
src/Greeting.php
tests/GreetingTest.php
```

Der Snapshot von Commit B enthält nun zusätzlich die Testdatei. Die Datei `src/Greeting.php` ist unverändert und kann daher auf denselben gespeicherten Inhalt wie in Commit A verweisen.

### Commit C: Begrüßung ändern

```text
composer.json
src/Greeting.php
tests/GreetingTest.php
```

Nun wird der Inhalt verändert:

```php
public function message(): string
{
    return 'Hallo, Git!';
}
```

Commit C enthält wieder den vollständigen Projektzustand. Für `composer.json` und `tests/GreetingTest.php` kann Git bereits bekannte Inhalte verwenden. Für die geänderte Datei `src/Greeting.php` speichert Git einen neuen Inhalt.

Vereinfacht lässt sich die Historie so lesen:

```text
Commit A
└── composer.json
└── src/Greeting.php [Version 1]

Commit B
└── composer.json
└── src/Greeting.php [Version 1]
└── tests/GreetingTest.php

Commit C
└── composer.json
└── src/Greeting.php [Version 2]
└── tests/GreetingTest.php
```

Jeder Commit ist ein klar definierter Projektzustand. Git erkennt dabei automatisch, welche Inhalte bereits existieren.

---

## Warum dieses Modell so nützlich ist

Das Snapshot-Modell erklärt viele alltägliche Git-Funktionen besonders gut.

### Alte Projektzustände ansehen

Du kannst jederzeit einen früheren Commit untersuchen:

```bash
git show <commit-hash>
```

Oder du wechselst gezielt zu einem historischen Zustand:

```bash
git switch --detach <commit-hash>
```

Du siehst dann das Projekt so, wie es zu diesem Commit gespeichert wurde.

> ⚠️ In diesem Zustand arbeitest du meist in einem *Detached HEAD*. Änderungen sind möglich, aber nicht automatisch einem normalen Branch zugeordnet.

### Einen Branch erstellen

Ein Branch ist im Kern ein beweglicher Name für einen Commit und damit für einen Snapshot der Historie.

Wenn du einen Feature-Branch erstellst, beginnt dieser beim aktuellen Snapshot. Danach entwickelt sich der Branch mit eigenen neuen Snapshots weiter.

```text
A --- B --- C  main
           \
            D --- E  feature/login
```

- `C` ist der gemeinsame Ausgangszustand.
- `D` und `E` sind neue Snapshots auf dem Feature-Branch.
- `main` verweist weiterhin auf `C`, bis dort weitere Commits entstehen.

### Einen Merge durchführen

Beim Mergen versucht Git, verschiedene Entwicklungsstände zu einem neuen gemeinsamen Snapshot zusammenzuführen.

Git betrachtet dafür typischerweise:

1. den gemeinsamen Ausgangszustand,
2. den Zustand des aktuellen Branches,
3. den Zustand des einzufügenden Branches.

Das Ergebnis ist ein neuer Snapshot, häufig mit einem Merge-Commit.

### Änderungen zurückholen

Wenn ein früherer Commit einen funktionierenden Zustand enthält, kannst du daraus gezielt Dateien oder Inhalte wiederherstellen. Du musst nicht mühsam manuell rekonstruieren, welche Änderungen irgendwann vorgenommen wurden.

Beispiel:

```bash
git restore --source=<commit-hash> -- src/Greeting.php
```

Damit übernimmst du die Version der Datei aus einem bestimmten historischen Snapshot in dein Arbeitsverzeichnis.

---

## Snapshots und die drei Bereiche von Git

Das Snapshot-Modell hängt direkt mit den drei zentralen Bereichen von Git zusammen:

| Bereich | Bedeutung im Snapshot-Modell |
|---|---|
| **Arbeitsverzeichnis** | Der aktuell ausgecheckte Projektzustand auf deiner Festplatte, den du bearbeitest |
| **Index** oder *Staging Area* | Der vorbereitete Zustand für den nächsten Snapshot |
| **Lokales Repository** | Die dauerhaft gespeicherten Snapshots und ihre Historie |

Ein typischer Ablauf sieht so aus:

```text
Arbeitsverzeichnis
      │
      │ git add
      ▼
Index
      │
      │ git commit
      ▼
Repository mit neuem Snapshot
```

Wenn du eine Datei änderst, betrifft das zunächst nur dein Arbeitsverzeichnis. Mit `git add` legst du fest, welche Version dieser Datei in den nächsten Snapshot aufgenommen wird. Erst `git commit` erzeugt den neuen gespeicherten Zustand.

Das ist ein entscheidender Unterschied zu einem bloßen automatischen Speichern.

---

## Der Index: Entwurf des nächsten Snapshots

Die Staging Area ist besonders sinnvoll, wenn du mehrere Änderungen gleichzeitig bearbeitest, aber nicht alles gemeinsam committen möchtest.

Angenommen, du hast parallel:

- einen Fehler in `src/Greeting.php` behoben,
- eine neue Funktion begonnen,
- Tippfehler in `README.md` korrigiert.

Mit dem Index kannst du gezielt einen sauberen Snapshot vorbereiten:

```bash
git add src/Greeting.php
git commit -m "fix: Begrüßung bei leerem Namen korrigieren"
```

Die noch unvollständige Funktion und die Dokumentationsänderung bleiben zunächst außerhalb dieses Commits.

Der Commit beschreibt dadurch einen klaren, überprüfbaren Zustand:

> „Der Fehler ist behoben, ohne andere unfertige Arbeiten einzuschließen.“

---

## Dateien werden nicht als „umbenannt“ gespeichert

Eine häufig überraschende Konsequenz des Snapshot-Modells betrifft Umbenennungen.

Wenn du ausführst:

```bash
git mv src/Greeting.php src/Greeter.php
git commit -m "refactor: Greeting in Greeter umbenennen"
```

speichert Git grundsätzlich einen neuen Snapshot mit:

- einer nicht mehr vorhandenen Datei unter `src/Greeting.php`,
- einer vorhandenen Datei unter `src/Greeter.php`.

Git kann beim Vergleich erkennen, dass die Inhalte sehr ähnlich oder identisch sind. Dann zeigt es die Änderung als Umbenennung an.

```bash
git log --follow -- src/Greeter.php
```

Die Umbenennung ist also häufig eine **Erkennung beim Vergleich**, keine zwingend separat gespeicherte Operation.

Das gilt ähnlich für verschobene Dateien und für viele Arten von Dateiumstrukturierungen.

---

## Snapshot-Modell und Speicherbedarf

Git speichert Inhalte anhand ihres Hashwerts. Gleicher Inhalt erzeugt denselben identifizierbaren Objektinhalt und kann wiederverwendet werden.

Praktisch bedeutet das:

- Eine unveränderte Datei wird nicht bei jedem Commit vollständig dupliziert.
- Identische Inhalte können mehrfach referenziert werden.
- Git komprimiert und packt ältere Objekte zusätzlich effizient.
- Ein Repository mit vielen Commits ist nicht automatisch so groß wie viele vollständige ZIP-Archive des Projekts.

Trotzdem solltest du große Binärdateien wie Videos, Datenbank-Dumps oder erzeugte Build-Artefakte nicht unbedacht versionieren. Schon kleine Änderungen in solchen Dateien können zu großen zusätzlichen Objekten führen.

Für geeignete große Binärdateien gibt es später Git LFS. Generierte Dateien, Caches, Zugangsdaten und lokale IDE-Dateien gehören häufig in `.gitignore`.

---

## Typische Missverständnisse vermeiden

### „Git speichert nur Unterschiede“

Nicht als grundlegendes Denkmodell. Git speichert **Zustände als verknüpfte Objekte** und kann Unterschiede zwischen diesen Zuständen berechnen.

### „Jeder Commit kopiert das gesamte Projekt“

Ein Commit beschreibt den vollständigen Zustand. Identische Inhalte werden aber effizient wiederverwendet.

### „Ein Commit sichert automatisch alles“

Nein. Ein Commit enthält nur das, was du zuvor in die Staging Area aufgenommen hast.

Prüfe daher vor jedem Commit:

```bash
git status
git diff --staged
```

### „Git erkennt jede Umbenennung dauerhaft“

Git erkennt Umbenennungen meist beim Vergleich ähnlicher Inhalte. Bei umfangreichen Änderungen kann diese Erkennung ausbleiben oder anders ausfallen.

### „Ein Snapshot ist ein Backup ohne Grenzen“

Git ist sehr hilfreich zur Wiederherstellung versionierter Dateien. Nicht versionierte Dateien, ignorierte Dateien und nie committed Änderungen sind jedoch nicht automatisch geschützt. Ein echtes Backup bleibt wichtig.

---

## Praktische Kontrolle mit Git

Mit diesen Befehlen untersuchst du Snapshots und ihre Unterschiede im Alltag:

```bash
# Aktuellen Zustand und vorgemerkte Änderungen prüfen
git status

# Nicht vorgemerkte Änderungen ansehen
git diff

# Vorgemerkte Änderungen zum nächsten Snapshot ansehen
git diff --staged

# Aktuellen Commit mit seinem Vorgänger vergleichen
git diff HEAD~1 HEAD

# Inhalt eines bestimmten Commits anzeigen
git show <commit-hash>

# Historische Snapshots in kompakter Form auflisten
git log --oneline --decorate --graph
```

In PhpStorm findest du dieselbe Idee im **Git Log**:

- Jeder Eintrag steht für einen Commit und damit für einen gespeicherten Projektzustand.
- Ein Klick auf einen Commit zeigt die aus dem Vergleich abgeleiteten Änderungen.
- Über **Compare with Current** oder ähnliche Vergleichsfunktionen vergleichst du historische Snapshots mit deinem aktuellen Stand.
- Die Diff-Ansicht zeigt Unterschiede; sie ersetzt aber nicht das grundlegende Verständnis, dass Git Zustände gegenüberstellt.

---

## Merksätze

- **Ein Commit ist ein Snapshot eines vorbereiteten Projektzustands.**
- **Git zeigt Diffs, indem es Snapshots miteinander vergleicht.**
- **Unveränderte Inhalte werden effizient wiederverwendet.**
- **Der Index ist der Entwurf für den nächsten Snapshot.**
- **Branches zeigen auf Commits und damit auf bestimmte Zustände der Historie.**
- **Saubere Commits erzeugen verständliche, überprüfbare Zustände.**

Wenn du Git als Sammlung miteinander verbundener Projektzustände verstehst, wirken spätere Befehle deutlich weniger wie Magie: `branch`, `merge`, `rebase`, `restore` und `revert` werden dann zu unterschiedlichen Wegen, Snapshots zu erstellen, zu vergleichen oder wiederherzustellen.

# Repository, Commit und Branch

## Drei Grundbegriffe für die tägliche Git-Arbeit

Fast jede Git-Aktion dreht sich um drei Begriffe:

- **Repository**: der verwaltete Projektbestand inklusive Geschichte
- **Commit**: ein dauerhaft gespeicherter, beschrifteter Projektzustand
- **Branch**: eine bewegliche Entwicklungslinie innerhalb eines Repositorys

Wer diese Begriffe sauber voneinander trennt, versteht viele Git-Befehle nicht mehr als einzelne Kommandos, sondern als nachvollziehbare Zustandsänderungen.

---

## Das Repository: Projekt und Geschichte an einem Ort

Ein **Repository** ist der Bereich, den Git verwaltet. Es enthält nicht nur die aktuellen Dateien eines Projekts, sondern auch deren vollständige nachvollziehbare Entwicklung.

In einem Repository speichert Git unter anderem:

- Dateien des Projekts,
- frühere Versionen dieser Dateien,
- Commits mit Autor, Zeitpunkt und Nachricht,
- Branches und Tags,
- Einstellungen für dieses konkrete Projekt,
- Informationen über verbundene Server, etwa GitHub.

Ein lokales Git-Repository entsteht beispielsweise mit:

```bash
git init
```

Danach legt Git im Projektordner einen versteckten Unterordner namens `.git` an. Dieser Ordner ist das technische Herz des Repositorys.

```text
mein-projekt/
├── .git/
├── src/
├── tests/
├── README.md
└── composer.json
```

> **Wichtig:** Der Ordner `.git` enthält die Git-Datenbank mit der Historie. Wird er gelöscht, bleiben zwar die Projektdateien erhalten, aber Git „vergisst“ Commits, Branches, Einstellungen und die gesamte Versionsgeschichte.

### Lokale und entfernte Repositories

Ein Repository kann ausschließlich auf dem eigenen Computer liegen. Das ist ein **lokales Repository**.

Später kann es mit einem Server verbunden werden, zum Beispiel mit GitHub. Das dortige Repository wird als **entferntes Repository** oder *Remote Repository* bezeichnet.

```text
Lokaler Computer                   GitHub
────────────────                   ──────
Arbeitskopie                       Entferntes Repository
Git-Historie        ←── Sync ──→   Gemeinsame Git-Historie
Eigene Branches                    Veröffentlichte Branches
```

Git funktioniert aber bereits vollständig ohne GitHub und ohne Internetverbindung. GitHub erweitert Git um Zusammenarbeit, Hosting, Reviews, Issues und Automatisierung. Es ersetzt Git nicht.

---

## Der Commit: ein nachvollziehbarer Projektzustand

Ein **Commit** ist ein gespeicherter Zustand des Projekts zu einem bestimmten Zeitpunkt. Er hält fest, welche Dateien und Inhalte zu diesem Zeitpunkt zum Projekt gehören.

Ein Commit ist daher **kein bloßer Speichern-Knopf**. Er ist eine bewusste Aussage über die Entwicklung des Projekts.

Beispiele für sinnvolle Commit-Aussagen:

- „Registrierung mit E-Mail-Validierung hinzugefügt“
- „Fehlerhafte Berechnung der Mehrwertsteuer korrigiert“
- „API-Dokumentation für Benutzerendpunkt ergänzt“
- „PHPUnit-Tests für Passwort-Reset hinzugefügt“

Weniger hilfreich sind Nachrichten wie:

- „Änderungen“
- „Update“
- „Fix“
- „WIP“
- „asdf“

Eine gute Commit-Nachricht beantwortet knapp die Frage:

> *Was wurde in diesem Schritt fachlich oder technisch verändert?*

### Was Git in einem Commit speichert

Ein Commit enthält mehr als den Inhalt der Dateien. Vereinfacht gehören dazu:

- ein eindeutiger Bezeichner, meist als Hash dargestellt,
- der gespeicherte Projektzustand,
- eine Commit-Nachricht,
- Autor und Zeitpunkt,
- Committer und Zeitpunkt der tatsächlichen Speicherung,
- ein oder mehrere Vorgänger-Commits.

Ein Commit könnte in einer Kurzansicht so aussehen:

```text
Commit: 8f3c1a2
Autor:  Maria Beispiel
Datum:  2025-03-08

Validierung für Registrierungsformular hinzugefügt
```

Der lange technische Bezeichner ist ein Hash, zum Beispiel:

```text
8f3c1a2d7e4b0c4af95e3b8d1e6f9a2c7b4d5e6f
```

Im Alltag genügt meist ein eindeutiger Anfang dieses Hashes, etwa `8f3c1a2`.

### Commits bilden eine Geschichte

Jeder neue Commit verweist normalerweise auf seinen Vorgänger. Dadurch entsteht eine chronologische, technisch präzise Projektgeschichte.

```text
A ─── B ─── C
```

Dabei könnte gelten:

```text
A  Projektgrundstruktur erstellt
B  Benutzeranmeldung implementiert
C  Anmeldung mit Tests abgesichert
```

Der aktuelle Projektstand ist dann Commit `C`. Git kann aber jederzeit die Zustände von `A` oder `B` untersuchen, vergleichen oder bei Bedarf wiederherstellen.

### Commits sind lokale Sicherungspunkte

Ein Commit wird zunächst nur im lokalen Repository gespeichert. Er ist also noch nicht automatisch auf GitHub sichtbar und auch nicht für Kolleginnen und Kollegen verfügbar.

```text
Dateien ändern
      ↓
Commit lokal erstellen
      ↓
Commit zu GitHub übertragen
```

Das Übertragen zu einem Remote erfolgt später mit `git push`.

Diese Trennung ist bewusst: Du kannst lokal sauber arbeiten, Commits vorbereiten, korrigieren und testen, bevor du Änderungen mit anderen teilst.

---

## Ein Commit ist kein Dateiarchiv

Ein verbreitetes Denkmodell lautet: Git speichere bei jedem Commit einfach eine vollständige ZIP-Datei des Projekts. Das ist als erste Vorstellung nützlich, aber technisch nicht ganz richtig.

Git behandelt jeden Commit als vollständigen **Snapshot** des Projektzustands. Intern speichert Git identische Inhalte jedoch effizient nur einmal und verknüpft sie wieder.

Das entscheidende mentale Modell lautet:

> Ein Commit beschreibt, wie das gesamte Projekt zu einem bestimmten Zeitpunkt aussieht.

Git speichert also nicht primär die Anweisung „Zeile 12 wurde geändert“, sondern einen neuen Projektzustand, der auf bereits bekannten Inhalten aufbaut.

Das erklärt später unter anderem, warum Git:

- Änderungen sehr zuverlässig vergleichen kann,
- Branches schnell erstellt,
- alte Zustände einfach wiederherstellen kann,
- mehrere Entwicklungswege effizient verwaltet.

---

## Der Branch: eine Entwicklungslinie

Ein **Branch** ist eine benannte Entwicklungslinie. Er zeigt auf einen bestimmten Commit und bewegt sich weiter, wenn auf diesem Branch neue Commits entstehen.

Ein frisch initialisiertes Repository besitzt meist einen Standard-Branch namens `main`.

```text
main
  ↓
A ─── B ─── C
```

Der Name `main` zeigt hier auf den neuesten Commit `C`.

Wenn ein weiterer Commit entsteht, verschiebt Git den Branch-Zeiger automatisch:

```text
A ─── B ─── C ─── D
                  ↑
                main
```

Der Branch enthält dabei nicht selbst alle Dateien und auch keine Kopie der Commits. Er ist vielmehr ein **beweglicher Verweis** auf den neuesten Commit einer Entwicklungslinie.

> **Merksatz:** Ein Branch ist kein Projektordner und keine vollständige Projektkopie. Er ist ein Name, der auf einen Commit zeigt.

---

## Warum Branches wichtig sind

Branches ermöglichen es, mehrere Arbeiten parallel durchzuführen, ohne den stabilen Hauptstand direkt zu gefährden.

Angenommen, die produktive Anwendung befindet sich auf `main`:

```text
A ─── B ─── C
            ↑
          main
```

Nun soll eine neue Passwort-Reset-Funktion entwickelt werden. Dafür wird ein Feature-Branch angelegt:

```text
A ─── B ─── C
            ↑
          main
            ↑
   feature/password-reset
```

Zu Beginn zeigen beide Branches auf denselben Commit `C`. Danach entstehen die neuen Commits nur auf dem Feature-Branch:

```text
A ─── B ─── C ─── D ─── E
            ↑           ↑
          main   feature/password-reset
```

Die neue Funktion kann entwickelt, getestet und geprüft werden, ohne den Stand auf `main` zu verändern.

Erst wenn die Arbeit fertig ist, wird der Feature-Branch wieder mit `main` zusammengeführt. Dieser Vorgang heißt **Merge**.

```text
A ─── B ─── C ───────────── F
            │               ↑
            D ─── E       main
                ↑
      feature/password-reset
```

Die genaue Form der Historie hängt von der gewählten Merge-Strategie ab. Das Prinzip bleibt jedoch gleich: Branches erlauben isolierte Entwicklung und kontrollierte Integration.

---

## HEAD: Wo arbeite ich gerade?

Git muss wissen, auf welchem Branch du gerade arbeitest. Dafür verwendet Git die Referenz **HEAD**.

HEAD zeigt normalerweise auf den aktuell ausgecheckten Branch:

```text
A ─── B ─── C
            ↑
          main
            ↑
           HEAD
```

Wenn du den Branch wechselst, folgt HEAD diesem Branch:

```text
A ─── B ─── C ─── D
            ↑           ↑
          main   feature/login
                        ↑
                       HEAD
```

Neue Commits werden dann auf `feature/login` erstellt. Der Branch `main` bleibt unverändert auf Commit `C`.

In der Kommandozeile zeigt dieser Befehl die vorhandenen lokalen Branches an:

```bash
git branch
```

Der Stern markiert den aktuell aktiven Branch:

```text
* main
  feature/login
  feature/password-reset
```

Mit modernen Git-Versionen wechselst du einen Branch meist so:

```bash
git switch feature/login
```

Die Arbeit mit Branches wird in einem späteren Kapitel ausführlich behandelt. Für den Einstieg genügt dieses Modell:

- **HEAD** markiert deine aktuelle Arbeitsposition.
- Der aktive **Branch** bestimmt, wohin neue Commits geschrieben werden.
- Ein neuer Commit bewegt den aktiven Branch weiter.

---

## Repository, Commit und Branch im Zusammenhang

Die drei Begriffe gehören zusammen, erfüllen aber unterschiedliche Aufgaben:

| Begriff | Aufgabe | Beispiel |
|---|---|---|
| **Repository** | Verwaltet Projektdateien, Historie und Git-Metadaten | Das gesamte PHP-Projekt mit allen Commits |
| **Commit** | Speichert einen nachvollziehbaren Projektzustand | „Login-Validierung ergänzt“ |
| **Branch** | Kennzeichnet eine Entwicklungslinie und zeigt auf ihren neuesten Commit | `main`, `feature/login` |

Eine vereinfachte Darstellung:

```text
Repository
│
├── Branch main
│   └── A ─── B ─── C
│
└── Branch feature/login
    └── A ─── B ─── C ─── D ─── E
```

Die Commits `A`, `B` und `C` werden von beiden Branches geteilt. Erst ab `D` entwickelt sich der Feature-Branch unabhängig weiter.

---

## Praxisbeispiel: Entwicklung einer kleinen Funktion

Stell dir ein PHP-Projekt für eine Aufgabenverwaltung vor. Das Repository enthält zunächst drei Commits:

```text
A  Projekt mit Composer eingerichtet
B  Aufgabenliste implementiert
C  PHPUnit-Grundkonfiguration ergänzt
```

Der Standard-Branch `main` zeigt auf den letzten Commit:

```text
A ─── B ─── C
            ↑
          main
```

Nun soll eine Funktion zum Markieren erledigter Aufgaben entstehen.

### 1. Feature-Branch erstellen

```bash
git switch -c feature/complete-task
```

Git erstellt den Branch und wechselt sofort dorthin:

```text
A ─── B ─── C
            ↑
          main
            ↑
feature/complete-task
            ↑
           HEAD
```

### 2. Funktion implementieren und committen

Nach der Implementierung und passenden Tests wird ein Commit erstellt:

```bash
git add src/Task.php tests/TaskTest.php
git commit -m "Erledigte Aufgaben markieren"
```

Die Historie sieht danach so aus:

```text
A ─── B ─── C ─── D
            ↑       ↑
          main  feature/complete-task
```

### 3. Weiterarbeiten, ohne `main` zu verändern

Ein weiterer Commit ergänzt die Darstellung im Benutzerinterface:

```bash
git add templates/tasks.php
git commit -m "Erledigte Aufgaben visuell hervorheben"
```

```text
A ─── B ─── C ─── D ─── E
            ↑               ↑
          main  feature/complete-task
```

Währenddessen bleibt `main` auf dem getesteten Stand `C`. Andere Teammitglieder können dort arbeiten, ohne unvollständige Änderungen an der neuen Funktion zu übernehmen.

---

## Häufige Missverständnisse

### „Ein Branch ist eine Kopie des Projekts“

Nicht im üblichen Sinn. Git kopiert nicht bei jedem neuen Branch das gesamte Projektverzeichnis. Ein Branch ist hauptsächlich ein zusätzlicher Zeiger auf einen Commit. Deshalb sind Branches in Git schnell und günstig.

### „Ein Commit wird automatisch auf GitHub gespeichert“

Nein. Ein Commit entsteht zunächst lokal. Erst ein Push überträgt ihn an ein entferntes Repository.

```bash
git push
```

### „Ich brauche für jede Änderung einen neuen Branch“

Nicht zwingend. Für kleine persönliche Experimente kann Arbeit direkt auf `main` sinnvoll sein. In Teamprojekten und bei größeren Änderungen sind separate Feature-Branches jedoch meist der sichere Standard.

### „Ein Branch muss nach dem Zusammenführen bleiben“

Nein. Ist eine Funktion integriert, wird ihr Feature-Branch häufig gelöscht. Die enthaltenen Commits bleiben erhalten, sofern sie in die Zielhistorie übernommen wurden.

### „Ein Commit muss möglichst viele Änderungen enthalten“

Das Gegenteil ist meist besser: Ein Commit sollte eine **abgeschlossene, logisch zusammengehörige Änderung** darstellen. Kleine, verständliche Commits erleichtern Reviews, Fehlersuche und spätere Korrekturen.

---

## Praktische Leitlinien

Für den Einstieg helfen diese Regeln:

1. **Ein Repository pro klar abgegrenztem Projekt**  
   Ein Repository sollte eine zusammenhängende Anwendung, Bibliothek oder Konfiguration verwalten.

2. **Commits klein und verständlich halten**  
   Ein Commit sollte idealerweise eine Aufgabe, Fehlerbehebung oder fachliche Änderung beschreiben.

3. **Aussagekräftige Commit-Nachrichten schreiben**  
   Die Nachricht soll auch Wochen später ohne erneutes Lesen des Codes verständlich sein.

4. **Für neue Funktionen eigene Branches verwenden**  
   Namen wie `feature/login`, `fix/tax-calculation` oder `docs/setup-guide` machen den Zweck sichtbar.

5. **Den stabilen Hauptbranch schützen**  
   `main` sollte in Teamprojekten möglichst nur getestete und überprüfte Änderungen enthalten.

6. **Vor einer Änderung den aktuellen Branch prüfen**  
   Viele Fehler entstehen, weil versehentlich auf dem falschen Branch gearbeitet wird.

```bash
git status
```

Git zeigt dabei unter anderem an, auf welchem Branch du dich befindest.

---

## Zusammenfassung

Ein Git-Repository ist das verwaltete Projekt mitsamt seiner vollständigen Historie. Ein Commit speichert einen bewusst gewählten, beschrifteten Projektzustand. Ein Branch benennt eine Entwicklungslinie und zeigt auf ihren aktuellsten Commit.

Das zentrale Bild lautet:

```text
Repository
├── enthält die gesamte Historie
├── besteht aus vielen Commits
└── organisiert parallele Entwicklung über Branches
```

Oder noch kürzer:

> **Das Repository ist der Speicherort, der Commit ist der Zustand, der Branch ist die Entwicklungslinie.**

Mit diesem Modell lassen sich die nächsten Git-Schritte — insbesondere Staging, Commit-Erstellung, Branch-Wechsel und Zusammenführen — systematisch verstehen.

# Git und GitHub unterscheiden

## Zwei Begriffe, zwei Aufgaben

**Git** und **GitHub** werden oft in einem Atemzug genannt, sind aber grundverschiedene Dinge:

- **Git** ist ein Versionskontrollsystem. Es läuft primär lokal auf deinem Computer und verwaltet die Geschichte deiner Dateien.
- **GitHub** ist eine Online-Plattform, die Git-Repositories hostet und Zusammenarbeit, Reviews, Automatisierung und Projektorganisation ergänzt.

Die Kurzform lautet:

> **Git verwaltet Versionen. GitHub verbindet Menschen und Repositories.**

Du kannst Git vollständig ohne GitHub einsetzen. Umgekehrt basiert ein GitHub-Repository in der Regel auf Git.

---

## Git: das lokale Versionskontrollsystem

Git ist freie Software, die von Linus Torvalds entwickelt wurde. Es speichert die Entwicklung eines Projekts als Folge von **Commits**. Jeder Commit beschreibt einen nachvollziehbaren Stand des Projekts.

Git arbeitet in einem lokalen Repository auf deinem Rechner. Sobald du ein Repository mit `git init` anlegst oder mit `git clone` kopierst, enthält dein Projekt einen versteckten Ordner namens `.git`. Darin liegen unter anderem:

- die Commit-Historie,
- Branches und Tags,
- die Staging Area,
- lokale Konfigurationen,
- Referenzen auf entfernte Repositories,
- Informationen zur Wiederherstellung über Reflogs.

Ein Repository kann deshalb auch ohne Internetverbindung sinnvoll genutzt werden.

### Typische Git-Aufgaben

Mit Git erledigst du beispielsweise diese Arbeitsschritte:

```bash
git status
git add src/Calculator.php
git commit -m "Füge Addition hinzu"
git switch -c feature/subtraction
git merge feature/subtraction
git log --oneline
```

Diese Befehle funktionieren **lokal**. Sie benötigen weder ein GitHub-Konto noch eine Netzwerkverbindung.

### Git ist kein Server und keine Website

Git selbst stellt keine zentrale Website, keine Benutzerverwaltung und keine Pull-Request-Oberfläche bereit. Es kennt zwar entfernte Repositories, sogenannte **Remotes**, aber Git schreibt nicht vor, wo diese liegen.

Ein Remote kann zum Beispiel sein:

- ein Repository auf GitHub,
- ein Repository auf GitLab oder Bitbucket,
- ein Git-Server im Unternehmen,
- ein Repository auf einem eigenen Server,
- ein Verzeichnis in einem lokalen Netzwerk,
- theoretisch sogar ein anderer Ordner auf demselben Computer.

---

## GitHub: eine Plattform rund um Git

GitHub ist ein kommerzieller Cloud-Dienst von GitHub, Inc., das zu Microsoft gehört. Die Plattform speichert Git-Repositories auf Servern und ergänzt Git um Funktionen für Zusammenarbeit und Projektmanagement.

Ein Repository auf GitHub ist also ein **entferntes Git-Repository**, das über das Internet erreichbar ist. Üblicherweise erhält es den Remote-Namen `origin`.

```bash
git remote -v
```

Eine typische Ausgabe sieht so aus:

```text
origin  git@github.com:beispielkonto/mein-projekt.git (fetch)
origin  git@github.com:beispielkonto/mein-projekt.git (push)
```

Die URL zeigt: Das lokale Repository ist mit einem Repository auf GitHub verbunden.

### Funktionen, die GitHub zusätzlich liefert

GitHub erweitert reines Git um eine umfangreiche Web-Plattform:

- **Repository-Hosting** für öffentliche und private Projekte
- **Pull Requests** für vorgeschlagene Änderungen und Code Reviews
- **Issues** für Fehler, Aufgaben und Feature-Wünsche
- **GitHub Actions** für Tests, Builds, Deployments und Releases
- **Projects** für Planung und Projektübersichten
- **Discussions** für langfristige technische oder Community-Diskussionen
- **Wiki** für ergänzende Dokumentation
- **Teams, Rollen und Berechtigungen** für Organisationen
- **Branch-Schutzregeln** und verpflichtende Prüfungen
- **Security-Funktionen**, etwa Secret Scanning, Dependabot und Code Scanning
- **Releases** mit Versionshinweisen und Dateien zum Herunterladen

Keine dieser Funktionen ist Bestandteil von Git selbst.

---

## Der zentrale Vergleich

| Aspekt | Git | GitHub |
|---|---|---|
| Art | Versionskontrollsystem | Hosting- und Kollaborationsplattform |
| Läuft primär | Lokal auf deinem Rechner | Auf Servern und im Webbrowser |
| Internet erforderlich | Nein, für lokale Arbeit nicht | Ja, normalerweise für die Nutzung |
| Kernaufgabe | Dateien, Commits, Branches und Historie verwalten | Repositories teilen und Zusammenarbeit organisieren |
| Wird installiert | Ja, beispielsweise über Git for Windows | Nein, Nutzung per Browser, API oder Client |
| Kennt Pull Requests | Nein | Ja |
| Kennt Issues und Projektboards | Nein | Ja |
| Kann allein verwendet werden | Ja | Nein, Git ist die technische Grundlage |
| Beispiele für Alternativen | Mercurial, Subversion | GitLab, Bitbucket, Azure Repos, Gitea |

---

## Ein praktisches Bild: Notizbuch und gemeinsamer Arbeitsraum

Eine hilfreiche Analogie ist ein persönliches Notizbuch:

- **Git** ist dein Notizbuch mit einer lückenlosen Versionsgeschichte. Du kannst Seiten ergänzen, Fehler korrigieren, Kapitel verzweigen und frühere Stände nachschlagen.
- **GitHub** ist ein gemeinsamer Arbeitsraum mit Kopien dieser Notizbücher. Dort können andere Personen Änderungen ansehen, kommentieren, prüfen, zusammenführen und automatisiert testen lassen.

Das Notizbuch funktioniert auch dann, wenn du allein arbeitest oder keine Internetverbindung hast. Der gemeinsame Arbeitsraum wird wichtig, sobald du dein Projekt sichern, veröffentlichen oder mit anderen entwickeln möchtest.

Diese Analogie hat allerdings eine Grenze: GitHub speichert nicht nur eine einfache Sicherungskopie. Es ist ein vollwertiges, ebenfalls Git-basiertes Repository mit zusätzlicher Plattformfunktionalität.

---

## Ein typischer Ablauf mit Git und GitHub

In der Praxis greifen beide Werkzeuge ineinander.

1. Du erstellst oder klonst ein **lokales Git-Repository**.
2. Du änderst Dateien in deinem Arbeitsverzeichnis.
3. Du nimmst ausgewählte Änderungen mit `git add` in die Staging Area auf.
4. Du erzeugst lokal einen Commit mit `git commit`.
5. Du überträgst den Commit mit `git push` zu GitHub.
6. Auf GitHub erstellst du bei Bedarf einen Pull Request.
7. Teammitglieder prüfen die Änderungen, hinterlassen Kommentare und geben sie frei.
8. GitHub führt den Branch nach den Teamregeln zusammen oder löst automatisierte Prüfungen aus.
9. Du holst die neue gemeinsame Historie mit `git fetch` oder `git pull` zurück auf deinen Computer.

Wichtig ist die Reihenfolge: **Ein Commit entsteht zunächst lokal in Git.** Erst ein Push macht ihn für das Remote-Repository auf GitHub verfügbar.

---

## Lokale und entfernte Historie unterscheiden

Ein häufiger Anfängerfehler besteht darin, die lokale und die entfernte Historie als identisch zu betrachten. Tatsächlich können sie voneinander abweichen.

Angenommen, dein aktueller lokaler Branch `main` enthält einen Commit, den du noch nicht veröffentlicht hast:

```text
Lokal:    A — B — C
GitHub:   A — B
```

Commit `C` existiert bereits vollständig in deinem lokalen Git-Repository. Erst mit diesem Befehl wird er nach GitHub übertragen:

```bash
git push origin main
```

Danach entspricht die Historie wieder einander:

```text
Lokal:    A — B — C
GitHub:   A — B — C
```

Andersherum können Teammitglieder Commits auf GitHub veröffentlicht haben, die du noch nicht abgerufen hast. Dann hilft:

```bash
git fetch origin
```

GitHub ist daher nicht „Git in der Cloud“, sondern ein **entferntes Repository mit einer Kollaborationsplattform darum herum**.

---

## GitHub ist nicht die einzige Git-Plattform

Git ist ein offener Standard und nicht an GitHub gebunden. Ein lokales Git-Repository kann mit unterschiedlichen Anbietern verbunden werden.

Bekannte Alternativen sind:

| Plattform | Typischer Einsatz |
|---|---|
| GitLab | Cloud-Angebot oder selbst betriebene Unternehmensinstanz |
| Bitbucket | Häufig in Teams mit Atlassian-Werkzeugen wie Jira |
| Azure Repos | Integration in Microsoft Azure DevOps |
| Gitea | Schlanke, selbst hostbare Open-Source-Lösung |
| Forgejo | Community-orientierte, selbst hostbare Git-Plattform |

Die grundlegenden Git-Befehle bleiben dabei gleich:

```bash
git clone
git fetch
git pull
git push
```

Was sich ändert, sind vor allem die Weboberfläche, Rechteverwaltung, Automatisierungen und Begriffe der Plattform. GitHub verwendet beispielsweise den Begriff **Pull Request**. Bei GitLab heißt eine vergleichbare Funktion **Merge Request**.

---

## GitHub ist auch nicht GitHub Desktop

Zusätzlich kann der Name **GitHub Desktop** verwirren.

GitHub Desktop ist eine grafische Anwendung für Git und GitHub. Sie vereinfacht häufige Git-Aktionen, etwa Commits, Branch-Wechsel und Pushes. Sie ist jedoch weder Git selbst noch die GitHub-Webplattform.

Die drei Begriffe lassen sich klar einordnen:

| Begriff | Bedeutung |
|---|---|
| Git | Technisches Versionskontrollsystem |
| GitHub | Web-Plattform für Git-Hosting und Zusammenarbeit |
| GitHub Desktop | Grafische Anwendung zur Bedienung von Git und GitHub |

Auch PhpStorm ist in diesem Sinn ein Client: Die IDE ruft im Hintergrund Git-Funktionen auf, zeigt ihre Ergebnisse grafisch an und kann zusätzlich mit GitHub verbunden werden.

---

## Was PhpStorm dabei übernimmt

PhpStorm kann sowohl mit lokalem Git als auch mit GitHub arbeiten.

### Lokale Git-Funktionen in PhpStorm

Ohne GitHub-Anmeldung kannst du in PhpStorm bereits:

- ein Repository initialisieren,
- Änderungen vergleichen,
- Dateien zur Staging Area hinzufügen,
- Commits erstellen,
- Branches anlegen und wechseln,
- Merges und Rebases durchführen,
- die lokale Historie untersuchen.

Dafür muss Git auf Windows installiert und in PhpStorm konfiguriert sein.

### GitHub-Funktionen in PhpStorm

Nach der Verbindung mit einem GitHub-Konto kann PhpStorm zusätzlich:

- Projekte auf GitHub veröffentlichen,
- Repositories klonen,
- Pull Requests erstellen und prüfen,
- Pull-Request-Kommentare lesen und beantworten,
- Issues anzeigen,
- Remotes komfortabel verwalten.

Die IDE ersetzt dabei nicht das Verständnis der zugrunde liegenden Git-Abläufe. Sie bietet lediglich eine andere Bedienoberfläche für viele davon.

---

## Häufige Missverständnisse

### „Ich habe GitHub installiert.“

GitHub ist hauptsächlich ein Webdienst und wird nicht wie Git installiert. Möglich ist, dass du stattdessen eines dieser Werkzeuge installiert hast:

- Git for Windows,
- GitHub Desktop,
- die GitHub CLI `gh`,
- eine IDE-Erweiterung oder eine Anmeldung in PhpStorm.

Präziser wäre zum Beispiel: „Ich habe Git for Windows installiert und mein Repository mit GitHub verbunden.“

### „Meine Dateien sind sicher auf GitHub, weil ich einen Commit erstellt habe.“

Ein lokaler Commit ist noch nicht auf GitHub gesichert. Erst `git push` überträgt ihn zu einem Remote.

Prüfe den Zustand mit:

```bash
git status
```

Git meldet häufig ausdrücklich, wenn dein lokaler Branch Commits enthält, die noch nicht übertragen wurden.

### „GitHub erstellt meine Commits.“

GitHub kann über die Weboberfläche Commits erzeugen, etwa beim Bearbeiten einer Datei im Browser oder beim Zusammenführen eines Pull Requests. Die meisten Commits erstellst du jedoch lokal mit Git oder über PhpStorm.

### „Ohne GitHub kann ich Git nicht nutzen.“

Git funktioniert vollständig ohne GitHub. Das ist nützlich für:

- private Entwürfe,
- Projekte ohne Internetzugang,
- lokale Experimente,
- interne Server,
- vertrauliche Quelltexte,
- Schulungs- und Übungsprojekte.

### „Ein Branch auf GitHub ist dasselbe wie mein lokaler Branch.“

Sie sind verwandt, aber nicht identisch. Beispielsweise sind `main` und `origin/main` unterschiedliche Referenzen:

- `main` bezeichnet deinen lokalen Branch.
- `origin/main` repräsentiert den zuletzt bekannten Stand des Branches auf dem Remote `origin`.

Git aktualisiert `origin/main` erst durch Kommunikation mit dem Remote, etwa per `git fetch`.

---

## Die richtige Begriffswahl im Alltag

Eine präzise Sprache verhindert Missverständnisse im Team:

| Ungenau | Präziser |
|---|---|
| „Ich habe es in GitHub committed.“ | „Ich habe lokal committed und nach GitHub gepusht.“ |
| „GitHub hat einen Konflikt.“ | „Der Pull Request kann nicht automatisch gemergt werden.“ |
| „Ich ziehe GitHub.“ | „Ich hole Änderungen vom Remote mit `git pull`.“ |
| „Der Branch ist auf GitHub.“ | „Der lokale Branch wurde zu `origin/feature/login` gepusht.“ |
| „Git ist kaputt.“ | „Mein lokaler Branch und der Remote-Branch sind auseinander gelaufen.“ |

Diese Unterscheidung wird besonders wichtig, sobald mehrere Personen gleichzeitig an einem Projekt arbeiten.

---

## Merksatz

> **Git ist das Werkzeug für Versionsgeschichte. GitHub ist ein Ort und eine Plattform für gemeinsame Git-Projekte.**

Wenn du lokal Dateien änderst, stagen, committen, branchen oder zurücksetzen möchtest, arbeitest du primär mit **Git**. Wenn du Änderungen veröffentlichst, Pull Requests prüfst, Issues planst oder automatisierte Tests auf einem Server ausführst, nutzt du Funktionen von **GitHub**.

Im nächsten Schritt lernst du typische Git-Workflows kennen und kannst Git sowie GitHub gezielt für Einzelarbeit und Teamarbeit einordnen.

# Typische Git-Workflows im Überblick

## Lernziele

Nach diesem Abschnitt kannst du:

- typische Git-Workflows voneinander unterscheiden,
- für Einzelarbeit, kleine Teams und Open-Source-Projekte einen passenden Ablauf wählen,
- lokale Arbeitsschritte von der Zusammenarbeit über ein Remote-Repository trennen,
- verstehen, warum Branches und Pull Requests zentrale Werkzeuge professioneller Teams sind,
- erkennen, dass ein Workflow eine *Teamvereinbarung* ist — nicht bloß eine Befehlsfolge.

---

## Was bedeutet „Git-Workflow“?

Ein **Git-Workflow** beschreibt die vereinbarten Schritte, nach denen ein Team Änderungen entwickelt, prüft, integriert und veröffentlicht.

Git selbst schreibt keinen bestimmten Ablauf vor. Es stellt Werkzeuge bereit:

- Commits speichern nachvollziehbare Änderungen.
- Branches ermöglichen parallele Arbeit.
- Merges oder Rebases führen Entwicklungslinien zusammen.
- Remotes verbinden lokale Repositories mit gemeinsamen Servern wie GitHub.
- Pull Requests strukturieren Diskussionen und Reviews.

Ein Workflow beantwortet vor allem organisatorische Fragen:

- Auf welchem Branch beginnt neue Arbeit?
- Wie werden Änderungen benannt und in kleine Einheiten zerlegt?
- Wann dürfen Änderungen in den Hauptbranch?
- Wer prüft eine Änderung?
- Welche automatischen Tests müssen bestehen?
- Wie werden Releases und dringende Fehlerkorrekturen behandelt?

> Git ist das Werkzeug. Der Workflow ist die gemeinsame Arbeitsweise.

---

## Die gemeinsame Grundlage fast aller Workflows

Unabhängig vom konkreten Modell durchläuft eine Änderung meist dieselben Stationen:

1. **Ausgangszustand aktualisieren**  
   Die Entwicklerin oder der Entwickler holt aktuelle Änderungen aus dem gemeinsamen Repository.

2. **Isoliert entwickeln**  
   Die Arbeit findet in einem passenden Branch statt — bei sehr kleinen Projekten manchmal direkt auf dem Hauptbranch.

3. **Kleine Commits erstellen**  
   Jede logisch zusammenhängende Änderung wird als eigener Commit gespeichert.

4. **Änderung prüfen**  
   Lokale Tests, statische Analyse, Linter und ein eigener Blick auf den Diff reduzieren Fehler frühzeitig.

5. **Änderung veröffentlichen**  
   Der Branch wird zu GitHub oder einem anderen Remote gepusht.

6. **Integration vorbereiten**  
   Ein Pull Request macht die Änderung sichtbar, diskutierbar und überprüfbar.

7. **Automatisch und menschlich prüfen**  
   CI prüft beispielsweise Tests und Codequalität. Teammitglieder führen Reviews durch.

8. **In den Zielbranch integrieren**  
   Nach erfolgreicher Prüfung wird die Änderung gemergt, gesquasht oder rebased.

9. **Branch aufräumen**  
   Nicht mehr benötigte Feature-Branches werden gelöscht.

Dieser Ablauf lässt sich als allgemeines Muster lesen:

```text
Hauptbranch aktualisieren
        ↓
Arbeitsbranch erstellen
        ↓
Änderung entwickeln
        ↓
Kleine Commits erstellen
        ↓
Tests und Selbstprüfung
        ↓
Branch veröffentlichen
        ↓
Pull Request und Review
        ↓
Integration in Hauptbranch
        ↓
Branch löschen
```

---

## Der direkte Workflow für Einzelprojekte

Bei einem persönlichen Lern-, Demo- oder Kleinstprojekt arbeitet häufig nur eine Person am Repository. Dann kann die Entwicklung direkt auf dem Hauptbranch stattfinden, der heute meist `main` heißt.

Ein vereinfachter Ablauf:

```text
Änderung vornehmen
        ↓
Änderung testen
        ↓
Commit erstellen
        ↓
Nach GitHub pushen
```

Beispiel:

```bash
git status
git add src/Calculator.php
git commit -m "Addiere Methode für Multiplikation"
git push
```

### Vorteile

- Sehr wenig organisatorischer Aufwand.
- Schnell und leicht verständlich.
- Für Übungsprojekte und private Experimente gut geeignet.

### Nachteile

- Es gibt keine isolierte Arbeitslinie für unfertige Änderungen.
- Fehler können direkt auf dem Hauptbranch landen.
- Reviews und automatisierte Qualitätskontrollen werden leicht übersprungen.
- Bei mehreren Mitwirkenden entstehen schnell Konflikte.

Für ein persönliches Repository ist direkteres Arbeiten oft angemessen. Sobald jedoch eine Änderung riskant, größer oder gemeinsam überprüft werden soll, lohnt sich ein eigener Branch.

---

## Der zentrale Workflow

Der **zentrale Workflow** ähnelt der Arbeitsweise klassischer zentraler Versionskontrollsysteme: Alle Teammitglieder arbeiten direkt mit einem gemeinsamen Hauptbranch.

```text
Entwicklerin A ── Commit und Push ──→ main im Remote-Repository
Entwickler B  ── Commit und Push ──→ main im Remote-Repository
Entwickler C  ── Commit und Push ──→ main im Remote-Repository
```

Obwohl Git ein verteiltes System ist, kann ein Team es auf diese zentralisierte Weise verwenden. Das Remote-Repository ist dann die maßgebliche gemeinsame Stelle.

### Typischer Ablauf

1. Aktuellen Stand abrufen.
2. Direkt auf `main` entwickeln.
3. Änderungen committen.
4. Vor dem Push neue Änderungen anderer Personen integrieren.
5. Änderungen nach `main` pushen.

### Stärken

- Einfaches Modell mit wenigen Branches.
- Für sehr kleine, eng abgestimmte Teams möglich.
- Wenig Prozessaufwand.

### Risiken

- Unfertige oder fehlerhafte Änderungen können den Hauptbranch beeinträchtigen.
- Mehrere parallele Änderungen erzeugen häufiger Integrationskonflikte.
- Code Reviews vor der Integration sind nicht automatisch Teil des Prozesses.
- Ein kaputter Hauptbranch kann alle Teammitglieder blockieren.

Der zentrale Workflow ist für Lernzwecke nützlich, aber für die meisten professionellen Teams zu riskant. Moderne Plattformen wie GitHub fördern deshalb branchbasierte Zusammenarbeit mit Pull Requests.

---

## Der Feature-Branch-Workflow

Beim **Feature-Branch-Workflow** erhält jede eigenständige Aufgabe einen eigenen Branch. Der Hauptbranch bleibt dabei möglichst stabil und jederzeit integrierbar.

Typische Branchnamen sind:

```text
feature/add-invoice-export
fix/login-validation
docs/update-installation-guide
chore/update-dependencies
```

Ein Feature-Branch entsteht aus dem aktuellen Hauptbranch:

```text
main
  └── feature/add-invoice-export
```

Während der Entwicklung enthält der Feature-Branch mehrere Commits:

```text
main
  └── feature/add-invoice-export
        ├── Add export service
        ├── Add CSV formatter
        └── Add export tests
```

Nach Review und erfolgreichen Prüfungen wird die Arbeit zurück in `main` integriert:

```text
main ────────●──────────────●
              \            /
feature         ●──●──●────
```

### Typischer Ablauf

1. `main` aktualisieren.
2. Einen Branch für eine klar abgegrenzte Aufgabe erstellen.
3. Die Änderung in kleinen, nachvollziehbaren Commits umsetzen.
4. Tests lokal ausführen.
5. Den Branch veröffentlichen.
6. Einen Pull Request nach `main` erstellen.
7. Review und CI abwarten.
8. Die Änderung integrieren.
9. Den Feature-Branch löschen.

### Vorteile

- Unfertige Arbeit bleibt vom Hauptbranch getrennt.
- Mehrere Aufgaben können parallel entwickelt werden.
- Pull Requests schaffen einen klaren Ort für Diskussion und Review.
- Automatisierte Tests können vor dem Merge verpflichtend sein.
- Änderungen lassen sich gezielt zurückstellen oder verwerfen.

### Wichtige Regel: Branches kurzlebig halten

Ein Feature-Branch sollte nicht wochenlang vom Hauptbranch getrennt bleiben. Je länger er existiert, desto größer wird das Risiko für:

- komplexe Merge-Konflikte,
- überholte Annahmen,
- schwer überprüfbare Pull Requests,
- doppelte oder widersprüchliche Arbeit.

Besser sind kleine, regelmäßig integrierte Änderungen. Ein Branch für „neue Rechnungsfunktion“ ist sinnvoller als ein monatelanger Branch für „Version 3 komplett neu schreiben“.

---

## Pull-Request-Workflow

Ein **Pull Request** ist keine Git-Funktion im engeren Sinn, sondern eine Funktion von Plattformen wie GitHub. Er bittet darum, Änderungen aus einem Quellbranch in einen Zielbranch zu übernehmen.

Beispielsweise:

```text
feature/add-invoice-export → main
```

Der Pull Request bündelt wichtige Informationen:

- die betroffenen Commits,
- den vollständigen Diff,
- die Beschreibung der Änderung,
- verknüpfte Issues,
- Kommentare und Review-Entscheidungen,
- Ergebnisse automatisierter Prüfungen.

### Ein sinnvoller Pull Request beantwortet

- *Was* wurde verändert?
- *Warum* ist die Änderung nötig?
- *Wie* wurde sie getestet?
- Welche Risiken, Einschränkungen oder offenen Punkte gibt es?
- Welches Issue wird dadurch gelöst?

Eine kurze, gute Beschreibung könnte lauten:

> „Dieser Pull Request ergänzt einen CSV-Export für Rechnungen. Der Export berücksichtigt Rechnungsnummer, Datum, Kundschaft und Gesamtbetrag. PHPUnit-Tests decken leere Listen sowie mehrere Rechnungen ab.“

### Pull Requests sind mehr als eine Freigabe

Ein professioneller Pull Request dient nicht nur dazu, Fehler zu finden. Er unterstützt auch:

- Wissenstransfer im Team,
- gemeinsame Architekturentscheidungen,
- Dokumentation technischer Gründe,
- Sicherheitsprüfungen,
- konsistente Codequalität.

Ein Review bedeutet dabei nicht: „Die Verantwortung liegt jetzt bei der prüfenden Person.“ Die Autorin oder der Autor bleibt für die Änderung verantwortlich.

---

## GitHub Flow

**GitHub Flow** ist ein schlanker, weit verbreiteter Workflow. Er basiert auf einem dauerhaft stabilen Hauptbranch und kurzen Arbeitsbranches.

Die Grundidee lautet:

> Alles auf `main` ist grundsätzlich bereit für eine Veröffentlichung.

### Ablauf von GitHub Flow

1. Der Branch `main` enthält einen funktionierenden, freigegebenen Stand.
2. Für jede Aufgabe wird ein neuer Branch von `main` erstellt.
3. Die Änderung wird in kleinen Commits entwickelt.
4. Der Branch wird frühzeitig nach GitHub gepusht.
5. Ein Pull Request eröffnet Review und automatisierte Prüfungen.
6. Nach erfolgreicher Prüfung wird die Änderung nach `main` integriert.
7. Die Änderung wird bei Bedarf direkt aus `main` ausgeliefert.

```text
main ─────●────────────●────────────●──
           \          /              \
feature-a   ●──●──●──                 \
                                            Release
feature-b               ●──●──●──────●
```

### Wann GitHub Flow gut passt

GitHub Flow eignet sich besonders für:

- Webanwendungen mit häufigen Deployments,
- Teams mit guter Testautomatisierung,
- SaaS-Produkte,
- Projekte mit kontinuierlicher Auslieferung,
- kleine bis mittlere Teams mit kurzen Änderungszyklen.

### Voraussetzung: `main` muss geschützt sein

Damit GitHub Flow zuverlässig funktioniert, sollte der Hauptbranch nicht beliebig beschreibbar sein. Typische Schutzregeln sind:

- Pull Request vor dem Merge verpflichtend,
- mindestens eine Review-Freigabe,
- erfolgreiche CI-Prüfungen,
- keine direkten Pushes nach `main`,
- aktuelle Zielbranch-Basis vor dem Merge,
- optional eine Merge Queue bei hoher Teamaktivität.

Diese Regeln werden später als **Branch-Schutz** oder **Rulesets** genauer behandelt.

---

## Git Flow

**Git Flow** verwendet mehr dauerhafte Branches und folgt stärker einem klassischen Release-Zyklus. Die zwei zentralen Branches sind üblicherweise:

- `main` für veröffentlichte, produktive Versionen,
- `develop` für die nächste geplante Entwicklungsversion.

Zusätzlich entstehen zeitlich begrenzte Branches:

- `feature/...` für neue Funktionen,
- `release/...` zur Vorbereitung einer Version,
- `hotfix/...` für dringende Fehlerkorrekturen in Produktion.

```text
main     ─────●──────────────────●────────●──
                \                /          \
develop  ───●────●────●────●────●────●──────●──
                  \        \
feature-a           ●──●──●
feature-b                    ●──●
```

### Typischer Ablauf

1. Neue Funktionen starten von `develop`.
2. Fertige Features werden nach `develop` integriert.
3. Für eine bevorstehende Veröffentlichung entsteht ein `release/...`-Branch.
4. Nach finaler Prüfung wird der Release-Branch nach `main` übernommen und getaggt.
5. Wichtige Produktionsfehler erhalten einen `hotfix/...`-Branch von `main`.
6. Ein Hotfix wird sowohl nach `main` als auch nach `develop` integriert.

### Vorteile

- Klare Trennung zwischen produktivem Stand und laufender Entwicklung.
- Gut nachvollziehbare Release-Vorbereitung.
- Sinnvoll bei versionierter Software mit geplanten Auslieferungen.

### Nachteile

- Mehr Branches und mehr Merge-Vorgänge.
- Höherer organisatorischer Aufwand.
- Lang lebende Branches können Integrationen erschweren.
- Für kontinuierlich ausgelieferte Webanwendungen oft unnötig schwergewichtig.

Git Flow ist nicht „professioneller“ als GitHub Flow. Es passt lediglich zu anderen Rahmenbedingungen, etwa zu Produkten mit festen Release-Terminen, langen Testphasen oder unterstützten Wartungsversionen.

---

## Trunk-Based Development

Bei **Trunk-Based Development** integriert das Team sehr häufig in einen gemeinsamen Hauptentwicklungszweig, den *Trunk*. In Git heißt dieser Branch oft `main`.

Der entscheidende Unterschied zum klassischen Feature-Branch-Workflow: Branches sind extrem kurzlebig oder werden nur lokal verwendet. Änderungen werden klein gehalten und häufig integriert.

```text
main ──●──●──●──●──●──●──●──●──
         \ /     \ /     \ /
        kurz     kurz    kurz
```

### Voraussetzungen

Trunk-Based Development funktioniert nur zuverlässig, wenn ein Team technische Disziplin mitbringt:

- umfassende automatisierte Tests,
- schnelle CI-Pipelines,
- kleine und häufige Commits,
- starke Code-Review-Kultur,
- Mechanismen wie Feature Flags für unvollständige Funktionen,
- konsequente Pflege eines funktionsfähigen Hauptbranches.

### Geeignete Einsatzbereiche

- Teams mit kontinuierlicher Integration und Auslieferung,
- Produkte mit hoher Entwicklungsgeschwindigkeit,
- große Teams, die Integrationsstau vermeiden müssen,
- Systeme mit guter Testabdeckung.

Ohne zuverlässige Tests kann dieser Workflow riskant sein. Häufiges Integrieren ersetzt keine Qualitätsprüfung — es macht sie zwingender.

---

## Forking-Workflow

Der **Forking-Workflow** ist besonders in Open-Source-Projekten üblich. Beitragende erhalten nicht direkt Schreibrechte auf das Original-Repository, sondern erstellen eine eigene Serverkopie, einen **Fork**.

```text
Original-Repository
        ↓ Fork
Persönliches GitHub-Repository
        ↓ Clone
Lokales Repository
        ↓ Push
Persönlicher Fork
        ↓ Pull Request
Original-Repository
```

Dabei gibt es meist zwei Remotes:

- `origin`: der persönliche Fork,
- `upstream`: das ursprüngliche Projekt.

### Typischer Ablauf

1. Ein Projekt auf GitHub forken.
2. Den Fork lokal klonen.
3. Das Original als `upstream` hinterlegen.
4. Einen Feature-Branch erstellen.
5. Änderungen entwickeln und zum eigenen Fork pushen.
6. Einen Pull Request vom Fork zum Original-Repository erstellen.
7. Den eigenen Fork regelmäßig mit `upstream` synchronisieren.

### Vorteile

- Maintainer behalten die Kontrolle über Schreibrechte.
- Externe Beiträge sind ohne direkten Repository-Zugriff möglich.
- Änderungen bleiben zunächst im eigenen Bereich.
- Gut skalierbar für große Communities.

### Nachteile

- Ein zusätzlicher Remote und Synchronisationsschritte erhöhen die Komplexität.
- Neue Mitwirkende müssen Fork, `origin` und `upstream` verstehen.
- Pull Requests können aus veralteten Forks entstehen, wenn nicht regelmäßig synchronisiert wird.

---

## Release- und Hotfix-Workflows

Viele Teams benötigen neben normaler Feature-Entwicklung einen Ablauf für Veröffentlichungen und dringende Produktionsfehler.

### Release-Branch

Ein **Release-Branch** friert den Funktionsumfang einer bevorstehenden Version ein. Während neue Features weiterentwickelt werden, konzentriert sich der Release-Branch auf:

- Tests,
- Fehlerkorrekturen,
- Dokumentation,
- Versionsnummern,
- Release Notes,
- Freigaben.

Beispiel:

```text
main
  ├── feature/new-reporting
  └── release/2.4.0
```

Nach erfolgreicher Veröffentlichung wird der Stand typischerweise getaggt, etwa als `v2.4.0`.

### Hotfix-Branch

Ein **Hotfix-Branch** korrigiert einen kritischen Fehler in einer bereits veröffentlichten Version. Er startet von dem Branch oder Tag, der den produktiven Stand repräsentiert.

```text
main ─────●────────────●────
           \
hotfix      ●──●────────────
```

Wichtig ist, dass ein Hotfix nicht nur in den produktiven Branch gelangt. Die Korrektur muss auch in die laufende Entwicklung übernommen werden. Sonst taucht derselbe Fehler in der nächsten Version erneut auf.

---

## Welcher Workflow passt zu welchem Projekt?

| Situation | Geeigneter Einstieg | Warum |
|---|---|---|
| Persönliches Lernprojekt | Direkter Workflow auf `main` oder kurze Feature-Branches | Minimaler Aufwand, schneller Lernfortschritt |
| Kleines Team mit wenigen Änderungen | Feature-Branch-Workflow mit Pull Requests | Gute Balance aus Sicherheit und Einfachheit |
| Webanwendung mit häufigen Deployments | GitHub Flow | Stabile Hauptlinie, kurze Branches, schnelle Integration |
| Versionierte Software mit festen Releases | Git Flow oder ein vereinfachter Release-Branch-Workflow | Geplante Release-Phasen und Hotfixes klar abbildbar |
| Team mit starker Testautomatisierung | Trunk-Based Development | Häufige Integration reduziert langfristige Abweichungen |
| Open-Source-Projekt | Forking-Workflow | Beiträge ohne direkte Schreibrechte ermöglichen |
| Großes Unternehmen mit Compliance-Anforderungen | Feature-Branches, Pull Requests, Schutzregeln und Release-Prozess | Nachvollziehbarkeit, Freigaben und kontrollierte Berechtigungen |

Ein Team muss nicht ein Modell unverändert übernehmen. Häufig ist ein bewusst vereinfachter, dokumentierter Mischansatz sinnvoll.

Beispiel:

- Entwicklung nach GitHub Flow,
- Releases über Tags,
- Hotfixes über kurze `hotfix/...`-Branches,
- verpflichtende Tests und mindestens ein Review vor jedem Merge.

---

## Merge, Squash und Rebase im Workflow

Wenn ein Pull Request fertig ist, muss entschieden werden, *wie* seine Änderungen in den Zielbranch gelangen. Die drei häufigsten Methoden sind:

| Methode | Ergebnis in der Historie | Typischer Einsatz |
|---|---|---|
| Merge Commit | Verbindet zwei Entwicklungslinien mit einem Merge-Commit | Sichtbare Branch-Historie erwünscht |
| Squash Merge | Fasst alle Branch-Commits zu einem Commit zusammen | Kleine, saubere Hauptbranch-Historie |
| Rebase and Merge | Spielt Branch-Commits linear auf den Zielbranch | Lineare Historie, einzelne Commits sollen erhalten bleiben |

Diese Entscheidung ist kein rein ästhetisches Detail. Sie beeinflusst:

- die Lesbarkeit der Historie,
- die Rückverfolgbarkeit einzelner Arbeitsschritte,
- die Größe eines späteren Reverts,
- den Umgang mit automatisierten Release Notes.

Für Einsteigerteams ist **Squash Merge** oft ein guter Standard: Der Feature-Branch darf mehrere Arbeitscommits enthalten, während `main` pro Pull Request einen klaren Commit erhält. Später werden Merge- und Rebase-Strategien ausführlich behandelt.

---

## Ein praxistauglicher Standardworkflow für viele Teams

Für die meisten PHP-Projekte mit GitHub und PhpStorm ist dieser Ablauf ein solides Fundament:

1. Ein Issue beschreibt die Aufgabe.
2. Ein kurzer Feature- oder Fix-Branch entsteht von `main`.
3. Die Umsetzung erfolgt in kleinen, testbaren Commits.
4. PHPUnit, statische Analyse und Formatierungsprüfungen laufen lokal.
5. Der Branch wird zu GitHub gepusht.
6. Ein Pull Request verknüpft die Änderung mit dem Issue.
7. GitHub Actions führt die vorgesehenen Prüfungen aus.
8. Mindestens eine qualifizierte Person führt ein Review durch.
9. Nach erfolgreicher CI und Freigabe wird gemergt oder gesquasht.
10. Der Branch wird gelöscht.
11. `main` bleibt jederzeit in einem integrierbaren, idealerweise auslieferbaren Zustand.

Dieser Ablauf verbindet Geschwindigkeit mit Kontrolle, ohne unnötig kompliziert zu werden.

---

## Grundsätze für jeden Workflow

Ein guter Workflow folgt einigen Regeln, unabhängig von Tool, Teamgröße oder Branch-Modell.

### Änderungen klein halten

Kleine Änderungen sind leichter:

- zu verstehen,
- zu testen,
- zu prüfen,
- zu integrieren,
- zurückzunehmen.

Ein Pull Request mit einer klaren Aufgabe ist wertvoller als ein Sammelpaket aus Feature, Refactoring, Formatierung und Abhängigkeitsupdate.

### Den Hauptbranch schützen

Direkte Pushes nach `main` sollten in Teamprojekten normalerweise vermieden werden. Pull Requests, Reviews und CI schaffen eine kontrollierte Integrationsschleuse.

### Früh und regelmäßig integrieren

Lange getrennte Branches führen zu Konflikten und Überraschungen. Regelmäßige Synchronisierung mit dem Hauptbranch reduziert dieses Risiko.

### Automatisierung als Sicherheitsnetz nutzen

Tests, Linter und statische Analyse ersetzen kein Review. Sie prüfen jedoch wiederholbare Regeln zuverlässig und entlasten Menschen von Routineaufgaben.

### Konventionen dokumentieren

Ein Team sollte wichtige Entscheidungen schriftlich festhalten, zum Beispiel:

- Branch-Namensschema,
- Commit-Nachrichtenformat,
- erforderliche Prüfungen,
- Anzahl notwendiger Reviews,
- Merge-Strategie,
- Umgang mit Hotfixes,
- Regeln für Force Pushes.

Eine kurze `CONTRIBUTING.md` oder ein Abschnitt im Projekt-README verhindert viele Missverständnisse.

---

## Häufige Fehlannahmen

### „Ein Branch ist nur für große Features nötig.“

Nein. Gerade kleine, klar abgegrenzte Änderungen profitieren von einem Branch und einem kleinen Pull Request. Der Aufwand ist gering, der Nutzen für Review und Rückverfolgbarkeit hoch.

### „Pull Requests sind nur Bürokratie.“

Ein schlecht gepflegter Pull Request kann bürokratisch wirken. Ein guter Pull Request ist dagegen ein Ort für Qualitätsprüfung, Kommunikation und Wissensweitergabe.

### „Git Flow ist immer der professionelle Standard.“

Git Flow ist ein mögliches Modell, aber nicht universell passend. Für viele moderne Webprojekte ist GitHub Flow einfacher und effektiver.

### „Der Hauptbranch darf nie kaputtgehen.“

Das ist ein wichtiges Ziel. Realistisch ist jedoch: Fehler können passieren. Deshalb braucht ein Team Tests, Reviews, Monitoring, schnelle Reverts und einen klaren Hotfix-Prozess.

### „Viele lange Branches bedeuten gute Organisation.“

Oft ist das Gegenteil der Fall. Lang lebende Branches erhöhen die Distanz zum Hauptbranch und erschweren Integration. Gute Organisation bedeutet vor allem: kleine, nachvollziehbare und häufig integrierte Arbeit.

---

## Merksätze

- **Ein Workflow ist eine Teamvereinbarung, keine Git-Pflicht.**
- **Branches isolieren Arbeit; Commits dokumentieren sie.**
- **Pull Requests machen Änderungen überprüfbar und diskutierbar.**
- **Kurze Branches und kleine Pull Requests reduzieren Integrationsrisiken.**
- **Der Hauptbranch sollte geschützt, geprüft und möglichst jederzeit verwendbar sein.**
- **Der beste Workflow ist der einfachste Ablauf, der die Anforderungen des Teams zuverlässig erfüllt.**

Im weiteren Kurs werden die Bausteine dieser Workflows — Branches, Merges, Rebases, Remotes, Pull Requests, Reviews, Releases und Automatisierung — Schritt für Schritt praktisch vertieft.

# Häufige Anfängerfehler und Denkmodelle

## Warum Denkmodelle wichtiger sind als Befehle

Viele Git-Probleme entstehen nicht, weil ein Befehl unbekannt ist, sondern weil das zugrunde liegende Modell fehlt. Wer Git nur als Sammlung von Kommandos lernt, merkt sich etwa:

```bash
git add .
git commit -m "Änderungen"
git push
```

Das funktioniert in einfachen Situationen. Sobald aber ein Konflikt, ein falscher Commit oder eine Änderung auf dem falschen Branch auftaucht, fehlt die Orientierung.

Ein belastbares Verständnis beginnt mit dieser Grundidee:

> Git verwaltet nicht einfach Dateien. Git verwaltet **Versionen von Projektzuständen** und die Beziehungen zwischen diesen Versionen.

Die folgenden Denkmodelle helfen dabei, Git-Situationen ruhig zu analysieren, statt Befehle auf Verdacht auszuprobieren.

---

## Das wichtigste Modell: Git hat mehrere Zustände

Eine Datei kann in Git nicht nur „da“ oder „gespeichert“ sein. Für die tägliche Arbeit sind drei Bereiche entscheidend:

1. **Arbeitsverzeichnis**  
   Die Dateien, die gerade im Editor liegen und bearbeitet werden.

2. **Staging Area** oder **Index**  
   Die Auswahl der Änderungen, die im *nächsten* Commit landen soll.

3. **Lokales Repository**  
   Die bereits erstellte, lokale Commit-Historie.

Später kommt häufig noch ein vierter Bezugspunkt hinzu:

4. **Entferntes Repository**  
   Beispielsweise ein Repository auf GitHub.

Der typische Weg einer Änderung sieht so aus:

```text
Datei bearbeiten
      ↓
Arbeitsverzeichnis
      ↓ git add
Staging Area
      ↓ git commit
lokale Historie
      ↓ git push
GitHub oder anderer Remote
```

### Die zentrale Frage bei jedem Problem

Bevor du einen Git-Befehl eingibst, frage dich:

> **Wo befindet sich die Änderung gerade – und wohin soll sie?**

Diese Frage ist oft hilfreicher als die Suche nach einem vermeintlichen „Rückgängig-Befehl“.

| Situation | Die Änderung befindet sich gerade | Typisches Ziel |
|---|---|---|
| Datei wurde bearbeitet, aber noch nicht vorgemerkt | Arbeitsverzeichnis | Staging Area oder verwerfen |
| Falsche Datei wurde für den Commit ausgewählt | Staging Area | Zurück ins Arbeitsverzeichnis |
| Commit wurde lokal erstellt, aber noch nicht veröffentlicht | Lokales Repository | Commit korrigieren oder Historie anpassen |
| Commit wurde bereits auf GitHub veröffentlicht | Remote und lokale Historie | Nachvollziehbar korrigieren, nicht unbedacht umschreiben |

Der Befehl `git status` beantwortet genau diese Zustandsfrage und sollte daher zum Standard werden.

```bash
git status
```

---

## Denkmodell: Ein Commit ist ein Snapshot, kein Änderungsprotokoll

Anfänger stellen sich einen Commit oft als Liste einzelner Änderungen vor, etwa:

> „In diesem Commit wurde Zeile 18 in Datei A angepasst.“

Das ist als Anzeige nicht falsch, aber als Modell unvollständig. Git speichert bei einem Commit grundsätzlich einen **vollständigen Snapshot des vorgemerkten Projektzustands**.

Ein Commit bedeutet eher:

> „So sah das gesamte Projekt zu diesem Zeitpunkt aus.“

Git kann daraus sehr effizient die Unterschiede zwischen zwei Snapshots berechnen. Deshalb wirken Commits in Tools und Diffs häufig wie Änderungslisten. Intern und gedanklich ist aber der Snapshot entscheidend.

### Konsequenz für die Praxis

Ein Commit sollte einen **in sich stimmigen Zustand** festhalten:

- Die Anwendung lässt sich idealerweise ausführen.
- Tests sind möglichst grün.
- Die Änderung erfüllt genau einen nachvollziehbaren Zweck.
- Andere Teammitglieder können verstehen, *warum* der Snapshot entstanden ist.

Schlecht wäre ein Commit wie:

```text
WIP
```

Oder:

```text
Neue Funktion, CSS angepasst, Debug-Ausgaben, Composer aktualisiert
```

Besser wäre eine fachlich klare Trennung:

```text
feat: E-Mail-Adresse bei der Registrierung validieren
```

```text
test: Validierung ungültiger E-Mail-Adressen abdecken
```

```text
style: Formularabstände auf der Registrierungsseite vereinheitlichen
```

Ein guter Commit ist keine Momentaufnahme der eigenen Arbeitszeit. Er ist eine verständliche Einheit in der gemeinsamen Projektgeschichte.

---

## Denkmodell: Git speichert lokale Arbeit nicht automatisch auf GitHub

Ein besonders häufiger Irrtum lautet:

> „Ich habe einen Commit erstellt, also ist die Änderung jetzt auf GitHub.“

Das stimmt nicht. Ein Commit wird zunächst nur im **lokalen Repository** erstellt. Erst ein Push überträgt ihn an ein entferntes Repository.

```text
git commit  →  lokale Historie
git push    →  entfernte Historie
```

Umgekehrt lädt `git pull` nicht einfach „alles Neue“ herunter. Es holt Änderungen vom Remote und integriert sie in den aktuellen lokalen Branch.

### Vier Fragen zur Einordnung

Wenn du nicht sicher bist, ob etwas gesichert oder veröffentlicht ist, unterscheide präzise:

1. Wurde die Datei gespeichert?
2. Wurde die Änderung mit `git add` vorgemerkt?
3. Wurde ein lokaler Commit erstellt?
4. Wurde dieser Commit zu GitHub übertragen?

Diese vier Schritte sind unabhängig. Eine gespeicherte Datei ist noch kein Commit; ein lokaler Commit ist noch keine Veröffentlichung.

> **Merksatz:** Ein Commit sichert eine Version lokal. Ein Push teilt diese Version mit einem Remote.

---

## Denkmodell: Git und GitHub sind verschiedene Systeme

Git und GitHub werden im Alltag oft zusammen genannt, erfüllen aber unterschiedliche Aufgaben.

- **Git** ist das lokale Versionskontrollsystem. Es verwaltet Commits, Branches, Historie und Änderungen auf dem eigenen Rechner.
- **GitHub** ist eine Plattform für gehostete Git-Repositories und Zusammenarbeit. Sie ergänzt Git unter anderem um Pull Requests, Issues, Reviews, Actions und Zugriffsverwaltung.

Du kannst Git vollständig ohne GitHub verwenden:

```bash
git init
git add .
git commit -m "Initialer Stand"
```

Und GitHub kann ohne ein lokales Repository kaum sinnvoll genutzt werden: GitHub speichert zwar Git-Repositories, ersetzt aber nicht die lokale Git-Arbeit.

### Typischer Denkfehler

> „GitHub hat meinen Code verloren.“

Oft liegt die Änderung nur lokal vor, wurde auf einem anderen Branch erstellt oder noch nicht gepusht. Bevor du von Datenverlust ausgehst, prüfe deshalb:

```bash
git status
git log --oneline
git branch
```

Erst danach sollte nach Problemen bei GitHub, dem Netzwerk oder Berechtigungen gesucht werden.

---

## Denkmodell: Ein Branch ist keine Projektkopie

Anfänger behandeln Branches häufig wie getrennte Projektordner:

> „Wenn ich einen Branch erstelle, wird das Projekt dupliziert.“

Ein Branch ist in Git vor allem ein **beweglicher Name für einen Commit**. Er markiert den aktuellen Endpunkt einer Entwicklungslinie.

```text
main     → Commit A
feature  → Commit A
```

Sobald auf `feature` ein neuer Commit entsteht, bewegt sich nur dieser Branch weiter:

```text
main     → Commit A
feature  → Commit B
```

Das Projekt wird nicht jedes Mal vollständig kopiert. Diese Leichtgewichtigkeit ist einer der Gründe, warum Branches in Git so günstig und alltäglich sind.

### Praktische Konsequenz

Du darfst Branches häufig und gezielt einsetzen:

- für ein Feature,
- für einen Fehler,
- für ein Experiment,
- für eine Dokumentationsänderung,
- für einen Pull Request.

Ein Branch ist kein Zeichen dafür, dass eine Aufgabe riesig oder riskant sein muss. Im Gegenteil: Kleine, kurzlebige Branches machen Änderungen besser isolierbar und überprüfbar.

---

## Denkmodell: HEAD zeigt, wo du gerade arbeitest

`HEAD` ist ein zentraler Begriff, der zunächst abstrakt wirken kann. Vereinfacht bedeutet er:

> **HEAD markiert den aktuell ausgecheckten Stand.**

Meist zeigt `HEAD` auf den aktuell aktiven Branch. Wenn du auf `main` arbeitest, zeigt `HEAD` auf `main`. Ein neuer Commit verschiebt dann den Branch und damit indirekt auch `HEAD`.

```text
HEAD → main → letzter Commit
```

Wenn du den Branch wechselst, wechselt auch dein Arbeitskontext:

```text
HEAD → feature/login → letzter Feature-Commit
```

### Warum das wichtig ist

Bevor du commitest, mergest, zurücksetzt oder Dateien wiederherstellst, solltest du wissen:

- Auf welchem Branch befinde ich mich?
- Welcher Commit ist aktuell ausgecheckt?
- Soll die nächste Änderung wirklich hier entstehen?

Diese Informationen liefert:

```bash
git status
```

Auch PhpStorm zeigt den aktuellen Branch deutlich in der Statusleiste und im Branch-Menü an. Ein kurzer Blick vor einer größeren Aktion verhindert viele Fehler.

---

## Häufiger Fehler: Direkt auf `main` arbeiten

Gerade bei Einzelprojekten wirkt es zunächst bequem, alle Änderungen direkt auf `main` vorzunehmen. In Teams und bei Pull-Request-Workflows führt das jedoch oft zu Problemen:

- Unfertige Arbeit vermischt sich mit stabilem Code.
- Mehrere Aufgaben werden schwer voneinander trennbar.
- Reviews werden unübersichtlich.
- Ein Fehler ist schwieriger isoliert zurückzunehmen.
- Synchronisierung mit anderen wird konfliktanfälliger.

Ein besseres Grundmuster ist:

```text
main
  └── feature/registrierung-validieren
```

Die Arbeit findet auf dem Feature-Branch statt. Erst wenn sie fertig, getestet und überprüft ist, wird sie in den Hauptbranch integriert.

### Ausnahme: Kleine persönliche Experimente

In einem lokalen Lernrepository oder bei einer sehr kleinen, isolierten Änderung kann direkte Arbeit auf `main` vertretbar sein. Entscheidend ist nicht ein starres Verbot, sondern die Frage:

> **Muss diese Änderung getrennt entwickelt, geprüft oder später nachvollzogen werden?**

Wenn die Antwort „ja“ lautet, ist ein eigener Branch sinnvoll.

---

## Häufiger Fehler: Alles mit `git add .` vormerken

Der Befehl

```bash
git add .
```

ist nicht grundsätzlich falsch. Er nimmt jedoch viele Änderungen auf einmal in die Staging Area. Das kann versehentlich einschließen:

- Debug-Ausgaben,
- lokale Konfigurationsdateien,
- nicht fertiggestellte Änderungen,
- Zugangsdaten,
- IDE-Dateien,
- Änderungen einer anderen Aufgabe.

### Besseres Denkmodell: Die Staging Area ist eine bewusste Auswahl

Die Staging Area ist kein lästiger Zwischenschritt. Sie ist eine **Zusammenstellung des nächsten Commits**.

Statt gedankenlos alles vorzumerken, prüfe zunächst:

```bash
git status
git diff
```

Danach kannst du gezielt einzelne Dateien hinzufügen:

```bash
git add src/Validator.php
git add tests/ValidatorTest.php
```

Später lernst du auch, einzelne Teile einer Datei vorzumerken. Damit lassen sich logisch getrennte Commits erstellen, selbst wenn mehrere Änderungen gleichzeitig im Arbeitsverzeichnis liegen.

> **Merksatz:** `git add` bedeutet nicht „speichern“, sondern „für den nächsten Snapshot auswählen“.

---

## Häufiger Fehler: Den Status nicht prüfen

Viele riskante Git-Aktionen beginnen mit einer Vermutung:

- „Ich glaube, alles ist committed.“
- „Ich bin bestimmt auf dem richtigen Branch.“
- „Die Änderung müsste schon auf GitHub sein.“
- „Der Merge müsste fertig sein.“

Git verlangt jedoch keine Vermutungen. Es liefert Informationen.

### Der sichere Mini-Check

Vor und nach wichtigen Schritten lohnt sich:

```bash
git status
```

Achte dabei auf:

- den aktuellen Branch,
- nicht verfolgte Dateien,
- geänderte, aber nicht vorgemerkte Dateien,
- vorgemerkte Änderungen,
- lokale Commits vor oder hinter dem Upstream-Branch,
- laufende Operationen wie Merge oder Rebase.

Ergänzend helfen:

```bash
git log --oneline --decorate -n 10
```

```bash
git diff
```

```bash
git diff --staged
```

Damit beantwortest du drei verschiedene Fragen:

| Frage | Geeigneter Befehl |
|---|---|
| In welchem Zustand befindet sich das Repository? | `git status` |
| Was wurde noch nicht vorgemerkt? | `git diff` |
| Was landet im nächsten Commit? | `git diff --staged` |
| Welche Commits liegen zuletzt vor? | `git log --oneline` |

---

## Häufiger Fehler: Commit und Push verwechseln

Ein klassischer Ablauf sieht so aus:

1. Datei bearbeiten
2. Commit erstellen
3. Browser öffnen
4. Auf GitHub keine Änderung finden
5. Verunsicherung

Die Ursache ist meist einfach: Der Push fehlt.

```bash
git push
```

Umgekehrt kann auch ein Push scheitern, obwohl der Commit erfolgreich erstellt wurde. Das betrifft dann nicht die lokale Historie, sondern den Datentransfer zum Remote. Typische Ursachen sind:

- fehlende Anmeldung,
- falsche Berechtigung,
- ein anderer Stand auf dem Remote,
- Netzwerkprobleme,
- ein noch nicht eingerichteter Upstream-Branch.

### Sicheres Vorgehen

Wenn ein Push fehlschlägt:

1. Lies die Fehlermeldung vollständig.
2. Prüfe mit `git status`, ob der lokale Commit vorhanden ist.
3. Prüfe den aktuellen Branch.
4. Prüfe erst dann Anmeldung, Remote-URL oder Synchronisationskonflikte.

Wiederhole nicht blind denselben Befehl und nutze insbesondere keinen erzwungenen Push, nur um eine Fehlermeldung verschwinden zu lassen.

---

## Häufiger Fehler: `pull` als harmlose Aktualisierung betrachten

`git pull` wird oft als reiner Download verstanden. Tatsächlich besteht ein Pull vereinfacht aus zwei Schritten:

1. Änderungen vom Remote abrufen.
2. Diese Änderungen lokal integrieren.

Das Integrieren kann einen Merge oder Rebase auslösen und unter Umständen Konflikte erzeugen.

### Besseres Denkmodell

Ein Pull verändert möglicherweise den lokalen Projektzustand. Deshalb ist es sinnvoll, vorher zu prüfen:

```bash
git status
```

Sind lokale Änderungen vorhanden, solltest du wissen, ob sie mit den eingehenden Änderungen kollidieren könnten.

Für mehr Kontrolle kann es hilfreich sein, gedanklich zwischen zwei Aufgaben zu unterscheiden:

```bash
git fetch
```

holt Informationen und neue Commits vom Remote, ohne den aktuellen Branch direkt zu verändern.

Danach kannst du untersuchen, was sich geändert hat, und die Integration bewusst durchführen. Die konkreten Varianten werden später ausführlich behandelt; wichtig ist hier vor allem das Verständnis:

> Ein Pull ist nicht nur Empfang, sondern auch Integration.

---

## Häufiger Fehler: Konfliktmarker als Git-Fehler missverstehen

Wenn Git einen Merge-Konflikt meldet, bedeutet das nicht, dass Git beschädigt ist oder dass etwas „kaputtgegangen“ ist. Git kann zwei Änderungen lediglich nicht eindeutig automatisch kombinieren.

In einer Datei können dann Markierungen wie diese erscheinen:

```text
<<<<<<< HEAD
Lokale Variante
=======
Eingehende Variante
>>>>>>> anderer-branch
```

Diese Markierungen sind eine Aufforderung zur Entscheidung:

- Welche Variante ist fachlich korrekt?
- Müssen beide Varianten kombiniert werden?
- Fehlt Kontext aus Tests, Anforderungen oder Gesprächen?

### Der richtige Umgang mit Konflikten

1. Nicht in Panik geraten.
2. Den Konfliktbereich und den fachlichen Zweck verstehen.
3. Die gewünschte Endfassung schreiben.
4. Konfliktmarker vollständig entfernen.
5. Datei testen und prüfen.
6. Die Git-Operation kontrolliert fortsetzen.

Ein Konflikt ist kein Makel. Er zeigt, dass zwei Entwicklungslinien dieselbe Stelle unterschiedlich verändert haben und eine menschliche Entscheidung erforderlich ist.

---

## Häufiger Fehler: Änderungen vor einem Branch-Wechsel ignorieren

Vor dem Wechsel des Branches sollten lokale Änderungen bewusst behandelt werden. Andernfalls entstehen Unsicherheiten:

- Gehört diese Änderung zum alten oder neuen Branch?
- Wurde sie unbeabsichtigt übernommen?
- Verhindert sie den Wechsel?
- Wird sie später versehentlich committet?

### Praktische Regel

Vor einem Branch-Wechsel:

```bash
git status
```

Danach bewusst entscheiden:

- Änderungen committen, wenn sie einen sinnvollen Zwischenstand bilden.
- Änderungen gezielt verwerfen, wenn sie nicht gebraucht werden.
- Änderungen vorübergehend sicher ablegen, wenn sie später fortgesetzt werden sollen.

Wichtig ist nicht, immer sofort zu committen. Wichtig ist, den Arbeitszustand nicht unbemerkt mitzunehmen.

---

## Häufiger Fehler: Unfertige oder gemischte Commits erstellen

Ein Commit mit vielen unabhängigen Änderungen erschwert fast alles:

- Reviews,
- Fehlersuche,
- Rücknahme einzelner Änderungen,
- Cherry-Picks,
- spätere Historienanalyse,
- Verständlichkeit für andere Personen.

Ein Beispiel für einen problematischen Commit:

```text
Fixes und Änderungen
```

Er enthält vielleicht gleichzeitig:

- einen Bugfix,
- eine Umbenennung,
- Formatierungsänderungen,
- eine neue Funktion,
- aktualisierte Abhängigkeiten.

### Besseres Denkmodell: Ein Commit beantwortet eine Frage

Ein guter Commit sollte idealerweise eine klare Frage beantworten können:

> **Welchen Zweck erfüllt diese Änderung?**

Beispiele:

- „Warum wurde die Passwortlänge angepasst?“
- „Warum wird diese Ausnahme jetzt abgefangen?“
- „Warum wurde die Abhängigkeit aktualisiert?“
- „Warum wurde die Datenbankabfrage umgestellt?“

Wenn ein Commit mehrere unabhängige Antworten benötigt, sollte er wahrscheinlich aufgeteilt werden.

---

## Häufiger Fehler: Geheimnisse und lokale Dateien committen

Ein Repository ist kein privater Arbeitsordner. Alles, was committed wird, kann langfristig in der Historie verbleiben und nach einem Push für weitere Personen sichtbar werden.

Besonders kritisch sind:

- Passwörter,
- API-Schlüssel,
- Tokens,
- private Schlüssel,
- Datenbank-Zugangsdaten,
- produktive Konfigurationsdateien,
- personenbezogene Testdaten.

Auch wenn eine Datei später gelöscht wird, kann sie in älteren Commits weiterhin vorhanden sein.

### Sicheres Denkmodell

> Was committed wird, gehört zur nachvollziehbaren Projektgeschichte.

Prüfe daher vor jedem Commit die vorgemerkten Änderungen:

```bash
git diff --staged
```

Für Konfigurationen eignet sich oft dieses Muster:

```text
.env.example
```

wird versioniert und enthält nur Platzhalter, während die echte lokale Datei etwa über `.gitignore` ausgeschlossen wird:

```text
.env
```

Die Regeln für Ignore-Dateien und die sichere Behandlung von Geheimnissen folgen in einem eigenen Kapitel. Die wichtigste Gewohnheit beginnt jedoch sofort: **Nie sensible Inhalte ungeprüft stagen oder committen.**

---

## Häufiger Fehler: Dateilöschung mit Versionsverlust gleichsetzen

Wenn eine Datei im Arbeitsverzeichnis gelöscht wird, ist sie nicht automatisch für immer verloren. Wenn sie bereits committed war, kennt Git ältere Versionen weiterhin.

Das führt zu einem wichtigen Denkmodell:

> Die aktuelle Arbeitskopie ist nur ein sichtbarer Zustand, nicht die gesamte Historie.

Solange ein Commit erreichbar ist, lassen sich frühere Inhalte meist wieder anzeigen oder wiederherstellen. Dennoch gilt: Nicht jede ungespeicherte oder nie committete Änderung kann Git retten.

### Was Git typischerweise retten kann

| Situation | Rettungschance |
|---|---|
| Datei war in einem Commit enthalten | Sehr gut |
| Commit wurde lokal erstellt, aber noch nicht gepusht | Meist sehr gut |
| Branch wurde versehentlich gelöscht | Häufig gut |
| Datei wurde nur bearbeitet, nie gespeichert und nie committed | Git kann nicht helfen |
| Nicht vorgemerkte Änderung wurde bewusst überschrieben | Nur mit anderen Sicherungen eventuell möglich |

Git ist eine starke Absicherung für versionierte Zustände, aber kein Ersatz für bewusstes Speichern, Backups oder vorsichtigen Umgang mit destruktiven Befehlen.

---

## Häufiger Fehler: Befehle aus dem Internet blind kopieren

Bei Fehlermeldungen ist die Versuchung groß, einen gefundenen Befehl sofort auszuführen. Besonders gefährlich sind Befehle mit Optionen wie:

```bash
--hard
--force
--force-with-lease
```

Diese Optionen sind nicht grundsätzlich falsch. Sie haben wichtige, legitime Anwendungsfälle. Ohne Verständnis können sie jedoch lokale Arbeit entfernen oder gemeinsame Historien überschreiben.

### Die Drei-Fragen-Regel vor risikoreichen Befehlen

Bevor du einen Befehl ausführst, frage:

1. **Was wird dadurch verändert?**  
   Arbeitsverzeichnis, Staging Area, lokale Historie, Remote oder mehrere Bereiche?

2. **Welche Daten könnten verloren gehen?**  
   Nicht gespeicherte, nicht vorgemerkte, lokale oder veröffentlichte Änderungen?

3. **Wie komme ich zurück, falls das Ergebnis falsch ist?**  
   Gibt es einen Commit, einen Branch, einen Stash, ein Backup oder einen nachvollziehbaren Ausgangspunkt?

Wenn du diese Fragen nicht beantworten kannst, stoppe und untersuche den Zustand. Ein zusätzlicher Blick auf `git status` kostet Sekunden; eine beschädigte gemeinsame Historie kann dagegen viel Zeit kosten.

---

## Häufiger Fehler: Git als Gegner betrachten

Git-Meldungen wirken am Anfang oft streng oder unverständlich. Häufig schützen sie aber vor einem riskanten Zustand.

Beispiele:

- Git verweigert einen Branch-Wechsel, damit lokale Änderungen nicht überschrieben werden.
- Git verweigert einen Push, damit fremde Commits nicht unbemerkt verloren gehen.
- Git meldet einen Konflikt, weil keine sichere automatische Entscheidung möglich ist.
- Git verweigert einen Commit, wenn nichts vorgemerkt wurde.

Statt die Meldung als Hindernis zu sehen, lies sie als Zustandsbeschreibung:

> „Git erklärt mir, welche Annahme gerade nicht erfüllt ist.“

Diese Haltung verändert die Fehlersuche grundlegend. Nicht „Wie zwinge ich Git dazu?“, sondern:

> **„Welchen Zustand schützt Git – und was möchte ich fachlich wirklich erreichen?“**

---

## Ein systematisches Denkmodell für jede Git-Situation

Wenn etwas unerwartet passiert, hilft dieser Ablauf:

### 1. Anhalten

Keine weiteren Befehle auf Verdacht ausführen. Insbesondere keine Befehle, die Historie oder Arbeitsdateien überschreiben könnten.

### 2. Zustand erfassen

```bash
git status
```

Optional ergänzen:

```bash
git log --oneline --decorate -n 10
```

```bash
git branch --all
```

### 3. Ziel formulieren

Beschreibe ohne Git-Befehl, was erreicht werden soll:

- „Diese Datei soll nicht im nächsten Commit landen.“
- „Mein lokaler Branch soll die Änderungen vom Server enthalten.“
- „Der letzte Commit hat die falsche Nachricht.“
- „Ich möchte den Bugfix aus einem anderen Branch übernehmen.“

Eine klare Zielformulierung verhindert, dass ein unpassender Befehl nur zufällig plausibel wirkt.

### 4. Betroffenen Bereich bestimmen

| Ziel | Hauptbereich |
|---|---|
| Datei bearbeiten oder verwerfen | Arbeitsverzeichnis |
| Auswahl für nächsten Commit ändern | Staging Area |
| Lokalen Commit korrigieren | Lokale Historie |
| Änderungen austauschen | Remote und Tracking-Branch |
| Entwicklung trennen | Branches |

### 5. Kleinste sichere Aktion wählen

Bevorzuge eine gezielte, nachvollziehbare Aktion gegenüber einer globalen oder erzwungenen Aktion.

Beispiel: Wenn nur eine Datei versehentlich vorgemerkt wurde, ist es besser, genau diese Datei aus der Staging Area zu nehmen, als pauschal große Teile des Repository-Zustands zurückzusetzen.

### 6. Ergebnis prüfen

Nach jeder Veränderung:

```bash
git status
```

Und bei relevanten Änderungen:

```bash
git diff
```

Diese Schleife aus **analysieren → handeln → prüfen** ist eine der wichtigsten professionellen Git-Gewohnheiten.

---

## Ein praktischer Vor-Commit-Check

Vor einem Commit kannst du diese kurze Checkliste verwenden:

- [ ] Bin ich auf dem richtigen Branch?
- [ ] Weiß ich, welchen Zweck dieser Commit erfüllt?
- [ ] Enthält der Commit nur zusammengehörige Änderungen?
- [ ] Habe ich die vorgemerkten Änderungen geprüft?
- [ ] Sind keine Zugangsdaten, Debug-Ausgaben oder lokalen Dateien enthalten?
- [ ] Ist die Commit-Nachricht konkret und verständlich?
- [ ] Wurde die relevante Anwendung oder der relevante Test ausgeführt?

Die technische Prüfung beginnt mit:

```bash
git status
```

Dann:

```bash
git diff --staged
```

Erst danach folgt der Commit.

---

## Ein praktischer Vor-Push-Check

Ein Push veröffentlicht Arbeit für andere Personen und häufig auch für Automatisierungen. Prüfe daher kurz:

- [ ] Liegen die richtigen Commits auf dem aktuellen Branch?
- [ ] Sind Tests oder Qualitätsprüfungen erfolgreich?
- [ ] Enthält die Historie keine versehentlichen oder geheimen Inhalte?
- [ ] Ist klar, in welches Remote-Repository und auf welchen Branch gepusht wird?
- [ ] Wurden aktuelle Änderungen des Teams berücksichtigt?

Danach ist ein Push keine blinde Routine, sondern eine bewusste Veröffentlichung.

---

## Die wichtigsten Merksätze

> **Git verwaltet Zustände und Historien, nicht nur Dateien.**

> **Ein Commit ist ein lokaler Snapshot des vorgemerkten Projektzustands.**

> **`git add` wählt Inhalte für den nächsten Commit aus.**

> **Ein Push veröffentlicht lokale Commits auf einem Remote; ein Commit allein tut das nicht.**

> **Ein Branch ist eine leichte Entwicklungslinie, keine vollständige Projektkopie.**

> **Ein Konflikt ist eine notwendige fachliche Entscheidung, kein Git-Defekt.**

> **Vor jeder riskanten Aktion zuerst den Zustand prüfen.**

> **`git status` ist kein Notfallwerkzeug, sondern ein alltäglicher Kompass.**

Mit diesen Denkmodellen werden die folgenden Git-Befehle nicht mehr wie isolierte Zauberformeln wirken. Sie werden zu gezielten Werkzeugen, mit denen du Änderungen sicher zwischen klar erkennbaren Zuständen bewegst.

# Arbeitsumgebung unter Windows 11 einrichten

Du installierst Git for Windows und richtest Git Bash, PowerShell, Windows Terminal sowie den Credential Manager ein. Das Kapitel behandelt PATH, Dateisystempfade, Zeilenenden, symbolische Links und grundlegende Windows-Besonderheiten, die später Konflikte verursachen können.

# Git for Windows installieren

## Ziel dieser Lektion

Du installierst **Git for Windows** auf Windows 11 und prüfst anschließend, ob Git in der Kommandozeile korrekt verfügbar ist.

Git for Windows bringt mehrere Komponenten mit:

- die Git-Kommandozeile,
- **Git Bash** als Unix-ähnliche Shell,
- Git-Unterstützung für PowerShell und die Eingabeaufforderung,
- hilfreiche Werkzeuge wie OpenSSH und Git Credential Manager.

> **Hinweis:** Die eigentliche Git-Konfiguration – Name, E-Mail-Adresse, Standard-Branch und Authentifizierung – folgt in späteren Lektionen. Hier geht es zunächst um eine saubere Installation.

---

## Voraussetzungen

Für die Installation benötigst du:

- Windows 11,
- ein Benutzerkonto mit Berechtigung zum Installieren von Programmen,
- eine Internetverbindung,
- idealerweise einen aktuellen Browser.

Schließe vor der Installation offene Terminals, PowerShell-Fenster und PhpStorm. Dadurch werden neue PATH-Einstellungen anschließend zuverlässig erkannt.

---

## Git for Windows sicher herunterladen

Lade Git ausschließlich von der offiziellen Projektseite herunter:

- [git-scm.com/download/win](https://git-scm.com/download/win)

Die Seite erkennt Windows normalerweise automatisch und startet den Download der passenden Installationsdatei. Falls nicht, wähle die aktuelle **64-Bit-Version für Windows**.

Die heruntergeladene Datei trägt üblicherweise einen Namen ähnlich wie:

```text
Git-2.xx.x-64-bit.exe
```

> ⚠️ Lade Git nicht von inoffiziellen Download-Portalen herunter. Gerade Entwicklerwerkzeuge sollten immer aus vertrauenswürdigen Quellen stammen.

---

## Installation starten

1. Öffne den Download-Ordner im Windows-Explorer.
2. Doppelklicke auf die Installationsdatei.
3. Bestätige die Windows-Sicherheitsabfrage mit **„Ja“**, sofern sie erscheint.
4. Lies die Lizenzinformationen und wähle **„Next“**.

Falls Windows SmartScreen eine Warnung zeigt, prüfe zunächst sorgfältig, ob die Datei tatsächlich von der offiziellen Git-for-Windows-Seite stammt. Nur dann kannst du über **„Weitere Informationen“** und **„Trotzdem ausführen“** fortfahren.

---

## Installationsoptionen sinnvoll wählen

Der Installer stellt mehrere Entscheidungen. Die Standardwerte sind meist gut gewählt. Einige Optionen sind dennoch wichtig, weil sie die tägliche Arbeit mit Git, PowerShell und PhpStorm beeinflussen.

### Installationsordner

Als Standard wird meist dieser Ordner vorgeschlagen:

```text
C:\Program Files\Git
```

Übernimm diesen Vorschlag.

Ein systemweiter Installationsordner sorgt dafür, dass Git für alle Windows-Benutzer verfügbar ist und von Entwicklungswerkzeugen wie PhpStorm leicht gefunden wird.

---

### Komponenten auswählen

Im Bereich **„Select Components“** kannst du normalerweise die Vorauswahl beibehalten. Besonders sinnvoll sind diese Komponenten:

- **Windows Explorer integration**  
  Ergänzt Kontextmenüeinträge wie „Git Bash Here“ im Explorer.

- **Git Bash Here**  
  Öffnet Git Bash direkt im aktuellen Ordner.

- **Git GUI Here**  
  Ist optional. Git GUI wird im Kurs nicht benötigt, schadet aber nicht.

- **Git LFS**  
  Sollte aktiviert bleiben. Git LFS wird später für große Binärdateien relevant.

- **Associate .git\* configuration files with the default text editor**  
  Kann aktiviert bleiben. Damit lassen sich Git-Konfigurationsdateien bequem öffnen.

- **Associate .sh files to be run with Bash**  
  Kann ebenfalls aktiviert bleiben, insbesondere wenn du später Shell-Skripte verwendest.

> **Empfehlung:** Übernimm die Standardauswahl, sofern dein Unternehmen keine eigene Installationsrichtlinie vorgibt.

---

### Standardeditor für Git auswählen

Der Installer fragt nach dem Editor, den Git beispielsweise beim Bearbeiten von Commit-Nachrichten verwendet.

Für Einsteiger ist **„Use Vim“** oft unpraktisch, weil Vim eine eigenständige Bedienlogik besitzt. Wähle stattdessen einen Editor, mit dem du sicher arbeiten kannst.

Geeignete Optionen sind:

- **Visual Studio Code**, wenn du ihn bereits verwendest,
- **Nano**, wenn du einen einfachen Terminaleditor bevorzugst,
- **Notepad** oder **Notepad++**, falls verfügbar,
- später gegebenenfalls **PhpStorm**.

Wenn du noch keinen bevorzugten Editor hast, ist **Nano** eine unkomplizierte Wahl. Die Einstellung kannst du jederzeit später ändern.

> 💡 PhpStorm wird in einem eigenen Kapitel als Git-Umgebung eingerichtet. Die Auswahl hier ist daher keine endgültige Entscheidung.

---

### PATH-Umgebung konfigurieren

Diese Entscheidung ist besonders wichtig. Wähle die Option:

```text
Git from the command line and also from 3rd-party software
```

Je nach Installer-Version lautet die Option ähnlich, etwa:

```text
Git from the command line and also from 3rd-party software
```

Dadurch wird Git in die Windows-Umgebungsvariable **PATH** aufgenommen. Anschließend funktioniert der Befehl `git` in:

- Git Bash,
- PowerShell,
- Windows Terminal,
- der Eingabeaufforderung,
- dem integrierten Terminal von PhpStorm,
- vielen weiteren Entwicklungswerkzeugen.

Wähle **nicht** die Option, die Git nur in Git Bash verfügbar macht. Sie würde Git in PowerShell und PhpStorm unnötig schwer nutzbar machen.

---

### SSH-Programm auswählen

Für die SSH-Verbindung zu GitHub wird ein SSH-Client benötigt. Wähle:

```text
Use bundled OpenSSH
```

Git for Windows bringt damit eine geprüfte OpenSSH-Version mit. Diese Einstellung ist für die meisten Windows-11-Systeme die sicherste und unkomplizierteste Wahl.

Die Einrichtung eines SSH-Schlüssels sowie die Verbindung zu GitHub folgen später.

---

### HTTPS-Transport-Backend auswählen

Wähle:

```text
Use the OpenSSL library
```

Diese Variante ist der übliche Standard für Git for Windows und funktioniert zuverlässig mit GitHub sowie den meisten Git-Servern.

In Unternehmensumgebungen mit speziellen Zertifikatsrichtlinien kann die Option **„Use the native Windows Secure Channel library“** sinnvoll sein. Verwende sie aber nur, wenn deine IT-Abteilung dies ausdrücklich empfiehlt.

---

### Zeilenenden konfigurieren

Windows und Unix-artige Systeme behandeln Zeilenenden unterschiedlich:

- Windows verwendet traditionell `CRLF`,
- Linux und macOS verwenden üblicherweise `LF`.

Wähle im Installer:

```text
Checkout Windows-style, commit Unix-style line endings
```

Diese Option entspricht im Regelfall folgender Git-Konfiguration:

```bash
git config --global core.autocrlf true
```

Damit werden Textdateien im Windows-Arbeitsverzeichnis mit Windows-Zeilenenden ausgecheckt, beim Commit jedoch in das plattformübergreifende `LF`-Format überführt.

Das ist für viele klassische Windows-Projekte ein brauchbarer Startwert. Für professionelle Teams wird die genaue Zeilenendenstrategie später zusätzlich mit `.gitattributes` abgesichert. Diese Datei gehört ins Repository und sorgt dafür, dass Regeln nicht nur lokal, sondern für alle Teammitglieder gelten.

> **Wichtig:** Ändere Zeilenenden nicht unüberlegt in bestehenden Projekten. Andernfalls können große, inhaltlich leere Diffs entstehen.

---

### Terminal-Emulator für Git Bash

Wähle in der Regel:

```text
Use MinTTY
```

MinTTY ist das typische Terminalfenster von Git Bash und bietet eine angenehme Bedienung, gute Unicode-Unterstützung sowie Kopieren und Einfügen per Maus.

Alternativ kann die Windows-Konsole sinnvoll sein, wenn du eine besonders enge Integration mit älteren Konsolenprogrammen benötigst. Für den Kurs und die meisten Entwicklungsprojekte ist **MinTTY** die bessere Wahl.

---

### Verhalten von `git pull`

Wähle:

```text
Default fast-forward or merge
```

Das entspricht dem klassischen, einsteigerfreundlichen Git-Verhalten: Wenn möglich, wird ein Fast-Forward durchgeführt; andernfalls entsteht bei Bedarf ein Merge.

Die Unterschiede zwischen Pull mit Merge, Pull mit Rebase und Fast-Forward-only werden später ausführlich behandelt. Für die Installation solltest du keine globale Rebase-Strategie erzwingen.

---

### Credential Helper

Wähle:

```text
Git Credential Manager
```

Der **Git Credential Manager** speichert und verwaltet Anmeldedaten sicher über die Windows-Anmeldeinformationsverwaltung. Das ist besonders wichtig, wenn du GitHub über HTTPS verwendest.

GitHub akzeptiert für Git-Operationen über HTTPS keine Kontopasswörter mehr. Stattdessen verwendest du später einen Personal Access Token oder meldest dich über den Credential Manager an.

> 🔐 Zugangsdaten gehören niemals in Quellcode, Commit-Nachrichten oder Repository-Dateien.

---

### Zusätzliche Optionen

Die restlichen Optionen kannst du im Normalfall auf ihren Standardwerten lassen. Typische Empfehlungen:

| Installer-Option | Empfehlung | Begründung |
|---|---|---|
| Extra file system caching | Aktiviert lassen | Verbessert die Geschwindigkeit bei vielen Dateien. |
| Enable symbolic links | Nur bei Bedarf | Erfordert oft zusätzliche Windows-Einstellungen oder Administratorrechte. |
| Enable experimental support for pseudo consoles | Standardwert beibehalten | Kann moderne Terminalintegration verbessern, ist aber nicht entscheidend. |
| Enable experimental built-in add -i/-p | Standardwert beibehalten | Betrifft interaktives Staging; wird später behandelt. |

Bei **symbolischen Links** ist Vorsicht sinnvoll: Windows behandelt sie anders als Linux. Aktiviere die Option nur bewusst, wenn dein Projekt sie verwendet oder wenn eine Teamvorgabe besteht.

---

## Installation abschließen

Klicke auf **„Install“**. Nach wenigen Momenten ist Git for Windows installiert.

Am Ende zeigt der Installer häufig Optionen wie:

- **Launch Git Bash**
- **View Release Notes**

Du kannst **„Launch Git Bash“** aktiviert lassen und anschließend auf **„Finish“** klicken.

Nun öffnet sich Git Bash. Du erkennst sie an einer Eingabeaufforderung, die ungefähr so aussieht:

```text
Max@PC MINGW64 ~
$
```

Der konkrete Benutzername und Rechnername unterscheiden sich natürlich.

---

## Installation in Git Bash prüfen

Gib in Git Bash folgenden Befehl ein:

```bash
git --version
```

Die Ausgabe sollte etwa so aussehen:

```text
git version 2.xx.x.windows.x
```

Die genaue Versionsnummer kann abweichen. Entscheidend ist, dass Git eine Version ausgibt und keine Fehlermeldung erscheint.

Prüfe außerdem, wo Git gefunden wurde:

```bash
which git
```

Eine typische Ausgabe lautet:

```text
/mingw64/bin/git
```

Das zeigt: Git Bash verwendet die Git-Installation korrekt.

---

## Installation in PowerShell prüfen

Git sollte nicht nur in Git Bash, sondern auch in PowerShell funktionieren.

1. Öffne das Startmenü.
2. Suche nach **PowerShell**.
3. Starte **Windows PowerShell** oder **PowerShell**.
4. Führe aus:

```powershell
git --version
```

Du solltest erneut eine Git-Versionsnummer erhalten.

Zusätzlich kannst du den von Windows aufgelösten Programmpfad prüfen:

```powershell
Get-Command git
```

Eine erfolgreiche Ausgabe enthält unter anderem einen Pfad ähnlich diesem:

```text
C:\Program Files\Git\cmd\git.exe
```

Wenn `git --version` in Git Bash funktioniert, aber in PowerShell nicht, wurde Git vermutlich nicht korrekt zum PATH hinzugefügt oder PowerShell war während der Installation noch geöffnet.

Schließe in diesem Fall alle PowerShell- und Terminalfenster und öffne sie erneut. Falls das Problem bleibt, prüfst du die PATH-Konfiguration in einer späteren Lektion gezielt.

---

## Schneller Funktionstest in einem Übungsordner

Lege einen unverfänglichen Testordner an. In PowerShell geht das beispielsweise so:

```powershell
mkdir C:\Projekte\git-installation-test
cd C:\Projekte\git-installation-test
git init
```

Bei Erfolg erscheint eine Meldung ähnlich wie:

```text
Initialized empty Git repository in C:/Projekte/git-installation-test/.git/
```

Kontrolliere den Zustand des neuen Repositorys:

```powershell
git status
```

Eine typische Ausgabe ist:

```text
On branch master

No commits yet

nothing to commit
```

Die Bezeichnung des anfänglichen Branches kann je nach Git-Version und Konfiguration `master` oder `main` sein. Die globale Einstellung für den Standard-Branch richtest du in einer späteren Lektion bewusst ein.

Du kannst den Testordner danach wieder löschen. Das Repository enthält noch keine wichtigen Daten.

---

## Häufige Installationsprobleme

### „git“ wird nicht erkannt

In PowerShell oder der Eingabeaufforderung kann diese Meldung erscheinen:

```text
git : Der Begriff „git“ ist nicht als Name eines Cmdlet ...
```

**Wahrscheinliche Ursachen:**

1. Das Terminal war während der Installation geöffnet.
2. Git wurde nicht in den PATH aufgenommen.
3. Die Installation wurde nicht vollständig abgeschlossen.

**Lösung:**

1. Schließe alle Terminals und öffne ein neues Fenster.
2. Starte Windows bei Bedarf neu.
3. Prüfe erneut mit:

   ```powershell
   git --version
   ```

4. Falls der Fehler bleibt, führe den Git-for-Windows-Installer erneut aus und wähle die PATH-Option für Kommandozeile und Drittsoftware.

---

### Mehrere Git-Installationen verursachen Verwirrung

Manchmal ist Git bereits über andere Programme installiert worden, beispielsweise durch:

- Visual Studio,
- GitHub Desktop,
- Scoop,
- Chocolatey,
- WSL,
- ältere Git-for-Windows-Versionen.

Prüfe in PowerShell, welche Git-Programme gefunden werden:

```powershell
where.exe git
```

Idealerweise erscheint ein klarer Eintrag wie:

```text
C:\Program Files\Git\cmd\git.exe
```

Erscheinen mehrere Pfade, entscheidet die Reihenfolge im PATH darüber, welche Version ausgeführt wird. Das ist nicht immer ein Fehler, kann aber bei unterschiedlichen Versionen und Konfigurationen zu schwer nachvollziehbarem Verhalten führen.

> **Praxisregel:** Verwende für die Windows-Kommandozeile möglichst eine klar definierte Git-for-Windows-Installation. Git innerhalb von WSL ist eine getrennte Linux-Umgebung und wird unabhängig davon verwaltet.

---

### Sicherheitssoftware blockiert die Installation

In verwalteten Unternehmensumgebungen kann Sicherheitssoftware Installationen blockieren oder Git-Komponenten einschränken.

Wende dich in diesem Fall an die IT-Abteilung und teile mit, dass du **Git for Windows von git-scm.com** benötigst. Installiere keine nicht freigegebenen Alternativen und deaktiviere keine Schutzmechanismen eigenmächtig.

---

## Checkliste

Nach dieser Lektion solltest du Folgendes bestätigen können:

- [ ] Git for Windows stammt von der offiziellen Website.
- [ ] Git ist unter `C:\Program Files\Git` oder einem bewusst gewählten Pfad installiert.
- [ ] `git --version` funktioniert in Git Bash.
- [ ] `git --version` funktioniert in PowerShell.
- [ ] `git init` und `git status` funktionieren in einem Testordner.
- [ ] Git Credential Manager wurde installiert oder aktiviert.
- [ ] Du weißt, dass Benutzername, E-Mail-Adresse, Standard-Branch und GitHub-Anmeldung noch separat eingerichtet werden.

Im nächsten Schritt wählst und prüfst du die Installationsoptionen sowie die wichtigsten Windows-spezifischen Einstellungen noch genauer.

# Installationsoptionen richtig auswählen

## Ziel der Installation

Git for Windows bringt nicht nur den Git-Befehl mit, sondern auch mehrere Begleitwerkzeuge:

- **Git Bash** als Unix-ähnliche Kommandozeile,
- Git für **PowerShell**, Windows Terminal und CMD,
- einen **SSH-Client**,
- den **Git Credential Manager** für sichere Anmeldungen,
- optionale Kontextmenüeinträge im Windows-Explorer,
- Werkzeuge für Zeilenenden, Zertifikate und Dateisystembesonderheiten.

Die Installationsoptionen bestimmen, wie gut Git später mit Windows 11, PhpStorm und GitHub zusammenspielt. Für einen typischen PHP-Entwicklungsrechner sind die nachstehenden Empfehlungen eine sichere, alltagstaugliche Grundlage.

> **Hinweis:** Bezeichnungen und Reihenfolge einzelner Dialoge können je nach Version von Git for Windows leicht abweichen. Die Entscheidungen und ihre Bedeutung bleiben jedoch weitgehend gleich.

---

## Vor der Installation

Lade Git ausschließlich von der offiziellen Seite herunter:

<https://git-scm.com/download/win>

Für die meisten aktuellen Windows-11-Systeme wählst du die **64-Bit-Version**. Eine ARM64-Version ist passend, wenn dein Windows-Gerät tatsächlich auf ARM-Hardware läuft, etwa bestimmte Snapdragon-basierte Geräte.

Prüfe im Zweifel unter **Einstellungen → System → Info → Systemtyp**, welche Architektur dein System verwendet.

Die Installation darf in der Regel mit dem Standardkonto erfolgen. Administratorrechte sind nur nötig, wenn Git systemweit für alle Benutzer installiert werden soll oder Unternehmensrichtlinien dies verlangen.

---

## Komponenten auswählen

Der Dialog **„Select Components“** legt fest, welche Zusatzfunktionen installiert werden.

### Empfohlene Auswahl

| Option | Empfehlung | Begründung |
|---|---:|---|
| Additional icons | Optional | Fügt eine Git-Bash-Verknüpfung auf dem Desktop hinzu. Nicht erforderlich, aber für Einsteiger praktisch. |
| Windows Explorer integration | Aktivieren | Ermöglicht Git Bash und Git GUI direkt aus Explorer-Ordnern. |
| Git Bash Here | Aktivieren | Öffnet Git Bash im aktuell ausgewählten Ordner. Sehr nützlich. |
| Git GUI Here | Optional | Git GUI ist ein älteres grafisches Werkzeug. Für PhpStorm-Nutzer meist nicht notwendig. |
| Git LFS | Aktivieren | Installiert Unterstützung für große Dateien. Auch wenn du Git LFS noch nicht nutzt, schadet die Option nicht. |
| Associate .git configuration files | Aktivieren | Ordnet Git-Konfigurationsdateien einem Editor zu. |
| Associate .sh files | Optional | Praktisch, wenn du Shell-Skripte bearbeitest; nicht zwingend erforderlich. |
| Check daily for Git for Windows updates | Optional | Sinnvoll auf privaten Rechnern; in verwalteten Unternehmensumgebungen oft unerwünscht. |
| Add a Git Bash Profile to Windows Terminal | Aktivieren | Erzeugt ein Git-Bash-Profil in Windows Terminal. |

### Explorer-Integration sinnvoll begrenzen

Aktiviere bevorzugt **„Git Bash Here“**, aber überlege bei **„Git GUI Here“**, ob du den Explorer wirklich mit zusätzlichen Einträgen erweitern möchtest.

Für die tägliche Arbeit reichen meist:

- Git Bash im Windows Terminal,
- das integrierte Terminal in PhpStorm,
- die grafischen Git-Funktionen von PhpStorm.

Die Explorer-Integration ist vor allem dann hilfreich, wenn du spontan in einem Projektordner arbeiten möchtest.

---

## Standardeditor für Git festlegen

Git benötigt gelegentlich einen Texteditor, etwa für:

- Commit-Nachrichten ohne `-m`,
- Merge-Commit-Nachrichten,
- interaktive Rebase-Pläne,
- Bearbeitung von Konfigurationsdateien.

Im Dialog **„Choosing the default editor used by Git“** stehen meist mehrere Editoren zur Auswahl.

### Empfehlung: Visual Studio Code oder ein vertrauter Editor

Wenn Visual Studio Code installiert ist und du ihn gelegentlich nutzt, ist **Visual Studio Code** eine gute Wahl. Er öffnet Commit-Nachrichten und Rebase-Dateien verständlich und komfortabel.

Wenn du keinen zusätzlichen Editor einsetzen möchtest, ist **Vim** technisch zuverlässig, für Einsteiger aber ungewohnt. Die Bedienung unterscheidet sich deutlich von normalen Windows-Editoren und kann beim ersten Commit irritieren.

Für einen einsteigerfreundlichen Start gilt daher:

1. **Visual Studio Code**, wenn vorhanden und vertraut.
2. **Nano**, falls vom Installer angeboten und du eine einfache Terminal-Lösung bevorzugst.
3. **Vim** nur, wenn du Vim bereits kennst oder gezielt lernen möchtest.

PhpStorm kann ebenfalls als Git-Editor konfiguriert werden. Für viele Aufgaben öffnet PhpStorm aber ohnehin eigene Dialoge. Die globale Git-Editorwahl bleibt dennoch relevant, insbesondere bei Terminal-Befehlen.

> **Praxisregel:** Wähle keinen Editor, den du nicht wenigstens schließen und speichern kannst. Ein blockierter Editor ist eine häufige Ursache für scheinbar „hängende“ Git-Befehle.

---

## PATH-Umgebung richtig einrichten

Der Dialog **„Adjusting your PATH environment“** ist besonders wichtig. Er entscheidet, aus welchen Terminals der Befehl `git` erreichbar ist.

Typischerweise bietet der Installer drei Varianten an.

### Nur Git Bash verwenden

Sinngemäß lautet die Option:

> „Use Git from Git Bash only“

Git wird nur innerhalb von Git Bash verfügbar gemacht.

**Nicht empfohlen**, wenn du mit PhpStorm, PowerShell oder Windows Terminal arbeitest. Viele Werkzeuge erwarten, dass `git.exe` über die Windows-Umgebungsvariable `PATH` erreichbar ist.

### Git aus der Kommandozeile und Drittsoftware verwenden

Sinngemäß:

> „Git from the command line and also from 3rd-party software“

Dies ist die **empfohlene Standardauswahl**.

Git wird damit verfügbar in:

- Git Bash,
- PowerShell,
- Windows Terminal,
- CMD,
- PhpStorm,
- vielen Entwicklungswerkzeugen und Automatisierungsskripten.

Diese Einstellung ergänzt den PATH gezielt um Git, ohne unnötig viele Unix-Werkzeuge global verfügbar zu machen.

### Git und Unix-Werkzeuge global verfügbar machen

Sinngemäß:

> „Use Git and optional Unix tools from the Command Prompt“

Diese Variante stellt zusätzlich viele Unix-Befehle wie `find`, `grep` oder `sort` systemweit bereit.

Das kann praktisch wirken, birgt aber ein Risiko: Unix-Werkzeuge können Windows-Befehle gleichen Namens überlagern oder Skripte unerwartet beeinflussen. Besonders in Unternehmensumgebungen und bei älteren Automatisierungen kann das zu schwer nachvollziehbaren Problemen führen.

**Für die meisten Nutzer nicht empfohlen.** Nutze Unix-Werkzeuge stattdessen innerhalb von Git Bash oder WSL, falls du Linux-Werkzeuge benötigst.

---

## SSH-Client auswählen

Git benötigt SSH, wenn du Repositories über SSH mit GitHub verbinden möchtest, beispielsweise über eine URL wie:

```text
git@github.com:organisation/projekt.git
```

Der Installer fragt meist nach dem SSH-Programm.

### Empfohlene Wahl: gebündeltes OpenSSH

Wähle:

> „Use bundled OpenSSH“

Das mit Git for Windows ausgelieferte OpenSSH ist abgestimmt, aktuell und funktioniert zuverlässig in Git Bash, PowerShell, Windows Terminal und PhpStorm.

### Wann das externe OpenSSH sinnvoll sein kann

Windows 11 enthält häufig bereits einen eigenen OpenSSH-Client. Die Option **„Use external OpenSSH“** ist sinnvoll, wenn:

- dein Unternehmen zentral verwaltete SSH-Konfigurationen bereitstellt,
- ein vorhandener SSH-Agent verbindlich verwendet werden muss,
- du bewusst nur den Windows-Systemclient einsetzen möchtest,
- Sicherheitsrichtlinien eine bestimmte OpenSSH-Version vorgeben.

Für einen persönlichen Entwicklungsrechner oder den Einstieg ist das gebündelte OpenSSH die robustere Wahl.

> **Wichtig:** Verwende nicht unkontrolliert mehrere SSH-Konfigurationen. Wenn Git Bash, PowerShell und PhpStorm unterschiedliche Schlüssel oder SSH-Programme verwenden, entstehen schwer verständliche Authentifizierungsprobleme.

---

## HTTPS-Transport-Backend auswählen

Für HTTPS-Verbindungen zu GitHub muss Git Zertifikate prüfen. Der Installer bietet meist zwei Varianten an.

### OpenSSL-Bibliothek verwenden

Sinngemäß:

> „Use the OpenSSL library“

Git bringt eine eigene Zertifikatsverwaltung mit. Diese Wahl ist auf vielen Systemen zuverlässig und war lange die Standardempfehlung.

### Windows Secure Channel verwenden

Sinngemäß:

> „Use the native Windows Secure Channel library“

Diese Option nutzt den Windows-Zertifikatsspeicher. Zertifikate, die Windows bereits als vertrauenswürdig kennt, werden auch von Git akzeptiert.

### Welche Wahl ist richtig?

Für einen üblichen privaten Windows-11-Rechner funktionieren **beide Varianten**. Die Standardauswahl des Installers ist in der Regel eine vernünftige Wahl.

**Windows Secure Channel** ist besonders passend, wenn:

- dein Unternehmen eigene Root-Zertifikate verteilt,
- ein Proxy HTTPS-Verbindungen kontrolliert,
- Zertifikate zentral über Windows verwaltet werden.

**OpenSSL** ist passend, wenn:

- du eine möglichst eigenständige Git-Installation bevorzugst,
- keine Unternehmenszertifikate eingebunden werden müssen,
- du die Standardauswahl beibehalten möchtest.

> **Sicherheitsregel:** Deaktiviere die Zertifikatsprüfung nicht mit Einstellungen wie `http.sslVerify=false`. Das löst keine Vertrauensprobleme, sondern umgeht eine wichtige Schutzfunktion.

---

## Zeilenenden korrekt konfigurieren

Der Dialog **„Configuring the line ending conversions“** betrifft einen häufigen Unterschied zwischen Windows und Unix-Systemen.

Windows verwendet traditionell die Zeilenendung **CRLF**, während Linux, macOS und die meisten Serverumgebungen **LF** verwenden.

Technisch:

$$
\text{Windows-Zeilenende} = \text{CRLF}
$$

$$
\text{Unix-Zeilenende} = \text{LF}
$$

Git kann beim Auschecken und Speichern automatisch zwischen beiden Darstellungen umwandeln.

### Empfohlene Auswahl für Windows-Entwicklung

Wähle üblicherweise:

> „Checkout Windows-style, commit Unix-style line endings“

Diese Auswahl entspricht typischerweise:

```bash
git config --global core.autocrlf true
```

Das Verhalten lautet:

- Beim Auschecken werden Textdateien im Arbeitsverzeichnis als CRLF bereitgestellt.
- Beim Commit speichert Git Textdateien mit LF im Repository.

Damit bleiben Repository-Inhalte auf Servern und in gemischten Teams konsistent, während Windows-Editoren trotzdem mit CRLF arbeiten können.

### Alternative für strikt normalisierte Projekte

Manche Teams verwenden bewusst LF auch im Windows-Arbeitsverzeichnis. Dann kann folgende Einstellung passend sein:

```bash
git config --global core.autocrlf input
```

Sie konvertiert beim Commit nach LF, verändert aber Zeilenenden beim Auschecken nicht.

Diese Variante ist verbreitet, wenn:

- Editor und Projekt konsequent auf LF eingestellt sind,
- `.gitattributes` die Zeilenenden verbindlich steuert,
- Container, WSL oder Linux-nahe Werkzeuge im Einsatz sind.

Für den Einstieg unter Windows 11 ist `core.autocrlf=true` meist die unkompliziertere Wahl. Später wird die teamweite, reproduzierbare Steuerung über `.gitattributes` wichtiger als eine persönliche globale Einstellung.

---

## Terminal-Emulator für Git Bash wählen

Git Bash benötigt ein Terminalfenster. Der Installer bietet meist zwei Optionen:

- **MinTTY**
- die klassische **Windows-Konsole**

### Empfehlung: MinTTY

Wähle:

> „Use MinTTY“

MinTTY bietet eine angenehmere Nutzung von Git Bash:

- bessere Textauswahl und Kopierfunktionen,
- gute Unicode-Unterstützung,
- flexiblere Fensterdarstellung,
- konsistenteres Unix-artiges Verhalten.

### Windows-Konsole nur bei Sonderfällen

Die Windows-Konsole kann sinnvoll sein, wenn du alte Windows-Programme direkt innerhalb von Git Bash verwenden musst und diese Probleme mit MinTTY haben.

Für die normale Git-Arbeit, PHP-Projekte und PhpStorm ist **MinTTY** die bessere Wahl. Zusätzlich kannst du Git Bash später im Windows Terminal verwenden.

---

## Verhalten von `git pull` festlegen

Neuere Git-for-Windows-Installer fragen nach dem Standardverhalten von `git pull`.

Ein Pull besteht konzeptionell aus zwei Schritten:

$$
\texttt{git pull} = \texttt{git fetch} + \text{Integration lokaler Änderungen}
$$

Die Integration kann per Merge, Rebase oder ausschließlich als Fast-Forward erfolgen.

### Empfohlene Wahl für den Einstieg: Fast-Forward oder Merge

Wenn angeboten, ist **Fast-forward or merge** eine sichere Wahl. Git führt einen Fast-Forward aus, wenn möglich, und erstellt anderenfalls einen Merge.

Das ist transparent und verändert vorhandene lokale Commits nicht nachträglich.

### Rebase nur mit bewusstem Teamstandard

Die Option **Rebase** kann eine lineare Historie erzeugen, schreibt aber lokale Commits beim Pull um. Das ist nützlich, wenn dein Team diesen Ablauf verbindlich nutzt und du Rebase sicher beherrschst.

Für den Anfang ist sie nicht die beste Standardwahl. Rebase wird später gezielt und kontrolliert eingesetzt.

### Fast-Forward only als strenge Schutzoption

**Fast-forward only** bricht den Pull ab, sobald lokale und entfernte Historie auseinanderlaufen. Das verhindert automatische Merge-Commits, verlangt aber eine bewusste Entscheidung:

```bash
git pull --rebase
```

oder:

```bash
git merge origin/main
```

Diese Einstellung eignet sich gut für Teams mit klaren Regeln, kann Einsteiger aber zunächst häufiger mit Abbrüchen konfrontieren.

---

## Credential Helper aktivieren

GitHub akzeptiert für Git-Operationen über HTTPS kein Kontopasswort mehr. Stattdessen kommen beispielsweise Personal Access Tokens oder browserbasierte Anmeldungen zum Einsatz.

Wähle im Dialog zum Credential Helper:

> „Git Credential Manager“

Der **Git Credential Manager** speichert Zugangsdaten nicht als Klartext in einer Projektdatei. Er verwendet unter Windows den geschützten Windows-Anmeldeinformationsmanager und unterstützt moderne Anmeldeflüsse.

Das ist besonders hilfreich für:

- HTTPS-URLs von GitHub,
- Anmeldung über den Browser,
- tokenbasierte Authentifizierung,
- mehrere GitHub-Konten,
- Zugriff auf private Organisationen.

Die Zugangsdaten kannst du später in Windows unter **Anmeldeinformationsverwaltung** prüfen oder entfernen.

> **Wichtig:** Ein Personal Access Token ist wie ein Passwort zu behandeln. Speichere ihn nie in Quellcode, Commit-Nachrichten, Screenshots oder unverschlüsselten Textdateien.

---

## Zusätzliche Optionen am Ende der Installation

Je nach Installer-Version erscheinen noch weitere Auswahlmöglichkeiten.

### Dateisystem-Caching aktivieren

Aktiviere:

> „Enable file system caching“

Diese Option verbessert die Leistung, insbesondere bei größeren Repositories. Git kann Dateiinformationen effizienter wiederverwenden.

Für typische Entwicklungsprojekte ist das die richtige Wahl.

### Symbolische Links aktivieren

Die Option **„Enable symbolic links“** sollte nur bewusst aktiviert werden.

Symbolische Links funktionieren unter Windows 11 grundsätzlich besser als früher, können aber abhängig von Benutzerrechten, Entwicklermodus, Netzlaufwerken und Sicherheitsrichtlinien problematisch sein.

Aktiviere sie, wenn:

- dein Projekt tatsächlich symbolische Links versioniert,
- du den Windows-Entwicklermodus aktiviert hast oder passende Rechte besitzt,
- alle Teammitglieder und Zielsysteme damit umgehen können.

Lass sie zunächst deaktiviert, wenn du keinen konkreten Bedarf hast. Git kann symbolische Links dann nicht vollständig wie auf Linux behandeln, aber du vermeidest unerwartete Berechtigungsprobleme.

### Pseudo-Konsole oder Legacy-Konsole

Manche Installer-Versionen fragen nach dem Verhalten der Konsole, beispielsweise nach **Pseudo Console Support**.

Die moderne Standardauswahl ist in der Regel sinnvoll. Ändere sie nur, wenn du konkrete Kompatibilitätsprobleme mit alten Konsolenanwendungen beobachtest.

---

## Empfohlene Konfiguration im Überblick

Für einen typischen PHP-Workflow mit Windows 11, GitHub und PhpStorm empfiehlt sich folgende Zusammenfassung:

| Installationsbereich | Empfohlene Entscheidung |
|---|---|
| Explorer-Integration | Git Bash Here aktivieren |
| Git LFS | Aktivieren |
| Windows Terminal-Profil | Aktivieren |
| Standardeditor | Visual Studio Code oder ein vertrauter Editor |
| PATH | Git aus Kommandozeile und Drittsoftware verwenden |
| SSH | Gebündeltes OpenSSH verwenden |
| HTTPS-Zertifikate | Standardauswahl; in Unternehmen häufig Windows Secure Channel |
| Zeilenenden | Windows auschecken, Unix committen |
| Git-Bash-Terminal | MinTTY verwenden |
| Pull-Verhalten | Fast-forward oder Merge |
| Credential Helper | Git Credential Manager |
| Dateisystem-Caching | Aktivieren |
| Symbolische Links | Nur bei konkretem Bedarf aktivieren |

---

## Nach der Installation prüfen

Öffne **PowerShell**, Windows Terminal oder Git Bash und prüfe zuerst, ob Git gefunden wird:

```bash
git --version
```

Eine erfolgreiche Ausgabe ähnelt diesem Muster:

```text
git version 2.x.x.windows.x
```

Prüfe danach, von welchem Pfad Git gestartet wird.

In PowerShell:

```powershell
Get-Command git
```

In Git Bash:

```bash
which git
```

Kontrolliere außerdem die wichtigsten vom Installer gesetzten Einstellungen:

```bash
git config --global --get core.autocrlf
git config --global --get credential.helper
git config --global --get pull.rebase
```

Nicht jede Installation setzt alle Werte sichtbar als globale Konfiguration. Eine leere Ausgabe ist daher nicht automatisch ein Fehler; manche Vorgaben stammen aus der Systemkonfiguration oder bleiben auf dem Git-Standardwert.

Alle wirksamen Konfigurationswerte inklusive ihrer Herkunft zeigst du mit diesem Befehl an:

```bash
git config --list --show-origin
```

---

## Häufige Fehlentscheidungen

### Git ist nur in Git Bash verfügbar

**Ursache:** Bei der PATH-Auswahl wurde „Git Bash only“ gewählt.

**Folge:** PowerShell, PhpStorm oder andere Werkzeuge finden `git` möglicherweise nicht.

**Lösung:** Git erneut installieren und die Option für Kommandozeile und Drittsoftware wählen. Alternativ kann der PATH manuell korrigiert werden; eine Neuinstallation ist für Einsteiger jedoch meist sicherer.

### GitHub fragt bei jedem Push erneut nach Zugangsdaten

**Mögliche Ursachen:**

- Git Credential Manager wurde nicht aktiviert,
- gespeicherte Zugangsdaten sind ungültig,
- es wird eine HTTPS-URL verwendet, aber kein Token oder Browser-Login abgeschlossen,
- mehrere GitHub-Konten werden vermischt.

**Lösung:** Den Git Credential Manager aktivieren und gespeicherte GitHub-Anmeldeinformationen in der Windows-Anmeldeinformationsverwaltung prüfen.

### Unerwartete Änderungen in fast allen Dateien

**Typische Ursache:** Zeilenenden wurden automatisch umgewandelt oder das Projekt verwendet eigene Regeln.

**Lösung:** Nicht sofort alles committen. Prüfe zuerst:

```bash
git status
git diff --ignore-space-at-eol
```

Untersuche anschließend die Datei `.gitattributes`, falls sie vorhanden ist. Sie kann die globale Einstellung `core.autocrlf` für dieses Repository übersteuern.

### SSH funktioniert im Terminal, aber nicht in PhpStorm

**Typische Ursache:** PhpStorm verwendet einen anderen SSH-Client, einen anderen Schlüssel oder einen anderen Agenten.

**Lösung:** Später in PhpStorm unter den Git- und SSH-Einstellungen prüfen, welcher SSH-Executable-Pfad und welcher Authentifizierungsmodus aktiv sind. Verwende möglichst konsistent denselben Schlüsselbestand.

---

## Entscheidungshilfe für spätere Änderungen

Die meisten Installationsentscheidungen lassen sich nachträglich ändern. Du musst Git nicht bei jeder kleinen Anpassung neu installieren.

Beispiele:

```bash
git config --global core.autocrlf true
```

```bash
git config --global pull.rebase false
```

```bash
git config --global credential.helper manager
```

Für größere Änderungen, insbesondere an PATH, SSH-Komponente oder Explorer-Integration, ist eine erneute Ausführung des Git-for-Windows-Installers oft der sauberste Weg. Der Installer erkennt eine vorhandene Installation und bietet üblicherweise eine Anpassung oder Aktualisierung an.

> **Merksatz:** Wähle bei der Installation sichere, konservative Standards. Git Bash, Git im PATH, Git Credential Manager und eine kontrollierte Zeilenendenstrategie bilden die wichtigste Grundlage für die weitere Arbeit.

# Git Bash, PowerShell und CMD vergleichen

## Drei Konsolen, drei Aufgabenbereiche

Unter Windows 11 kannst du Git aus verschiedenen Kommandozeilen heraus verwenden. Die wichtigsten sind:

- **Git Bash** – eine Unix-ähnliche Shell, die mit Git for Windows installiert wird
- **PowerShell** – die moderne Windows-Shell für Administration und Automatisierung
- **Eingabeaufforderung** bzw. **CMD** – die klassische Windows-Konsole

Alle drei können denselben Git-Befehl ausführen, sofern Git korrekt installiert und über die PATH-Variable erreichbar ist:

```bash
git --version
git status
git commit -m "Dokumentation ergänzen"
```

Der Unterschied liegt also nicht in Git selbst, sondern in der Umgebung: Pfade, Dateibefehle, Skripte, Variablen und die Art, wie Ausgaben verarbeitet werden, unterscheiden sich deutlich.

> **Grundregel:** Git-Kommandos bleiben weitgehend gleich. Shell-spezifisch sind vor allem Befehle *um Git herum*.

---

## Git Bash

Git Bash wird zusammen mit **Git for Windows** installiert. Sie stellt eine Bash-Umgebung bereit, die sich an Linux und macOS orientiert. Viele in Git-Dokumentationen, Tutorials und Open-Source-Projekten verwendete Befehle funktionieren dort direkt.

### Typische Eigenschaften

- Unix-ähnliche Befehle wie `ls`, `cd`, `cat`, `grep` und `rm`
- Pfadangaben im Unix-Stil
- Gute Kompatibilität mit vielen Git-Anleitungen
- Enthält üblicherweise SSH, OpenSSH-Agent, Git und weitere Hilfsprogramme
- Besonders geeignet für Git, PHP-Projekte, Composer und Shell-Skripte

Ein typischer Startbildschirm könnte so aussehen:

```bash
alex@PC MINGW64 ~
$
```

`~` steht für dein persönliches Benutzerverzeichnis.

### Pfade in Git Bash

Windows-Pfade werden in Git Bash normalerweise anders geschrieben:

| Windows | Git Bash |
|---|---|
| `C:\Users\Alex` | `/c/Users/Alex` |
| `D:\Projekte\shop` | `/d/Projekte/shop` |
| `C:\Program Files\Git` | `/c/Program Files/Git` |

In einen Projektordner wechselst du beispielsweise so:

```bash
cd /c/Users/Alex/Projekte/mein-projekt
```

Enthält ein Pfad Leerzeichen, muss er in Anführungszeichen stehen:

```bash
cd "/c/Users/Alex/Meine Projekte/mein-projekt"
```

### Häufige Dateibefehle in Git Bash

```bash
pwd
ls
ls -la
mkdir mein-projekt
touch README.md
cp quelle.txt ziel.txt
mv alt.txt neu.txt
rm datei.txt
```

Dabei bedeuten die wichtigsten Befehle:

- `pwd` zeigt den aktuellen Ordner an.
- `ls` listet Dateien und Ordner auf.
- `mkdir` erstellt einen Ordner.
- `touch` erstellt eine leere Datei oder aktualisiert ihren Zeitstempel.
- `cp` kopiert Dateien.
- `mv` verschiebt oder benennt Dateien um.
- `rm` löscht Dateien.

⚠️ `rm` besitzt keinen Papierkorb. Eine damit gelöschte Datei ist in der Regel sofort entfernt. Verwende insbesondere `rm -rf` nur mit äußerster Vorsicht.

### Wann Git Bash besonders sinnvoll ist

Git Bash ist für diesen Kurs meist die beste Wahl, wenn du:

- Git anhand von Dokumentation und Tutorials lernen möchtest,
- Git-Befehle unter Windows möglichst ähnlich wie unter Linux oder macOS verwenden willst,
- mit SSH-Schlüsseln arbeitest,
- Shell-Skripte aus Open-Source-Projekten ausführen musst,
- Befehle wie `grep`, `find`, `sed` oder `cat` nutzen möchtest.

Für Einsteiger ist Git Bash oft angenehmer, weil viele Git-Beispiele im Internet genau diese oder eine sehr ähnliche Umgebung voraussetzen.

---

## PowerShell

PowerShell ist die moderne Kommandozeile von Windows. Sie ist auf Systemverwaltung, Automatisierung und strukturierte Datenverarbeitung ausgelegt. Unter Windows 11 ist sie standardmäßig verfügbar.

Je nach Installation begegnen dir zwei Varianten:

- **Windows PowerShell** – die ältere, vorinstallierte Variante
- **PowerShell** bzw. PowerShell 7+ – die moderne, plattformübergreifende Weiterentwicklung

Für Git funktionieren beide Varianten grundsätzlich gleich.

### Typische Eigenschaften

- Native Integration in Windows
- Zugriff auf Windows-Dienste, Registry, Prozesse und Dateisystem
- Leistungsfähige Skriptsprache
- Verarbeitung von Objekten statt nur Textzeilen
- Git kann direkt verwendet werden, wenn es im PATH liegt

Ein typischer Prompt sieht etwa so aus:

```powershell
PS C:\Users\Alex>
```

### Pfade in PowerShell

PowerShell verwendet normalerweise klassische Windows-Pfade:

```powershell
cd C:\Users\Alex\Projekte\mein-projekt
```

Alternativ akzeptiert PowerShell in vielen Fällen auch Schrägstriche:

```powershell
cd C:/Users/Alex/Projekte/mein-projekt
```

Bei Leerzeichen setzt du den gesamten Pfad in Anführungszeichen:

```powershell
cd "C:\Users\Alex\Meine Projekte\mein-projekt"
```

### Häufige Dateibefehle in PowerShell

```powershell
Get-Location
Get-ChildItem
New-Item -ItemType Directory mein-projekt
New-Item -ItemType File README.md
Copy-Item quelle.txt ziel.txt
Move-Item alt.txt neu.txt
Remove-Item datei.txt
```

PowerShell kennt zusätzlich viele kurze Aliase:

```powershell
pwd
ls
mkdir mein-projekt
cp quelle.txt ziel.txt
mv alt.txt neu.txt
rm datei.txt
```

Diese Kurzformen sehen Git-Bash-Befehlen ähnlich, sind aber nicht immer exakt gleich. Hinter `ls` steckt in PowerShell beispielsweise `Get-ChildItem`, nicht der Unix-Befehl `ls`.

> Verwende bei PowerShell-Skripten möglichst die vollständigen Befehlsnamen wie `Get-ChildItem` oder `Remove-Item`. Das macht Skripte verständlicher und vermeidet Missverständnisse zwischen Shells.

### Besonderheit: PowerShell verarbeitet Objekte

Git Bash und CMD behandeln Kommandoausgaben hauptsächlich als Text. PowerShell verarbeitet dagegen oft strukturierte .NET-Objekte.

Ein Beispiel: Alle laufenden Prozesse anzeigen und nach einem Namen filtern:

```powershell
Get-Process | Where-Object ProcessName -like "*php*"
```

Das ist für Windows-Automatisierung sehr nützlich, aber für einfache Git-Aufgaben zunächst nicht entscheidend.

### Wann PowerShell besonders sinnvoll ist

PowerShell ist eine gute Wahl, wenn du:

- ohnehin häufig mit Windows arbeitest,
- Windows-spezifische Aufgaben automatisierst,
- Skripte für Dateien, Dienste, Prozesse oder Netzwerkverwaltung schreibst,
- Git und Windows-Administration in einer einheitlichen Umgebung kombinieren willst,
- das integrierte Terminal von PhpStorm oder Windows Terminal mit einem Windows-Profil nutzen möchtest.

Git-Befehle selbst funktionieren in PowerShell zuverlässig:

```powershell
git status
git add .
git commit -m "Startprojekt anlegen"
git log --oneline
```

---

## Die Eingabeaufforderung CMD

CMD, offiziell `cmd.exe`, ist die klassische Eingabeaufforderung von Windows. Sie ist seit vielen Windows-Versionen vorhanden und besonders ressourcenschonend. Für moderne Automatisierung bietet sie jedoch deutlich weniger Möglichkeiten als PowerShell.

Ein CMD-Prompt sieht typischerweise so aus:

```cmd
C:\Users\Alex>
```

### Typische Eigenschaften

- Auf praktisch jedem Windows-System verfügbar
- Einfach und schnell zu starten
- Kompatibel mit älteren Batch-Dateien
- Weniger komfortabel für Automatisierung als PowerShell
- Keine Unix-typischen Werkzeuge wie `grep`, `cat` oder `touch` ohne zusätzliche Installation

### Pfade und Dateibefehle in CMD

CMD verwendet Windows-Pfade:

```cmd
cd C:\Users\Alex\Projekte\mein-projekt
```

Bei einem Wechsel auf ein anderes Laufwerk brauchst du entweder zwei Schritte:

```cmd
D:
cd \Projekte\mein-projekt
```

Oder du verwendest `cd /d`, das Laufwerk und Ordner gemeinsam wechselt:

```cmd
cd /d D:\Projekte\mein-projekt
```

Häufige Dateibefehle:

```cmd
cd
dir
mkdir mein-projekt
type nul > README.md
copy quelle.txt ziel.txt
move alt.txt neu.txt
del datei.txt
rmdir mein-ordner
```

Auch hier gilt: `del` und `rmdir` verschieben nichts in den Papierkorb.

### Git in CMD verwenden

Wenn Git im PATH eingerichtet wurde, funktionieren Git-Befehle wie gewohnt:

```cmd
git --version
git init
git status
git add README.md
git commit -m "Ersten Commit erstellen"
```

CMD ist deshalb nicht ungeeignet für Git. Es ist lediglich weniger komfortabel, wenn du viele Dateisystem-, Such- oder Automatisierungsbefehle benötigst.

### Wann CMD noch sinnvoll ist

CMD ist passend, wenn du:

- ein altes Batch-Skript mit `.bat` oder `.cmd` ausführen musst,
- auf einem eingeschränkten Windows-System arbeitest,
- eine einfache, überall verfügbare Konsole brauchst,
- gezielt ältere Windows-Werkzeuge verwendest.

Für neue persönliche Git-Workflows ist Git Bash oder PowerShell normalerweise die bessere Wahl.

---

## Direkter Vergleich

| Kriterium | Git Bash | PowerShell | CMD |
|---|---|---|---|
| Primärer Zweck | Git und Unix-nahe Entwicklung | Windows-Administration und Automatisierung | Klassische Windows-Kommandos |
| Pfadstil | `/c/Users/Alex` | `C:\Users\Alex` | `C:\Users\Alex` |
| Unix-Befehle | Sehr gut verfügbar | Teilweise als Aliase vorhanden | Meist nicht verfügbar |
| Git-Dokumentationen nachvollziehen | Sehr gut | Gut | Gut |
| Windows-Systemverwaltung | Eingeschränkt | Sehr gut | Eingeschränkt |
| Moderne Skripte | Bash-Skripte | PowerShell-Skripte | Batch-Skripte |
| Einstieg für Git | Sehr empfehlenswert | Empfehlenswert | Möglich, aber weniger komfortabel |
| Typische Skriptdateien | `.sh` | `.ps1` | `.bat`, `.cmd` |

---

## Dieselbe Git-Aufgabe in allen drei Konsolen

Angenommen, dein Projekt liegt unter `C:\Users\Alex\Projekte\demo-app`.

### Git Bash

```bash
cd /c/Users/Alex/Projekte/demo-app
git status
git add README.md
git commit -m "README ergänzen"
```

### PowerShell

```powershell
cd C:\Users\Alex\Projekte\demo-app
git status
git add README.md
git commit -m "README ergänzen"
```

### CMD

```cmd
cd /d C:\Users\Alex\Projekte\demo-app
git status
git add README.md
git commit -m "README ergänzen"
```

Ab `git status` sind die Befehle identisch. Du musst also nicht für jede Shell eine neue Git-Sprache lernen.

---

## Unterschiede bei Variablen und Umgebungsvariablen

Shells unterscheiden sich deutlich darin, wie sie Variablen schreiben und lesen. Das wird wichtig, sobald du Konfigurationen prüfst, Tokens temporär setzt oder Skripte verwendest.

### Git Bash

```bash
name="Alex"
echo "$name"

echo "$HOME"
echo "$PATH"
```

Eine Umgebungsvariable wird für einen einzelnen Befehl gesetzt:

```bash
GIT_EDITOR=vim git commit
```

### PowerShell

```powershell
$name = "Alex"
Write-Output $name

$HOME
$env:PATH
```

Eine Umgebungsvariable wird beispielsweise so gesetzt:

```powershell
$env:GIT_EDITOR = "notepad"
git commit
```

### CMD

```cmd
set name=Alex
echo %name%

echo %USERPROFILE%
echo %PATH%
```

Für eine einzelne CMD-Sitzung:

```cmd
set GIT_EDITOR=notepad
git commit
```

> **Wichtig:** Beispielbefehle für Bash, PowerShell und CMD solltest du nicht unbesehen mischen. Besonders Variablen, Anführungszeichen, Schleifen und Pipes verhalten sich unterschiedlich.

---

## Anführungszeichen richtig einsetzen

Datei- und Ordnernamen mit Leerzeichen sind unter Windows häufig. Beispiele sind `C:\Program Files` oder ein Projektordner wie `Meine Projekte`.

In allen drei Konsolen sind doppelte Anführungszeichen für solche Pfade die sichere Standardwahl:

```bash
cd "/c/Users/Alex/Meine Projekte/demo-app"
```

```powershell
cd "C:\Users\Alex\Meine Projekte\demo-app"
```

```cmd
cd /d "C:\Users\Alex\Meine Projekte\demo-app"
```

Für Git-Commit-Nachrichten verwendest du ebenfalls meist doppelte Anführungszeichen:

```bash
git commit -m "Fehler beim Login beheben"
```

Bei komplexen Sonderzeichen, Variablen oder mehrzeiligen Skripten unterscheiden sich die Regeln der Shells. Für normale Git-Kommandos reichen doppelte Anführungszeichen in der Regel aus.

---

## Welche Shell solltest du verwenden?

Für diesen Kurs bietet sich folgende praktische Entscheidung an:

### Git Bash als Standard für Git lernen

Nutze **Git Bash**, wenn du die Git-Kommandozeile systematisch lernen möchtest. Die meisten Beispiele in diesem Kurs lassen sich dort direkt übernehmen. Außerdem ähneln die Befehle vielen Server-, CI- und Open-Source-Umgebungen.

### PowerShell für Windows-nahe Arbeit

Nutze **PowerShell**, wenn du Windows administrierst, Dateien und Prozesse automatisierst oder bereits mit PowerShell vertraut bist. Git funktioniert dort vollständig; achte nur bei zusätzlichen Shell-Befehlen auf die abweichende Syntax.

### CMD nur bei konkretem Bedarf

Nutze **CMD**, wenn ein älteres Skript oder eine bestimmte Anleitung dies verlangt. Für einen neuen Git-Workflow ist CMD normalerweise nicht die erste Wahl.

> **Empfehlung für den Einstieg:** Arbeite in den nächsten Kapiteln überwiegend mit **Git Bash**. Öffne PowerShell bewusst gelegentlich mit, damit du die Pfad- und Syntaxunterschiede kennenlernst.

---

## Windows Terminal als gemeinsame Oberfläche

**Windows Terminal** ist keine eigene Shell. Es ist eine moderne Terminal-Anwendung, in der du unterschiedliche Shells als Tabs oder Profile öffnen kannst:

- Git Bash
- PowerShell
- Eingabeaufforderung
- Windows Subsystem for Linux, falls installiert
- SSH-Verbindungen zu Servern

Damit musst du nicht zwischen verschiedenen Anwendungen wechseln. Du kannst etwa einen Git-Bash-Tab für Git-Kommandos und einen PowerShell-Tab für Windows-Aufgaben verwenden.

Die Shell erkennst du am Prompt:

| Prompt-Beispiel | Aktive Shell |
|---|---|
| `alex@PC MINGW64 ~` | Git Bash |
| `PS C:\Users\Alex>` | PowerShell |
| `C:\Users\Alex>` | CMD |

Diese Unterscheidung ist wichtig, wenn ein kopierter Befehl einen Fehler ausgibt. Prüfe dann zuerst, für welche Shell der Befehl geschrieben wurde.

---

## Git in PhpStorm und in der Konsole

PhpStorm verwendet Git nicht über eine eigene, abweichende Git-Variante. Die IDE ruft die installierte Git-Anwendung im Hintergrund auf. Deshalb gelten dieselben Konzepte:

- Repository
- Branch
- Staging Area
- Commit
- Remote
- Fetch, Pull und Push

Die Konsole bleibt trotzdem wertvoll:

- Sie zeigt Git-Ausgaben vollständig und unmittelbar.
- Sie eignet sich für seltene oder fortgeschrittene Optionen.
- Viele Fehler lassen sich in der Konsole präziser untersuchen.
- Git-Dokumentationen enthalten fast immer CLI-Beispiele.
- Du verstehst besser, welche Aktion eine IDE-Schaltfläche tatsächlich ausführt.

PhpStorm kann ein integriertes Terminal mit Git Bash, PowerShell oder CMD öffnen. Welche Shell dort startet, legst du später in den Terminal-Einstellungen fest.

---

## Kurzer Selbsttest

Öffne nacheinander Git Bash, PowerShell und CMD. Führe in jeder Konsole diese Befehle aus:

```text
git --version
git config --global user.name
git config --global user.email
```

Prüfe danach den aktuellen Ordner:

```bash
pwd
```

```powershell
Get-Location
```

```cmd
cd
```

Wenn `git --version` in einer Shell funktioniert, in einer anderen aber nicht, ist Git wahrscheinlich nicht in allen Sitzungen über den PATH verfügbar. Schließe zunächst alle geöffneten Terminals und starte sie neu. Besteht das Problem weiter, wird die PATH-Konfiguration im nächsten Abschnitt gezielt geprüft.

---

## Merksätze

- **Git ist in allen Shells dasselbe; die Umgebung darum herum ist unterschiedlich.**
- **Git Bash** ist die beste Standardwahl, um Git anhand vieler Anleitungen zu lernen.
- **PowerShell** ist die stärkste Wahl für Windows-Automatisierung.
- **CMD** ist vor allem für Kompatibilität mit älteren Windows-Skripten relevant.
- Pfade, Variablen und Dateibefehle sind shellabhängig.
- Bei Fehlermeldungen solltest du immer prüfen, *welche Shell* gerade aktiv ist.

# Windows Terminal konfigurieren

Windows Terminal bündelt PowerShell, Eingabeaufforderung, Git Bash und weitere Shells in einer modernen Oberfläche. Für die Git-Arbeit unter Windows 11 ist es besonders praktisch: Du kannst mehrere Terminals in Tabs öffnen, Arbeitsverzeichnisse gezielt starten und ein einheitliches Profil für Git Bash anlegen.

> **Ziel:** Nach diesem Abschnitt startest du Git Bash bequem im Windows Terminal, öffnest Repositories direkt im passenden Ordner und kennst die wichtigsten Einstellungen für eine zuverlässige tägliche Arbeit.

## Windows Terminal installieren und aktualisieren

Auf aktuellen Windows-11-Systemen ist Windows Terminal meist bereits installiert. Öffne das Startmenü und suche nach **Windows Terminal**.

Falls es fehlt oder aktualisiert werden soll:

1. Öffne den **Microsoft Store**.
2. Suche nach **Windows Terminal**.
3. Wähle **Installieren** oder **Aktualisieren**.

Alternativ lässt sich Windows Terminal über `winget` installieren:

```powershell
winget install --id Microsoft.WindowsTerminal
```

Prüfe anschließend die installierte Version:

```powershell
wt --version
```

Die Ausgabe enthält beispielsweise eine Versionsnummer wie `1.22.x`. Entscheidend ist nicht die konkrete Nummer, sondern dass der Befehl ohne Fehlermeldung funktioniert.

## Die Oberfläche verstehen

Windows Terminal verwaltet jede Kommandozeilenumgebung als **Profil**. Ein Profil definiert unter anderem:

- welche Anwendung gestartet wird,
- in welchem Ordner sie startet,
- welches Symbol, Farbschema und Schriftbild verwendet wird,
- ob das Profil als Administrator geöffnet wird,
- welche Umgebung beim Öffnen eines neuen Tabs standardmäßig erscheint.

Typische automatisch erkannte Profile sind:

| Profil | Typischer Zweck |
|---|---|
| **Windows PowerShell** | Klassische Windows-Verwaltung und bestehende Skripte |
| **PowerShell** | Moderne PowerShell-Version, falls installiert |
| **Eingabeaufforderung** | Kompatibilität mit älteren `cmd.exe`-Befehlen |
| **Git Bash** | Git-Befehle und Unix-ähnliche Werkzeuge aus Git for Windows |
| **Azure Cloud Shell** | Arbeit mit Azure, falls eingerichtet |
| **Ubuntu** oder andere WSL-Distributionen | Linux-Umgebung über Windows Subsystem for Linux |

Für diesen Kurs sind vor allem **Git Bash** und **PowerShell** relevant:

- **Git Bash** eignet sich hervorragend für Git-Tutorials und viele plattformübergreifende Befehle.
- **PowerShell** ist nützlich für Windows-spezifische Aufgaben, etwa Dateisystem-, Netzwerk- oder Verwaltungsbefehle.

## Git Bash als Terminalprofil prüfen

Wenn Git for Windows installiert wurde, erkennt Windows Terminal Git Bash in der Regel automatisch. Öffne Windows Terminal und klicke auf den Pfeil neben dem Pluszeichen **+**. In der Liste sollte **Git Bash** erscheinen.

Wähle den Eintrag aus. Ein Git-Bash-Tab zeigt typischerweise einen Prompt ähnlich diesem:

```bash
max@PC MINGW64 ~
$
```

Prüfe darin Git:

```bash
git --version
```

Erwartet wird eine Ausgabe ähnlich wie:

```text
git version 2.x.x.windows.x
```

Wenn Git Bash nicht in der Profilliste erscheint, schließe Windows Terminal vollständig und öffne es erneut. Die automatische Profilerkennung erfolgt beim Start.

Falls das Profil weiterhin fehlt, kannst du es manuell anlegen.

## Ein Git-Bash-Profil manuell erstellen

Öffne die Einstellungen über eine der folgenden Möglichkeiten:

- Klicke auf den Pfeil neben **+** und wähle **Einstellungen**.
- Verwende die Tastenkombination `Strg` + `,`.

Wähle links **Neues Profil hinzufügen** und dann **Neue leere Konfiguration**. Trage anschließend diese Werte ein:

| Einstellung | Empfohlener Wert |
|---|---|
| Name | `Git Bash` |
| Befehlszeile | `C:\Program Files\Git\bin\bash.exe -l -i` |
| Startverzeichnis | `%USERPROFILE%` |
| Symbol | `C:\Program Files\Git\mingw64\share\git\git-for-windows.ico` |

Die Optionen `-l -i` haben einen Zweck:

- `-l` startet Bash als *Login-Shell*. Dadurch werden die üblichen Git-for-Windows-Startdateien geladen.
- `-i` startet eine interaktive Shell, die für die tägliche Arbeit mit Eingaben vorgesehen ist.

Der Installationspfad kann abweichen. Prüfe im Explorer, ob Git tatsächlich unter `C:\Program Files\Git` installiert ist. Bei einer benutzerbezogenen Installation liegt Git häufig unter folgendem Pfad:

```text
C:\Users\<Benutzername>\AppData\Local\Programs\Git
```

Passe den Pfad im Profil entsprechend an.

### Profil über die JSON-Datei konfigurieren

Die grafischen Einstellungen reichen für die meisten Fälle aus. Fortgeschrittene können jedoch direkt die JSON-Konfiguration bearbeiten. Öffne dazu in den Einstellungen unten links **JSON-Datei öffnen**.

Ein Git-Bash-Profil innerhalb von `profiles` → `list` kann beispielsweise so aussehen:

```json
{
    "name": "Git Bash",
    "commandline": "C:\\Program Files\\Git\\bin\\bash.exe -l -i",
    "startingDirectory": "%USERPROFILE%",
    "icon": "C:\\Program Files\\Git\\mingw64\\share\\git\\git-for-windows.ico",
    "hidden": false
}
```

Beachte dabei zwei wichtige Details:

1. In JSON müssen Backslashes als `\\` geschrieben werden.
2. Nach dem Speichern lädt Windows Terminal die Änderungen normalerweise automatisch. Andernfalls öffnest du ein neues Fenster.

> **Hinweis:** Bearbeite die JSON-Datei nur gezielt. Ein fehlendes Komma oder eine zusätzliche Klammer kann verhindern, dass Windows Terminal die Konfiguration lädt.

## Ein sinnvolles Startverzeichnis festlegen

Ein Terminal startet standardmäßig oft im Benutzerprofil, also etwa hier:

```text
C:\Users\max
```

Für Git ist das eine gute allgemeine Ausgangsbasis. Du kannst dort beispielsweise einen Ordner für alle Entwicklungsprojekte anlegen:

```powershell
mkdir $HOME\Projekte
```

In Git Bash lautet der vergleichbare Befehl:

```bash
mkdir -p ~/Projekte
```

Wenn du deine Repositories immer in diesem Ordner speicherst, setze für dein Git-Bash-Profil als **Startverzeichnis**:

```text
%USERPROFILE%\Projekte
```

Damit öffnet jeder neue Git-Bash-Tab direkt im Projektbereich.

Ein Startverzeichnis sollte nicht auf ein einzelnes Repository festgelegt werden, sofern du parallel an mehreren Projekten arbeitest. Ein zentraler Ordner wie `Projekte`, `Code` oder `Repositories` ist flexibler.

## Git Bash als Standardprofil festlegen

Wenn Git Bash deine primäre Arbeitsumgebung für Git sein soll, kannst du sie als Standardprofil konfigurieren.

1. Öffne die **Einstellungen** von Windows Terminal.
2. Wähle links **Start**.
3. Setze bei **Standardprofil** den Eintrag **Git Bash**.
4. Speichere die Einstellung.

Ab jetzt startet Windows Terminal beim Öffnen direkt mit Git Bash.

Das ist eine Komfortentscheidung, keine technische Notwendigkeit. Git funktioniert ebenso in PowerShell, sofern Git korrekt im `PATH` verfügbar ist. Die Wahl des Standardprofils sollte zu deinem Arbeitsstil passen:

- Wähle **Git Bash**, wenn du überwiegend Kursbefehle, Bash-Skripte oder Unix-Programme verwendest.
- Wähle **PowerShell**, wenn du häufig Windows-Automatisierung und PowerShell-Skripte nutzt.

## Repository direkt im Windows Terminal öffnen

Besonders effizient ist das Öffnen eines Terminals direkt im Ordner eines Projekts.

### Über den Explorer

Navigiere im Datei-Explorer zu deinem Repository. Klicke mit der rechten Maustaste auf einen freien Bereich im Ordner und wähle:

```text
In Terminal öffnen
```

Windows Terminal startet im aktuellen Verzeichnis. Welches Profil erscheint, hängt vom festgelegten Standardprofil ab.

### Mit der Adressleiste des Explorers

Klicke in die Adressleiste des Explorers, gib Folgendes ein und bestätige mit `Enter`:

```text
wt
```

Dadurch öffnet sich Windows Terminal im aktuell angezeigten Ordner.

### Mit dem Befehl `wt`

Der Befehl `wt` steuert Windows Terminal aus anderen Konsolen oder Skripten. Um Git Bash in einem bestimmten Projektordner zu öffnen, verwende beispielsweise:

```powershell
wt -p "Git Bash" -d C:\Users\max\Projekte\mein-projekt
```

Die Optionen bedeuten:

| Option | Bedeutung |
|---|---|
| `-p "Git Bash"` | Startet das Profil mit dem Namen „Git Bash“ |
| `-d <Pfad>` | Legt das Startverzeichnis fest |

Wenn der Profilname Leerzeichen enthält, muss er in Anführungszeichen stehen.

In Git Bash kannst du das aktuelle Repository in einem neuen Git-Bash-Tab öffnen:

```bash
wt -p "Git Bash" -d .
```

Der Punkt `.` steht für das aktuelle Verzeichnis.

## Tabs, Bereiche und Arbeitsabläufe nutzen

Windows Terminal kann mehrere Shells gleichzeitig verwalten. Das ist für Git besonders nützlich, weil du verschiedene Aufgaben trennen kannst.

Ein sinnvoller Ablauf könnte so aussehen:

| Tab oder Bereich | Aufgabe |
|---|---|
| Git Bash im Feature-Branch | Änderungen bearbeiten, `git status`, `git add`, `git commit` |
| Zweiter Git-Bash-Tab im selben Repository | Logs, Diffs oder Vergleiche prüfen |
| PowerShell | Windows-spezifische Befehle und Skripte ausführen |
| PhpStorm-Terminal | Befehle direkt im Kontext der IDE ausführen |

Erstelle einen neuen Tab mit:

```text
Strg + Umschalt + T
```

Ein Bereich teilt das aktuelle Terminalfenster in mehrere nebeneinanderliegende Konsolen. Das Kontextmenü des Tabs bietet dafür je nach Version Optionen wie **Bereich teilen**. Alternativ lassen sich Bereiche über die Befehlspalette anlegen.

> **Praxisregel:** Verwende getrennte Tabs oder Bereiche nicht als Ersatz für getrennte Arbeitsverzeichnisse. Wenn du gleichzeitig an zwei Branches arbeiten möchtest, nutze später `git worktree` oder klone das Repository getrennt. Zwei Terminals im selben Arbeitsverzeichnis sehen immer denselben Git-Zustand.

## Darstellung für Git-Ausgaben verbessern

Git-Diffs, Logs und Konfliktmarker profitieren von einer gut lesbaren Schrift und ausreichendem Kontrast.

Öffne die Einstellungen und wähle dein **Git-Bash-Profil**. Unter **Darstellung** sind diese Werte empfehlenswert:

| Einstellung | Empfehlung | Begründung |
|---|---|---|
| Schriftart | Cascadia Mono, Consolas oder JetBrains Mono | Zeichen und Einrückungen bleiben klar unterscheidbar |
| Schriftgröße | 11 bis 14 | Gut lesbar bei Diffs und längeren Logs |
| Zeilenhöhe | Standard oder leicht erhöht | Erleichtert das Lesen dichter Ausgaben |
| Farbschema | Kontrastreiches dunkles oder helles Schema | Konfliktmarker und Diff-Farben bleiben erkennbar |
| Transparenz | Dezent oder deaktiviert | Text sollte stets gut lesbar bleiben |

Eine **Monospace-Schriftart** ist wichtig, weil jedes Zeichen dieselbe Breite besitzt. Nur so bleiben Einrückungen, Tabellenähnliche Ausgaben und Diff-Strukturen zuverlässig ausgerichtet.

Vermeide sehr kleine Schrift und starke Transparenz. Beides erschwert insbesondere die Arbeit mit langen Commit-Hashes, Dateipfaden und Konfliktmarkern.

## Kopieren und Einfügen sicher verwenden

In Windows Terminal gelten üblicherweise moderne Tastenkombinationen:

| Aktion | Tastenkombination |
|---|---|
| Kopieren | `Strg` + `C`, wenn kein Prozess läuft oder Text markiert ist |
| Einfügen | `Strg` + `V` |
| Alles auswählen | `Strg` + `A` |
| Suchen | `Strg` + `Umschalt` + `F` |
| Neuer Tab | `Strg` + `Umschalt` + `T` |

Bei Konsolenprogrammen hat `Strg` + `C` eine zweite Bedeutung: Es kann einen laufenden Prozess abbrechen. Das ist beispielsweise bei einem versehentlich gestarteten, lange laufenden Befehl sinnvoll, kann aber auch einen gerade aktiven Git-Vorgang unterbrechen.

Markiere daher zum Kopieren zuerst den gewünschten Text. Windows Terminal erkennt die Auswahl und kopiert dann statt den Prozess abzubrechen.

> ⚠️ **Sicherheitsregel:** Füge Git-Befehle aus Webseiten, Chats oder Tickets nicht blind ein. Lies jeden Befehl vollständig, bevor du ihn ausführst — besonders Befehle mit `reset --hard`, `clean`, `push --force`, `rm` oder Pipe-Weiterleitungen.

## Nützliche Profileinstellungen für Git Bash

Für die tägliche Arbeit reichen wenige, bewusst gewählte Einstellungen.

### Administratorrechte nicht standardmäßig aktivieren

Git benötigt normalerweise **keine Administratorrechte**. Starte Git Bash deshalb nicht dauerhaft als Administrator.

Ein erhöhtes Terminal kann zu unerwünschten Dateibesitzern oder Berechtigungen führen und erhöht bei versehentlichen Befehlen den möglichen Schaden. Öffne ein Administrator-Terminal nur für konkrete Systemaufgaben, etwa bei bestimmten Installationen oder globalen Konfigurationen.

### Terminaltitel sinnvoll setzen

Windows Terminal zeigt den Titel eines Tabs an. Git Bash setzt oft automatisch den aktuellen Ordner oder Hostnamen. Das ist normalerweise ausreichend.

Bei vielen offenen Tabs hilft es, Tabs eindeutig zu benennen. Nutze dafür im Tab-Kontextmenü die Funktion zum Umbenennen oder lege unterschiedliche Profile für verschiedene Aufgaben an, beispielsweise:

- `Git Bash`
- `Git Bash – Projekte`
- `PowerShell – Verwaltung`

Vermeide jedoch zu viele fast identische Profile. Eine übersichtliche Profilliste ist wertvoller als maximale Anpassbarkeit.

### Quake-Modus als optionale Schnellkonsole

Windows Terminal bietet einen optionalen *Quake-Modus*: Ein Terminal gleitet vom oberen Bildschirmrand ein und aus. Das kann nützlich sein, wenn du sehr häufig kurze Git-Abfragen wie `git status` oder `git log --oneline` ausführst.

Die Funktion ist rein optional. Für Einsteiger ist ein normales Terminalfenster meist übersichtlicher, weil mehrere Tabs und längere Ausgaben leichter nachvollziehbar bleiben.

## Git-Farben im Terminal prüfen

Git verwendet in Git Bash standardmäßig Farben für Statusmeldungen, Branches und Diffs. Prüfe dies in einem Repository:

```bash
git status
```

Typische Farbbedeutungen sind:

- **Rot:** Änderungen sind noch nicht für den Commit vorgemerkt.
- **Grün:** Änderungen liegen bereits in der Staging Area.
- **Weitere Farben:** Abhängig vom Git-Theme und vom jeweiligen Befehl.

Falls Git keine Farben zeigt, prüfe zunächst die Konfiguration:

```bash
git config --global --get color.ui
```

Eine sinnvolle Einstellung ist:

```bash
git config --global color.ui auto
```

`auto` bedeutet: Git verwendet Farben, wenn die Ausgabe in einem interaktiven Terminal erscheint, aber nicht zwingend bei einer Umleitung in eine Datei.

## Grundlegende Funktionsprüfung

Führe nach der Konfiguration diese Prüfung in einem Git-Bash-Tab aus:

```bash
git --version
git config --global --get user.name
git config --global --get user.email
pwd
```

Die Befehle prüfen nacheinander:

1. Git ist erreichbar.
2. Dein Git-Autorenname ist gesetzt.
3. Deine Git-E-Mail-Adresse ist gesetzt.
4. Du befindest dich im erwarteten Arbeitsverzeichnis.

Erstelle anschließend testweise einen Projektordner:

```bash
mkdir -p ~/Projekte/terminal-test
cd ~/Projekte/terminal-test
git init
git status
```

Eine erfolgreiche Ausgabe enthält einen Hinweis auf ein neu initialisiertes Repository und zeigt einen sauberen Arbeitsstand an. Lösche den Testordner später nur dann, wenn du ihn nicht für die folgenden Übungen verwenden möchtest:

```bash
cd ..
rm -rf terminal-test
```

> ⚠️ `rm -rf` löscht Dateien ohne Papierkorb. Prüfe mit `pwd` und `ls` immer zuerst, in welchem Ordner du dich befindest. Auf Windows ist Löschen über den Explorer für Einsteiger oft sicherer.

## Häufige Probleme und Lösungen

### Git Bash fehlt in der Profilliste

**Mögliche Ursache:** Git for Windows wurde nach Windows Terminal installiert oder die automatische Erkennung ist fehlgeschlagen.

**Lösung:**

1. Schließe alle Windows-Terminal-Fenster.
2. Starte Windows Terminal erneut.
3. Prüfe den Installationspfad von Git.
4. Lege bei Bedarf das Profil manuell mit `bash.exe -l -i` an.

### `git` wird in Git Bash nicht gefunden

**Mögliche Ursache:** Die Git-for-Windows-Installation ist unvollständig oder das falsche Programm wird als Profil gestartet.

**Lösung:** Prüfe den Pfad in der Profilkonfiguration. Verwende bevorzugt:

```text
C:\Program Files\Git\bin\bash.exe
```

Starte danach einen neuen Tab und teste erneut:

```bash
git --version
```

### Sonderzeichen oder Umlaute werden falsch dargestellt

**Mögliche Ursache:** Eine ungeeignete Schriftart, ältere Konsoleneinstellungen oder eine problematische Zeichencodierung.

**Lösung:**

1. Wähle im Profil eine moderne Schrift wie **Cascadia Mono**.
2. Aktualisiere Windows Terminal und Git for Windows.
3. Öffne ein neues Git-Bash-Fenster.
4. Prüfe zunächst, ob Dateinamen mit Umlauten im Explorer korrekt gespeichert sind.

Windows Terminal verwendet standardmäßig Unicode-fähige Einstellungen. Vermeide deshalb veraltete Konsolenfenster, wenn moderne Git-Ausgaben und Dateinamen korrekt dargestellt werden sollen.

### Terminal startet im falschen Ordner

**Mögliche Ursache:** Das Profil besitzt ein fest eingetragenes Startverzeichnis oder die Option „In Terminal öffnen“ wurde aus einem anderen Ordner aufgerufen.

**Lösung:** Prüfe im Git-Bash-Profil die Einstellung **Startverzeichnis**. Für einen neutralen Startpunkt eignet sich:

```text
%USERPROFILE%\Projekte
```

### PowerShell findet Git, Git Bash aber nicht — oder umgekehrt

**Mögliche Ursache:** Unterschiedliche `PATH`-Konfigurationen oder eine unvollständige Git-Installation.

**Lösung:** Vergleiche die Befehle in beiden Umgebungen:

```powershell
git --version
```

```bash
git --version
```

Für den Kurs genügt es zunächst, wenn Git Bash zuverlässig funktioniert. Die systemweite `PATH`-Konfiguration wird im nächsten Abschnitt gesondert geprüft.

## Empfehlungen für den weiteren Kurs

Richte Windows Terminal bewusst schlicht und stabil ein:

- Verwende **Git Bash** als gut erreichbares Profil.
- Starte standardmäßig in einem zentralen Projektordner.
- Nutze eine gut lesbare Monospace-Schrift.
- Öffne Repositories über **„In Terminal öffnen“** direkt im jeweiligen Ordner.
- Arbeite normalerweise **ohne Administratorrechte**.
- Prüfe vor riskanten Befehlen stets `git status` und das aktuelle Verzeichnis.

Damit steht eine verlässliche Kommandozeilenumgebung bereit. Im nächsten Schritt prüfst du, ob Git systemweit über die `PATH`-Variable erreichbar ist und wie sich unterschiedliche Shells dabei verhalten.

# Git in der PATH-Variable prüfen

## Lernziel

Nach dieser Einheit kannst du sicher feststellen, ob Git unter Windows 11 systemweit über die `PATH`-Variable erreichbar ist. Du erkennst typische Fehlermeldungen, verstehst den Unterschied zwischen verschiedenen Terminals und weißt, wie du eine fehlerhafte PATH-Konfiguration sauber korrigierst.

---

## Was bedeutet `PATH`?

`PATH` ist eine Windows-Umgebungsvariable. Sie enthält eine geordnete Liste von Verzeichnissen, in denen Windows nach ausführbaren Programmen sucht.

Wenn du in einem Terminal Folgendes eingibst:

```powershell
git --version
```

sucht Windows unter anderem in allen Verzeichnissen aus `PATH` nach einer Datei wie `git.exe`.

Ist das Git-Installationsverzeichnis enthalten, wird Git gefunden und gestartet. Fehlt es, erscheint eine Fehlermeldung wie:

```text
git : Der Begriff „git“ ist entweder nicht als Name eines Cmdlet,
einer Funktion, einer Skriptdatei oder eines ausführbaren Programms erkannt.
```

Die PATH-Variable macht es also möglich, Git aus *jedem beliebigen Ordner* aufzurufen, ohne den vollständigen Programmpfad eingeben zu müssen.

Ohne PATH-Eintrag müsste ein Git-Aufruf beispielsweise so aussehen:

```powershell
& "C:\Program Files\Git\cmd\git.exe" --version
```

Das ist technisch möglich, aber im Alltag unpraktisch.

---

## Git in PowerShell prüfen

Öffne **Windows PowerShell** oder ein PowerShell-Profil im Windows Terminal und führe aus:

```powershell
git --version
```

Bei einer erfolgreichen Installation sieht die Ausgabe ähnlich aus:

```text
git version 2.47.1.windows.1
```

Die genaue Versionsnummer kann bei dir abweichen.

Prüfe anschließend, *welche* ausführbare Datei PowerShell verwendet:

```powershell
Get-Command git
```

Eine typische Ausgabe enthält einen Pfad wie diesen:

```text
CommandType     Name       Version    Source
-----------     ----       -------    ------
Application     git.exe    2.47.1...  C:\Program Files\Git\cmd\git.exe
```

Besonders wichtig ist die Spalte **Source**. Sie zeigt, welche `git.exe` tatsächlich ausgeführt wird.

### Nur den vollständigen Git-Pfad ausgeben

Für eine kompakte Prüfung eignet sich:

```powershell
(Get-Command git).Source
```

Erwartete Ausgabe:

```text
C:\Program Files\Git\cmd\git.exe
```

---

## Git in der Eingabeaufforderung prüfen

Öffne die klassische **Eingabeaufforderung** — `cmd.exe` — und führe aus:

```cmd
git --version
```

Danach kannst du mit `where` prüfen, welche Git-Installation gefunden wird:

```cmd
where git
```

Beispiel:

```text
C:\Program Files\Git\cmd\git.exe
```

Falls mehrere Treffer erscheinen, sind mehrere Git-Programme oder Git-Pfade in deiner PATH-Variable vorhanden:

```text
C:\Program Files\Git\cmd\git.exe
C:\Tools\Git\cmd\git.exe
```

> **Empfehlung:** Verwende nach Möglichkeit nur eine aktive Git-for-Windows-Installation. Mehrere Versionen können zu schwer nachvollziehbaren Unterschieden zwischen Terminal, IDE und Automatisierung führen.

---

## Git in Git Bash prüfen

Öffne **Git Bash** über das Startmenü und führe aus:

```bash
git --version
```

Ergänzend zeigt dieser Befehl den aufgelösten Pfad:

```bash
which git
```

Typische Ausgabe:

```text
/mingw64/bin/git
```

Git Bash verwendet eine Unix-ähnliche Pfaddarstellung. Der angezeigte Pfad entspricht typischerweise einer Datei innerhalb deiner Git-for-Windows-Installation.

Git Bash funktioniert häufig auch dann noch, wenn Git in PowerShell oder CMD nicht gefunden wird. Der Grund: Git Bash startet mit einer eigenen, von Git for Windows vorbereiteten Umgebung. Deshalb ist eine erfolgreiche Prüfung in Git Bash **kein vollständiger Beweis**, dass Git auch in der Windows-PATH-Variable korrekt eingetragen ist.

Prüfe Git daher mindestens einmal zusätzlich in PowerShell oder CMD.

---

## Die PATH-Variable anzeigen

### In PowerShell

Um die PATH-Einträge der aktuellen Sitzung anzuzeigen:

```powershell
$env:Path -split ';'
```

Suche in der Ausgabe nach einem Eintrag wie:

```text
C:\Program Files\Git\cmd
```

Oder filtere direkt nach Git:

```powershell
$env:Path -split ';' | Where-Object { $_ -match 'Git' }
```

Eine typische Ausgabe lautet:

```text
C:\Program Files\Git\cmd
```

### In CMD

In der Eingabeaufforderung kannst du die gesamte Variable ausgeben:

```cmd
echo %PATH%
```

Die Ausgabe ist lang und verwendet Semikolons als Trennzeichen:

```text
C:\Windows\system32;C:\Windows;C:\Program Files\Git\cmd;...
```

---

## Welcher Git-Pfad gehört in PATH?

Bei einer Standardinstallation von **Git for Windows** ist meist dieser Eintrag sinnvoll:

```text
C:\Program Files\Git\cmd
```

Darin befindet sich unter anderem:

```text
C:\Program Files\Git\cmd\git.exe
```

Dieser Pfad stellt Git für PowerShell, CMD, Windows Terminal, PhpStorm und viele andere Windows-Programme bereit.

Manchmal findest du auch:

```text
C:\Program Files\Git\bin
```

oder:

```text
C:\Program Files\Git\mingw64\bin
```

Diese Verzeichnisse können funktionieren, sind aber für den allgemeinen Windows-Einsatz normalerweise nicht die beste erste Wahl. Der Ordner `cmd` ist der übliche und von Git for Windows vorgesehene PATH-Eintrag.

> **Wichtig:** Füge nicht wahllos mehrere Unterordner derselben Git-Installation zu PATH hinzu. Mehrere Treffer für Hilfsprogramme können unerwartete Nebeneffekte verursachen.

---

## Prüfschritt: Git außerhalb des Installationsordners ausführen

Wechsle in einen beliebigen Ordner, der nichts mit Git zu tun hat, etwa dein Benutzerverzeichnis:

```powershell
Set-Location $HOME
git --version
```

Oder in CMD:

```cmd
cd %USERPROFILE%
git --version
```

Wenn Git jetzt erfolgreich ausgeführt wird, funktioniert die PATH-Auflösung unabhängig vom aktuellen Arbeitsordner.

Als zusätzlicher Test kannst du ein Git-Kommando ohne Repository ausführen:

```powershell
git config --global --list
```

Wenn Git erreichbar ist, zeigt der Befehl deine globale Konfiguration an oder bleibt ohne Ausgabe, falls noch keine Werte gesetzt wurden. Es darf dabei keine Meldung erscheinen, dass `git` unbekannt sei.

---

## Häufige Fehlermeldungen richtig einordnen

### „git“ ist nicht erkannt

PowerShell kann beispielsweise melden:

```text
git : Der Begriff „git“ ist nicht als Name eines Cmdlet,
einer Funktion, einer Skriptdatei oder eines ausführbaren Programms erkannt.
```

CMD verwendet oft diese Formulierung:

```text
'git' is not recognized as an internal or external command,
operable program or batch file.
```

**Bedeutung:** Windows findet keine passende `git.exe` über PATH.

Mögliche Ursachen:

- Git for Windows wurde nicht installiert.
- Bei der Installation wurde keine PATH-Integration ausgewählt.
- Das Terminal war bereits geöffnet, bevor Git installiert wurde.
- Der PATH-Eintrag wurde manuell entfernt oder beschädigt.
- Du arbeitest in einer Umgebung mit abweichenden oder eingeschränkten Variablen.

### „git“ wird gefunden, aber die falsche Version startet

Wenn `where git` mehrere Pfade ausgibt, kann eine alte Installation Vorrang haben. Prüfe daher:

```cmd
where git
git --version
```

In PowerShell:

```powershell
Get-Command git -All
```

Die Reihenfolge in PATH ist entscheidend: Windows verwendet im Regelfall den ersten passenden Fund.

### Git funktioniert in Git Bash, aber nicht in PowerShell

Das weist meist auf einen fehlenden oder unvollständigen PATH-Eintrag hin. Git Bash bringt ihre eigene Umgebung mit; PowerShell übernimmt dagegen die Windows-Umgebungsvariablen.

Prüfe in PowerShell:

```powershell
Get-Command git
```

Wird kein Pfad ausgegeben, musst du Git for Windows reparieren oder den PATH-Eintrag ergänzen.

---

## PATH-Konfiguration sicher korrigieren

### Bevorzugter Weg: Git for Windows erneut ausführen

Der zuverlässigste Weg ist meist, den Git-for-Windows-Installer erneut zu starten und die bestehende Installation zu **ändern** oder zu **reparieren**.

Achte im Installationsdialog auf die Option zur PATH-Integration. Wähle die Einstellung, die Git über die Windows-Kommandozeile und Programme von Drittanbietern verfügbar macht. Die Bezeichnung kann je nach Installer-Version leicht variieren, enthält aber typischerweise einen Hinweis auf:

```text
Git from the command line and also from 3rd-party software
```

Diese Auswahl fügt den benötigten Eintrag üblicherweise automatisch hinzu.

### Manueller Weg: PATH-Eintrag ergänzen

Wenn Git korrekt installiert ist, aber der Eintrag fehlt, kannst du ihn manuell ergänzen.

1. Öffne das Startmenü und suche nach **Umgebungsvariablen**.
2. Wähle **Systemumgebungsvariablen bearbeiten**.
3. Klicke im Dialog auf **Umgebungsvariablen**.
4. Wähle unter *Benutzervariablen* oder *Systemvariablen* den Eintrag **Path**.
5. Klicke auf **Bearbeiten**.
6. Klicke auf **Neu**.
7. Trage den Git-Pfad ein:

   ```text
   C:\Program Files\Git\cmd
   ```

8. Bestätige alle Fenster mit **OK**.
9. Schließe alle geöffneten Terminals und öffne ein neues Terminalfenster.

Prüfe anschließend erneut:

```powershell
git --version
(Get-Command git).Source
```

> **Hinweis:** Für einen einzelnen Windows-Benutzer genügt in der Regel ein Eintrag unter den *Benutzervariablen*. Ein Eintrag unter den *Systemvariablen* ist sinnvoll, wenn Git für alle Benutzerkonten des Computers verfügbar sein soll.

---

## Warum muss das Terminal neu gestartet werden?

Umgebungsvariablen werden beim Start eines Prozesses übernommen. Ein bereits geöffnetes PowerShell-, CMD- oder Windows-Terminal-Fenster kennt Änderungen an PATH daher noch nicht automatisch.

Nach einer Installation oder PATH-Änderung gilt:

1. Alle Terminalfenster schließen.
2. Windows Terminal gegebenenfalls vollständig beenden.
3. Ein neues Terminal öffnen.
4. `git --version` erneut ausführen.

Auch PhpStorm sollte neu gestartet werden, wenn es während der Git-Installation bereits geöffnet war. Die IDE übernimmt die Umgebung ebenfalls beim Start.

---

## Prüfung aus PhpStorm heraus

Nachdem Git in PowerShell oder CMD gefunden wird, prüfst du die IDE-Anbindung separat:

1. Öffne in PhpStorm **File → Settings**.
2. Navigiere zu **Version Control → Git**.
3. Kontrolliere das Feld **Path to Git executable**.
4. Klicke auf **Test**.

PhpStorm sollte eine Meldung ähnlich dieser anzeigen:

```text
Git version is 2.47.1.windows.1
```

Falls PhpStorm Git nicht findet, obwohl `git --version` im Terminal funktioniert, kannst du den Pfad direkt eintragen:

```text
C:\Program Files\Git\cmd\git.exe
```

Die explizite Angabe ist besonders hilfreich, wenn mehrere Git-Versionen installiert sind oder PhpStorm mit einer abweichenden Umgebung gestartet wurde.

---

## Kompakte Diagnose-Checkliste

Führe diese Befehle nacheinander in PowerShell aus:

```powershell
git --version
Get-Command git
(Get-Command git).Source
$env:Path -split ';' | Where-Object { $_ -match 'Git' }
```

Eine funktionierende Konfiguration erfüllt diese Kriterien:

- `git --version` gibt eine Git-Version aus.
- `Get-Command git` zeigt eine Anwendung namens `git.exe`.
- Der aufgelöste Pfad verweist auf die gewünschte Git-for-Windows-Installation.
- PATH enthält typischerweise `C:\Program Files\Git\cmd`.
- PhpStorm bestätigt die Git-Version im VCS-Testdialog.

---

## Merksatz

> **Git Bash kann Git kennen, obwohl Windows Git noch nicht über PATH kennt.**  
> Entscheidend für eine zuverlässige Nutzung in PowerShell, CMD, Windows Terminal und PhpStorm ist der erfolgreiche Test mit `git --version` außerhalb von Git Bash.

# Benutzername und E-Mail konfigurieren

## Warum Git einen Namen und eine E-Mail-Adresse braucht

Jeder Git-Commit enthält Angaben darüber, **wer die Änderung erstellt** hat. Git verwendet dafür zwei Konfigurationswerte:

- `user.name` – der sichtbare Autorenname
- `user.email` – die E-Mail-Adresse des Autors

Diese Informationen werden dauerhaft in jeden neuen Commit geschrieben. Sie erscheinen später beispielsweise:

- in `git log`,
- in GitHub-Commitansichten,
- bei Pull Requests und Code Reviews,
- in Release- und Audit-Historien.

> Git prüft nicht, ob Name und E-Mail-Adresse „echt“ sind. Dennoch sollten sie bewusst gewählt werden: Sie sind Teil der nachvollziehbaren Projektgeschichte.

Ein Commit speichert dabei mindestens Autor, Zeitpunkt, Nachricht und Inhalt. Vereinfacht:

```text
Autor: Max Mustermann <max@example.de>
Datum: 2025-03-08
Nachricht: Add validation for registration form
```

---

## Globale Identität für alle Repositories festlegen

Unter Windows 11 wird die Identität normalerweise **global** eingerichtet. Dann gilt sie für alle Git-Repositories des aktuellen Windows-Benutzerkontos.

Öffne Git Bash, PowerShell oder das Terminal in PhpStorm und führe diese Befehle aus:

```bash
git config --global user.name "Max Mustermann"
git config --global user.email "max.mustermann@example.de"
```

Ersetze die Beispielwerte durch deine gewünschte Commit-Identität.

Ein typisches Beispiel mit beruflicher Adresse:

```bash
git config --global user.name "Maria Schneider"
git config --global user.email "maria.schneider@beispielunternehmen.de"
```

Für persönliche Open-Source-Projekte könnte die Konfiguration so aussehen:

```bash
git config --global user.name "Maria Schneider"
git config --global user.email "maria.schneider@example.com"
```

Die Anführungszeichen sind besonders beim Namen sinnvoll, weil er Leerzeichen enthält.

---

## Konfiguration überprüfen

Lies die gerade gesetzten Werte mit folgenden Befehlen aus:

```bash
git config --global user.name
git config --global user.email
```

Die Ausgabe sollte beispielsweise so aussehen:

```text
Maria Schneider
maria.schneider@example.com
```

Alternativ kannst du beide Werte gemeinsam anzeigen:

```bash
git config --global --get-regexp "^user\."
```

Beispielausgabe:

```text
user.name Maria Schneider
user.email maria.schneider@example.com
```

Mit diesem Befehl lässt sich außerdem die gesamte globale Git-Konfiguration prüfen:

```bash
git config --global --list
```

Eine mögliche Ausgabe:

```text
user.name=Maria Schneider
user.email=maria.schneider@example.com
init.defaultbranch=main
```

---

## Wo Git die globale Konfiguration speichert

Git speichert die globale Konfiguration unter Windows in einer Datei im Benutzerprofil. Der Pfad ist üblicherweise:

```text
C:\Users\DeinWindowsBenutzername\.gitconfig
```

Git Bash zeigt denselben Speicherort in Unix-Schreibweise an:

```text
~/.gitconfig
```

Den tatsächlich verwendeten Ursprung eines Konfigurationswerts findest du mit:

```bash
git config --show-origin --get user.name
git config --show-origin --get user.email
```

Eine mögliche Ausgabe in Git Bash:

```text
file:C:/Users/maria/.gitconfig    Maria Schneider
```

Das ist besonders nützlich, wenn mehrere Konfigurationsebenen vorhanden sind.

---

## Die Konfigurationsebenen verstehen

Git kann Werte auf mehreren Ebenen speichern. Für Name und E-Mail sind vor allem diese drei Ebenen relevant:

1. **Systemweit**  
   Gilt für alle Windows-Benutzer und alle Repositories auf dem Computer.

2. **Global**  
   Gilt für alle Repositories eines Windows-Benutzerkontos.

3. **Lokal**  
   Gilt nur für ein bestimmtes Repository.

Die Priorität lautet:

$$
\text{lokal} > \text{global} > \text{systemweit}
$$

Ein lokal gesetzter Wert überschreibt also die globale Einstellung.

In der Praxis ist dieses Vorgehen sinnvoll:

- Eine persönliche Standardidentität wird **global** eingerichtet.
- Für ein Kundenprojekt oder ein Arbeitsrepository wird bei Bedarf eine **lokale** Geschäftsidentität gesetzt.

---

## Unterschiedliche Identitäten für private und berufliche Projekte

Viele Entwicklerinnen und Entwickler verwenden verschiedene E-Mail-Adressen:

- private Adresse für Lernprojekte oder Open Source,
- geschäftliche Adresse für Unternehmensprojekte,
- datenschutzfreundliche GitHub-`noreply`-Adresse für öffentliche Commits.

Angenommen, deine globale Konfiguration ist privat:

```bash
git config --global user.name "Maria Schneider"
git config --global user.email "maria.schneider@example.com"
```

Für ein berufliches Repository wechselst du zuerst in dessen Verzeichnis:

```bash
cd C:\Projekte\kundenportal
```

Dann setzt du die lokale Identität **ohne** `--global`:

```bash
git config user.name "Maria Schneider"
git config user.email "maria.schneider@beispielunternehmen.de"
```

Diese Einstellungen werden in der Datei `.git/config` innerhalb dieses einen Repositories gespeichert.

Prüfe die lokale Konfiguration:

```bash
git config --local --list
```

Oder frage gezielt ab, welche Werte Git für das aktuelle Repository tatsächlich verwendet:

```bash
git config user.name
git config user.email
```

Wichtig: Diese beiden Befehle zeigen den wirksamen Wert an. Git berücksichtigt dabei die Priorität aller Ebenen.

---

## Die Herkunft eines Werts eindeutig prüfen

Wenn unklar ist, ob eine globale oder lokale Einstellung verwendet wird, hilft:

```bash
git config --show-origin --get-regexp "^user\."
```

Beispielausgabe:

```text
file:C:/Users/maria/.gitconfig              user.name Maria Schneider
file:C:/Projekte/kundenportal/.git/config   user.email maria.schneider@beispielunternehmen.de
```

Daran erkennst du:

- Der Name stammt aus der globalen Konfiguration.
- Die E-Mail-Adresse wurde lokal für das Kundenprojekt überschrieben.

Für eine vollständige Übersicht inklusive aller Ebenen verwende:

```bash
git config --list --show-origin
```

---

## GitHub-E-Mail-Adresse richtig zuordnen

Damit GitHub Commits deinem Konto zuordnen kann, muss die im Commit verwendete E-Mail-Adresse zu deinem GitHub-Konto passen.

In GitHub findest du deine hinterlegten E-Mail-Adressen unter:

**Settings → Emails**

Dort kannst du:

- eine E-Mail-Adresse hinzufügen und bestätigen,
- eine primäre Commit-Adresse auswählen,
- die Sichtbarkeit deiner E-Mail-Adresse steuern,
- eine GitHub-`noreply`-Adresse verwenden.

Wenn du eine bestätigte Adresse verwendest, kann GitHub den Commit normalerweise deinem Profil zuordnen. Ohne Zuordnung erscheint der Commit zwar im Repository, wird aber möglicherweise nicht in deinem GitHub-Profil berücksichtigt.

> **Wichtig:** Die Commit-E-Mail-Adresse und die Adresse für die Anmeldung bei GitHub müssen nicht identisch sein. Entscheidend ist, dass die Commit-Adresse im GitHub-Konto hinterlegt und verifiziert ist.

---

## Private E-Mail-Adresse auf GitHub schützen

Bei öffentlichen Repositories ist die E-Mail-Adresse aus Commits grundsätzlich sichtbar. Wer seine private Adresse nicht in einer öffentlichen Git-Historie veröffentlichen möchte, kann die von GitHub bereitgestellte `noreply`-Adresse nutzen.

Sie hat typischerweise dieses Format:

```text
12345678+benutzername@users.noreply.github.com
```

Oder, abhängig von den GitHub-Einstellungen:

```text
benutzername@users.noreply.github.com
```

Die genaue Adresse zeigt GitHub im Bereich **Settings → Emails** an. Übernimm sie exakt in deine Git-Konfiguration:

```bash
git config --global user.email "12345678+benutzername@users.noreply.github.com"
```

Diese Variante bietet zwei Vorteile:

- GitHub kann Commits weiterhin deinem Konto zuordnen.
- Deine persönliche E-Mail-Adresse erscheint nicht in öffentlichen Commit-Daten.

Für berufliche oder interne Repositories können allerdings Unternehmensrichtlinien verlangen, dass die geschäftliche Adresse verwendet wird. Prüfe deshalb immer die Vorgaben des Teams.

---

## Name und E-Mail nachträglich ändern

Eine globale Einstellung lässt sich jederzeit überschreiben:

```bash
git config --global user.name "Neuer Name"
git config --global user.email "neue.adresse@example.com"
```

Auch eine lokale Einstellung kann geändert werden:

```bash
git config user.name "Neuer Name"
git config user.email "neue.adresse@beispielunternehmen.de"
```

Die Änderung gilt jedoch nur für **zukünftige Commits**. Bereits vorhandene Commits behalten ihre gespeicherten Autorendaten.

### Den letzten noch nicht veröffentlichten Commit korrigieren

Wenn nur der letzte Commit die falsche Identität enthält und noch nicht veröffentlicht wurde, kannst du ihn mit der aktuellen Identität neu erstellen:

```bash
git commit --amend --reset-author --no-edit
```

Dabei gilt:

- `--amend` ersetzt den letzten Commit.
- `--reset-author` übernimmt den aktuell konfigurierten Namen und die aktuelle E-Mail-Adresse.
- `--no-edit` behält die bisherige Commit-Nachricht.

> ⚠️ Ändere veröffentlichte Commits nicht leichtfertig. Eine nachträgliche Änderung erzeugt neue Commit-Hashes und kann die Zusammenarbeit im Team stören.

Die systematische Korrektur von Autorendaten in mehreren oder bereits veröffentlichten Commits wird später beim Thema Historienbereinigung behandelt.

---

## Typische Fehlermeldung: „Author identity unknown“

Ohne konfigurierte Identität verweigert Git das Erstellen eines Commits häufig mit einer Meldung wie:

```text
Author identity unknown

Please tell me who you are.

Run

  git config --global user.email "you@example.com"
  git config --global user.name "Your Name"

to set your account's default identity.
```

Die Lösung ist genau die globale Konfiguration:

```bash
git config --global user.name "Dein Name"
git config --global user.email "deine.adresse@example.com"
```

Prüfe danach die Werte:

```bash
git config --global --get-regexp "^user\."
```

Versuche anschließend erneut zu committen.

---

## Commit-Identität ist keine Anmeldung

Ein häufiger Anfängerfehler besteht darin, `user.name` und `user.email` mit GitHub-Zugangsdaten zu verwechseln.

Die Git-Konfiguration beschreibt nur die **Autorenangabe eines Commits**:

```bash
git config --global user.name "Maria Schneider"
git config --global user.email "maria.schneider@example.com"
```

Sie authentifiziert dich **nicht** bei GitHub.

Für das Klonen, Pushen und Abrufen privater Repositories brauchst du zusätzlich eine Authentifizierung, beispielsweise über:

- HTTPS mit Personal Access Token und Git Credential Manager,
- SSH mit einem SSH-Schlüssel,
- die GitHub-Anmeldung in PhpStorm.

Diese Themen folgen im Kapitel zu GitHub-Konto, Remotes und Authentifizierung.

---

## Konfiguration in PhpStorm kontrollieren

PhpStorm verwendet für Git-Commits in der Regel die Git-Konfiguration des aktiven Repositories. Deshalb ist die Konfiguration über das Terminal zuverlässig und transparent.

Du kannst die Werte auch im integrierten Terminal von PhpStorm prüfen:

```bash
git config user.name
git config user.email
```

Achte besonders darauf, wenn du mehrere Projekte gleichzeitig geöffnet hast. Jedes Repository kann eigene lokale Werte in `.git/config` besitzen.

Vor einem wichtigen Commit kannst du im Terminal kontrollieren, welche Identität Git wirklich verwendet:

```bash
git var GIT_AUTHOR_IDENT
```

Eine mögliche Ausgabe:

```text
Maria Schneider <maria.schneider@beispielunternehmen.de> 1741435200 +0100
```

Das ist die Identität, die Git für einen neuen Commit als Autor verwenden würde.

---

## Empfohlene Einrichtung für den Kurs

Für die Übungen dieses Kurses genügt eine globale Konfiguration. Verwende entweder eine bestätigte GitHub-Adresse oder deine GitHub-`noreply`-Adresse:

```bash
git config --global user.name "Dein Name"
git config --global user.email "deine-github-adresse@users.noreply.github.com"
```

Prüfe danach:

```bash
git config --global --get-regexp "^user\."
```

Wenn beide Werte korrekt ausgegeben werden, ist deine Commit-Identität eingerichtet. Jeder kommende Commit kann nun eindeutig einer Autorin oder einem Autor zugeordnet werden.

# Standard-Branch und Standard-Editor festlegen

## Ziel: konsistente Vorgaben für neue Repositories und Git-Texte

Zwei globale Einstellungen erleichtern die tägliche Arbeit erheblich:

- **Standard-Branch**: Git verwendet bei neu initialisierten Repositories automatisch einen gewünschten Branch-Namen, meist `main`.
- **Standard-Editor**: Git öffnet bei Commit-Nachrichten, Merge-Nachrichten oder interaktiven Rebase-Vorgängen einen Editor, den du zuverlässig bedienen kannst.

Diese Einstellungen gelten zunächst für *deinen Windows-Benutzeraccount* und werden in der globalen Git-Konfiguration gespeichert.

> **Wichtig:** Die Wahl von `main` ist heute weit verbreitet, aber keine technische Pflicht. Übernimm im Team immer die vereinbarte Branch-Konvention.

---

## Den Standard-Branch festlegen

Historisch verwendete Git für den ersten Branch häufig `master`. Moderne Git-Versionen und viele Hosting-Plattformen verwenden standardmäßig `main`. Mit `init.defaultBranch` legst du fest, welchen Namen **zukünftige** lokale Repositories nach `git init` erhalten.

Öffne Git Bash, PowerShell oder das Terminal in PhpStorm und führe aus:

```bash
git config --global init.defaultBranch main
```

Prüfe anschließend den gespeicherten Wert:

```bash
git config --global --get init.defaultBranch
```

Die Ausgabe sollte lauten:

```text
main
```

### Wirkung beim nächsten `git init`

Lege testweise ein neues Verzeichnis an und initialisiere es:

```bash
mkdir git-branch-test
cd git-branch-test
git init
```

Git bestätigt je nach Version beispielsweise:

```text
Initialized empty Git repository in C:/Users/dein-name/git-branch-test/.git/
```

Solange noch kein Commit existiert, zeigt `git branch` unter Umständen keinen lokalen Branch an. Nach dem ersten Commit prüfst du den Namen mit:

```bash
git branch --show-current
```

Erwartete Ausgabe:

```text
main
```

### Was diese Einstellung *nicht* verändert

`init.defaultBranch` benennt keine bestehenden Branches um. Sie beeinflusst außerdem weder bereits geklonte Repositories noch die Standard-Branches auf GitHub.

Für ein vorhandenes lokales Repository kannst du den aktuellen Branch bei Bedarf umbenennen:

```bash
git branch -m master main
```

Wenn der Branch bereits auf GitHub veröffentlicht wurde, müssen auch Remote-Branch, Standard-Branch-Einstellung auf GitHub und gegebenenfalls Pull Requests berücksichtigt werden. Das ist eine Teamentscheidung und sollte nicht spontan in einem gemeinsam genutzten Repository erfolgen.

---

## Den Standard-Editor verstehen

Git benötigt einen Editor, sobald Text eingegeben oder bestätigt werden muss, etwa für:

- Commit-Nachrichten ohne `-m`,
- Merge-Commit-Nachrichten,
- `git revert`,
- annotierte Tags,
- interaktive Rebase-Pläne,
- Konfliktlösungen mit fortgesetztem Rebase.

Ohne eigene Konfiguration verwendet Git for Windows oft **Vim**. Vim ist leistungsfähig, aber für Einsteiger ungewohnt: Ein versehentlich geöffneter Editor kann dann wie ein „hängender“ Git-Befehl wirken.

Der zentrale Konfigurationswert lautet:

```text
core.editor
```

---

## Einen geeigneten Editor auswählen

### Option 1: Windows-Editor für einen einfachen Einstieg

Für einen unkomplizierten Start kannst du den vorinstallierten Editor Notepad festlegen:

```bash
git config --global core.editor notepad.exe
```

Diese Wahl ist besonders geeignet, wenn du Git zunächst in der Kommandozeile lernst und nur Commit-Nachrichten bearbeiten möchtest.

**Vorteile**

- Auf jedem Windows-11-System verfügbar
- Keine zusätzliche Installation
- Einfach zu bedienen

**Grenzen**

- Keine Syntaxhervorhebung
- Nicht ideal für umfangreiche Rebase-Pläne oder längere Texte

---

### Option 2: Visual Studio Code als Git-Editor

Wenn Visual Studio Code installiert ist und der Befehl `code` in der PATH-Variable verfügbar ist, ist dies eine sehr gute allgemeine Wahl:

```bash
git config --global core.editor "code --wait"
```

Die Option `--wait` ist entscheidend: Git wartet dadurch, bis das geöffnete Dokument geschlossen wurde. Ohne diese Option würde Git den nächsten Schritt möglicherweise ausführen, bevor du die Nachricht gespeichert hast.

Prüfe zuerst, ob Visual Studio Code aus dem Terminal erreichbar ist:

```bash
code --version
```

Wenn eine Versionsnummer erscheint, ist der Befehl verfügbar.

> **Hinweis:** Ist `code` nicht bekannt, installiere Visual Studio Code erneut und aktiviere dabei die Option, den Befehl zur PATH-Variable hinzuzufügen. Danach muss das Terminal neu gestartet werden.

---

### Option 3: PhpStorm im normalen Git-Workflow verwenden

Für Commits über die PhpStorm-Oberfläche ist `core.editor` meist nicht relevant: PhpStorm zeigt eigene Dialoge für Commit-Nachrichten, Merge-Vorgänge und interaktive Rebase-Aktionen an.

Das bedeutet:

- **Git-Befehle im Terminal** verwenden den unter `core.editor` festgelegten Editor.
- **Git-Aktionen in PhpStorm** verwenden normalerweise die integrierten PhpStorm-Werkzeuge.

Für die meisten PHP-Projekte ist daher eine praktische Kombination:

- PhpStorm für tägliche Commits, Diffs, Merges und Reviews,
- ein einfacher Terminal-Editor wie Notepad oder Visual Studio Code als Rückfalloption für reine CLI-Befehle.

PhpStorm selbst als globalen Git-Texteditor einzurichten, ist möglich, aber nur sinnvoll, wenn ein funktionierender Kommandozeilen-Starter mit Warteoption eingerichtet wurde. Für den Einstieg erhöht das unnötig die Komplexität.

---

## Die aktuelle Editor-Konfiguration prüfen

Mit folgendem Befehl liest du den effektiven globalen Wert aus:

```bash
git config --global --get core.editor
```

Beispielausgabe für Notepad:

```text
notepad.exe
```

Oder für Visual Studio Code:

```text
code --wait
```

Um zusätzlich zu sehen, *aus welcher Konfigurationsdatei* ein Wert stammt, verwende:

```bash
git config --show-origin --get core.editor
```

Eine typische Ausgabe unter Windows lautet:

```text
file:C:/Users/dein-name/.gitconfig    code --wait
```

Die globale Konfiguration liegt üblicherweise in:

```text
C:\Users\dein-name\.gitconfig
```

Du solltest diese Datei normalerweise nicht manuell bearbeiten. `git config` setzt Werte korrekt und vermeidet Syntaxfehler.

---

## Die Editor-Konfiguration praktisch testen

Lege ein kleines Test-Repository an oder verwende ein Übungsrepository. Erstelle eine Datei und füge sie zum Index hinzu:

```bash
echo Test > editor-test.txt
git add editor-test.txt
```

Starte dann einen Commit **ohne** die Option `-m`:

```bash
git commit
```

Git öffnet nun den konfigurierten Editor mit einer Vorlage für die Commit-Nachricht.

Schreibe beispielsweise:

```text
test: Editor-Konfiguration prüfen
```

Speichere die Datei und schließe den Editor. Anschließend sollte Git den Commit abschließen.

Prüfe die Historie:

```bash
git log --oneline -1
```

Beispiel:

```text
a1b2c3d test: Editor-Konfiguration prüfen
```

### Falls Git scheinbar wartet

Wenn ein Git-Befehl nicht weiterläuft, ist meist ein Editor geöffnet und wartet auf Eingabe. Das ist kein Fehler.

- **Notepad:** Nachricht speichern und Fenster schließen.
- **Visual Studio Code:** Datei speichern und den Editor-Tab oder das Fenster schließen.
- **Vim:** Mit `Esc`, dann `:wq` und `Enter` speichern und beenden. Mit `Esc`, dann `:q!` und `Enter` ohne Speichern abbrechen.

---

## Konfigurationshierarchie beachten

Git liest Einstellungen aus mehreren Ebenen. Ein lokaler Repository-Wert kann deine globale Einstellung überschreiben.

| Ebene | Gültigkeit | Beispiel |
|---|---|---|
| System | Alle Benutzer des Computers | Git-for-Windows-Installation |
| Global | Dein Windows-Benutzerkonto | `C:\Users\dein-name\.gitconfig` |
| Lokal | Ein bestimmtes Repository | `.git\config` |
| Worktree | Ein einzelner Arbeitsbaum | Spezielle Mehr-Worktree-Konfiguration |

Zeige alle gesetzten Werte inklusive Herkunft an:

```bash
git config --list --show-origin
```

Ist in einem bestimmten Repository ein anderer Editor gesetzt, prüfst du ihn mit:

```bash
git config --local --get core.editor
```

Einen lokalen Wert entfernst du bei Bedarf so:

```bash
git config --local --unset core.editor
```

Danach greift wieder die globale Einstellung.

---

## Umgebungsvariablen können den Editor übersteuern

In seltenen Fällen wird `core.editor` ignoriert, weil eine Umgebungsvariable einen anderen Editor vorgibt. Die wichtigsten Variablen sind:

1. `GIT_EDITOR`
2. `core.editor`
3. `VISUAL`
4. `EDITOR`

Die weiter oben stehende Einstellung hat Vorrang. Prüfe in Git Bash beispielsweise:

```bash
echo $GIT_EDITOR
echo $VISUAL
echo $EDITOR
```

In PowerShell lautet die Abfrage:

```powershell
$env:GIT_EDITOR
$env:VISUAL
$env:EDITOR
```

Ist `GIT_EDITOR` gesetzt, hat diese Variable Vorrang vor `core.editor`. Für eine dauerhaft nachvollziehbare Konfiguration ist `git config --global core.editor ...` in den meisten Fällen die bessere Wahl.

---

## Empfohlene Grundkonfiguration für diesen Kurs

Für eine moderne, einheitliche Ausgangslage:

```bash
git config --global init.defaultBranch main
git config --global core.editor notepad.exe
```

Wenn du Visual Studio Code verwendest, ersetze die zweite Zeile durch:

```bash
git config --global core.editor "code --wait"
```

Kontrolliere beide Werte anschließend:

```bash
git config --global --get init.defaultBranch
git config --global --get core.editor
```

Damit ist Git auf Windows 11 so vorbereitet, dass neue lokale Repositories mit `main` beginnen und textbasierte Git-Aktionen in einem beherrschbaren Editor geöffnet werden.

# Credential Manager einrichten

## Ziel dieser Einrichtung

Der **Git Credential Manager** — kurz *GCM* — verwaltet Zugangsdaten für Git-Server sicher. Unter Windows 11 speichert er Anmeldungen normalerweise im **Windows-Anmeldeinformationsmanager** und verhindert, dass du Benutzername, Token oder Passwort bei jedem `git pull` und `git push` erneut eingeben musst. 🔐

Für GitHub wird der Credential Manager vor allem bei **HTTPS-Remotes** verwendet:

```text
https://github.com/beispielkonto/mein-projekt.git
```

Bei SSH-Remotes übernimmt dagegen der SSH-Agent die Authentifizierung. Dazu mehr im Kapitel über Remotes und Authentifizierung.

> **Wichtig:** GitHub akzeptiert für Git-Operationen über HTTPS kein Kontopasswort mehr. Stattdessen verwendest du eine Browser-Anmeldung über den Credential Manager oder einen Personal Access Token.

---

## Was der Credential Manager tut

Der Credential Manager vermittelt zwischen Git, dem Git-Hoster und der sicheren Windows-Anmeldeverwaltung.

1. Git benötigt Zugang zu einem geschützten Remote-Repository.
2. Git ruft den konfigurierten Credential Helper auf.
3. Der Credential Manager prüft, ob bereits gültige Zugangsdaten existieren.
4. Falls nicht, öffnet er normalerweise den Browser zur Anmeldung.
5. Nach erfolgreicher Anmeldung speichert Windows die erhaltene Berechtigung sicher.
6. Git kann künftig auf das Repository zugreifen, ohne erneut nach Zugangsdaten zu fragen.

Der Ablauf gilt nicht nur für GitHub, sondern unter anderem auch für Azure DevOps, GitLab und Bitbucket — abhängig von deren Konfiguration.

---

## Voraussetzung: Git for Windows mit Credential Manager

Bei der Installation von **Git for Windows** sollte die Option für den **Git Credential Manager** aktiviert sein. In aktuellen Git-for-Windows-Versionen ist dies üblicherweise die empfohlene Standardauswahl.

Prüfe zunächst, ob Git verfügbar ist:

```bash
git --version
```

Prüfe anschließend, welcher Credential Helper konfiguriert ist:

```bash
git config --show-origin --get-all credential.helper
```

Eine typische Ausgabe unter Windows sieht ähnlich aus:

```text
file:C:/Program Files/Git/etc/gitconfig    manager
```

Der Wert `manager` bedeutet, dass Git den modernen Git Credential Manager verwendet.

> Die genaue Dateiposition kann je nach Installation abweichen. Entscheidend ist der Wert `manager`, nicht der exakte Pfad.

---

## Credential Manager aktivieren

Falls keine Ausgabe erscheint oder ein anderer Helper eingetragen ist, kannst du den Credential Manager für dein Benutzerkonto aktivieren:

```bash
git config --global credential.helper manager
```

Danach kontrollierst du die Einstellung erneut:

```bash
git config --global --get credential.helper
```

Erwartete Ausgabe:

```text
manager
```

Die Option `--global` speichert die Einstellung in deiner persönlichen Git-Konfiguration. Unter Windows liegt diese normalerweise in:

```text
C:\Users\<Benutzername>\.gitconfig
```

Du kannst die Konfigurationsquelle vollständig anzeigen lassen:

```bash
git config --global --list --show-origin
```

---

## Sichere Speicherung unter Windows verstehen

Der Credential Manager legt Zugangsdaten nicht im Repository und auch nicht in einer Projektdatei ab. Die sichere Speicherung erfolgt im **Windows-Anmeldeinformationsmanager**.

Du öffnest ihn über die Windows-Suche:

1. Drücke die Windows-Taste.
2. Suche nach `Anmeldeinformationsverwaltung`.
3. Öffne **Anmeldeinformationsverwaltung**.
4. Wähle **Windows-Anmeldeinformationen**.

Dort können Einträge erscheinen, die sich auf GitHub oder andere Git-Dienste beziehen, beispielsweise:

```text
git:https://github.com
```

Die genaue Bezeichnung kann abhängig von GCM-Version, Anmeldeverfahren und Git-Hoster variieren.

### Was du dort tun darfst — und was nicht

| Aktion | Zweck | Empfehlung |
|---|---|---|
| Eintrag ansehen | Gespeicherte Git-Anmeldung prüfen | Unbedenklich |
| Eintrag entfernen | Defekte oder falsche Anmeldung zurücksetzen | Sinnvoll bei Authentifizierungsproblemen |
| Eintrag bearbeiten | Zugangsdaten manuell ersetzen | Nur bei klarer Ursache |
| Token kopieren oder weitergeben | Geheimnis offenlegen | Niemals |
| Zugangsdaten in Dateien speichern | Sicherheitsrisiko | Niemals |

> Entfernst du einen Eintrag, werden keine Repository-Dateien und keine Commits gelöscht. Bei der nächsten geschützten HTTPS-Operation fordert Git lediglich eine neue Anmeldung an.

---

## Die erste Anmeldung bei GitHub durchführen

Die eigentliche Anmeldung erfolgt beim ersten Zugriff auf ein **privates** GitHub-Repository per HTTPS.

Wechsle in ein vorhandenes lokales Repository:

```bash
cd C:\Projekte\mein-projekt
```

Prüfe die Remote-URL:

```bash
git remote -v
```

Eine HTTPS-Verbindung sieht beispielsweise so aus:

```text
origin  https://github.com/beispielkonto/mein-projekt.git (fetch)
origin  https://github.com/beispielkonto/mein-projekt.git (push)
```

Starte dann eine Operation, die Zugriff auf GitHub benötigt:

```bash
git fetch origin
```

Falls noch keine gültige Anmeldung gespeichert ist, passiert in der Regel Folgendes:

1. Git startet den Credential Manager.
2. Ein Browserfenster öffnet sich.
3. Du meldest dich bei GitHub an.
4. GitHub fragt gegebenenfalls nach einer Freigabe für den Git Credential Manager.
5. Nach erfolgreicher Bestätigung kehrst du zur Git Bash zurück.
6. `git fetch` wird ausgeführt.

Bei aktivierter Zwei-Faktor-Authentifizierung bestätigst du die Anmeldung zusätzlich mit deinem zweiten Faktor.

### Alternative: Zugriff mit einem privaten Repository testen

Wenn du noch kein lokales Repository besitzt, kannst du die Verbindung mit einem Repository testen, auf das dein GitHub-Konto Zugriff hat:

```bash
git ls-remote https://github.com/<BENUTZER>/<PRIVATES-REPOSITORY>.git
```

Ersetze die Platzhalter durch deinen GitHub-Benutzernamen und den Namen eines privaten Repositorys.

Bei Erfolg listet Git Referenzen auf, beispielsweise:

```text
a1b2c3d4e5f6...    HEAD
a1b2c3d4e5f6...    refs/heads/main
```

Ein öffentliches Repository ist für diesen Test weniger geeignet, weil es ohne Anmeldung lesbar sein kann.

---

## Browser-Anmeldung und Token unterscheiden

Der Credential Manager kann die Anmeldung oft direkt über den Browser durchführen. Das ist für den Einstieg die komfortabelste und sicherste Methode.

Es gibt jedoch Situationen, in denen Git nach einem Benutzernamen und einem Passwort fragt. Bei GitHub gilt dann:

- Als **Benutzername** verwendest du deinen GitHub-Benutzernamen.
- Als **Passwort** verwendest du einen Personal Access Token.
- Dein normales GitHub-Kontopasswort funktioniert dafür nicht.

Ein Token ist ein geheimes Zugangsmittel. Behandle ihn mindestens so sorgfältig wie ein Passwort.

### Wann ein Token erforderlich sein kann

Ein Personal Access Token kann sinnvoll oder notwendig sein, wenn:

- die Browser-Anmeldung nicht funktioniert,
- du ohne grafische Oberfläche arbeitest,
- ein Unternehmensnetzwerk Browser-Weiterleitungen blockiert,
- ein spezieller Automatisierungszugang eingerichtet wird,
- du einen Git-Hoster verwendest, für den kein vollständiger Browser-Flow verfügbar ist.

Für die alltägliche Arbeit auf einem persönlichen Windows-11-PC sollte die Browser-Anmeldung über GCM normalerweise bevorzugt werden.

---

## Unsichere Credential Helper vermeiden

Git unterstützt mehrere Credential Helper. Nicht alle speichern Geheimnisse gleich sicher.

### Der unsichere `store`-Helper

Dieser Befehl ist für normale Arbeitsumgebungen **nicht geeignet**:

```bash
git config --global credential.helper store
```

Der Helper `store` schreibt Zugangsdaten im Klartext in eine Datei, typischerweise nach:

```text
C:\Users\<Benutzername>\.git-credentials
```

Dort könnten Token im Klartext stehen. Jeder Prozess oder Benutzer mit ausreichendem Dateizugriff könnte sie potenziell auslesen.

Wenn `store` versehentlich konfiguriert wurde, entferne die Einstellung:

```bash
git config --global --unset-all credential.helper
```

Aktiviere danach wieder den Windows Credential Manager:

```bash
git config --global credential.helper manager
```

Falls die Datei `.git-credentials` existiert und sensible Daten enthält, lösche sie erst, nachdem du geprüft hast, dass sie nicht mehr benötigt wird. Widerrufe anschließend den möglicherweise enthaltenen Token auf GitHub.

### Der `cache`-Helper

Der Helper `cache` hält Zugangsdaten nur vorübergehend im Speicher. Er ist unter Linux häufiger anzutreffen, bietet unter Windows aber meist keinen Vorteil gegenüber dem Credential Manager.

```bash
git config --global credential.helper cache
```

Auch diese Einstellung solltest du für diesen Kurs nicht verwenden. Der empfohlene Wert bleibt:

```bash
git config --global credential.helper manager
```

---

## Credential Manager über die Kommandozeile prüfen

Zusätzlich zur Git-Konfiguration kannst du prüfen, ob der Credential Manager grundsätzlich erreichbar ist:

```bash
git credential-manager --version
```

Je nach Git-for-Windows-Version kann die Ausgabe beispielsweise eine Versionsnummer enthalten:

```text
2.x.x
```

Für eine Diagnose stellt GCM in aktuellen Versionen häufig folgenden Befehl bereit:

```bash
git credential-manager diagnose
```

Die Diagnose kann Systeminformationen und Konfigurationsdetails erfassen. Teile die Ausgabe nicht ungeprüft öffentlich, etwa in Issues oder Chat-Nachrichten: Sie kann technische Informationen über deine Umgebung enthalten.

---

## Gespeicherte GitHub-Anmeldung zurücksetzen

Wenn Git wiederholt den falschen Account verwendet, ein Token abgelaufen ist oder eine Anmeldung fehlschlägt, ist ein kontrolliertes Zurücksetzen meist der sauberste Weg.

### Methode 1: Windows-Anmeldeinformationsverwaltung

1. Öffne **Anmeldeinformationsverwaltung** über die Windows-Suche.
2. Wähle **Windows-Anmeldeinformationen**.
3. Suche nach Einträgen für GitHub oder nach Einträgen, die mit `git:` beginnen.
4. Entferne den passenden Eintrag.
5. Führe im Repository erneut `git fetch` oder `git push` aus.
6. Melde dich im Browser mit dem korrekten GitHub-Konto an.

### Methode 2: Zugangsdaten gezielt ablehnen

Du kannst Git auch anweisen, eine bestimmte HTTPS-Anmeldung zu verwerfen:

```bash
printf "protocol=https\nhost=github.com\n\n" | git credential reject
```

In Git Bash funktioniert `printf` direkt. Anschließend fordert Git beim nächsten geschützten Zugriff neue Zugangsdaten an.

> Wenn mehrere GitHub-Konten, Organisationsrichtlinien oder unterschiedliche Hosts beteiligt sind, ist die Windows-Anmeldeinformationsverwaltung oft leichter nachzuvollziehen.

---

## Mehrere GitHub-Konten verwenden

Viele Entwicklerinnen und Entwickler nutzen beispielsweise ein privates GitHub-Konto und ein Organisationskonto. Der Credential Manager kann mehrere Anmeldungen verwalten, aber die Zuordnung muss klar bleiben.

Für HTTPS ist wichtig:

- Git erkennt primär den Host, etwa `github.com`.
- Mehrere Konten auf demselben Host können zu unerwarteten Anmeldungen führen.
- Ein privater Account darf nicht versehentlich für ein Unternehmensrepository verwendet werden.
- Organisationen können zusätzliche Sicherheitsrichtlinien wie SSO verlangen.

Prüfe vor einem Push immer die Zieladresse:

```bash
git remote -v
```

Wenn erforderlich, kannst du für ein Repository eine andere Remote-URL setzen:

```bash
git remote set-url origin https://github.com/<ORGANISATION>/<REPOSITORY>.git
```

Bei regelmäßigem Arbeiten mit mehreren Konten ist SSH häufig übersichtlicher, weil unterschiedliche Schlüssel gezielt verschiedenen Konten zugeordnet werden können. Dieses Thema folgt später im Kurs.

---

## GitHub-Single-Sign-On beachten

Organisationen auf GitHub können Single Sign-On über einen Identitätsanbieter verlangen. In diesem Fall reicht eine allgemeine GitHub-Anmeldung möglicherweise nicht aus.

Typische Hinweise:

- Du kannst dich bei GitHub anmelden, aber ein Organisationsrepository nicht lesen oder pushen.
- GitHub meldet, dass eine SSO-Autorisierung erforderlich ist.
- Ein Token ist vorhanden, aber nicht für die Organisation freigegeben.

Lösung:

1. Öffne GitHub im Browser.
2. Melde dich mit dem richtigen Konto an.
3. Folge der SSO-Aufforderung deiner Organisation.
4. Autorisiere gegebenenfalls den verwendeten Token für die Organisation.
5. Führe `git fetch` oder `git push` erneut aus.

Bei Unternehmenskonten gelten zusätzlich die Sicherheitsvorgaben deiner Organisation. Umgehungen durch private Tokens oder fremde Konten sind keine gute Lösung.

---

## Zusammenspiel mit PhpStorm

PhpStorm kann Git auf zwei Ebenen nutzen:

- **Git-Kommandozeile:** PhpStorm ruft das installierte Git-Programm auf. HTTPS-Vorgänge können dabei den Git Credential Manager verwenden.
- **GitHub-Integration:** PhpStorm kann zusätzlich eine eigene GitHub-Anmeldung verwalten, etwa für Pull Requests, Issues oder Repository-Ansichten.

Das bedeutet:

- Eine erfolgreiche GitHub-Anmeldung in PhpStorm garantiert nicht automatisch, dass Git Bash bereits Zugangsdaten besitzt.
- Eine funktionierende Anmeldung über GCM garantiert nicht automatisch, dass PhpStorm für GitHub-Funktionen angemeldet ist.
- Für `fetch`, `pull` und `push` über HTTPS ist der Credential Manager die zentrale sichere Grundlage.

Prüfe in PhpStorm unter **Datei → Einstellungen → Versionskontrolle → Git**, ob der Pfad zu Git korrekt ist. Verwende dort die Schaltfläche **Test**, um die Git-Installation zu prüfen.

---

## Häufige Probleme und Lösungen

### Git fragt bei jeder Aktion erneut nach Zugangsdaten

Prüfe zuerst den konfigurierten Helper:

```bash
git config --show-origin --get-all credential.helper
```

Falls `manager` fehlt, setze ihn erneut:

```bash
git config --global credential.helper manager
```

Prüfe außerdem, ob du tatsächlich HTTPS verwendest:

```bash
git remote -v
```

Bei einer SSH-URL wie dieser ist der Credential Manager nicht zuständig:

```text
git@github.com:beispielkonto/mein-projekt.git
```

### GitHub lehnt Benutzername und Passwort ab

Verwende nicht dein normales GitHub-Passwort. Starte möglichst erneut den Browser-Flow, indem du die gespeicherten GitHub-Anmeldedaten im Windows-Anmeldeinformationsmanager entfernst.

Falls ein Token verlangt wird, verwende einen gültigen Personal Access Token mit den notwendigen Berechtigungen.

### Der Browser öffnet sich nicht

Mögliche Ursachen sind restriktive Unternehmensrichtlinien, blockierte Browser-Protokolle oder eine beschädigte GCM-Installation.

Prüfe zunächst die Version:

```bash
git credential-manager --version
```

Führe anschließend eine Git-Operation direkt in Git Bash aus:

```bash
git fetch origin
```

Erscheint dort eine konkrete Fehlermeldung, notiere sie vollständig. Aktualisiere bei Bedarf Git for Windows über den offiziellen Installer und achte darauf, dass der Git Credential Manager mitinstalliert bleibt.

### Ein falsches GitHub-Konto wird verwendet

1. Entferne die GitHub-bezogenen Einträge im Windows-Anmeldeinformationsmanager.
2. Kontrolliere die Remote-URL mit `git remote -v`.
3. Führe `git fetch origin` aus.
4. Melde dich im Browser mit dem gewünschten Konto an.

### Push wird trotz erfolgreicher Anmeldung abgelehnt

Eine erfolgreiche Anmeldung bestätigt nur deine Identität. Sie bedeutet nicht automatisch, dass du Schreibrechte besitzt.

Prüfe:

- Ist die Remote-URL korrekt?
- Hast du Schreibrechte für das Repository?
- Pushst du auf einen geschützten Branch?
- Erfordert die Organisation SSO?
- Wurde der Branch auf GitHub inzwischen verändert?

Bei fehlenden Rechten kann eine Meldung wie `Permission denied` oder `Write access not granted` erscheinen. Das ist kein Credential-Manager-Fehler, sondern ein Berechtigungs- oder Workflow-Thema.

---

## Sicherheitsregeln für Zugangsdaten

Behalte diese Regeln als feste Routine bei:

- **Speichere Tokens nie in Quellcodedateien.**
- **Committe niemals Dateien mit Zugangsdaten.**
- **Teile Tokens nicht in Chat-Nachrichten, Screenshots oder Tickets.**
- **Verwende den Credential Manager statt Klartextspeicherung.**
- **Lösche nicht mehr benötigte Tokens auf GitHub.**
- **Aktiviere Zwei-Faktor-Authentifizierung für dein GitHub-Konto.**
- **Widerrufe und ersetze einen Token sofort, wenn er versehentlich veröffentlicht wurde.**

Ein Token, der in einem Commit gelandet ist, gilt als kompromittiert — auch wenn der Commit später gelöscht wird. Die Wiederherstellung und Bereinigung solcher Fälle wird in einem späteren Kapitel ausführlich behandelt.

---

## Abschlussprüfung

Führe diese Prüfungen aus:

```bash
git --version
```

```bash
git config --show-origin --get-all credential.helper
```

```bash
git credential-manager --version
```

Die Credential-Helper-Konfiguration sollte `manager` enthalten.

Prüfe anschließend in einem Repository mit HTTPS-Remote:

```bash
git remote -v
```

```bash
git fetch origin
```

Wenn der Zugriff ohne wiederholte Passwortabfrage gelingt und keine Zugangsdaten im Klartext gespeichert wurden, ist der Credential Manager korrekt eingerichtet. ✅

# Zeilenenden mit core.autocrlf verstehen

## Warum Zeilenenden wichtig sind

Textdateien bestehen aus einzelnen Zeilen. Damit ein Programm erkennt, wo eine Zeile endet, verwendet das Betriebssystem ein *Zeilenende*.

Die zwei wichtigsten Varianten sind:

- **LF** (*Line Feed*, `\n`) – üblich unter Linux und macOS
- **CRLF** (*Carriage Return + Line Feed*, `\r\n`) – traditionell unter Windows

Eine PHP-Datei kann fachlich identisch sein, obwohl sie unterschiedliche Zeilenenden verwendet. Git erkennt diese Unterschiede jedoch auf Dateiebene. Ohne klare Regeln können dadurch Diffs entstehen, die scheinbar jede Zeile einer Datei geändert zeigen.

> **Beispiel:** Eine Datei enthält 300 Zeilen PHP-Code. Ein Teammitglied speichert sie mit LF statt CRLF. Inhaltlich wurde nichts verändert, Git zeigt aber möglicherweise 300 entfernte und 300 hinzugefügte Zeilen an.

Das erschwert Reviews, erhöht Konfliktrisiken und verdeckt echte Änderungen.

---

## Das Grundprinzip von `core.autocrlf`

Die Git-Konfiguration `core.autocrlf` steuert, ob Git Zeilenenden beim **Auschecken** und **Einchecken** automatisch umwandelt.

Git unterscheidet dabei zwei Richtungen:

1. **Checkout**: Git schreibt Dateien aus dem Repository in dein Arbeitsverzeichnis.
2. **Commit**: Git übernimmt Inhalte aus dem Arbeitsverzeichnis in die Repository-Historie.

Das gewünschte Ziel in vielen plattformübergreifenden Projekten lautet:

- Im Repository liegen Textdateien einheitlich mit **LF** vor.
- Unter Windows dürfen Arbeitskopien bei Bedarf **CRLF** verwenden.

Der typische Ablauf sieht so aus:

```text
Repository mit LF
        ↓ Checkout
Arbeitsverzeichnis unter Windows mit CRLF
        ↓ git add und Commit
Repository wieder mit LF
```

Damit bleibt die Historie auf allen Plattformen konsistent, während lokale Werkzeuge im vertrauten Zeilenende arbeiten können.

---

## Die drei Werte von `core.autocrlf`

Prüfe zunächst die aktuell wirksame Einstellung:

```bash
git config --show-origin --get core.autocrlf
```

Die Option `--show-origin` zeigt zusätzlich, *aus welcher Konfigurationsdatei* der Wert stammt. Das ist hilfreich, wenn globale und lokale Einstellungen voneinander abweichen.

### `core.autocrlf=true`

```bash
git config --global core.autocrlf true
```

Diese Einstellung ist für viele klassische Windows-Setups geeignet.

Git verhält sich dann grundsätzlich so:

- Beim **Checkout**: LF wird zu CRLF umgewandelt.
- Beim **Commit**: CRLF wird wieder zu LF normalisiert.

Die Repository-Historie bleibt dadurch bei Textdateien typischerweise LF-basiert.

**Empfehlung für Einsteiger unter Windows 11:** Wenn ein Projekt noch keine verbindliche `.gitattributes`-Datei besitzt und du mit klassischen Windows-Werkzeugen arbeitest, ist `true` ein sinnvoller Ausgangspunkt.

---

### `core.autocrlf=input`

```bash
git config --global core.autocrlf input
```

Diese Variante normalisiert Zeilenenden nur beim Hinzufügen zum Repository:

- Beim **Checkout**: Git verändert die Zeilenenden nicht.
- Beim **Commit**: CRLF wird zu LF normalisiert.

Das bedeutet: Dateien bleiben im Arbeitsverzeichnis so, wie dein Editor sie speichert. CRLF wird beim Commit dennoch als LF in Git abgelegt.

Diese Einstellung wird häufig unter Linux und macOS verwendet. Sie kann unter Windows ebenfalls sinnvoll sein, wenn PhpStorm und das Team konsequent LF verwenden.

---

### `core.autocrlf=false`

```bash
git config --global core.autocrlf false
```

Git führt dann keine automatische Konvertierung über diese Einstellung durch.

Das ist nicht automatisch falsch. Es verlangt aber, dass ein Projekt seine Zeilenenden auf andere Weise zuverlässig regelt – idealerweise mit einer versionierten `.gitattributes`-Datei. Ohne Projektregeln kann diese Einstellung dazu führen, dass LF und CRLF unkontrolliert in die Historie gelangen.

---

## Empfehlung für dieses Windows-11-Setup

Für einen sicheren Einstieg kannst du global Folgendes konfigurieren:

```bash
git config --global core.autocrlf true
```

Kontrolliere anschließend den gespeicherten Wert:

```bash
git config --global --get core.autocrlf
```

Die erwartete Ausgabe lautet:

```text
true
```

Diese Einstellung gilt für alle Repositories deines Windows-Benutzerkontos, sofern ein Repository sie nicht lokal überschreibt.

> ⚠️ **Wichtig:** `core.autocrlf` ist eine lokale Arbeitsumgebungs-Einstellung. Sie wird normalerweise nicht mit dem Repository geteilt. Teamweit reproduzierbare Regeln gehören später in eine versionierte `.gitattributes`-Datei.

---

## Globale, lokale und wirksame Konfiguration unterscheiden

Git kann denselben Konfigurationswert auf mehreren Ebenen speichern:

- **Systemweit**: für alle Benutzer des Computers
- **Global**: für dein Windows-Benutzerkonto
- **Lokal**: nur für ein bestimmtes Repository

Prüfe alle gefundenen Werte:

```bash
git config --show-origin --get-all core.autocrlf
```

Ein Beispiel könnte so aussehen:

```text
file:C:/Users/alex/.gitconfig  true
file:.git/config               false
```

In diesem Fall überschreibt die lokale Einstellung `false` den globalen Wert `true`.

Den lokalen Wert prüfst du innerhalb eines Repositorys mit:

```bash
git config --local --get core.autocrlf
```

Du kannst ihn gezielt setzen:

```bash
git config --local core.autocrlf true
```

Oder wieder entfernen, damit die globale Einstellung greift:

```bash
git config --local --unset core.autocrlf
```

---

## Warnungen zu Zeilenenden richtig verstehen

Beim Hinzufügen von Dateien kann Git Warnungen ausgeben, etwa:

```text
warning: in the working copy of 'src/Calculator.php', LF will be replaced by CRLF the next time Git touches it
```

Diese Meldung bedeutet nicht zwingend, dass ein Fehler vorliegt. Git informiert dich darüber, dass die Datei in deiner Windows-Arbeitskopie künftig mit CRLF erscheinen wird.

Bei `core.autocrlf=true` ist das erwartbares Verhalten:

- Git speichert die Datei intern beziehungsweise im Commit als LF.
- Git kann sie bei einem späteren Checkout als CRLF in das Arbeitsverzeichnis schreiben.

Problematisch wird es erst, wenn ein Commit ausschließlich aus ungewollten Zeilenende-Änderungen besteht oder wenn das Team keine einheitliche Regel verfolgt.

---

## Den Zustand einer Datei prüfen

Mit Git kannst du analysieren, welche Zeilenenden Git für eine Datei erkennt:

```bash
git ls-files --eol src/Calculator.php
```

Eine mögliche Ausgabe lautet:

```text
i/lf    w/crlf  attr/                  src/Calculator.php
```

Die Teile haben folgende Bedeutung:

- `i/lf`: Im **Index** liegt die Datei mit LF vor.
- `w/crlf`: Im **Working Tree**, also im Arbeitsverzeichnis, liegt sie mit CRLF vor.
- `attr/`: Für diese Datei greift derzeit kein besonderes Attribut.

Diese Kombination ist unter Windows mit `core.autocrlf=true` normal.

Wenn im Arbeitsverzeichnis LF verwendet wird, kann die Ausgabe stattdessen so aussehen:

```text
i/lf    w/lf    attr/                  src/Calculator.php
```

Prüfe alle verfolgten Dateien mit:

```bash
git ls-files --eol
```

Das ist besonders nützlich, wenn du vor einem Pull Request unerwartet große Diffs bemerkst.

---

## Zeilenenden in PhpStorm einstellen

PhpStorm kann Zeilenenden unabhängig von Git speichern. Deshalb sollten IDE und Git nicht gegeneinander arbeiten.

Den Zeilenend-Typ der aktuell geöffneten Datei erkennst und änderst du in PhpStorm normalerweise über die Statusleiste am unteren Fensterrand. Dort steht beispielsweise:

```text
CRLF
```

oder:

```text
LF
```

Ein Klick darauf erlaubt, das Zeilenende für die aktuelle Datei zu ändern.

Für neue Dateien kannst du die Standardvorgabe in den Einstellungen festlegen:

```text
File → Settings → Editor → Code Style → Line separator
```

Für moderne PHP-Projekte ist **LF** oft die robusteste teamweite Wahl – auch unter Windows. Wenn dein Projekt bereits `.gitattributes` verwendet, hat dessen Regelwerk Vorrang für die Git-Normalisierung.

> 💡 **Praxisregel:** Ändere Zeilenenden nicht beiläufig während fachlicher Änderungen. Wenn eine Umstellung notwendig ist, führe sie als separaten, klar benannten Commit durch.

---

## Warum `.gitattributes` langfristig besser ist

`core.autocrlf` ist benutzerabhängig: Jedes Teammitglied kann einen anderen Wert gesetzt haben. Eine Datei namens `.gitattributes` liegt dagegen im Repository und wird gemeinsam versioniert.

Eine einfache, robuste Grundlage lautet:

```gitattributes
* text=auto
```

Damit erkennt Git Textdateien automatisch und normalisiert sie beim Einchecken grundsätzlich auf LF.

Für ein PHP-Projekt kann eine präzisere Variante sinnvoll sein:

```gitattributes
*.php  text eol=lf
*.xml  text eol=lf
*.yml  text eol=lf
*.yaml text eol=lf
*.json text eol=lf
*.md   text eol=lf
*.sh   text eol=lf

*.bat  text eol=crlf
*.cmd  text eol=crlf

*.png  binary
*.jpg  binary
*.jpeg binary
*.gif  binary
*.zip  binary
*.pdf  binary
```

Diese Regeln bedeuten:

- PHP-, Konfigurations-, Markdown- und Shell-Dateien werden mit LF behandelt.
- Windows-Batchdateien werden gezielt mit CRLF ausgecheckt.
- Binärdateien werden nicht als Text interpretiert und nicht umgewandelt.

Die detaillierte Arbeit mit `.gitattributes` folgt später im Kurs. Für die erste Einrichtung genügt die Erkenntnis:

> **`core.autocrlf` regelt deine lokale Git-Umgebung; `.gitattributes` definiert verbindliche Regeln für das Projekt.**

---

## Bereits vorhandene Projekte nicht unbedacht umwandeln

Wenn du `core.autocrlf` in einem bestehenden Repository erstmals setzt, sollte Git nicht automatisch einen riesigen Änderungsblock erzeugen. Prüfe deshalb immer zuerst:

```bash
git status
```

Untersuche auffällige Änderungen:

```bash
git diff --check
```

Und sieh dir den tatsächlichen Diff an:

```bash
git diff
```

Wenn Git plötzlich sehr viele geänderte Zeilen anzeigt, obwohl du keinen Code bearbeitet hast, könnten Zeilenenden die Ursache sein.

In einem Teamprojekt solltest du dann **nicht sofort committen**. Kläre stattdessen:

1. Gibt es bereits eine `.gitattributes`-Datei?
2. Welche Zeilenenden verwendet der Hauptbranch?
3. Welche Teamregel gilt für PHP-, Shell- und Batchdateien?
4. Soll eine einmalige, abgestimmte Normalisierung erfolgen?

Eine absichtliche Normalisierung aller Textdateien ist möglich, sollte aber als eigener Teamentscheid behandelt werden. Sie verändert potenziell viele Dateien und erschwert sonst die parallele Arbeit an Feature-Branches.

---

## Typische Situationen und passende Reaktionen

### Jede Zeile einer Datei erscheint geändert

**Wahrscheinliche Ursache:** Die Datei wurde mit einem anderen Zeilenende gespeichert.

Prüfe:

```bash
git diff --ignore-space-at-eol
```

Verschwindet der Großteil des Diffs mit dieser Option, handelt es sich wahrscheinlich um Zeilenende-Unterschiede.

Prüfe zusätzlich:

```bash
git ls-files --eol pfad/zur/datei.php
```

**Reaktion:** Verwirf die unbeabsichtigte Änderung oder stelle das richtige Zeilenende in PhpStorm wieder her. Committe keine reine Zeilenende-Änderung zusammen mit einer fachlichen Änderung.

---

### Eine Shell-Datei funktioniert auf Linux nicht

**Wahrscheinliche Ursache:** Die Datei hat CRLF statt LF. Shells können das unsichtbare Carriage-Return-Zeichen als Teil eines Befehls interpretieren.

**Reaktion:** Speichere `.sh`-Dateien mit LF und sichere dies mit `.gitattributes` ab:

```gitattributes
*.sh text eol=lf
```

---

### Eine Batchdatei funktioniert unter Windows nicht wie erwartet

**Wahrscheinliche Ursache:** Die Datei wurde mit LF gespeichert, obwohl das verwendete Windows-Werkzeug CRLF erwartet.

**Reaktion:** Verwende für `.bat`- und `.cmd`-Dateien eine explizite Regel:

```gitattributes
*.bat text eol=crlf
*.cmd text eol=crlf
```

---

### Git warnt bei jedem `git add`

**Wahrscheinliche Ursache:** Git kündigt lediglich eine erwartete Umwandlung zwischen LF im Repository und CRLF im Arbeitsverzeichnis an.

**Reaktion:** Kontrolliere mit `git ls-files --eol`, ob die Datei erwartungsgemäß behandelt wird. Wenn die Teamregeln stimmen und der Diff fachlich korrekt ist, ist die Warnung meist harmlos.

---

## Empfohlene Basiskonfiguration

Für die Übungen dieses Kurses unter Windows 11:

```bash
git config --global core.autocrlf true
git config --global core.safecrlf warn
```

`core.safecrlf=warn` weist dich auf Umwandlungen hin, bei denen Git einen möglichen Datenverlust oder eine nicht eindeutig umkehrbare Konvertierung erkennt. Es blockiert den Vorgang nicht, macht dich aber aufmerksam.

Prüfe die Konfiguration anschließend:

```bash
git config --global --get-regexp "core\.(autocrlf|safecrlf)"
```

Eine passende Ausgabe wäre:

```text
core.autocrlf true
core.safecrlf warn
```

---

## Checkliste vor dem ersten Commit

- [ ] `core.autocrlf` ist mit `git config --global --get core.autocrlf` geprüft.
- [ ] PhpStorm speichert neue Dateien mit dem zum Projekt passenden Zeilenende.
- [ ] `git status` zeigt nur beabsichtigte Änderungen.
- [ ] `git diff` enthält keine unerwarteten Änderungen an jeder einzelnen Zeile.
- [ ] Vorhandene `.gitattributes`-Regeln wurden beachtet.
- [ ] Shell-Skripte, PHP-Dateien und Konfigurationsdateien verwenden im Team konsistente Regeln.
- [ ] Batchdateien werden bei Bedarf gezielt als CRLF behandelt.

Mit diesem Verständnis vermeidest du einen der häufigsten plattformübergreifenden Git-Fehler: große, irreführende Diffs, die ausschließlich aus unsichtbaren Zeilenende-Unterschieden bestehen.

# Lange Pfade und Dateirechte unter Windows

## Warum Windows bei Pfaden und Dateirechten besondere Aufmerksamkeit braucht

Git wurde ursprünglich in einer Unix-Umgebung entwickelt. Windows 11 unterstützt Git hervorragend, unterscheidet sich jedoch bei zwei Themen grundlegend von Linux und macOS:

- **Pfadlängen:** Tiefe Verzeichnisstrukturen können technische Längenlimits überschreiten.
- **Dateirechte:** Windows nutzt primär NTFS-Berechtigungen statt des Unix-Ausführungsbits.

Diese Unterschiede werden besonders sichtbar, wenn ein Team plattformübergreifend arbeitet, etwa mit Windows-Entwicklung, Linux-Containern und einer CI-Pipeline auf GitHub Actions.

> **Ziel:** Das Repository soll auf jedem System zuverlässig klonbar sein, ohne dass lokale Windows-Einstellungen versehentlich Änderungen an Dateirechten erzeugen.

---

## Lange Pfade verstehen

Ein Dateipfad setzt sich aus Laufwerk, Verzeichnissen und Dateinamen zusammen, zum Beispiel:

```text
C:\Users\Anna\source\mein-projekt\vendor\beispiel\paket\src\Komponente\SehrLangerDateiname.php
```

Historisch sind viele Windows-Programme auf eine maximale Pfadlänge von **260 Zeichen** ausgerichtet. Dieses klassische Limit wird oft als `MAX_PATH` bezeichnet.

Ein PHP-Projekt kann dieses Limit schnell erreichen:

- Ein langer Benutzername und ein tiefes Arbeitsverzeichnis.
- Verschachtelte Composer-Abhängigkeiten in `vendor`.
- Lange Namespace- und Klassennamen.
- Generierte Dateien, Caches oder Testdaten.
- Monorepos mit vielen Ebenen.

Ein problematischer Pfad könnte beispielsweise so aussehen:

```text
C:\Users\Anna\Documents\Kunden\SehrWichtigesUnternehmensprojekt\backend\vendor\anbieter\framework\src\Component\Configuration\Generated\VeryLongGeneratedConfigurationFileName.php
```

### Typische Symptome

Wenn Git oder ein anderes Werkzeug mit zu langen Pfaden scheitert, erscheinen unter anderem Meldungen wie:

```text
Filename too long
```

```text
error: unable to create file ...: Filename too long
```

```text
Path too long
```

Mögliche Folgen sind:

- `git clone` bricht unvollständig ab.
- `git checkout` kann einzelne Dateien nicht erzeugen.
- `git pull` oder ein Branch-Wechsel scheitert.
- Composer kann Abhängigkeiten nicht vollständig installieren.
- PhpStorm zeigt Dateien als fehlend oder nicht synchronisiert an.

---

## Unterstützung für lange Pfade in Windows aktivieren

Windows 11 kann lange Pfade grundsätzlich unterstützen. Damit dies zuverlässig funktioniert, müssen jedoch sowohl Windows als auch die jeweilige Anwendung dafür vorbereitet sein.

### Lange Win32-Pfade in Windows aktivieren

Die Einstellung ist in Windows 11 Pro, Enterprise und Education über Gruppenrichtlinien erreichbar.

1. Öffne das Startmenü.
2. Suche nach `gpedit.msc`.
3. Starte den **Editor für lokale Gruppenrichtlinien**.
4. Navigiere zu:

   ```text
   Computerkonfiguration
   > Administrative Vorlagen
   > System
   > Dateisystem
   ```

5. Öffne die Richtlinie **„Win32 lange Pfade aktivieren“**.
6. Wähle **„Aktiviert“**.
7. Starte Windows neu.

In Windows 11 Home ist der Gruppenrichtlinien-Editor normalerweise nicht verfügbar. Die Einstellung kann stattdessen über die Registrierung gesetzt werden.

> ⚠️ Änderungen an der Windows-Registrierung sollten nur bewusst und mit den nötigen Berechtigungen durchgeführt werden.

Öffne PowerShell **als Administrator** und führe aus:

```powershell
New-ItemProperty `
  -Path "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" `
  -Name "LongPathsEnabled" `
  -Value 1 `
  -PropertyType DWORD `
  -Force
```

Danach Windows neu starten.

Den aktuellen Wert kannst du prüfen:

```powershell
Get-ItemProperty `
  -Path "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" `
  -Name "LongPathsEnabled"
```

Ein aktivierter Wert sieht so aus:

```text
LongPathsEnabled : 1
```

### Lange Pfade für Git aktivieren

Zusätzlich muss Git for Windows angewiesen werden, lange Pfade zu akzeptieren:

```bash
git config --global core.longpaths true
```

Die Einstellung überprüfen:

```bash
git config --global --get core.longpaths
```

Erwartete Ausgabe:

```text
true
```

Wenn Git für alle Benutzer des Computers konfiguriert werden soll, verwende eine administrative Konsole:

```bash
git config --system core.longpaths true
```

Die Herkunft aller gesetzten Werte zeigt:

```bash
git config --show-origin --get-all core.longpaths
```

Beispielausgabe:

```text
file:C:/Program Files/Git/etc/gitconfig    true
```

> **Wichtig:** `core.longpaths` ist eine lokale Git-Client-Einstellung. Sie wird nicht in das Repository übernommen und betrifft keine anderen Teammitglieder automatisch.

---

## Die beste Prävention: kurze lokale Projektpfade

Die Aktivierung langer Pfade ist sinnvoll, aber sie löst nicht jedes Problem. Nicht jede Anwendung, jedes Archivierungswerkzeug oder jede IDE-Komponente unterstützt lange Pfade vollständig.

Die wirksamste Prävention ist deshalb ein **kurzer Projektstammordner**.

### Ungünstige Struktur

```text
C:\Users\Anna\Documents\Projekte\Kunden\Unternehmen\Produkt\Backend\Repository
```

### Günstige Struktur

```text
C:\src\produkt
```

oder:

```text
D:\code\produkt
```

Ein kurzer Basisordner schafft viel Reserve für Abhängigkeiten, generierte Dateien und tief verschachtelte Testdaten.

Für diesen Kurs bietet sich beispielsweise folgende Struktur an:

```text
C:\src\git-kurs
```

Ein neues Repository klonst du dann etwa so:

```bash
cd /c/src
git clone git@github.com:beispielorganisation/git-kurs.git
```

Das Ergebnis:

```text
C:\src\git-kurs
```

### Empfehlungen für Teams

- Lege einen dokumentierten Arbeitsordner fest, etwa `C:\src` oder `D:\code`.
- Vermeide sehr lange Repository-Namen.
- Halte Verzeichnisnamen verständlich, aber kompakt.
- Prüfe generierte Ausgaben auf unnötig tiefe Strukturen.
- Versioniere `vendor` in PHP-Projekten in der Regel **nicht**. Composer erzeugt den Ordner lokal oder in der CI.
- Berücksichtige lange Pfade bei ZIP-Archiven, Deployment-Werkzeugen und Build-Prozessen.

---

## Pfadlängen gezielt untersuchen

PowerShell kann lange Dateipfade im aktuellen Projekt finden. Wechsle zunächst in das Repository:

```powershell
Set-Location C:\src\git-kurs
```

Anschließend lassen sich besonders lange Pfade auflisten:

```powershell
Get-ChildItem -Recurse -Force |
  Sort-Object { $_.FullName.Length } -Descending |
  Select-Object -First 20 FullName, @{Name="Laenge"; Expression={ $_.FullName.Length }}
```

Damit erhältst du die zwanzig längsten Pfade samt Zeichenanzahl.

Um nur Pfade ab 240 Zeichen anzuzeigen:

```powershell
Get-ChildItem -Recurse -Force |
  Where-Object { $_.FullName.Length -ge 240 } |
  Select-Object FullName, @{Name="Laenge"; Expression={ $_.FullName.Length }}
```

Die Grenze von 240 Zeichen ist bewusst etwas niedriger als das klassische Limit. Der verbleibende Spielraum schützt vor zusätzlichen Zeichen, die Werkzeuge temporär erzeugen können.

---

## Dateirechte: Windows und Unix denken unterschiedlich

Auf Linux und macOS besitzen Dateien klassische Unix-Modi. Besonders wichtig ist dabei das **Ausführungsbit**:

```text
-rwxr-xr-x
```

Die drei Gruppen stehen für:

- Eigentümer
- Gruppe
- andere Benutzer

Das `x` bedeutet: Die Datei darf als Programm oder Skript ausgeführt werden.

Unter Windows steuern dagegen NTFS-Berechtigungen den Zugriff. Diese sind wesentlich detaillierter und beziehen sich auf Benutzer, Gruppen und Zugriffsarten wie Lesen, Schreiben oder Ändern.

Eine typische Windows-Datei besitzt daher nicht einfach ein Unix-Ausführungsbit. Ob eine Datei gestartet werden kann, hängt unter anderem von Folgendem ab:

- Dateiendung, etwa `.exe`, `.bat`, `.cmd` oder `.ps1`
- NTFS-Berechtigungen
- PowerShell-Ausführungsrichtlinien
- Zuordnung zu installierten Programmen
- Sicherheitsmechanismen wie Microsoft Defender SmartScreen

Git kann die vollständigen Windows-ACLs nicht sinnvoll und plattformübergreifend versionieren. Stattdessen speichert Git im Normalfall nur eine vereinfachte Dateimodus-Information.

---

## Das Ausführungsbit in Git

Git unterscheidet bei regulären Dateien vor allem zwischen zwei Modi:

```text
100644
```

Dies beschreibt eine normale, **nicht ausführbare** Datei.

```text
100755
```

Dies beschreibt eine **ausführbare** Datei.

Weitere häufige Modi sind:

```text
040000
```

Ein Verzeichnis beziehungsweise ein Tree-Objekt.

```text
120000
```

Ein symbolischer Link.

Die Modusangaben sind Teil des Git-Index und damit Teil eines Commits. Deshalb bleiben sie beim Klonen und zwischen Betriebssystemen erhalten.

Ein Shell-Skript kann unter Linux beispielsweise ausführbar sein:

```bash
scripts/deploy.sh
```

In Git wäre es dann als `100755` gespeichert. Ein Windows-Entwickler kann den Inhalt bearbeiten und committen, ohne das Ausführungsbit zwangsläufig zu verändern — sofern Git passend konfiguriert ist.

---

## `core.filemode` unter Windows

Die Einstellung `core.filemode` legt fest, ob Git Änderungen am Ausführungsbit im Arbeitsverzeichnis erkennen soll.

Prüfe den aktuellen Wert:

```bash
git config --get core.filemode
```

Auf Windows ist häufig dieser Wert sinnvoll:

```text
false
```

Falls kein Wert ausgegeben wird, prüfe alle Konfigurationsebenen:

```bash
git config --show-origin --get-all core.filemode
```

Mit folgendem Befehl ignoriert Git lokale Änderungen am Ausführungsbit:

```bash
git config --global core.filemode false
```

Das ist für die meisten Windows-Arbeitsplätze empfehlenswert, weil NTFS und Git Bash Dateimodi nicht immer so abbilden wie ein Linux-Dateisystem.

> **Wichtig:** `core.filemode false` entfernt keine bereits versionierten Ausführungsrechte. Es verhindert lediglich, dass Git lokale Änderungen an diesem Bit als Arbeitsverzeichnisänderung meldet.

### Beispiel: Unerwartete Modusänderung

Angenommen, ein Skript wurde auf einem Linux-System ausführbar gemacht. Git zeigt dann unter Umständen:

```diff
old mode 100644
new mode 100755
```

Oder umgekehrt:

```diff
old mode 100755
new mode 100644
```

Wenn diese Änderung beabsichtigt ist, kann sie normal committed werden. Wenn sie nur durch die lokale Umgebung entstanden ist, sollte sie nicht versehentlich in einen Commit gelangen.

Prüfe stets zuerst den Status:

```bash
git status
```

Untersuche anschließend den Unterschied:

```bash
git diff --summary
```

Eine reine Rechteänderung erscheint beispielsweise so:

```text
mode change 100644 => 100755 scripts/deploy.sh
```

---

## Ausführungsrechte bewusst mit Git setzen

Wenn ein Skript auf Linux-Servern, in Docker-Containern oder in GitHub Actions direkt ausgeführt werden soll, setze das Ausführungsbit explizit in Git.

### Datei ausführbar machen

```bash
git update-index --chmod=+x scripts/deploy.sh
git commit -m "chore: make deployment script executable"
```

### Ausführungsbit entfernen

```bash
git update-index --chmod=-x scripts/deploy.sh
git commit -m "chore: remove executable permission from deployment script"
```

Kontrolliere die Änderung:

```bash
git diff --cached --summary
```

Beispiel:

```text
mode change 100644 => 100755 scripts/deploy.sh
```

Diese Befehle sind besonders nützlich, weil sie das gewünschte Git-Metadatum direkt setzen — unabhängig davon, wie Windows die Datei im lokalen Dateisystem behandelt.

### Rechte eines bereits committeten Pfads prüfen

```bash
git ls-tree HEAD scripts/deploy.sh
```

Mögliche Ausgabe:

```text
100755 blob 1234567890abcdef1234567890abcdef12345678    scripts/deploy.sh
```

Die führende Angabe `100755` bestätigt, dass Git die Datei als ausführbar speichert.

---

## Relevanz für PHP-Projekte

PHP-Dateien benötigen unter Windows normalerweise kein Ausführungsbit. Sie werden über den PHP-Interpreter gestartet:

```bash
php bin/console
```

Auf Linux kann dieselbe Datei jedoch direkt ausführbar sein:

```bash
./bin/console
```

Damit die zweite Variante funktioniert, braucht die Datei in der Regel:

1. Eine Shebang-Zeile, etwa:

   ```php
   #!/usr/bin/env php
   ```

2. Das Ausführungsbit `100755` in Git.

Das gilt häufig für:

- CLI-Werkzeuge in `bin/`
- Deployment-Skripte in `scripts/`
- Shell-Skripte mit der Endung `.sh`
- Entwicklerwerkzeuge und Generatoren
- CI-Hilfsskripte

Für eine reine PHP-Klassendatei wie `src/Service/UserService.php` wäre ein Ausführungsbit dagegen ungewöhnlich und sollte geprüft werden.

---

## Windows-Attribute sind keine Git-Dateirechte

Windows kennt Attribute wie:

- schreibgeschützt
- versteckt
- Systemdatei
- Archiv

Diese Attribute sind nicht mit Unix-Dateirechten gleichzusetzen. Git versioniert sie im Normalfall nicht.

Ein schreibgeschütztes Attribut kann jedoch lokale Git-Operationen stören, etwa beim Auschecken, Zurücksetzen oder Wechseln eines Branches. Wenn Git eine Datei nicht überschreiben kann, prüfe zunächst die Windows-Eigenschaften der Datei.

In PowerShell:

```powershell
Get-Item .\config\settings.php | Select-Object Name, Attributes
```

Ein schreibgeschütztes Attribut lässt sich entfernen:

```powershell
attrib -R .\config\settings.php
```

Für ein gesamtes Verzeichnis einschließlich Unterordnern:

```powershell
attrib -R .\temp\* /S /D
```

> ⚠️ Entferne Attribute nur in Projektordnern, deren Inhalt du kennst. Systemordner und fremde Verzeichnisse sollten nicht pauschal verändert werden.

---

## NTFS-Berechtigungen bei Zugriffsproblemen prüfen

Wenn Git Fehler wie „Permission denied“, „Access is denied“ oder „unable to unlink“ meldet, liegt die Ursache häufig nicht bei Git selbst. Häufige Gründe sind:

- Eine Datei ist in PhpStorm, einem Terminal oder einem anderen Programm gesperrt.
- Ein Virenscanner untersucht oder blockiert die Datei.
- Der Projektordner gehört einem anderen Windows-Benutzer.
- Das Repository liegt in einem geschützten Ordner.
- Der Ordner befindet sich in OneDrive, einem Netzlaufwerk oder einem synchronisierten Unternehmensspeicher.
- Die NTFS-Berechtigungen erlauben keinen Schreibzugriff.

Zeige die Berechtigungen eines Ordners an:

```powershell
Get-Acl C:\src\git-kurs | Format-List
```

Alternativ:

```powershell
icacls C:\src\git-kurs
```

Für persönliche Entwicklungsprojekte ist ein lokaler Ordner wie `C:\src` meist robuster als:

```text
C:\Program Files
```

```text
C:\Windows
```

```text
C:\Users\Name\OneDrive\Dokumente
```

Geschützte Systemordner und synchronisierte Ordner erhöhen die Wahrscheinlichkeit für Berechtigungs-, Sperr- und Synchronisationsprobleme.

---

## Dateisperren unter Windows erkennen

Windows erlaubt es Anwendungen häufig, Dateien exklusiv zu sperren. Das unterscheidet sich von vielen Linux-Workflows, bei denen Dateien während der Bearbeitung leichter ersetzt oder gelöscht werden können.

Wenn Git eine Datei nicht löschen oder überschreiben kann:

1. Schließe geöffnete Editoren, Vorschauprogramme und Terminals.
2. Beende gegebenenfalls PhpStorm vollständig.
3. Prüfe laufende PHP-, Node.js-, Composer- oder Testprozesse.
4. Warte kurz, falls Microsoft Defender die Datei prüft.
5. Wiederhole erst danach den Git-Befehl.

Bei hartnäckigen Sperren kann der Windows-Ressourcenmonitor helfen:

1. Öffne den Task-Manager.
2. Wähle **Leistung**.
3. Öffne den **Ressourcenmonitor**.
4. Wechsle zu **CPU**.
5. Suche im Bereich **Zugeordnete Handles** nach dem Dateinamen.

So lässt sich feststellen, welcher Prozess eine Datei oder ein Verzeichnis verwendet.

---

## PhpStorm und Dateirechte

PhpStorm zeigt Änderungen an Dateiinhalten und Git-Metadaten im Commit-Werkzeugfenster an. Eine Modusänderung kann dort als eigener Änderungstyp erscheinen.

Vor einem Commit solltest du daher nicht nur die Dateinamen, sondern auch die Diff-Ansicht kontrollieren:

1. Öffne das Werkzeugfenster **Commit**.
2. Wähle die geänderte Datei.
3. Prüfe, ob neben Inhaltsänderungen auch eine Modusänderung vorliegt.
4. Übernimm Rechteänderungen nur, wenn sie fachlich gewollt sind.

Für Shell-Skripte und Linux-CLI-Werkzeuge ist die Kommandozeile oft eindeutiger:

```bash
git diff --summary
```

```bash
git ls-tree HEAD -- scripts/deploy.sh
```

PhpStorm kann Windows-NTFS-Berechtigungen nicht als plattformübergreifende Git-Regel verwalten. Die maßgebliche Information für das Repository bleibt der Git-Dateimodus.

---

## Empfohlene Git-Konfiguration für einen Windows-Entwicklungsrechner

Für eine typische lokale Entwicklungsumgebung unter Windows 11 sind diese Einstellungen ein sinnvoller Ausgangspunkt:

```bash
git config --global core.longpaths true
git config --global core.filemode false
```

Prüfe beide Werte:

```bash
git config --global --get core.longpaths
git config --global --get core.filemode
```

Erwartete Ausgabe:

```text
true
false
```

Diese Konfiguration bedeutet:

- Git akzeptiert lange Pfade, soweit Windows und die verwendeten Werkzeuge dies unterstützen.
- Git meldet lokale Änderungen am Ausführungsbit nicht unnötig als Änderung.
- Bereits im Repository gespeicherte Ausführungsrechte bleiben erhalten.
- Bewusste Rechteänderungen können weiterhin mit `git update-index --chmod` vorgenommen werden.

---

## Diagnoseablauf bei Problemen

Wenn ein Checkout, Pull oder Branch-Wechsel auf Windows scheitert, arbeite strukturiert statt Befehle mehrfach zu wiederholen.

### Bei einem Pfadlängenfehler

1. Prüfe die Git-Einstellung:

   ```bash
   git config --get core.longpaths
   ```

2. Aktiviere sie bei Bedarf:

   ```bash
   git config --global core.longpaths true
   ```

3. Prüfe, ob lange Pfade in Windows aktiviert sind.
4. Klone oder verschiebe das Repository in einen kurzen Pfad, etwa:

   ```text
   C:\src\projekt
   ```

5. Prüfe besonders lange Pfade mit PowerShell.
6. Aktualisiere bei Bedarf Git for Windows und PhpStorm.

### Bei einem Rechte- oder Zugriffsfehler

1. Prüfe den Repository-Zustand:

   ```bash
   git status
   ```

2. Schließe Programme, die Dateien sperren könnten.
3. Prüfe, ob das Projekt in OneDrive oder einem geschützten Ordner liegt.
4. Prüfe NTFS-Berechtigungen:

   ```powershell
   icacls C:\src\projekt
   ```

5. Prüfe schreibgeschützte Attribute:

   ```powershell
   Get-Item .\betroffene-datei | Select-Object Name, Attributes
   ```

6. Prüfe bei reinen Modusänderungen:

   ```bash
   git diff --summary
   ```

7. Setze bei Bedarf das Ausführungsbit gezielt über Git statt über Windows-Dateieigenschaften.

---

## Praxisübung: Umgebung absichern

Lege ein kurzes lokales Arbeitsverzeichnis an:

```powershell
New-Item -ItemType Directory -Path C:\src -Force
```

Wechsle dorthin:

```powershell
Set-Location C:\src
```

Aktiviere die relevanten Git-Einstellungen:

```bash
git config --global core.longpaths true
git config --global core.filemode false
```

Prüfe die Konfiguration einschließlich ihrer Herkunft:

```bash
git config --show-origin --get-all core.longpaths
git config --show-origin --get-all core.filemode
```

Erstelle ein kleines Test-Repository:

```bash
mkdir git-windows-test
cd git-windows-test
git init
```

Lege ein Skript an:

```bash
echo echo Deployment > deploy.sh
```

Mache es bewusst ausführbar:

```bash
git add deploy.sh
git update-index --chmod=+x deploy.sh
git commit -m "chore: add executable deployment script"
```

Prüfe abschließend den gespeicherten Dateimodus:

```bash
git ls-tree HEAD deploy.sh
```

Die Ausgabe sollte mit `100755` beginnen.

---

## Merkpunkte

- **Kurze Projektpfade** sind die zuverlässigste Vorbeugung gegen Pfadprobleme.
- Aktiviere lange Pfade sowohl in **Windows** als auch in **Git** mit `core.longpaths`.
- Verwende für lokale Projekte vorzugsweise Pfade wie `C:\src\projekt`.
- Git speichert keine vollständigen Windows-NTFS-Berechtigungen.
- Für Git ist vor allem das Unix-Ausführungsbit relevant: `100644` oder `100755`.
- Setze Ausführungsrechte für plattformübergreifende Skripte bewusst mit `git update-index --chmod`.
- Mit `core.filemode false` vermeidest du auf Windows unnötige lokale Modusänderungen.
- Bei „Access denied“ sind Dateisperren, Virenscanner, OneDrive oder NTFS-Berechtigungen oft die eigentliche Ursache.

# Installation und Konfiguration testen

## Ziel: Installation und Grundeinstellungen zuverlässig prüfen

Nach der Installation von Git for Windows und der ersten Konfiguration sollte sichergestellt sein, dass:

- Git in der gewünschten Shell erreichbar ist,
- die installierte Version aktuell genug ist,
- Name und E-Mail-Adresse korrekt gesetzt sind,
- der Standard-Branch und Editor den Erwartungen entsprechen,
- der Git Credential Manager verfügbar ist,
- ein Test-Repository problemlos erstellt und verwendet werden kann.

> **Wichtig:** Führe die Befehle möglichst in der Shell aus, die du später überwiegend nutzen möchtest – etwa **Git Bash**, **PowerShell** oder das integrierte Terminal von PhpStorm.

---

## Git-Version prüfen

Öffne Git Bash, PowerShell oder Windows Terminal und führe aus:

```bash
git --version
```

Eine erfolgreiche Installation liefert etwa:

```text
git version 2.47.1.windows.1
```

Die konkrete Versionsnummer kann abweichen. Entscheidend ist, dass der Befehl ohne Fehlermeldung ausgeführt wird.

Alternativ zeigt dieser Befehl ausführlichere Build-Informationen:

```bash
git version --build-options
```

### Wenn `git` nicht gefunden wird

In PowerShell kann die Fehlermeldung ungefähr so aussehen:

```text
git : Der Begriff "git" ist nicht als Name eines Cmdlet, einer Funktion,
einer Skriptdatei oder eines ausführbaren Programms erkannt.
```

Dann ist Git entweder nicht korrekt installiert oder sein Installationsordner fehlt in der Umgebungsvariable `PATH`.

Prüfe zunächst, ob Windows Git findet:

```powershell
where.exe git
```

In Git Bash verwendest du stattdessen:

```bash
which git
```

Ein typisches Ergebnis unter Windows ist:

```text
C:\Program Files\Git\cmd\git.exe
```

Falls kein Pfad erscheint:

1. Schließe alle offenen Terminalfenster vollständig.
2. Öffne ein neues Terminal.
3. Führe `git --version` erneut aus.
4. Installiere Git for Windows gegebenenfalls erneut und wähle bei der Installation die Option, Git über die Kommandozeile und Drittprogramme verfügbar zu machen.

---

## Verwendete Git-Installation kontrollieren

Insbesondere auf Entwicklungsrechnern können mehrere Git-Installationen vorhanden sein, etwa über Git for Windows, eine IDE, WSL oder andere Entwicklerwerkzeuge.

Prüfe deshalb den tatsächlich verwendeten Pfad:

```bash
git --exec-path
```

Unter Git for Windows sieht das Ergebnis häufig ähnlich aus:

```text
C:/Program Files/Git/mingw64/libexec/git-core
```

Zusätzlich kannst du den ausführbaren Befehl ermitteln:

```powershell
Get-Command git
```

Beispielausgabe in PowerShell:

```text
CommandType     Name      Version    Source
-----------     ----      -------    ------
Application     git.exe   2.47.1.1   C:\Program Files\Git\cmd\git.exe
```

Wenn PhpStorm später eine andere Git-Version verwendet als dein Terminal, solltest du dies in den IDE-Einstellungen korrigieren. Eine einheitliche Git-Installation verhindert schwer nachvollziehbare Unterschiede im Verhalten.

---

## Globale Identität überprüfen

Jeder Commit enthält Informationen über die Person, die ihn erstellt hat. Prüfe daher die globale Konfiguration:

```bash
git config --global user.name
git config --global user.email
```

Beispiel:

```text
Max Mustermann
max.mustermann@example.com
```

Die Werte müssen zu der Identität passen, mit der du auf GitHub arbeiten möchtest. Besonders die E-Mail-Adresse ist wichtig: GitHub kann Commits nur dann zuverlässig deinem Konto zuordnen, wenn die Commit-E-Mail-Adresse bei GitHub hinterlegt oder als GitHub-`noreply`-Adresse eingerichtet ist.

Falls ein Wert fehlt oder falsch ist, setze ihn neu:

```bash
git config --global user.name "Max Mustermann"
git config --global user.email "max.mustermann@example.com"
```

### Vollständige Konfiguration anzeigen

Mit folgendem Befehl erhältst du alle wirksamen Konfigurationswerte:

```bash
git config --list
```

Für die Fehlersuche ist diese Variante besser geeignet:

```bash
git config --list --show-origin
```

Sie zeigt zusätzlich, *aus welcher Datei* ein Wert stammt:

```text
file:C:/Users/max/.gitconfig    user.name=Max Mustermann
file:C:/Users/max/.gitconfig    user.email=max.mustermann@example.com
file:C:/Program Files/Git/etc/gitconfig    core.autocrlf=true
```

So erkennst du, ob eine Einstellung systemweit, global für dein Benutzerkonto oder nur für ein bestimmtes Repository gesetzt wurde.

---

## Standard-Branch prüfen

Moderne Git-Repositories verwenden üblicherweise `main` als Anfangsbranch. Prüfe den eingestellten Standardwert:

```bash
git config --global init.defaultBranch
```

Das erwartete Ergebnis ist:

```text
main
```

Falls keine Ausgabe erscheint, ist kein globaler Standard gesetzt. Lege ihn fest:

```bash
git config --global init.defaultBranch main
```

Diese Einstellung betrifft nur **neu initialisierte** Repositories. Bestehende Repositories werden dadurch nicht umbenannt.

---

## Standard-Editor prüfen

Git öffnet bei bestimmten Aktionen einen Editor, etwa beim Schreiben einer Merge-Commit-Nachricht oder beim interaktiven Rebase. Unter Windows ist ein bewusst gewählter Editor wichtig, weil ein unerwartet gestarteter Konsoleneditor Einsteiger häufig verwirrt.

Prüfe zunächst, ob ein Editor konfiguriert ist:

```bash
git config --global core.editor
```

Mögliche Ausgaben sind:

```text
notepad
```

oder:

```text
code --wait
```

Für einen einfachen Einstieg ist Windows Editor geeignet:

```bash
git config --global core.editor notepad
```

Wenn Visual Studio Code installiert ist, ist diese Einstellung oft komfortabler:

```bash
git config --global core.editor "code --wait"
```

Die Option `--wait` ist entscheidend: Git muss warten, bis die Editor-Datei geschlossen wird. Ohne diese Option kann Git die Aktion fortsetzen, bevor du die Commit-Nachricht fertig geschrieben hast.

> **Hinweis:** PhpStorm kann für viele Git-Aktionen eigene Dialoge bereitstellen. Die Einstellung `core.editor` bleibt trotzdem relevant, wenn du Git direkt im Terminal verwendest.

---

## Zeilenenden-Konfiguration kontrollieren

Windows verwendet traditionell Zeilenenden mit CRLF, während Linux und viele Serverumgebungen LF verwenden. Prüfe den gesetzten Wert:

```bash
git config --global core.autocrlf
```

Bei einer üblichen Windows-Konfiguration lautet die Ausgabe:

```text
true
```

Falls du die im Kurs empfohlene Windows-Grundeinstellung verwenden möchtest:

```bash
git config --global core.autocrlf true
```

Die Bedeutung lautet:

- Beim Auschecken werden Textdateien auf **CRLF** umgestellt.
- Beim Commit werden sie wieder mit **LF** gespeichert.
- Das Repository bleibt dadurch für andere Plattformen konsistent.

Später sorgen `.gitattributes`-Dateien für noch präzisere und projektweit verbindliche Regeln. Die globale Einstellung ist aber eine sinnvolle Ausgangsbasis.

---

## Git Credential Manager testen

Git for Windows bringt normalerweise den **Git Credential Manager** mit. Er speichert und verwaltet Zugangsdaten für HTTPS-Verbindungen sicher über die Windows-Anmeldeinformationsverwaltung.

Prüfe die konfigurierte Credential-Hilfe:

```bash
git config --global credential.helper
```

Eine typische Ausgabe ist:

```text
manager
```

Je nach Version kann auch Folgendes erscheinen:

```text
manager-core
```

Prüfe zusätzlich, ob das Programm verfügbar ist:

```bash
git credential-manager --version
```

Beispiel:

```text
2.6.1
```

Wenn der Befehl nicht gefunden wird, prüfe zunächst die Git-Installation erneut. Installiere nicht vorschnell einen separaten Credential Manager, denn bei aktuellen Git-for-Windows-Versionen gehört er normalerweise zum Installationsumfang.

---

## Test-Repository anlegen

Eine erfolgreiche Versionsabfrage beweist nur, dass Git gestartet werden kann. Ein kleines Test-Repository bestätigt dagegen den vollständigen lokalen Workflow: Initialisierung, Staging, Commit und Historie.

Erstelle einen temporären Arbeitsordner:

```powershell
mkdir C:\Projekte\git-test
cd C:\Projekte\git-test
```

In Git Bash wäre derselbe Pfad beispielsweise:

```bash
mkdir -p /c/Projekte/git-test
cd /c/Projekte/git-test
```

Initialisiere das Repository:

```bash
git init
```

Eine erwartbare Ausgabe sieht so aus:

```text
Initialized empty Git repository in C:/Projekte/git-test/.git/
```

Prüfe den aktuellen Zustand:

```bash
git status
```

Bei einem leeren Repository erscheint ungefähr:

```text
On branch main

No commits yet

nothing to commit
```

Der Ordner enthält nun ein verstecktes Verzeichnis namens `.git`. Darin speichert Git seine Historie, Einstellungen, Referenzen und Objekte.

> **Achtung:** Lösche das Verzeichnis `.git` nicht. Damit würdest du die gesamte lokale Git-Historie und Repository-Konfiguration entfernen.

---

## Ersten Test-Commit erstellen

Erstelle eine Datei:

```powershell
"Git-Installation erfolgreich getestet." | Out-File -Encoding utf8 README.md
```

In Git Bash funktioniert beispielsweise:

```bash
echo "Git-Installation erfolgreich getestet." > README.md
```

Prüfe den Zustand:

```bash
git status
```

Git sollte die Datei als noch nicht verfolgt melden:

```text
Untracked files:
  README.md
```

Füge sie zur Staging Area hinzu:

```bash
git add README.md
```

Prüfe den Zustand erneut:

```bash
git status
```

Jetzt sollte Git die Datei als für den Commit vorgemerkt anzeigen:

```text
Changes to be committed:
  new file:   README.md
```

Erstelle den ersten Commit:

```bash
git commit -m "Initialen Test-Commit erstellen"
```

Eine erfolgreiche Ausgabe ähnelt diesem Beispiel:

```text
[main abc1234] Initialen Test-Commit erstellen
 1 file changed, 1 insertion(+)
 create mode 100644 README.md
```

Der kurze Hash wie `abc1234` ist nur ein Beispiel. Jeder Commit erhält eine eigene eindeutige Kennung.

Prüfe schließlich die Historie:

```bash
git log --oneline
```

Erwartetes Muster:

```text
abc1234 Initialen Test-Commit erstellen
```

Und kontrolliere den sauberen Zustand:

```bash
git status
```

Die gewünschte Ausgabe lautet:

```text
On branch main
nothing to commit, working tree clean
```

Damit ist die lokale Git-Installation einschließlich Benutzeridentität und Commit-Erstellung erfolgreich getestet. ✅

---

## Kompakte Abschlussprüfung

Die folgende Befehlsfolge liefert einen schnellen Überblick:

```bash
git --version
git config --global user.name
git config --global user.email
git config --global init.defaultBranch
git config --global core.editor
git config --global core.autocrlf
git config --global credential.helper
git credential-manager --version
```

Zusätzlich sollte im Test-Repository Folgendes funktionieren:

```bash
git status
git log --oneline
```

Wenn alle Befehle ohne Fehler laufen, ist die lokale Umgebung für die nächsten Schritte bereit.

---

## Typische Probleme und passende Lösungen

| Symptom | Wahrscheinliche Ursache | Geeignete Maßnahme |
|---|---|---|
| `git` wird nicht erkannt | Git fehlt im `PATH` oder das Terminal ist noch geöffnet | Terminal neu starten, `where.exe git` prüfen, Git-Installation kontrollieren |
| Commit wird wegen unbekannter Identität abgelehnt | `user.name` oder `user.email` fehlen | Beide Werte mit `git config --global` setzen |
| Der erste Branch heißt `master` statt `main` | `init.defaultBranch` war beim Initialisieren nicht gesetzt | Für neue Repositories `git config --global init.defaultBranch main` setzen; bestehenden Branch bei Bedarf umbenennen |
| Git öffnet einen ungewohnten Editor | Kein geeigneter `core.editor` gesetzt | Beispielsweise `git config --global core.editor notepad` verwenden |
| GitHub fragt bei HTTPS ständig nach Zugangsdaten | Credential Manager ist nicht eingerichtet oder nicht aktiv | `credential.helper` prüfen und später die GitHub-Anmeldung erneut durchführen |
| Unerwartet viele Dateiänderungen nach einem Checkout | Zeilenenden sind nicht einheitlich geregelt | `core.autocrlf` prüfen; später `.gitattributes` im Projekt ergänzen |

---

## Aufräumen des Testprojekts

Das Test-Repository kann als Übungsprojekt erhalten bleiben. Wenn du es nicht mehr brauchst, lösche ausschließlich den Projektordner:

```powershell
Remove-Item -Recurse -Force C:\Projekte\git-test
```

Oder in Git Bash:

```bash
rm -rf /c/Projekte/git-test
```

Verwende Löschbefehle immer bewusst: `Remove-Item -Recurse -Force` und `rm -rf` entfernen Ordner und Inhalte ohne Papierkorb.

---

## Checkliste

- [ ] `git --version` liefert eine Versionsnummer.
- [ ] `git` ist in Git Bash, PowerShell oder Windows Terminal erreichbar.
- [ ] `user.name` enthält den gewünschten Namen.
- [ ] `user.email` enthält die passende Commit-E-Mail-Adresse.
- [ ] `init.defaultBranch` ist auf `main` gesetzt.
- [ ] Ein sinnvoller Git-Editor ist konfiguriert.
- [ ] `core.autocrlf` ist bewusst festgelegt.
- [ ] Der Git Credential Manager ist verfügbar.
- [ ] Ein lokales Repository wurde erfolgreich initialisiert.
- [ ] Ein Test-Commit erscheint in `git log --oneline`.
- [ ] `git status` meldet nach dem Commit einen sauberen Arbeitsstand.

Im nächsten Kapitel wird PhpStorm mit dieser Git-Installation verbunden und als grafische Arbeitsumgebung für Commits, Diffs, Branches und GitHub vorbereitet.

# PhpStorm für Git und GitHub konfigurieren

Dieses Kapitel integriert Git vollständig in PhpStorm. Du lernst die VCS-Einstellungen, Commit-Oberfläche, Diff-Ansichten, Branch-Menüs, integrierten Terminals und GitHub-Anmeldung kennen. Zudem erfährst du, wann die grafische IDE und wann die Kommandozeile geeigneter ist.

# Git-Unterstützung in PhpStorm aktivieren

## Ziel dieser Einrichtung

PhpStorm besitzt eine integrierte Unterstützung für Git. Sie ergänzt die Git-Kommandozeile um grafische Ansichten für Änderungen, Commits, Branches, Konflikte, Historie und Remotes.

Damit PhpStorm Git verwenden kann, müssen zwei Voraussetzungen erfüllt sein:

1. **Git for Windows ist installiert** und im Terminal verfügbar.
2. PhpStorm kennt den Pfad zur Git-Programmdatei und das gewünschte Projekt ist als Git-Repository eingerichtet.

> **Wichtig:** Git ist kein optionales PhpStorm-Plugin, das separat installiert werden muss. Die Versionskontrollintegration gehört standardmäßig zur IDE. PhpStorm nutzt jedoch eine lokale Git-Installation, um Git-Befehle auszuführen.

---

## Voraussetzungen prüfen

Öffne vor der Einrichtung ein Terminal, beispielsweise **Git Bash**, **PowerShell** oder das integrierte Terminal von PhpStorm, und prüfe die Installation:

```powershell
git --version
```

Eine erfolgreiche Ausgabe ähnelt diesem Beispiel:

```text
git version 2.47.1.windows.1
```

Erscheint stattdessen eine Fehlermeldung wie `git is not recognized` oder `git: command not found`, ist Git entweder nicht installiert oder nicht in der `PATH`-Variable verfügbar. Richte in diesem Fall zunächst Git for Windows korrekt ein.

Prüfe außerdem, ob Git bereits eine Identität kennt:

```powershell
git config --global user.name
git config --global user.email
```

Diese Werte sind nicht nötig, um Git in PhpStorm zu *aktivieren*, aber spätestens für den ersten Commit erforderlich.

---

## Ein bestehendes Git-Repository in PhpStorm öffnen

Wenn dein Projekt bereits ein `.git`-Verzeichnis enthält, erkennt PhpStorm das Repository meistens automatisch.

1. Starte PhpStorm.
2. Wähle **File → Open**.
3. Öffne den **Stammordner** des Projekts — also den Ordner, in dem sich das versteckte Verzeichnis `.git` befindet.
4. Bestätige bei Bedarf, dass das Projekt in einem neuen Fenster oder im aktuellen Fenster geöffnet werden soll.

Nach dem Öffnen sollte PhpStorm die Git-Integration aktivieren. Typische Hinweise dafür sind:

- Der Projektname oder ein Branch-Name erscheint in der Statusleiste.
- Das Menü **Git** ist verfügbar.
- Im Projektfenster werden geänderte Dateien farblich markiert.
- Das Werkzeugfenster **Commit** kann über die linke oder untere Werkzeugleiste geöffnet werden.
- Unter **Git → Show Git Log** ist die Historie erreichbar.

Falls diese Elemente nicht erscheinen, prüfe die folgenden Schritte manuell.

---

## Ein neues Projekt unter Versionskontrolle stellen

Ein lokaler Projektordner ohne `.git`-Verzeichnis ist zunächst noch kein Git-Repository. Du kannst Git direkt aus PhpStorm aktivieren.

1. Öffne das gewünschte Projekt in PhpStorm.
2. Wähle im Hauptmenü **VCS → Enable Version Control Integration**.
3. Wähle im Dialog **Git** aus.
4. Bestätige mit **OK**.

PhpStorm führt im Hintergrund im Wesentlichen diesen Befehl aus:

```powershell
git init
```

Dadurch entsteht im Projektstamm ein verborgenes Verzeichnis namens `.git`. Es enthält die komplette lokale Git-Datenbank: Historie, Branch-Referenzen, Konfiguration, Index und weitere Metadaten.

### Ergebnis kontrollieren

Öffne das integrierte Terminal über **View → Tool Windows → Terminal** und führe aus:

```powershell
git status
```

Bei einem neuen Repository sieht die Ausgabe ungefähr so aus:

```text
On branch main

No commits yet

nothing to commit
```

Der Name des Anfangs-Branches kann je nach Git-Konfiguration auch `master` oder anders lauten. Für neue Projekte ist `main` heute die übliche Konvention.

---

## Git-Programm in PhpStorm konfigurieren

PhpStorm muss wissen, welche Git-Programmdatei es aufrufen soll. Öffne dazu:

**File → Settings → Version Control → Git**

Unter macOS wäre der entsprechende Pfad **PhpStorm → Settings → Version Control → Git**. In diesem Kurs liegt der Fokus jedoch auf Windows 11.

Im Feld **Path to Git executable** sollte normalerweise automatisch ein gültiger Pfad eingetragen sein, beispielsweise:

```text
C:\Program Files\Git\bin\git.exe
```

oder:

```text
C:\Program Files\Git\cmd\git.exe
```

Wähle anschließend **Test**.

Bei erfolgreicher Erkennung meldet PhpStorm etwa:

```text
Git executed successfully
```

Zusätzlich wird die gefundene Git-Version angezeigt.

### Welcher Git-Pfad ist korrekt?

Unter Windows existieren häufig mehrere ausführbare Git-Dateien. Für PhpStorm ist in der Regel einer dieser Pfade geeignet:

```text
C:\Program Files\Git\bin\git.exe
```

```text
C:\Program Files\Git\cmd\git.exe
```

Wenn PhpStorm Git automatisch gefunden hat und der Test erfolgreich ist, solltest du den Pfad nicht unnötig ändern.

> **Empfehlung:** Verwende dieselbe Git-for-Windows-Installation in PhpStorm, Git Bash und PowerShell. Unterschiedliche Git-Installationen können abweichende Konfigurationen, Credential Helper oder SSH-Einstellungen verwenden und später schwer nachvollziehbare Unterschiede verursachen.

---

## Versionskontrollzuordnung des Projektordners prüfen

PhpStorm verwaltet, welche Ordner eines Projekts welchem Versionskontrollsystem zugeordnet sind. Das ist besonders relevant bei komplexen Projekten, Monorepos oder verschachtelten Repositories.

Öffne:

**File → Settings → Version Control → Directory Mappings**

Dort sollte eine Zuordnung sichtbar sein:

| Verzeichnis | VCS |
|---|---|
| Projektstamm, beispielsweise `C:\Projekte\mein-projekt` | Git |

Fehlt die Zuordnung:

1. Klicke auf **+**.
2. Wähle den Projektstamm oder den Ordner mit dem `.git`-Verzeichnis.
3. Wähle als VCS **Git**.
4. Übernimm die Einstellungen mit **Apply** und **OK**.

### Nicht versehentlich einen Unterordner zuordnen

Die Zuordnung sollte normalerweise auf den Git-Projektstamm zeigen:

```text
mein-projekt/
├── .git/
├── src/
├── tests/
├── composer.json
└── README.md
```

Würdest du nur `src/` zuordnen, obwohl `.git/` im übergeordneten Projektordner liegt, können Historie, Änderungen und Branches unvollständig oder gar nicht angezeigt werden.

---

## Die Git-Integration im Alltag erkennen

Nach erfolgreicher Aktivierung arbeitet PhpStorm kontinuierlich mit dem lokalen Git-Repository. Du musst Git nicht vor jeder Änderung erneut einschalten.

### Dateistatus im Projektfenster

PhpStorm markiert Dateien abhängig von ihrem Git-Zustand. Die genaue Farbgebung hängt vom Farbschema ab, typische Bedeutungen sind jedoch:

- **neu oder unversioniert:** Die Datei wurde noch nicht zu Git hinzugefügt.
- **geändert:** Eine bereits verfolgte Datei wurde verändert.
- **hinzugefügt:** Die Datei ist für den nächsten Commit vorgemerkt.
- **gelöscht:** Eine verfolgte Datei wurde entfernt.
- **ignoriert:** Eine Regel aus `.gitignore` schließt die Datei aus.

Die Farben sind nur eine visuelle Hilfe. Die zuverlässige Quelle bleibt immer der Git-Zustand, den du auch mit folgendem Befehl prüfen kannst:

```powershell
git status
```

### Branch-Anzeige

In der Statusleiste zeigt PhpStorm üblicherweise den aktuell ausgecheckten Branch an, etwa:

```text
main
```

Ein Klick auf den Branch-Namen öffnet das Branch-Menü. Dort kannst du später Branches erstellen, wechseln, mergen, rebasen oder Remote-Branches ansehen.

### Commit-Werkzeugfenster

Das Werkzeugfenster **Commit** sammelt lokale Änderungen und erlaubt unter anderem:

- Dateien für einen Commit auszuwählen,
- Diffs vor dem Commit zu prüfen,
- Commit-Nachrichten zu schreiben,
- Prüfungen auszuführen,
- Änderungen direkt zu committen oder zu committen und zu pushen.

Die IDE ersetzt dabei nicht das Git-Modell. Sie stellt lediglich eine Oberfläche für dieselben grundlegenden Git-Operationen bereit.

---

## Aktivierung mit der Kommandozeile vergleichen

Die zentrale Aktion lässt sich sowohl in PhpStorm als auch im Terminal ausführen:

| Aufgabe | PhpStorm | Kommandozeile |
|---|---|---|
| Neues Git-Repository erstellen | **VCS → Enable Version Control Integration → Git** | `git init` |
| Repository-Zustand prüfen | Commit-Fenster oder Git-Ansichten | `git status` |
| Branch anzeigen | Statusleiste oder Branch-Menü | `git branch --show-current` |
| Änderungen ansehen | Commit-Fenster oder Diff-Ansicht | `git diff` |
| Git-Historie öffnen | **Git → Show Git Log** | `git log` |

Diese Zuordnung ist wichtig: Wenn du verstehst, welche Git-Operation PhpStorm ausführt, kannst du bei Problemen gezielt prüfen und bist nicht von der Benutzeroberfläche abhängig.

---

## Aktivierung testen

Lege zum Test eine Datei im Projektstamm an, beispielsweise `README.md`, mit folgendem Inhalt:

```markdown
# Mein Git-Übungsprojekt
```

Speichere die Datei. PhpStorm sollte sie nun als **unversionierte Datei** erkennen.

Prüfe anschließend im Terminal:

```powershell
git status
```

Die Ausgabe sollte einen ähnlichen Abschnitt enthalten:

```text
Untracked files:
  README.md
```

Füge die Datei testweise über PhpStorm zu Git hinzu:

1. Öffne das Werkzeugfenster **Commit**.
2. Aktiviere das Kontrollkästchen neben `README.md`.
3. Gib eine Commit-Nachricht ein, beispielsweise:

```text
docs: README hinzufügen
```

4. Wähle **Commit**.

Alternativ erledigst du exakt denselben Ablauf im Terminal:

```powershell
git add README.md
git commit -m "docs: README hinzufügen"
```

Zeige danach die Historie an:

```powershell
git log --oneline
```

Wenn der Commit erscheint, ist Git sowohl lokal als auch in PhpStorm korrekt aktiv.

---

## Häufige Probleme und ihre Ursachen

### PhpStorm findet Git nicht

**Symptom:** Der Test im Bereich **Settings → Version Control → Git** schlägt fehl.

**Typische Ursachen:**

- Git for Windows ist nicht installiert.
- Der hinterlegte Pfad zeigt auf eine nicht vorhandene Datei.
- Eine alte Git-Installation wurde entfernt, aber PhpStorm verwendet noch den alten Pfad.
- Die Datei `git.exe` ist durch Sicherheitssoftware blockiert.

**Lösung:** Suche `git.exe` im Installationsordner von Git for Windows, trage einen gültigen Pfad ein und führe erneut **Test** aus.

---

### Das Menü „Git“ fehlt oder zeigt keine Aktionen

**Symptom:** Das Projekt wird nicht als Git-Repository behandelt.

**Typische Ursachen:**

- Das Projekt enthält noch kein `.git`-Verzeichnis.
- Der falsche Ordner wurde geöffnet.
- Unter **Directory Mappings** ist keine Git-Zuordnung vorhanden.
- Das Repository liegt in einem übergeordneten Ordner, der nicht Teil des geöffneten Projekts ist.

**Lösung:** Öffne den tatsächlichen Repository-Stamm oder richte über **VCS → Enable Version Control Integration** ein neues Repository ein. Kontrolliere danach die Directory Mappings.

---

### Änderungen werden nicht angezeigt

**Symptom:** Eine gespeicherte Datei erscheint nicht im Commit-Fenster.

Prüfe zuerst im Terminal:

```powershell
git status
```

Mögliche Ursachen sind:

- Die Datei wird von `.gitignore` ausgeschlossen.
- Die Datei liegt außerhalb des Repository-Stamms.
- Die Datei wurde noch nicht gespeichert.
- PhpStorm ordnet das Verzeichnis nicht Git zu.
- Die Datei ist Teil einer anderen Changelist oder ein Filter blendet sie aus.

Ob eine Datei durch eine Ignore-Regel ausgeschlossen wird, kannst du präzise prüfen:

```powershell
git check-ignore -v pfad\zur\datei
```

Git zeigt dann die konkrete Ignore-Datei und Regel an, die den Ausschluss verursacht.

---

### Das Projekt enthält mehrere Git-Repositories

Ein Projekt kann mehrere unabhängige Repositories enthalten, etwa bei Modulen, Submodulen oder nebeneinanderliegenden Anwendungen:

```text
arbeitsbereich/
├── backend/
│   └── .git/
└── frontend/
    └── .git/
```

In diesem Fall kann PhpStorm mehrere Directory Mappings verwalten. Jedes Repository erhält eine eigene Git-Zuordnung. Prüfe besonders sorgfältig, in welchem Repository du gerade commitest, Branches wechselst oder Remotes konfigurierst.

> **Achtung:** Ein verschachteltes `.git`-Verzeichnis ist nicht automatisch ein Submodule. Ein Submodule ist ein bewusst in Git eingetragener Verweis auf ein anderes Repository. Mehrere zufällig verschachtelte Repositories führen dagegen oft zu Verwirrung.

---

## Sichere Ausgangskonfiguration

Nach diesem Abschnitt sollte dein Projekt diese Eigenschaften haben:

- Git for Windows ist installiert und über `git --version` erreichbar.
- PhpStorm kennt einen funktionierenden Pfad zu `git.exe`.
- Der Projektstamm ist Git zugeordnet.
- Ein `.git`-Verzeichnis existiert im Repository-Stamm.
- PhpStorm erkennt neue, geänderte und vorgemerkte Dateien.
- Der aktuelle Branch wird in der IDE angezeigt.
- `git status` im Terminal und die Anzeige in PhpStorm beschreiben denselben Zustand.

Damit ist die technische Grundlage gelegt. Als Nächstes prüfst du das Git-Programm und seine Version in PhpStorm genauer und richtest anschließend die Commit- und Historienwerkzeuge für den täglichen Workflow ein.

# Git-Programm und Version prüfen

Bevor PhpStorm sinnvoll mit Git zusammenarbeiten kann, muss die IDE wissen, *welches* Git-Programm auf deinem System verwendet werden soll – und ob dessen Version aktuell genug ist. Gerade unter Windows 11, wo häufig mehrere Git-Installationen parallel existieren (Git for Windows, WSL-Git, in PhpStorm gebündelte Tools), ist diese Prüfung kein optionaler Schritt, sondern die Grundlage für alle weiteren Kapitel.

### Warum die Version überhaupt eine Rolle spielt

Git entwickelt sich kontinuierlich weiter, und einige Befehle, die in diesem Kurs verwendet werden, setzen bestimmte Mindestversionen voraus. Läuft im Hintergrund eine veraltete Git-Version, meldet PhpStorm mitunter kryptische Fehler oder blendet Funktionen im Menü einfach aus, ohne dies deutlich zu kommentieren.

| Funktion | Benötigte Git-Version (mindestens) |
|---|---|
| `git switch` / `git restore` | 2.23 |
| `--force-with-lease` als Standardverhalten stabil | 2.30+ |
| Sparse Checkout im Cone-Modus | 2.25 |
| Partielle Klone (`--filter`) | 2.19 |
| Bessere Rebase-Autostash-Optionen | 2.9+ |

*Empfehlung:* Verwende durchgängig eine aktuelle Version aus der 2.4x-Reihe oder neuer, damit sämtliche in diesem Buch beschriebenen Befehle und PhpStorm-Funktionen zuverlässig zur Verfügung stehen.

### Die Git-Version über die Kommandozeile prüfen

Der schnellste und zuverlässigste Weg führt unabhängig von der IDE über ein Terminal:

```bash
git --version
```

Die Ausgabe sollte in etwa so aussehen:

```
git version 2.46.0.windows.1
```

Der Zusatz `windows` zeigt, dass tatsächlich *Git for Windows* aufgerufen wurde – und nicht etwa eine über WSL installierte Version oder ein Relikt einer alten Installation. Solltest du stattdessen eine deutlich ältere Version oder eine Fehlermeldung wie `git is not recognized` erhalten, liegt entweder ein PATH-Problem vor (siehe Kapitel 2) oder Git wurde noch nicht installiert.

### Den Git-Pfad in PhpStorm kontrollieren

PhpStorm besitzt eine eigene Einstellung, über die festgelegt wird, welche Git-Executable die IDE tatsächlich verwendet. Diese kann von der Version abweichen, die in deiner Kommandozeile aktiv ist – etwa wenn mehrere Installationen vorhanden sind.

1. Öffne **Datei → Einstellungen** (bzw. **File → Settings** bei englischer Oberfläche).
2. Navigiere zu **Version Control → Git**.
3. Prüfe das Feld **Path to Git executable**.

Im Normalfall trägt PhpStorm hier automatisch den Pfad zur global installierten Git-Version ein, üblicherweise:

```
C:\Program Files\Git\cmd\git.exe
```

### Die Test-Schaltfläche nutzen

Neben dem Pfadfeld befindet sich die Schaltfläche **Test**. Ein Klick darauf führt intern denselben Befehl aus wie `git --version` auf der Kommandozeile und zeigt das Ergebnis direkt in einem Dialogfenster an:

```
Git version 2.46.0 detected
```

Erscheint stattdessen eine Fehlermeldung, deutet dies meist auf eines der folgenden Probleme hin:

- **Falscher oder veralteter Pfad** – Git wurde neu installiert oder verschoben, PhpStorm zeigt aber noch auf den alten Speicherort.
- **Beschädigte Installation** – die `.exe`-Datei existiert, ist aber nicht ausführbar oder unvollständig.
- **Mehrere konkurrierende Installationen** – etwa eine ältere Version aus einem Paketmanager, die zufällig zuerst im Pfad gefunden wurde.

### Den Pfad manuell festlegen

Sollte die automatische Erkennung fehlschlagen oder du bewusst eine andere Git-Installation verwenden wollen, lässt sich der Pfad manuell setzen:

1. Klicke im Feld **Path to Git executable** auf das Ordnersymbol.
2. Navigiere zum gewünschten `git.exe`, typischerweise unter `C:\Program Files\Git\cmd\`.
3. Bestätige die Auswahl und klicke erneut auf **Test**, um die Erkennung zu verifizieren.

*Hinweis:* Verwende möglichst den Pfad im `cmd`-Unterordner (`Git\cmd\git.exe`) und nicht den im `bin`-Unterordner, da Letzterer für die Nutzung innerhalb von Bash-Umgebungen optimiert ist und in Kombination mit PhpStorms interner Prozessausführung gelegentlich zu Inkonsistenzen führen kann.

### Mehrere Git-Installationen unter Windows 11 erkennen

Es ist unter Windows keine Seltenheit, mehrere Git-Varianten gleichzeitig vorzufinden:

- **Git for Windows** – die im Kurs empfohlene, eigenständige Installation.
- **Git innerhalb von WSL** (Windows Subsystem for Linux) – separat installiert, mit eigenem Pfad und eigener Konfiguration.
- **Git aus Paketmanagern** wie Chocolatey oder Scoop – funktioniert meist zuverlässig, kann aber zu Versionskonflikten führen, wenn parallel weitere Installationen existieren.

PhpStorm sollte ausschließlich auf die für dieses Buch vorgesehene Git-for-Windows-Installation verweisen. Solltest du zusätzlich mit WSL arbeiten, achte darauf, Projekte nicht unbeabsichtigt zwischen beiden Welten zu vermischen, da sich Zeilenenden, Dateirechte und Pfadformate unterscheiden können.

### Automatische Erkennung vs. explizite Konfiguration

Für die meisten Einzelplatz-Setups reicht die automatische Erkennung vollkommen aus. In Team- oder Firmenumgebungen empfiehlt sich dennoch, den Pfad einmal bewusst zu prüfen und zu dokumentieren – besonders dann, wenn:

- Projekte über mehrere Rechner mit unterschiedlichen Installationswegen hinweg geteilt werden,
- Continuous-Integration-Umgebungen (siehe Kapitel 20) eine bestimmte Git-Version voraussetzen,
- ältere Legacy-Systeme im Unternehmen noch mit veralteten Git-Versionen arbeiten.

### Git aktualisieren

Wird eine veraltete Version erkannt, lässt sich Git for Windows unkompliziert aktualisieren:

```bash
git update-git-for-windows
```

Dieser Befehl prüft auf eine neuere Version und führt bei Bedarf den Installer automatisch aus. Alternativ kann die aktuelle Version jederzeit manuell von der offiziellen Git-for-Windows-Seite heruntergeladen und installiert werden – bestehende Konfigurationswerte (siehe Kapitel 2) bleiben dabei in der Regel erhalten.

### Checkliste für diesen Schritt

Bevor du mit den nächsten Abschnitten dieses Kapitels fortfährst, sollten folgende Punkte erfüllt sein:

- ✅ `git --version` liefert in der Kommandozeile eine aktuelle Version (mindestens 2.4x).
- ✅ PhpStorm zeigt unter **Version Control → Git** denselben Pfad und dieselbe Version an.
- ✅ Die **Test**-Schaltfläche bestätigt die Erkennung ohne Fehlermeldung.
- ✅ Es ist klar, welche Git-Installation tatsächlich aktiv ist, falls mehrere auf dem System vorhanden sind.

Ist all dies sichergestellt, steht einer reibungsvollen Integration von Git in PhpStorm nichts mehr im Weg – und die folgenden Abschnitte zur Versionskontrolle eines Projekts können ohne Umwege beginnen.

# Ein Projekt unter Versionskontrolle stellen

Bevor Commits, Branches oder Pull Requests überhaupt möglich sind, muss PhpStorm wissen, dass ein Projektverzeichnis von Git verwaltet werden soll. Technisch entspricht dieser Schritt exakt dem Kommandozeilenbefehl `git init`, wird in PhpStorm jedoch über einen geführten Dialog ausgeführt, der zusätzlich die *VCS-Zuordnung* (Directory Mapping) im Projekt hinterlegt. Diese Zuordnung ist der Grund, warum die IDE anschließend Dateifarben, Änderungslisten und das Commit-Fenster überhaupt anzeigen kann.

## Zwei Ausgangssituationen

In der Praxis triffst du in PhpStorm auf zwei unterschiedliche Startpunkte:

1. **Neues, noch unversioniertes Projekt** – ein lokaler Ordner mit PHP-Dateien, aber ohne `.git`-Verzeichnis.
2. **Bereits vorhandenes Repository** – das Projekt wurde per `git clone` oder außerhalb von PhpStorm erstellt und muss nur noch korrekt zugeordnet werden.

Dieses Unterkapitel behandelt den ersten Fall ausführlich, da er den eigentlichen Einrichtungsschritt darstellt.

## Schritt für Schritt: Version Control Integration aktivieren

1. Öffne das Projekt in PhpStorm.
2. Wähle im Menü **VCS → Enable Version Control Integration…**
3. Im erscheinenden Dialog wählst du als System **Git** aus.
4. Bestätige mit **OK**.

PhpStorm führt daraufhin im Hintergrund `git init` im Projektstammverzeichnis aus und erstellt das `.git`-Verzeichnis. Gleichzeitig trägt die IDE das Projektverzeichnis als *VCS Root* ein – sichtbar unter:

```
Settings/Preferences → Version Control → Directory Mappings
```

> **Praxistipp:** Ist das VCS-Menü nicht sichtbar, wurde entweder kein Projekt geöffnet oder es liegt bereits eine Zuordnung vor. In diesem Fall erscheint statt *Enable Version Control Integration* direkt das erweiterte VCS-Menü mit Commit-, Branch- und Log-Optionen.

## Was sich im Projektbaum ändert

Unmittelbar nach der Aktivierung markiert PhpStorm alle Dateien im *Project*-Werkzeugfenster farblich:

| Farbe | Bedeutung |
|---|---|
| Braun/Orange | Datei ist *unversioniert* (noch nicht zu Git hinzugefügt) |
| Grün | Datei ist neu hinzugefügt und für den nächsten Commit vorgemerkt |
| Blau | Datei ist bereits verfolgt und wurde geändert |
| Grau | Datei ist ignoriert (siehe `.gitignore`) |

Da direkt nach `git init` noch nichts vorgemerkt ist, erscheinen zunächst *alle* Dateien braun. Dies entspricht dem Zustand, den `git status` auf der Kommandozeile als „Untracked files“ ausweist.

## Dateien zur Versionskontrolle hinzufügen

PhpStorm bietet nach der Aktivierung häufig automatisch einen Hinweis an:

> *„The following files are not currently tracked by Git…“*

Über **Add** werden die ausgewählten Dateien in die Staging Area übernommen – identisch zu `git add`. Alternativ erreichst du dies jederzeit über:

- Rechtsklick auf Datei oder Ordner → **Git → Add**
- Tastenkürzel <kbd>Ctrl</kbd> + <kbd>Alt</kbd> + <kbd>A</kbd>

Vor diesem Schritt lohnt es sich, kurz zu prüfen, ob bereits eine `.gitignore`-Datei existiert, damit keine Abhängigkeiten wie `vendor/` oder IDE-Konfigurationsdateien versehentlich mit aufgenommen werden. Eine vertiefte Behandlung dieses Themas folgt im Kapitel *„Dateien ignorieren und Repository-Hygiene“*.

## Der Ablauf im Überblick

```mermaid
flowchart LR
    A["Projektordner ohne .git"] --> B["VCS -> Enable Version Control Integration"]
    B --> C["git init im Hintergrund"]
    C --> D["Directory Mapping wird angelegt"]
    D --> E["Dateien erscheinen als unversioniert"]
    E --> F["Dateien ueber Add vormerken"]
    F --> G["Bereit fuer ersten Commit"]

    style A fill:#374151,color:#ffffff
    style G fill:#065f46,color:#ffffff
```

## Directory Mappings verstehen

Gerade bei PHP-Projekten mit mehreren Modulen, einer separaten `docs`-Struktur oder eingebundenen Bibliotheken ist es wichtig zu wissen, *welches* Verzeichnis PhpStorm als Wurzel des Repositories betrachtet. Unter

```
Settings/Preferences → Version Control → Directory Mappings
```

siehst du die Zuordnung von Dateisystempfad zu VCS-System. In den allermeisten Fällen genügt ein einziger Eintrag mit dem Projektstammverzeichnis. Enthält dein Projekt jedoch mehrere unabhängige Repositories – etwa ein separates Repository für ein Composer-Paket innerhalb desselben PhpStorm-Projekts – kannst du hier zusätzliche Mappings ergänzen.

> **Warnung:** Verschachtelte `.git`-Verzeichnisse (ein Repository innerhalb eines anderen) führen ohne Submodule oder Subtree-Konfiguration zu Verwirrung, da Git das innere Repository ignoriert, PhpStorm es aber unter Umständen separat anzeigt. Vermeide dies, solange du die Konzepte aus Kapitel 27 noch nicht behandelt hast.

## Vergleich: IDE-Aktion und Git-Befehl

| PhpStorm-Aktion | Entsprechender Git-Befehl |
|---|---|
| VCS → Enable Version Control Integration | `git init` |
| Rechtsklick → Git → Add | `git add <Datei>` |
| Directory Mappings anzeigen | `git rev-parse --show-toplevel` |
| Farbliche Statusanzeige im Projektbaum | `git status` |

Diese Gegenüberstellung ist bewusst Teil jedes praktischen Kapitels dieses Kurses: Sie stellt sicher, dass du auch dann souverän bleibst, wenn kein grafisches Werkzeug zur Verfügung steht – etwa bei der Arbeit über SSH auf einem Server.

## Kontrolle des Ergebnisses

Nach erfolgreicher Aktivierung solltest du folgende Punkte überprüfen:

- Im Projektverzeichnis existiert ein `.git`-Ordner (sichtbar über den Datei-Explorer bei aktivierter Anzeige versteckter Dateien).
- Das VCS-Menü in PhpStorm zeigt nun vollständige Optionen wie **Commit**, **Push** und **Branches** an.
- Das *Commit*-Werkzeugfenster listet die vorgemerkten Dateien korrekt auf.

Damit ist das Fundament gelegt: Das Projekt befindet sich nun vollständig unter Versionskontrolle, und die IDE ist bereit, den ersten Commit entgegenzunehmen – der Gegenstand des folgenden Unterkapitels zur Konfiguration des Commit-Werkzeugfensters. 🗂️

# Commit-Werkzeugfenster konfigurieren

Das *Commit*-Werkzeugfenster ist die zentrale Anlaufstelle für alle Änderungen, die du in ein Repository einpflegen möchtest. Es zeigt dir auf einen Blick, welche Dateien bearbeitet, neu erstellt oder gelöscht wurden, und erlaubt dir, diese gezielt zu gruppieren, zu prüfen und mit einer aussagekräftigen Nachricht zu versehen, bevor sie als Commit in die Historie wandern.

Du öffnest es über:

```
View → Tool Windows → Commit
```

oder mit dem Tastaturkürzel `Alt + 0`. Standardmäßig erscheint es links am Bildschirmrand, kann aber wie jedes andere Werkzeugfenster angedockt, verschoben oder als eigenständiges Fenster „abgerissen“ werden.

---

## Modaler und nicht-modaler Commit

PhpStorm bietet zwei grundlegend unterschiedliche Arbeitsweisen für den Commit-Vorgang, die sich in ihrem Verhalten deutlich unterscheiden:

| Modus | Verhalten | Empfehlung |
|---|---|---|
| **Nicht-modal** *(Standard seit neueren Versionen)* | Der Commit-Bereich ist dauerhaft im Werkzeugfenster sichtbar; du kannst währenddessen weiterarbeiten, Dateien wechseln und andere Fenster nutzen. | Für den Alltag empfehlenswert, da flüssiger und weniger blockierend. |
| **Modal** *(klassischer Commit-Dialog)* | Ein separates Dialogfenster öffnet sich, blockiert andere Aktionen und muss explizit bestätigt oder abgebrochen werden. | Sinnvoll, wenn du einen klaren, unterbrechungsfreien Prüfungsschritt bevorzugst. |

Du steuerst dieses Verhalten unter:

```
Settings → Version Control → Commit
```

über die Option **„Use non-modal commit interface“**. Deaktivierst du sie, kehrst du zum klassischen, modalen Dialog zurück – eine Einstellung, die besonders Umsteiger von älteren PhpStorm-Versionen oder anderen IDEs oft bevorzugen.

---

## Wichtige Grundeinstellungen

Unter `Settings → Version Control → Commit` findest du die zentralen Schalter, mit denen sich der Commit-Vorgang an deinen Arbeitsstil anpassen lässt:

- **„Show unversioned files“** – zeigt nicht verfolgte Dateien direkt in der Commit-Liste an, statt sie zu verstecken.
- **„Before Commit“-Checks** – eine Reihe automatischer Prüfungen, die *vor* jedem Commit ausgeführt werden können (siehe nächster Abschnitt).
- **„Clear initial commit message“** – legt fest, ob das Nachrichtenfeld bei jedem neuen Commit leer beginnt oder die letzte Eingabe behält.
- **„Move Focus to the Commit Message Field“** – springt der Cursor nach dem Öffnen automatisch in das Nachrichtenfeld, was den Arbeitsfluss beschleunigt.

Diese Optionen wirken unscheinbar, summieren sich aber über Hunderte von Commits zu einem spürbaren Unterschied in der täglichen Effizienz.

---

## Automatische Prüfungen vor dem Commit

Eine der nützlichsten Funktionen des Commit-Werkzeugfensters sind die **„Before Commit“-Prüfungen**. Sie laufen automatisch ab, sobald du auf *Commit* klickst, und verhindern, dass unsaubere oder fehlerhafte Änderungen versehentlich in die Historie gelangen.

Zu den wichtigsten gehören:

- **Reformat code** – wendet den konfigurierten Code-Style automatisch auf die geänderten Dateien an.
- **Optimize imports** – entfernt ungenutzte und sortiert vorhandene Imports, besonders relevant in PHP-Klassen mit vielen `use`-Anweisungen.
- **Rearrange code** – ordnet Klassenmitglieder gemäß den definierten Regeln neu an.
- **Perform code analysis** – führt eine Inspektion durch und warnt vor Fehlern, bevor sie festgeschrieben werden.
- **Check TODO** – weist auf offene `TODO`-Kommentare in den betroffenen Dateien hin.

> *Praxistipp:* Aktiviere zu Beginn nicht alle Prüfungen gleichzeitig. Beginne mit „Reformat code“ und „Optimize imports“, um ein Gefühl für die automatischen Eingriffe zu entwickeln, bevor du strengere Analysen hinzufügst.

Jede Prüfung lässt sich einzeln ein- oder ausschalten und kann so konfiguriert werden, dass sie bei Verstößen den Commit blockiert oder lediglich eine Warnung anzeigt.

---

## Commit-Nachrichten strukturieren

Direkt im Werkzeugfenster befindet sich das Nachrichtenfeld für die Commit-Beschreibung. PhpStorm unterstützt dich dabei auf mehreren Ebenen:

- **Vorlagen (Commit Message Templates):** Unter `Settings → Version Control → Commit Message` kannst du eine feste Vorlage hinterlegen, etwa im Sinne der *Conventional Commits*:

```
<type>(<scope>): <subject>

<body>
```

- **Zeilenlängen-Hinweis:** Eine vertikale Linie im Eingabefeld markiert die empfohlene maximale Zeilenlänge der ersten Zeile (üblicherweise 72 Zeichen), was der gängigen Git-Konvention entspricht.
- **Verlauf früherer Nachrichten:** Über das Uhrsymbol im Nachrichtenfeld rufst du zuvor verwendete Commit-Nachrichten ab – praktisch bei wiederkehrenden Formulierungen innerhalb eines Features.

---

## Changelists gezielt nutzen

Das Commit-Werkzeugfenster gruppiert Änderungen standardmäßig in der *Default*-Changelist. Du kannst jedoch beliebig viele weitere Changelists anlegen, um thematisch getrennte Änderungen parallel vorzubereiten, ohne sie sofort zu committen.

- Über das Kontextmenü einer Datei wählst du **„Move to Another Changelist“**, um sie einer neuen Gruppe zuzuweisen.
- Jede Changelist besitzt einen eigenen Namen und optional einen Kommentar, was besonders hilfreich ist, wenn du an mehreren logisch getrennten Themen gleichzeitig arbeitest.
- Beim Commit wählst du gezielt aus, welche Changelist eingecheckt werden soll – die übrigen bleiben unberührt im Arbeitsverzeichnis erhalten.

Diese Funktion ersetzt in vielen Alltagssituationen das manuelle Stashen und erlaubt eine deutlich übersichtlichere Arbeitsweise, wenn mehrere kleine Aufgaben nebeneinander existieren.

---

## Diff-Vorschau direkt im Fenster

Ein oft übersehenes, aber äußerst hilfreiches Detail ist die integrierte Diff-Vorschau. Aktivierst du unter `Settings → Version Control → Commit` die Option **„Show diff preview on double click“**, öffnest du mit einem Doppelklick auf eine Datei sofort die Änderungsansicht, ohne das Commit-Fenster verlassen zu müssen.

Alternativ lässt sich die Vorschau dauerhaft als eingebettetes Panel neben der Dateiliste anzeigen – so behältst du beim Formulieren der Commit-Nachricht stets den inhaltlichen Kontext im Blick, was die Qualität deiner Beschreibungen merklich verbessert.

---

## Zusammenfassung

Das Commit-Werkzeugfenster ist weit mehr als ein einfacher „Speichern“-Knopf. Durch die Kombination aus **automatischen Prüfungen**, **strukturierten Nachrichtenvorlagen**, **flexiblen Changelists** und **integrierter Diff-Ansicht** wird es zu einem Werkzeug, das Disziplin und Geschwindigkeit gleichzeitig fördert. Wer diese Einstellungen bewusst an den eigenen Arbeitsstil anpasst, reduziert Flüchtigkeitsfehler erheblich und legt damit den Grundstein für eine saubere, nachvollziehbare Projekthistorie – ein Thema, das im weiteren Verlauf des Kurses noch vertieft wird. ✅

# Git- und Log-Werkzeugfenster erkunden

## Das Git-Werkzeugfenster als Kommandozentrale

Während das Commit-Werkzeugfenster den *Weg in* die Historie beschreibt, ist das **Git-Werkzeugfenster** dein Blick *auf* die Historie. Es fasst alles zusammen, was mit dem aktuellen Zustand deines Repositorys zu tun hat: Branches, Commits, lokale Änderungen und die tatsächlich ausgeführten Git-Befehle. Du öffnest es über `Alt` + `9` oder über *View → Tool Windows → Git*.

Das Fenster ist in mehrere Reiter unterteilt, die je nach PhpStorm-Version leicht unterschiedlich benannt sind, inhaltlich aber stets dieselben drei Aufgaben abbilden:

| Reiter | Aufgabe |
|---|---|
| **Log** | Commit-Graph, Branches, Tags, Details zu einzelnen Commits |
| **Local Changes** | Aktueller Stand von Arbeitsverzeichnis und Index (siehe Commit-Werkzeugfenster) |
| **Console** | Protokoll aller intern ausgeführten Git-Kommandozeilenbefehle |

## Der Log-Tab im Detail

Der **Log-Tab** ist das Herzstück des Fensters. Er visualisiert die Commit-Historie als Graph – vergleichbar mit `git log --graph --oneline --all`, nur interaktiv und deutlich übersichtlicher.

**Der Graphbereich** zeigt links die Commit-Linien mit farblich getrennten Branches. Jeder Knotenpunkt ist ein Commit; Verzweigungen und Zusammenführungen sind sofort erkennbar. Rechts daneben stehen Commit-Nachricht, Autor und Zeitpunkt.

**Das Detailpanel** öffnet sich, sobald du einen Commit anklickst. Es zeigt:

- die vollständige Commit-Nachricht,
- Autor, Committer und Zeitstempel,
- die betroffenen Dateien inklusive Diff-Vorschau per Doppelklick.

**Die Branch-Spalte** listet, welche lokalen und entfernten Branches auf den jeweiligen Commit zeigen – praktisch, um schnell zu erkennen, ob eine Änderung bereits gepusht wurde.

### Filtern und Suchen

Über der Graphansicht befindet sich eine Filterleiste, mit der du die angezeigte Historie gezielt einschränkst:

- **Branch-Filter**: nur bestimmte Branches oder *alle* anzeigen.
- **Benutzer-Filter**: Commits eines bestimmten Autors isolieren.
- **Datumsfilter**: Zeiträume eingrenzen.
- **Textsuche**: Commit-Nachrichten oder – über die Option „Search in commit contents“ – auch geänderte Dateiinhalte durchsuchen.

Diese Filter lassen sich kombinieren, was besonders bei größeren Projekten mit vielen parallelen Branches wertvoll ist, um sich schnell einen Überblick über den Fortschritt eines Features zu verschaffen.

### Kontextaktionen direkt im Graph

Ein Rechtsklick auf einen Commit öffnet ein Kontextmenü mit den wichtigsten Operationen, die du sonst über die Kommandozeile ausführen würdest:

- `Checkout Revision` – entspricht `git checkout <commit>`,
- `New Branch from Selected Commit`,
- `Cherry-Pick`,
- `Revert Commit`,
- `Reset Current Branch to Here`.

So lassen sich viele fortgeschrittene Git-Operationen ausführen, ohne den Befehl im Detail zu kennen – wichtig ist aber, dass du in späteren Kapiteln verstehst, *was* im Hintergrund tatsächlich passiert, um Fehlbedienungen zu vermeiden.

## Der Console-Tab: Transparenz statt Blackbox

Ein zentraler Vorteil von PhpStorm gegenüber rein grafischen Git-Clients ist der **Console-Tab**. Hier protokolliert die IDE jeden intern ausgeführten Git-Befehl im Klartext – inklusive Parametern und Rückgabewerten.

Dieser Reiter ist didaktisch besonders wertvoll: Klickst du beispielsweise in der Oberfläche auf *Pull*, kannst du in der Console exakt nachlesen, dass PhpStorm etwa

```
git fetch origin
git merge origin/main
```

ausgeführt hat. So verknüpfst du grafische Aktionen direkt mit dem zugrunde liegenden Kommandozeilenwissen, das dir in den folgenden Kapiteln immer wieder begegnet.

## Zusammenspiel der Reiter

```mermaid
flowchart LR
    A["Log-Tab: Commit-Historie und Branches"] --> D["Git-Werkzeugfenster"]
    B["Local Changes: Arbeitsverzeichnis und Index"] --> D
    C["Console: Ausgeführte Git-Befehle"] --> D
    D --> E["Vollständiger Überblick über Repository-Zustand"]
```

## Praktische Hinweise für den Alltag

- **Doppelklick auf einen Commit** öffnet direkt die Diff-Ansicht der geänderten Dateien – der schnellste Weg, eine fremde Änderung zu verstehen.
- **„Show Diff Preview on Double Click“** in den Einstellungen beschleunigt wiederkehrende Prüfungen.
- Nutze den Log-Tab regelmäßig *vor* riskanten Operationen wie Rebase oder Reset, um dir den aktuellen Branch-Zustand bewusst zu machen.
- Die **Console** solltest du dir angewöhnen zu beobachten, gerade in der Lernphase – sie ist dein Fenster zur eigentlichen Git-Mechanik hinter der Oberfläche.

Mit einem sicheren Umgang mit Log- und Console-Tab hast du die Grundlage geschaffen, um im nächsten Schritt Änderungen und Diffs gezielt zu untersuchen – ein Werkzeug, das dich durch den gesamten weiteren Kurs begleiten wird.

# Änderungen und Diffs anzeigen

## Änderungen sichtbar machen: Die Diff-Engine von PhpStorm

Bevor ein Commit entsteht, solltest du genau wissen, *was* sich geändert hat – nicht nur *dass* sich etwas geändert hat. PhpStorm bietet dafür eine der ausgereiftesten Diff-Darstellungen unter allen Git-Werkzeugen. Dieses Kapitel zeigt dir, wie du Änderungen auf Datei-, Zeilen- und Projektebene erkennst, interpretierst und gezielt nutzt.

### Warum die visuelle Diff-Ansicht wichtiger ist als `git diff`

Auf der Kommandozeile liefert `git diff` textbasierte Unterschiede mit `+`- und `-`-Präfixen. Das funktioniert, ist aber bei komplexen Änderungen, umformatiertem Code oder verschobenen Codeblöcken schnell unübersichtlich. PhpStorm übersetzt diese Rohdaten in eine strukturierte, farblich kodierte Ansicht mit:

- **Syntax-Highlighting** – auch im Diff bleibt PHP-, JavaScript- oder Twig-Code lesbar.
- **Intelligenter Zeilen- und Wort-Erkennung** – nicht nur ganze Zeilen, sondern auch einzelne geänderte Wörter innerhalb einer Zeile werden markiert.
- **Navigierbaren Blöcken** – du kannst zwischen Änderungsblöcken springen, statt zu scrollen.

Damit wird der Diff nicht nur zur Kontrolle vor dem Commit genutzt, sondern zu einem echten Analysewerkzeug im Alltag.

### Der Gutter: Änderungen direkt im Editor erkennen

Der wichtigste und unauffälligste Helfer ist der **Gutter** – der schmale Streifen links neben der Zeilennummer im Editor. Sobald eine Datei unter Versionskontrolle steht, markiert PhpStorm dort automatisch jede Abweichung gegenüber dem letzten Commit:

| Markierung | Bedeutung |
|---|---|
| Grüner Balken | Neu hinzugefügte Zeile |
| Blauer Balken | Geänderte Zeile |
| Roter Pfeil | Gelöschte Zeile *(an der Stelle, an der sie fehlt)* |

Ein Klick auf einen dieser Balken öffnet ein Kontextmenü mit drei zentralen Aktionen:

1. **Diff anzeigen** – öffnet die Detailansicht für genau diesen Änderungsblock.
2. **Rollback** – verwirft die Änderung dieser Zeile, ohne die gesamte Datei zurückzusetzen.
3. **Copy** – kopiert den ursprünglichen Inhalt zur Wiederverwendung.

Dieser Mechanismus ist besonders wertvoll, weil er *ohne* den Umweg über ein separates Fenster funktioniert – die Historie ist direkt im Arbeitskontext sichtbar.

### Die Diff-Ansicht öffnen

Es gibt mehrere gleichwertige Wege, eine vollständige Diff-Ansicht aufzurufen:

- Im **Commit-Werkzeugfenster** einen doppelten Klick auf eine geänderte Datei.
- Im **Git-Werkzeugfenster** (Reiter *Log*) einen Commit auswählen und die betroffene Datei doppelklicken.
- Über das Kontextmenü einer Datei im Projektbaum: *Git → Show Diff*.
- Mit der Tastenkombination \(\text{Strg} + \text{D}\) bei markierter Datei.

PhpStorm öffnet daraufhin die **Zwei-Spalten-Ansicht**: links der letzte committete Stand, rechts dein aktueller Arbeitsstand. Änderungsblöcke sind farblich hinterlegt, und über kleine Pfeile zwischen den Spalten lassen sich einzelne Blöcke gezielt in die eine oder andere Richtung übernehmen.

### Navigation innerhalb des Diffs

Für größere Dateien mit vielen Änderungen bietet die Diff-Ansicht eine eigene Navigationsleiste:

- **Nächster/vorheriger Unterschied** – über die Pfeiltasten am oberen Rand oder \(\text{F7}\) bzw. \(\text{Umschalt} + \text{F7}\).
- **Übersichtskarte** – am rechten Rand zeigt ein Miniatur-Streifen die Position aller Änderungen im Gesamtdokument, vergleichbar mit einer Landkarte.
- **Zeilenweiser Vergleich** – bei aktivierter Wort-Diff-Option werden nur die tatsächlich veränderten Zeichen hervorgehoben, nicht die ganze Zeile.

Diese Übersichtskarte ist besonders hilfreich, wenn eine Datei hunderte Zeilen umfasst, aber nur an wenigen Stellen tatsächlich bearbeitet wurde.

### Diffs zwischen beliebigen Revisionen

Die Diff-Funktion ist nicht auf den Vergleich „aktuell gegen letzten Commit“ beschränkt. Im **Git-Log** kannst du:

- **zwei beliebige Commits markieren** (mit gedrückter \(\text{Strg}\)-Taste) und über das Kontextmenü *Compare Versions* wählen,
- **einen Commit gegen den aktuellen Arbeitsstand** vergleichen,
- **eine einzelne Datei über mehrere Commits hinweg** verfolgen, indem du mit der rechten Maustaste auf die Datei im Log klickst und *Show Diff* wählst.

Damit lässt sich exakt nachvollziehen, wann und durch wen eine bestimmte Zeile eingeführt wurde – eine Vorstufe zur später behandelten `git blame`-Funktionalität.

### Der Unterschied zwischen „Changes“ und „Diff“ verstehen

Ein häufiges Missverständnis betrifft die Begriffe *Changes* und *Diff*:

- **Changes** bezeichnet die *Liste* der veränderten Dateien – sichtbar im Commit-Werkzeugfenster.
- **Diff** bezeichnet den *inhaltlichen Vergleich* einer einzelnen Datei zwischen zwei Zuständen.

PhpStorm verknüpft beide Konzepte eng: Aus der Änderungsliste gelangst du per Doppelklick direkt in den passenden Diff, ohne den Kontext zu verlieren.

### Lokale Historie als zusätzliches Netz

Unabhängig von Git führt PhpStorm eine eigene **Local History**, die jede gespeicherte Änderung protokolliert – auch solche, die nie committet wurden. Über *VCS → Local History → Show History* lässt sich der Zustand einer Datei zu jedem beliebigen Zeitpunkt einsehen und mit dem aktuellen Stand vergleichen.

> **Praktischer Hinweis:** Die lokale Historie ersetzt kein Commit, ist aber ein wertvolles Sicherheitsnetz für den Moment, bevor überhaupt ein `git add` erfolgt ist.

### Zusammenfassung

Die Diff-Fähigkeiten von PhpStorm reichen von der unauffälligen Gutter-Markierung bis zur detaillierten Mehrfach-Revisionsansicht. Wer diese Werkzeuge beherrscht, muss nicht mehr raten, was sich seit dem letzten Commit verändert hat – jede Zeile, jedes Wort und jede Historie lässt sich präzise und visuell nachvollziehen. Im nächsten Schritt verbindest du dieses Wissen mit deinem **GitHub-Konto**, um Änderungen nicht nur lokal zu betrachten, sondern auch remote zu teilen. 🔍

# GitHub-Konto mit PhpStorm verbinden

Damit PhpStorm Pull Requests anzeigen, Repositories veröffentlichen und Push- oder Fetch-Vorgänge gegenüber GitHub authentifizieren kann, benötigt die IDE eine eigene, von der reinen Git-Konfiguration unabhängige Verbindung zu deinem GitHub-Konto. Diese Verbindung ist mehr als nur eine Anmeldung: Sie stellt einen *Sicherheits-Token* bereit, über den PhpStorm im Namen deines Kontos handelt – etwa beim Erstellen von Repositories, beim Kommentieren von Pull Requests oder beim Anzeigen von Issues direkt im Editor.

## Warum eine separate Verbindung notwendig ist

Git selbst kennt GitHub nicht. Für Git ist ein Remote-Repository lediglich eine URL, die per HTTPS oder SSH angesprochen wird. GitHub-spezifische Funktionen – etwa das *Pull-Request-Werkzeugfenster*, die Anzeige von Reviews oder das direkte Erstellen eines Repositories aus der IDE – benötigen jedoch die *GitHub-API*. Diese API erfordert eine eigenständige Authentifizierung, die PhpStorm getrennt von den lokalen Git-Zugangsdaten verwaltet.

> 💡 **Merke:** Die Anmeldung bei GitHub in PhpStorm betrifft die *API-Integration*, nicht automatisch den Datenaustausch per `git push` oder `git pull`. Für Letzteres bleibt zusätzlich eine funktionierende HTTPS- oder SSH-Authentifizierung erforderlich, wie sie in einem späteren Kapitel vertieft wird.

## Voraussetzungen

Bevor du die Verbindung herstellst, sollten folgende Punkte erfüllt sein:

- Ein bestehendes **GitHub-Konto** mit verifizierter E-Mail-Adresse.
- **Zwei-Faktor-Authentifizierung** ist empfehlenswert, aber für die Erstverbindung nicht zwingend.
- Ein aktueller **Browser**, da die Anmeldung meist über den systemeigenen Webbrowser erfolgt.
- Eine funktionierende **Internetverbindung** ohne blockierende Firewall-Regeln für `github.com` und `api.github.com`.

## Die Verbindung einrichten

### Schritt 1: Einstellungen öffnen

Navigiere zu:

```
Datei → Einstellungen → Version Control → GitHub
```

Alternativ erreichst du denselben Dialog über das Menü `Git → GitHub → Zu GitHub anmelden…`, sobald du dich innerhalb eines Projekts befindest.

### Schritt 2: Anmeldemethode wählen

PhpStorm bietet in der Regel zwei gleichwertige Wege an:

| Methode | Ablauf | Empfehlung |
|---|---|---|
| **Log In via GitHub** | Öffnet den Standardbrowser, du meldest dich dort an und autorisierst PhpStorm per OAuth | Für die meisten Anwender die einfachste und sicherste Variante |
| **Log In with Token** | Du erzeugst manuell einen *Personal Access Token* auf GitHub und fügst ihn in PhpStorm ein | Sinnvoll bei eingeschränkten Berechtigungen, Firmenrichtlinien oder Automatisierung |

Der folgende Ablauf verdeutlicht den OAuth-basierten Anmeldeprozess:

```mermaid
sequenceDiagram
    participant P as PhpStorm
    participant B as Browser
    participant G as GitHub

    P->>B: Öffnet Autorisierungsseite
    B->>G: Login-Daten senden
    G->>B: Autorisierung bestätigen
    B->>G: Zugriff für PhpStorm erlauben
    G->>P: Token an PhpStorm übergeben
    P->>P: Token verschlüsselt speichern
```

### Schritt 3: Anmeldung über den Browser abschließen

Bei der Browser-Variante geschieht Folgendes:

1. PhpStorm öffnet eine GitHub-Autorisierungsseite.
2. Du meldest dich – falls noch nicht geschehen – mit deinem GitHub-Konto an.
3. GitHub zeigt an, welche **Berechtigungen** (Scopes) PhpStorm anfordert, etwa Zugriff auf Repositories, Pull Requests und Benutzerinformationen.
4. Nach Bestätigung kehrst du automatisch zu PhpStorm zurück; das Konto erscheint in der Liste der verbundenen Konten.

### Schritt 4: Anmeldung per Token als Alternative

Falls dein Unternehmen OAuth-Anmeldungen einschränkt oder du volle Kontrolle über die Berechtigungen behalten möchtest, erstellst du stattdessen einen Token direkt auf GitHub:

1. Auf GitHub: `Settings → Developer settings → Personal access tokens → Fine-grained tokens`.
2. Einen neuen Token mit einem aussagekräftigen Namen wie `PhpStorm – Arbeitsplatz` erzeugen.
3. **Ablaufdatum** und **Berechtigungsumfang** bewusst einschränken – etwa nur `repo` und `read:user`, statt vollständigen Kontozugriff zu gewähren.
4. Den Token einmalig kopieren, da er danach nicht erneut angezeigt wird.
5. In PhpStorm bei `Log In with Token` einfügen und bestätigen.

> ⚠️ **Sicherheitshinweis:** Ein Personal Access Token ist funktional einem Passwort gleichwertig. Bewahre ihn niemals im Klartext in Projektdateien oder Commits auf. Kapitel 21 vertieft den sicheren Umgang mit Tokens und deren Rotation.

## Mehrere GitHub-Konten verwalten

Gerade bei der Trennung von privaten und beruflichen Projekten ist es üblich, mehrere GitHub-Konten zu nutzen. PhpStorm unterstützt dies direkt:

- Im gleichen Einstellungsdialog kannst du über das **Plus-Symbol** ein weiteres Konto hinzufügen.
- Beim Veröffentlichen eines Repositories oder Erstellen eines Pull Requests fragt PhpStorm anschließend, **welches Konto** verwendet werden soll, sofern mehrere hinterlegt sind.
- Konten lassen sich jederzeit über das **Minus-Symbol** entfernen, ohne dass dies lokale Repository-Daten beeinflusst.

## Die Verbindung überprüfen

Nach erfolgreicher Anmeldung solltest du folgende Punkte kontrollieren:

1. Im Menü `Git → GitHub` erscheinen nun Aktionen wie `Create Pull Request` oder `View Pull Requests`.
2. Im Werkzeugfenster **Pull Requests** lassen sich bestehende Anfragen des verbundenen Kontos laden.
3. Beim Veröffentlichen eines neuen, lokalen Projekts über `Git → GitHub → Share Project on GitHub` wird das verbundene Konto automatisch als Ziel vorgeschlagen.

## Typische Probleme und ihre Lösung

| Symptom | Wahrscheinliche Ursache | Lösung |
|---|---|---|
| Browserfenster öffnet sich, aber Login bleibt hängen | Firewall oder Proxy blockiert `github.com` | Netzwerkeinstellungen unter `Einstellungen → Appearance & Behavior → System Settings → HTTP Proxy` prüfen |
| Token wird abgelehnt | Fehlende Berechtigungen oder abgelaufener Token | Neuen Token mit korrektem Scope erzeugen |
| Pull-Request-Werkzeugfenster bleibt leer | Konto ohne Zugriff auf das jeweilige Repository verbunden | Richtiges Konto im Projekt auswählen oder Repository-Berechtigung prüfen |
| Anmeldung wiederholt sich bei jedem Start | Zugangsdaten werden nicht dauerhaft gespeichert | Systemeigenen *Credential Store* statt reinen Arbeitsspeicher-Cache in den Einstellungen aktivieren |

## Zusammenfassung

Die Verbindung zwischen PhpStorm und GitHub bildet die Grundlage für nahezu alle komfortablen GitHub-Funktionen innerhalb der IDE – von der Veröffentlichung neuer Repositories bis zur Verwaltung von Pull Requests. Ob du dich per Browser-Login oder mit einem fein abgestimmten Personal Access Token anmeldest, hängt von deinen Sicherheitsanforderungen und organisatorischen Vorgaben ab. Entscheidend ist, dass du die vergebenen Berechtigungen bewusst wählst und die Verbindung regelmäßig überprüfst, bevor du im nächsten Schritt das **integrierte Terminal** einrichtest, um GitHub-Funktionen und klassische Git-Kommandozeile flexibel zu kombinieren.

# Integriertes Terminal einrichten

## Warum ein eigenes Git-Terminal in PhpStorm sinnvoll ist

Die grafischen Werkzeuge von PhpStorm decken den überwiegenden Teil des täglichen Git-Workflows ab – Commit-Dialog, Diff-Ansicht, Branch-Menü. Doch bestimmte Aufgaben lassen sich nur oder deutlich effizienter über die Kommandozeile lösen: interaktives Rebasing, komplexe `git log`-Filter, Plumbing-Befehle oder das schnelle Ausprobieren eines Befehls, bevor er zur Gewohnheit wird. Ein korrekt konfiguriertes *integriertes Terminal* verbindet beide Welten, ohne dass du zwischen Fenstern wechseln musst.

Unter Windows 11 ist diese Konfiguration nicht trivial, da mehrere Shells parallel existieren – **Git Bash**, **PowerShell** und **CMD** – und jede ihre eigenen Stärken sowie Eigenheiten bei Zeilenenden, Pfaden und Zeichenkodierung mitbringt.

---

## Terminal-Einstellungen öffnen

Die Konfiguration findest du unter:

```
Datei → Einstellungen → Werkzeuge → Terminal
```

Hier legst du fest, welche Shell standardmäßig gestartet wird, in welchem Verzeichnis das Terminal öffnet und wie es sich optisch sowie funktional verhält.

---

## Die richtige Shell auswählen

Für die Arbeit mit Git unter Windows kommen drei Kandidaten in Frage. Die Wahl beeinflusst, welche Befehle nativ funktionieren und wie Pfade interpretiert werden.

| Shell | Git-Integration | Besonderheiten | Empfehlung |
|---|---|---|---|
| **Git Bash** | Nativ, POSIX-kompatibel | Unix-Befehle wie `grep`, `sed`, `ls -la` verfügbar | *Standardwahl* für Git-Arbeit |
| **PowerShell** | Über Git for Windows nutzbar | Objektorientierte Pipeline, gute Skriptfähigkeiten | Für Automatisierung/Skripte |
| **CMD** | Funktional, aber eingeschränkt | Keine moderne Syntax, wenig Komfort | Nur bei Altlasten nötig |

Für nahezu alle Aufgaben in diesem Kurs ist **Git Bash** die sinnvollste Voreinstellung, da sie exakt dem Verhalten entspricht, das auch auf Linux- und macOS-Systemen üblich ist – ein klarer Vorteil, wenn du Anleitungen aus der offiziellen Git-Dokumentation eins zu eins übernehmen möchtest.

```mermaid
flowchart TD
    A["Aufgabe waehlen"] --> B{"Reine Git Befehle?"}
    B -->|Ja| C["Git Bash verwenden"]
    B -->|Nein| D{"Windows Automatisierung?"}
    D -->|Ja| E["PowerShell verwenden"]
    D -->|Nein| F["CMD nur bei Bedarf"]

    style C fill:#2e7d32,color:#ffffff
    style E fill:#1565c0,color:#ffffff
    style F fill:#616161,color:#ffffff
```

---

## Shell-Pfad korrekt hinterlegen

Damit PhpStorm Git Bash findet, muss der Pfad zur ausführbaren Datei exakt stimmen. Nach einer Standardinstallation von *Git for Windows* lautet er üblicherweise:

```
C:\Program Files\Git\bin\bash.exe
```

Trage diesen Pfad im Feld **Shell-Pfad** ein. Alternativ kannst du über die Schaltfläche mit dem Ordnersymbol direkt zur Datei navigieren, was Tippfehler vermeidet. Sollte PhpStorm die Shell nicht automatisch vorschlagen, ist dies meist ein Hinweis darauf, dass die Installation nicht in der PATH-Variable registriert wurde – ein Punkt, der bereits im vorherigen Kapitel geprüft wurde.

**Optionale Startparameter** kannst du im Feld *Shell-Pfad* direkt anhängen, etwa `--login -i`, um eine interaktive Login-Shell zu erzwingen und damit sicherzustellen, dass alle Umgebungsvariablen aus der `.bashrc` geladen werden.

---

## Startverzeichnis festlegen

Standardmäßig öffnet PhpStorm das Terminal im Stammverzeichnis des aktuellen Projekts. Das ist in der Regel die gewünschte Einstellung, da du sofort im richtigen Repository-Kontext arbeitest. Über die Option **Startverzeichnis** lässt sich dies bei Bedarf überschreiben – sinnvoll etwa bei Monorepo-Strukturen, in denen du meist in einem Unterordner arbeitest.

---

## Darstellung und Bedienkomfort

Für die tägliche Arbeit lohnt sich ein Blick auf folgende Einstellungen:

- **Schriftart und -größe**: Eine Monospace-Schrift mit guter Lesbarkeit für Zeichen wie `|`, `~` und `^`, die in Git-Befehlen häufig vorkommen.
- **Farbschema**: PhpStorm übernimmt standardmäßig das Editor-Farbschema; für Terminals ist oft ein dunkleres, kontrastreicheres Schema angenehmer.
- **Zeilenumbruch und Verlauf**: Die Anzahl der im Puffer gespeicherten Zeilen sollte großzügig bemessen sein, damit lange `git log`-Ausgaben nicht vorzeitig verworfen werden.
- **Kopieren bei Auswahl**: Diese Option beschleunigt das Übertragen von Commit-Hashes oder Branch-Namen erheblich, da kein explizites `Strg+C` nötig ist.

---

## Mehrere Terminals und Split-Ansicht

PhpStorm erlaubt beliebig viele Terminal-Tabs sowie eine horizontale oder vertikale Aufteilung innerhalb eines Tabs. In der Praxis hat sich folgende Aufteilung bewährt:

1. Ein Tab für allgemeine Git-Befehle (`status`, `log`, `diff`).
2. Ein Tab für laufende Prozesse wie `php artisan serve` oder Testläufe.
3. Bei Bedarf ein dritter Tab für Composer- oder npm-Befehle.

Diese Trennung verhindert, dass lange laufende Prozesse den Blick auf Git-Ausgaben verdecken.

---

## Zusammenspiel mit der Windows-Konfiguration

Da das integrierte Terminal letztlich dieselbe Git-Installation nutzt wie die eigenständige Git Bash aus Kapitel 2, gelten alle dort getroffenen Einstellungen unverändert weiter – insbesondere:

- `core.autocrlf` für die Behandlung von Zeilenenden,
- der konfigurierte Standard-Editor,
- der Credential Manager für die Authentifizierung.

Ein häufiger Stolperstein: Wird PhpStorm mit einem anderen Benutzerkontext oder über eine Verknüpfung mit abweichenden Umgebungsvariablen gestartet, kann das integrierte Terminal eine andere `PATH`-Variable sehen als eine manuell gestartete Git Bash. Im Zweifel hilft ein einfacher Test:

```bash
which git
git --version
echo $PATH
```

Weichen die Ausgaben von jenen ab, die du außerhalb von PhpStorm erhältst, liegt meist ein Konfigurationsproblem der Shell-Startdateien (`.bashrc`, `.bash_profile`) vor.

---

## Eigene Anpassungen dauerhaft einbinden

Wer regelmäßig mit Git-Aliasen oder Prompt-Anpassungen arbeitet, sollte diese nicht in PhpStorm selbst, sondern in der jeweiligen Shell-Konfigurationsdatei hinterlegen, damit sie unabhängig vom verwendeten Werkzeug greifen. Für Git Bash ist dies typischerweise die Datei:

```
~/.bashrc
```

Ein Beispiel für eine sinnvolle Ergänzung, die den aktuellen Branch direkt im Prompt anzeigt:

```bash
parse_git_branch() {
    git branch 2>/dev/null | sed -n '/\* /s///p'
}
export PS1='\u@\h \W$(parse_git_branch) \$ '
```

Nach dem Speichern lädst du die Datei im Terminal neu:

```bash
source ~/.bashrc
```

Diese Anpassung ist besonders wertvoll, weil sie *unabhängig* von PhpStorm funktioniert – ein Vorteil, sobald du auch außerhalb der IDE arbeitest.

---

## Terminal versus grafische Werkzeuge

Das integrierte Terminal ersetzt die GUI nicht, sondern ergänzt sie gezielt. Eine grobe Orientierung, wann welches Werkzeug vorzuziehen ist:

| Aufgabe | Empfohlenes Werkzeug |
|---|---|
| Einzelne Dateien stagen, Commit schreiben | *PhpStorm-Commit-Fenster* |
| Diffs visuell vergleichen | *PhpStorm-Diff-Ansicht* |
| Interaktiver Rebase mit vielen Commits | *Terminal* |
| Schnelle Statusprüfung zwischendurch | *Terminal* (`git status`) |
| Merge-Konflikte mit Drei-Wege-Ansicht | *PhpStorm-Merge-Werkzeug* |
| Plumbing- oder Debug-Befehle | *Terminal* |

Diese Faustregel wird dich durch den gesamten weiteren Kurs begleiten: Immer dort, wo Präzision und Geschwindigkeit der Tastatur gefragt sind, greifst du zum Terminal; immer dort, wo visuelle Übersicht zählt, nutzt du die grafischen Werkzeuge von PhpStorm.

---

## Kurzcheck zur Konfiguration

Bevor du mit dem nächsten Kapitel fortfährst, sollten folgende Punkte erfüllt sein:

- ✅ Git Bash ist als Standard-Shell im integrierten Terminal hinterlegt.
- ✅ `git --version` liefert im Terminal dieselbe Ausgabe wie außerhalb von PhpStorm.
- ✅ Das Startverzeichnis entspricht dem Projektstamm.
- ✅ Farbschema und Schriftgröße sind angenehm lesbar eingestellt.
- ✅ Eigene `.bashrc`-Anpassungen werden korrekt geladen.

Damit steht dir ein vollwertiges, produktiv nutzbares Terminal zur Verfügung, das nahtlos in den weiteren Kurs übergeht – etwa bei der Arbeit mit *Changelists* im nächsten Abschnitt.

# Changelists und Änderungsgruppen verwenden

## Die Idee hinter Changelists

Git selbst kennt nur *einen* Index – die Staging Area, in der alle vorgemerkten Änderungen unabhängig von ihrem thematischen Zusammenhang landen. PhpStorm erweitert dieses Modell um eine eigene, rein lokale Organisationsebene: **Changelists**. Sie gruppieren geänderte, hinzugefügte oder gelöschte Dateien nach thematischer Zugehörigkeit, *bevor* sie überhaupt zu einem Commit werden.

Das ist besonders dann wertvoll, wenn du an mehreren Aufgaben gleichzeitig arbeitest, ohne für jede sofort einen eigenen Branch anzulegen – etwa ein kleiner Bugfix „nebenbei“, während du an einem größeren Feature arbeitest. Changelists sorgen dafür, dass du diese Änderungen getrennt betrachten, einzeln committen und nicht versehentlich miteinander vermischen kannst.

> **Wichtig:** Changelists sind eine reine PhpStorm-Funktion. Sie werden nicht in Git gespeichert und existieren nicht auf der Kommandozeile. Ein Kollege, der dasselbe Repository ausschließlich mit `git` bearbeitet, sieht davon nichts.

## Die Standard-Changelist „Default“

Nach dem Öffnen eines Projekts legt PhpStorm automatisch eine Changelist mit dem Namen *Default* an. Alle neuen und geänderten Dateien landen zunächst dort, sofern du nichts anderes konfigurierst. Für einfache, lineare Arbeit reicht diese eine Liste völlig aus – erst bei paralleler oder verschachtelter Arbeit lohnt sich eine bewusste Aufteilung.

## Eine neue Changelist erstellen

Im **Commit**-Werkzeugfenster (siehe vorheriges Kapitel) kannst du zusätzliche Changelists anlegen:

1. Rechtsklick in den Bereich der Changelists → **New Changelist…**
2. Namen und optional eine Beschreibung vergeben
3. Festlegen, ob die neue Liste sofort **aktiv** werden soll

Die *aktive* Changelist ist diejenige, der PhpStorm automatisch neu erkannte oder neu hinzugefügte Dateien zuordnet. Es existiert immer genau eine aktive Changelist.

## Dateien zwischen Changelists verschieben

Änderungen lassen sich jederzeit einer anderen Changelist zuordnen:

- Datei im Commit-Fenster per **Drag & Drop** in eine andere Liste ziehen
- Über das Kontextmenü **Move to Another Changelist…** wählen
- Mehrere Dateien gleichzeitig markieren und gemeinsam verschieben

Das ist der zentrale Arbeitsschritt: Statt Änderungen nur über den Dateibaum zu betrachten, sortierst du sie inhaltlich – etwa „Bugfix Login“, „Refactoring Repository-Klasse“ oder „Experimentelle Änderung, noch nicht fertig“.

## Commits aus einzelnen Changelists erzeugen

Beim Commit im PhpStorm-Werkzeugfenster wählst du gezielt **eine** Changelist als Grundlage aus:

1. Changelist markieren, deren Inhalt committet werden soll
2. Über das Kontextmenü **Commit** oder den Commit-Button im Fenster ausführen
3. Nur die Dateien dieser Liste werden Bestandteil des Commits – alle anderen Changelists bleiben unangetastet

So entstehen saubere, thematisch klare Commits, selbst wenn im Arbeitsverzeichnis gleichzeitig mehrere unabhängige Änderungen offen sind – ganz ohne `git add -p` oder manuelles Selektieren einzelner Zeilen bei jedem Commit erneut.

```mermaid
flowchart LR
    A["Arbeitsverzeichnis mit vielen Aenderungen"] --> B["Changelist Bugfix"]
    A --> C["Changelist Feature"]
    A --> D["Changelist Experiment"]
    B --> E["Commit 1"]
    C --> F["Commit 2"]
    D -.->|bleibt offen| D
```

## Inaktive Changelists und ihr Nutzen

Eine Changelist muss nicht sofort committet werden. Du kannst sie beliebig lange „liegen lassen“, während du an einer anderen Liste weiterarbeitest. Das ist hilfreich für:

- **Angefangene, aber unfertige Experimente**, die noch nicht reif für einen Commit sind
- **Vorbereitete Änderungen für einen späteren Zeitpunkt**, etwa nach Abschluss eines Reviews
- **Getrennte Verantwortlichkeiten**, wenn du absichtlich mehrere kleine, unabhängige Themen parallel im selben Arbeitsverzeichnis verfolgst

## Changelists und Diffs

Jede Changelist besitzt eine eigene Diff-Übersicht. Ein Doppelklick auf eine Datei innerhalb einer Changelist öffnet den Diff nur für diese Datei – unabhängig davon, wie viele andere Änderungen im Projekt insgesamt offen sind. Das erleichtert die Kontrolle vor dem Commit erheblich, weil du dich ausschließlich auf den relevanten Ausschnitt konzentrierst.

## Abgrenzung zu Shelving

Changelists solltest du nicht mit dem *Shelf* verwechseln, einem verwandten, aber eigenständigen PhpStorm-Werkzeug:

| Merkmal | Changelist | Shelf |
| --- | --- | --- |
| Zweck | Thematische Gruppierung offener Änderungen | Temporäres Zurücklegen von Änderungen |
| Sichtbarkeit im Arbeitsverzeichnis | Ja, Dateien bleiben geändert sichtbar | Nein, Änderungen werden aus dem Arbeitsverzeichnis entfernt |
| Git-Äquivalent | Kein direktes Äquivalent | Ähnlich zu `git stash` |
| Typischer Einsatz | Parallele Commits vorbereiten | Kurzfristig „Platz schaffen“, z. B. für einen dringenden Branch-Wechsel |

Wenn du also nur kurzfristig störende Änderungen aus dem Weg räumen möchtest, ist der Shelf das passendere Werkzeug; für die dauerhafte, inhaltliche Organisation mehrerer parallel offener Themen sind Changelists die richtige Wahl.

## Praktische Hinweise für den Alltag

- **Sprechende Namen verwenden:** Eine Changelist namens „Fix #482 Validierung“ ist hilfreicher als „Changelist 2“.
- **Nicht zu granular arbeiten:** Für die meisten Aufgaben reicht die Default-Liste. Zusätzliche Changelists lohnen sich erst bei echter Parallelität.
- **Vor dem Commit prüfen:** Kontrolliere immer, welche Changelist aktuell aktiv ist, bevor du neue Dateien erstellst – sonst landen sie versehentlich in der falschen Gruppe.
- **Kein Ersatz für Branches:** Changelists ersetzen keine Branch-Strategie. Sie helfen bei kurzfristiger, lokaler Organisation, nicht bei langfristig getrennter Entwicklung.

Mit diesem Werkzeug behältst du auch in unübersichtlichen Arbeitsphasen die Kontrolle darüber, *was* in welchen Commit einfließt – ein wichtiger Baustein für die im nächsten Abschnitt behandelte Zuordnung von IDE-Aktionen zu den entsprechenden Git-Befehlen auf der Kommandozeile.

# IDE-Aktionen und CLI-Befehle zuordnen

## Warum diese Zuordnung wichtig ist

PhpStorm übersetzt jede Schaltfläche, jeden Menüpunkt und jede Diff-Ansicht letztlich in einen oder mehrere Git-Befehle, die im Hintergrund ausgeführt werden. Wer nur die Oberfläche bedient, ohne die zugrunde liegenden Kommandos zu kennen, gerät bei Fehlermeldungen, ungewöhnlichen Repository-Zuständen oder in fremden Umgebungen ohne IDE schnell an eine Grenze. Wer umgekehrt nur die Kommandozeile beherrscht, verschenkt die visuellen Vorteile von PhpStorm bei Diffs, Konflikten und Historienübersicht.

Dieses Kapitel schafft daher eine bewusste *Brücke*: Für jede zentrale IDE-Aktion wird der entsprechende Git-Befehl benannt, damit du jederzeit zwischen beiden Werkzeugen wechseln kannst – je nachdem, was in der jeweiligen Situation effizienter oder transparenter ist.

---

## Grundprinzip: PhpStorm ist eine Oberfläche über Git

PhpStorm ruft standardmäßig das auf deinem System installierte Git-Programm auf (siehe Abschnitt *„Git-Programm und Version prüfen“*). Es erzeugt keine eigene, abweichende Versionslogik. Das bedeutet:

- Jeder Commit über die Oberfläche entspricht exakt einem `git commit`.
- Jeder Branch-Wechsel entspricht einem `git switch` bzw. `git checkout`.
- Konflikte, Merges und Rebases folgen denselben internen Regeln wie auf der Kommandozeile.

Diese Deckungsgleichheit ist beabsichtigt und erlaubt es dir, ein und dasselbe Repository nahtlos mit beiden Werkzeugen zu bearbeiten – auch im Wechsel innerhalb eines Arbeitstages.

---

## Zuordnungstabelle: Kernaktionen

Die folgende Übersicht zeigt die wichtigsten Aktionen aus PhpStorms VCS-Menü, dem *Commit*-Werkzeugfenster und dem *Git*-Werkzeugfenster mit ihren CLI-Entsprechungen.

| PhpStorm-Aktion | Ort in der Oberfläche | Entsprechender Git-Befehl |
|---|---|---|
| Projekt unter Versionskontrolle stellen | *VCS → Enable Version Control Integration* | `git init` |
| Dateien vormerken | *Commit*-Fenster, Checkbox aktivieren | `git add <Datei>` |
| Commit erstellen | *Commit*-Fenster → *Commit* | `git commit -m "…"` |
| Commit und Push in einem Schritt | *Commit*-Fenster → *Commit and Push…* | `git commit -m "…"` gefolgt von `git push` |
| Letzten Commit ändern | *Commit*-Fenster → *Amend Commit* | `git commit --amend` |
| Änderungen ansehen | Doppelklick auf Datei im *Commit*-Fenster | `git diff` |
| Datei aus dem Commit ausschließen | Checkbox deaktivieren | `git restore --staged <Datei>` |
| Branch erstellen | *Git → Branches… → New Branch* | `git branch <Name>` oder `git checkout -b <Name>` |
| Branch wechseln | *Git → Branches…* → Branch auswählen → *Checkout* | `git switch <Name>` |
| Branches zusammenführen | *Git → Branches…* → *Merge into Current* | `git merge <Name>` |
| Rebase durchführen | *Git → Branches…* → *Rebase Current onto Selected* | `git rebase <Name>` |
| Änderungen abrufen | *Git → Fetch* | `git fetch` |
| Änderungen integrieren | *Git → Pull…* | `git pull` |
| Änderungen veröffentlichen | *Git → Push…* | `git push` |
| Arbeit zwischenlagern | *Git → Uncommitted Changes → Stash Changes…* | `git stash` |
| Stash anwenden | *Git → Uncommitted Changes → Unstash Changes…* | `git stash pop` bzw. `git stash apply` |
| Commit rückgängig machen | *Git → Uncommitted Changes* oder Log-Kontextmenü → *Revert Commit* | `git revert <Commit>` |
| Zu einem Commit zurücksetzen | Log-Kontextmenü → *Reset Current Branch to Here* | `git reset` |
| Datei-Historie ansehen | Rechtsklick auf Datei → *Git → Show History* | `git log --follow <Datei>` |
| Zeilenverantwortung prüfen | *Annotate*-Randleiste | `git blame <Datei>` |
| Repository klonen | *Get from VCS…* | `git clone <URL>` |

---

## Warum die Reihenfolge manchmal abweicht

Ein wichtiger Unterschied betrifft zusammengesetzte Aktionen. Der Button *Commit and Push* etwa führt intern zwei getrennte Git-Operationen aus, die auf der Kommandozeile ebenfalls zwei Befehle erfordern würden. PhpStorm bündelt dies lediglich komfortabel in einem Klick, ohne die eigentliche Git-Semantik zu verändern.

Ähnlich verhält es sich beim Branch-Wechsel mit gleichzeitigem Erstellen: *New Branch from Selected* entspricht `git checkout -b <Name> <Basis>` – ein einzelner CLI-Befehl, der in der IDE über einen kleinen Dialog abgebildet wird.

$$
\text{IDE-Aktion} \;=\; \text{ein oder mehrere Git-Befehle in fester Reihenfolge}
$$

---

## Entscheidungshilfe: IDE oder Kommandozeile?

```mermaid
flowchart TD
    A["Aufgabe steht an"] --> B{"Visuelle Übersicht nötig?"}
    B -->|Ja, z.B. Diff, Konflikt, Branch-Graph| C["PhpStorm verwenden"]
    B -->|Nein, einfacher Einzelbefehl| D{"Reproduzierbarkeit oder Skript nötig?"}
    D -->|Ja, z.B. CI, Automatisierung| E["Kommandozeile verwenden"]
    D -->|Nein, spontane Aktion| C

    style C fill:#2f6f4f,color:#ffffff
    style E fill:#37474f,color:#ffffff
```

Als grobe Faustregel gilt:

- **PhpStorm** eignet sich besonders für Diffs, Merge-Konflikte, Historienvergleiche und alles, was von einer visuellen Darstellung profitiert.
- **Die Kommandozeile** eignet sich für seltene, präzise Spezialbefehle, Automatisierung, Skripte und Situationen, in denen du exakt nachvollziehen musst, was passiert – etwa bei der Fehlersuche.

---

## Praktischer Tipp: Befehle in PhpStorm sichtbar machen

PhpStorm protokolliert die tatsächlich ausgeführten Git-Befehle im Werkzeugfenster **Version Control → Console**. Diese Ansicht ist besonders lehrreich: Jede Aktion, die du über Menüs auslöst, erscheint dort als exakter Befehl inklusive Parameter.

> **Empfehlung:** Aktiviere die *Console*-Registerkarte dauerhaft während der ersten Wochen mit PhpStorm. So verinnerlichst du die Zuordnung zwischen Oberfläche und Kommandozeile automatisch – ganz ohne Auswendiglernen.

Diese bewusste Verknüpfung beider Arbeitsweisen bildet die Grundlage für alle folgenden Kapitel, in denen Befehle und IDE-Funktionen gleichrangig und wechselseitig ergänzend eingesetzt werden.

# Das erste lokale Repository

Nun entsteht dein erstes Repository. Du initialisierst ein Projekt, prüfst seinen Zustand und verfolgst Dateien vom Arbeitsverzeichnis über die Staging Area bis zum Commit. Jeder Schritt wird sowohl mit Git-Befehlen als auch mit den entsprechenden Funktionen in PhpStorm durchgeführt.

# Ein Übungsprojekt anlegen

## Ziel dieses Abschnitts

Bevor du den ersten Befehl `git init` ausführst, brauchst du eine solide Ausgangsbasis: ein **Übungsprojekt**, an dem du die folgenden Kapitel gefahrlos durchspielen kannst. Dieses Projekt begleitet dich durch das gesamte vierte Kapitel – vom ersten Commit bis zum Vergleich von IDE- und Kommandozeilen-Workflow. Es lohnt sich daher, den Speicherort und die Struktur bewusst zu wählen, statt „irgendwo" schnell einen Ordner zu erstellen.

## Warum ein eigenes Testprojekt sinnvoll ist

Ein separates Übungsprojekt hat mehrere Vorteile gegenüber dem direkten Experimentieren in einem echten Arbeitsprojekt:

- **Risikofreiheit** – Fehlerhafte Commits, missglückte Resets oder gelöschte Dateien richten keinen Schaden an produktivem Code an.
- **Wiederholbarkeit** – Du kannst den Ordner jederzeit löschen und neu beginnen, wenn du dich „verrannt" hast.
- **Nachvollziehbarkeit** – Ein kleines, überschaubares Projekt macht `git log`, `git diff` und ähnliche Ausgaben leicht lesbar.
- **Übertragbarkeit** – Die hier erlernten Abläufe funktionieren identisch in jedem späteren PHP-Projekt.

## Den richtigen Speicherort wählen

Unter Windows 11 gibt es einige Fallstricke, die gerade Einsteiger häufig übersehen. Beachte folgende Punkte bereits *vor* dem Anlegen des Ordners:

### OneDrive vermeiden

Wenn dein Benutzerordner (`Dokumente`, `Desktop`) mit *OneDrive* synchronisiert wird, kann es zu Konflikten zwischen Git und dem Synchronisationsdienst kommen: OneDrive verändert Zeitstempel, sperrt Dateien kurzfristig oder synchronisiert das `.git`-Verzeichnis unnötig mit in die Cloud. Lege Übungsprojekte daher **außerhalb** synchronisierter Ordner ab, zum Beispiel direkt unter `C:\Users\<Name>\Projekte`.

### Kurze, einfache Pfade verwenden

Windows hatte historisch ein Limit von 260 Zeichen für Dateipfade. Auch wenn moderne Systeme lange Pfade unterstützen können (siehe Kapitel 2), ist es sinnvoll, tief verschachtelte Pfadstrukturen zu vermeiden. Ein Pfad wie

```
C:\Projekte\git-uebung
```

ist deutlich robuster als ein tief verschachtelter Pfad in einem OneDrive- oder Netzlaufwerk-Ordner.

### Keine Leerzeichen und Sonderzeichen im Ordnernamen

Leerzeichen, Umlaute oder Sonderzeichen im Projektpfad können in Kombination mit bestimmten Tools (Composer, PHPUnit, CI-Skripten) zu subtilen Fehlern führen. Verwende für den Ordnernamen ausschließlich Kleinbuchstaben, Ziffern und Bindestriche – ganz im Sinne späterer *Branch-Namenskonventionen* (siehe Kapitel 9).

## Projektstruktur planen

Für dieses Kapitel genügt ein sehr einfaches PHP-Projekt. Es soll klein bleiben, aber genügend Dateien enthalten, um sinnvolle Commits, Diffs und Umbenennungen zu demonstrieren:

```
git-uebung/
├── README.md
├── src/
│   └── Rechner.php
└── tests/
    └── RechnerTest.php
```

| Datei | Zweck |
|---|---|
| `README.md` | Kurzbeschreibung des Übungsprojekts |
| `src/Rechner.php` | Einfache PHP-Klasse als Beispielcode |
| `tests/RechnerTest.php` | Platzhalter für spätere Testübungen |

Diese Struktur reicht aus, um im weiteren Verlauf des Kapitels Dateien hinzuzufügen, zu ändern, umzubenennen und zu entfernen.

## Ordner und Dateien anlegen

Du kannst das Projekt sowohl über die Kommandozeile als auch über den Windows-Explorer anlegen. Für die Konsistenz mit späteren Kapiteln empfiehlt sich der Weg über *Git Bash* oder *PowerShell*.

### Variante 1: Git Bash

```bash
mkdir -p ~/Projekte/git-uebung/src
mkdir -p ~/Projekte/git-uebung/tests
cd ~/Projekte/git-uebung

echo "# Git-Übungsprojekt" > README.md
```

### Variante 2: PowerShell

```powershell
New-Item -ItemType Directory -Path "C:\Projekte\git-uebung\src" -Force
New-Item -ItemType Directory -Path "C:\Projekte\git-uebung\tests" -Force
Set-Location "C:\Projekte\git-uebung"

"# Git-Übungsprojekt" | Out-File -Encoding utf8 README.md
```

*Hinweis:* Achte in PowerShell auf die Kodierung. Git arbeitet intern mit UTF-8; Dateien, die PowerShell standardmäßig in UTF-16 speichert, können später zu unerwarteten Diffs führen (siehe Kapitel 29 zu `.gitattributes`).

### Beispielinhalt für `src/Rechner.php`

```php
<?php

declare(strict_types=1);

final class Rechner
{
    public function addieren(int $a, int $b): int
    {
        return $a + $b;
    }
}
```

### Beispielinhalt für `tests/RechnerTest.php`

```php
<?php

declare(strict_types=1);

// Platzhalter für spätere PHPUnit-Übungen.
```

Diese Dateien sind bewusst einfach gehalten – der Schwerpunkt dieses Kapitels liegt auf Git, nicht auf PHP-Architektur.

## Projekt in PhpStorm öffnen

Nachdem die Ordnerstruktur steht, öffnest du sie in PhpStorm, um beide Arbeitswege – Terminal und IDE – parallel nutzen zu können:

1. Starte PhpStorm und wähle **Datei → Öffnen…**.
2. Navigiere zum Ordner `git-uebung` und bestätige mit **OK**.
3. Wähle im folgenden Dialog **Als vertrauenswürdiges Projekt öffnen**, damit PhpStorm Indizierung und Codeanalyse ausführen darf.
4. Warte, bis die Indizierung abgeschlossen ist – erkennbar am Fortschrittsbalken unten rechts.

Zu diesem Zeitpunkt ist das Projekt noch **kein** Git-Repository. Das ändert sich erst im nächsten Abschnitt mit `git init` – bewusst als eigener, klar abgegrenzter Schritt.

## Checkliste vor dem nächsten Schritt

Bevor du weiterliest, sollten folgende Punkte erfüllt sein:

- [ ] Projektordner liegt außerhalb von OneDrive oder anderen Cloud-Synchronisationsordnern.
- [ ] Pfad ist kurz, enthält keine Leerzeichen oder Sonderzeichen.
- [ ] Ordnerstruktur mit `src/`, `tests/` und `README.md` ist vorhanden.
- [ ] Projekt ist in PhpStorm geöffnet und vollständig indiziert.
- [ ] Terminal (Git Bash oder PowerShell) ist im Projektordner geöffnet und einsatzbereit.

Mit dieser Grundlage bist du bereit für den eigentlichen Einstieg: die Initialisierung des Repositories mit `git init` und einem ersten Blick in das dabei entstehende `.git`-Verzeichnis.

# git init und das .git-Verzeichnis

## Der Moment, in dem ein Repository entsteht

Bevor Git eine einzige Datei verfolgen kann, muss es einen Ort haben, an dem es seine gesamte Buchführung ablegt. Genau das leistet der Befehl `git init`: Er verwandelt ein gewöhnliches Verzeichnis in ein *Git-Repository*, indem er darin ein verstecktes Unterverzeichnis namens `.git` anlegt. Dieses Verzeichnis ist keine Nebensächlichkeit – es *ist* das Repository. Alles, was du später über Commits, Branches, Remotes oder die Historie erfährst, ist letztlich nur eine strukturierte Sammlung von Dateien innerhalb dieses einen Ordners.

In diesem Abschnitt öffnest du das `.git`-Verzeichnis bewusst, statt es als Blackbox zu behandeln. Das schafft ein solides mentales Modell für alles Folgende.

### `git init` ausführen

Wechsle in Git Bash oder PowerShell in dein Übungsprojekt und führe aus:

```bash
cd C:\Users\DeinName\Projekte\uebungsprojekt
git init
```

Die Ausgabe sieht sinngemäß so aus:

```
Initialized empty Git repository in C:/Users/DeinName/Projekte/uebungsprojekt/.git/
```

Wichtig ist die Formulierung *„empty Git repository“*. Es wurden noch keine Dateien verfolgt, kein Commit erstellt – lediglich das Grundgerüst wurde angelegt. Ein Repository existiert also bereits, bevor überhaupt ein Commit gemacht wurde.

> **Hinweis:** Seit neueren Git-Versionen kannst du den initialen Branch direkt festlegen, etwa mit `git init -b main`. Das ist besonders unter Windows sinnvoll, da die Standardeinstellung je nach Konfiguration variieren kann (siehe Kapitel 2, Abschnitt *„Standard-Branch und Standard-Editor festlegen“*).

### Das `.git`-Verzeichnis sichtbar machen

Unter Windows 11 sind versteckte Dateien standardmäßig ausgeblendet. Um `.git` im Windows-Explorer zu sehen, aktiviere unter *Ansicht → Ausgeblendete Elemente* die Anzeige versteckter Ordner. Schneller geht es über die Kommandozeile:

```bash
ls -la
```

In PowerShell:

```powershell
Get-ChildItem -Force
```

Du solltest neben deinen Projektdateien einen Eintrag `.git` sehen – ein Verzeichnis, kein Symlink, keine spezielle Systemdatei. Das ist bewusst so gestaltet: Git funktioniert vollständig lokal und plattformunabhängig, ohne Betriebssystem-Dienste oder Datenbanken.

### Struktur des `.git`-Verzeichnisses

Wirf einen Blick in den Inhalt:

```bash
ls -la .git
```

Ein frisch initialisiertes Repository enthält typischerweise folgende Elemente:

| Element | Bedeutung |
|---|---|
| `HEAD` | Zeigt symbolisch auf den aktuell aktiven Branch |
| `config` | Repository-spezifische Konfiguration |
| `description` | Beschreibungstext, relevant für ältere Web-Oberflächen wie GitWeb |
| `hooks/` | Vorlagen für clientseitige und serverseitige Hooks |
| `info/` | Lokale Ausschlussregeln und Metainformationen |
| `objects/` | Der eigentliche Objektspeicher für Blobs, Trees und Commits |
| `refs/` | Referenzen auf Branches und Tags |

Zum aktuellen Zeitpunkt sind `objects/` und `refs/` noch weitgehend leer – schließlich wurde noch kein Inhalt committet. Das ändert sich, sobald du im nächsten Abschnitt deinen ersten Commit erstellst.

### `HEAD`: der Zeiger auf die Gegenwart

Öffne die Datei `HEAD` in einem Texteditor oder gib ihren Inhalt aus:

```bash
cat .git/HEAD
```

Die Ausgabe lautet üblicherweise:

```
ref: refs/heads/main
```

Das bedeutet: `HEAD` verweist nicht direkt auf einen Commit, sondern *symbolisch* auf einen Branch – konkret auf `refs/heads/main`. Da dieser Branch noch keinen Commit besitzt, existiert die referenzierte Datei `refs/heads/main` momentan noch gar nicht. Erst der erste Commit erzeugt sie. Dieses Verhalten ist ein gutes Beispiel dafür, dass Git mit *Verweisen auf Verweise* arbeitet – ein Konzept, das in Kapitel 23 vertieft wird.

### `config`: lokale Einstellungen

Die Datei `.git/config` enthält repository-spezifische Konfiguration, die Vorrang vor globalen Einstellungen hat:

```bash
cat .git/config
```

Direkt nach `git init` findest du dort meist nur einen minimalen Abschnitt:

```ini
[core]
    repositoryformatversion = 0
    filemode = false
    bare = false
    symlinks = false
    ignorecase = true
```

Bemerkenswert für Windows-Nutzer sind besonders `filemode = false` und `ignorecase = true` – beide spiegeln Eigenschaften des NTFS-Dateisystems wider und werden in Kapitel 29 im Detail erklärt.

### `objects/` und `refs/`: die beiden tragenden Säulen

Auch wenn diese Verzeichnisse aktuell leer wirken, lohnt sich ein kurzer Blick:

```bash
ls .git/objects
ls .git/refs
```

`objects/` wird später sämtliche Inhalte deines Projekts als inhaltsadressierte, unveränderliche Objekte speichern – Kapitel 22 widmet sich diesem *Content-Addressable Storage* ausführlich. `refs/` enthält die Unterordner `heads` und `tags`, die Branches beziehungsweise Tags als einfache Textdateien mit einem Commit-Hash abbilden.

### Visualisierung des Zusammenhangs

Das folgende Diagramm zeigt, wie die zentralen Bestandteile direkt nach `git init` zusammenhängen:

```mermaid
graph TD
    A["Arbeitsverzeichnis"] -->|git init| B[".git Verzeichnis"]
    B --> C["HEAD - verweist auf refs/heads/main"]
    B --> D["config - lokale Einstellungen"]
    B --> E["objects - noch leer"]
    B --> F["refs/heads - noch leer"]
    C -.->|symbolischer Verweis| F

    style B fill:#2f3b52,color:#ffffff
    style C fill:#3b5b3b,color:#ffffff
```

Der gestrichelte Pfeil verdeutlicht, dass `HEAD` lediglich *symbolisch* auf `refs/heads/main` zeigt – ein Ziel, das erst mit dem ersten Commit real wird.

### Ein bestehendes Verzeichnis erneut initialisieren

Führst du `git init` in einem Verzeichnis aus, das bereits ein Repository ist, richtet Git keinen Schaden an. Der Befehl ist *idempotent*: Bestehende Konfiguration, Objekte und Referenzen bleiben unverändert, Git meldet lediglich eine Reinitialisierung:

```
Reinitialized existing Git repository in ...
```

Das ist nützlich, wenn du beispielsweise versehentlich gelöschte Vorlagendateien in `hooks/` wiederherstellen möchtest, ohne die eigentliche Historie zu gefährden.

### Ein Repository wieder entfernen

Da das gesamte Repository ausschließlich im `.git`-Verzeichnis lebt, genügt dessen Löschung, um alle Versionsinformationen vollständig und unwiderruflich zu entfernen – deine eigentlichen Projektdateien bleiben dabei unberührt:

```powershell
Remove-Item -Recurse -Force .git
```

Dies solltest du nur bewusst und niemals in einem produktiven Projekt ohne Sicherung ausführen. Es demonstriert aber sehr eindringlich, dass Git keine externe Datenbank, sondern schlicht ein gut organisiertes Dateisystem nutzt.

### Blick in PhpStorm

Öffnest du das gerade initialisierte Verzeichnis in PhpStorm, erkennt die IDE das Repository automatisch anhand des `.git`-Ordners und aktiviert die VCS-Funktionen im Menü *Git*. PhpStorm blendet `.git` standardmäßig aus der Projektübersicht aus, da es sich um Metadaten und nicht um Projektinhalt handelt. Über *Einstellungen → Editor → File Types* lässt sich diese Ausblendung zwar anpassen, für den Alltag ist sie jedoch sinnvoll: Du arbeitest mit den komfortablen Werkzeugen der IDE, während das rohe `.git`-Verzeichnis unangetastet im Hintergrund verwaltet wird.

### Zwischenfazit

Mit `git init` hast du kein „Werkzeug gestartet“, sondern eine konkrete, inspizierbare Datenstruktur erzeugt. `HEAD`, `config`, `objects/` und `refs/` sind keine abstrakten Begriffe, sondern reale Dateien und Verzeichnisse, die du jederzeit öffnen kannst. Dieses Verständnis trägt dich durch den gesamten Kurs: Jeder spätere Befehl – ob `commit`, `branch`, `merge` oder `reset` – verändert am Ende nichts anderes als genau diese Dateien im `.git`-Verzeichnis.

Im nächsten Abschnitt nutzt du `git status`, um den aktuellen Zustand deines frisch initialisierten Repositorys systematisch zu lesen, bevor du die erste Datei zur Nachverfolgung vormerkst. 🗂️

# Den Zustand mit git status prüfen

## Den Zustand mit `git status` prüfen

Bevor du irgendeine Git-Operation ausführst – einen Commit erstellst, einen Branch wechselst oder Änderungen verwirfst – solltest du dir eine Frage stellen: *„In welchem Zustand befindet sich mein Repository gerade?“* Der Befehl `git status` ist die Antwort darauf. Er ist der wichtigste diagnostische Befehl in Git und sollte zur Selbstverständlichkeit werden, ähnlich wie ein Blick in den Rückspiegel vor dem Ausparken.

### Warum dieser Befehl so zentral ist

Git verändert nichts an deinen Dateien, ohne dass du es ausdrücklich anforderst. Das bedeutet aber auch: Es liegt an dir, jederzeit zu wissen, *was* sich im Arbeitsverzeichnis, in der Staging Area und im Repository befindet. `git status` liefert genau diese Momentaufnahme – ohne Nebenwirkungen, ohne Risiko. Er verändert niemals Dateien oder die Historie; du kannst ihn beliebig oft aufrufen.

> 💡 **Merksatz:** Im Zweifel `git status` ausführen – dieser Befehl kostet nichts und schützt vor teuren Fehlern.

### Grundlegender Aufruf

Im Übungsprojekt aus dem vorherigen Abschnitt reicht ein einfacher Aufruf:

```bash
git status
```

Direkt nach `git init`, wenn das Repository noch leer ist, liefert Git etwa folgende Ausgabe:

```text
Auf Branch main

Noch keine Commits

Nichts zu committen
```

Diese Ausgabe bestätigt drei wichtige Informationen gleichzeitig:

1. **Aktueller Branch** – hier `main`, der Standard-Branch.
2. **Commit-Historie** – es existiert noch kein einziger Commit.
3. **Arbeitsverzeichnis** – es gibt keine Änderungen, die Git registriert hat.

### Der typische Aufbau der Ausgabe

Sobald Dateien im Projekt vorhanden sind, wird die Ausgabe deutlich informativer. Angenommen, du hast eine neue Datei `index.php` erstellt:

```bash
git status
```

```text
Auf Branch main

Noch keine Commits

Unversionierte Dateien:
  (benutze "git add <Datei>..." zum Aufnehmen in das, was committet wird)
        index.php

nichts zum Commit vorgemerkt, aber es gibt unversionierte Dateien
(benutze "git add" zum Aufnehmen)
```

Diese Struktur begleitet dich durch den gesamten Kurs. Git gliedert die Ausgabe grundsätzlich in folgende Abschnitte:

| Abschnitt | Bedeutung |
|---|---|
| *Änderungen, die committet werden* | Inhalte in der Staging Area – bereit für den nächsten Commit |
| *Änderungen, die nicht zum Commit vorgemerkt sind* | Bereits verfolgte Dateien mit ungespeicherten Änderungen |
| *Unversionierte Dateien* | Dateien, die Git noch nicht kennt |

Besonders hilfreich: Git formuliert unter jeder Kategorie direkt den passenden Befehl, um den Zustand zu ändern. Diese Hinweistexte lohnt es sich, in den ersten Wochen bewusst zu lesen, statt sie zu überspringen.

### Den Zustand nach `git add` beobachten

Merke einen Teil der Datei nun mit `git add` vor:

```bash
git add index.php
git status
```

```text
Auf Branch main

Noch keine Commits

Änderungen, die committet werden:
  (benutze "git rm --cached <Datei>..." zum Entfernen aus der Staging-Area)
        neue Datei:     index.php
```

Die Datei ist jetzt aus der Kategorie *unversioniert* in die Kategorie *committen* gewandert. Genau dieses Verschieben zwischen den drei Bereichen – Arbeitsverzeichnis, Index und Repository – ist der Kern dessen, was `git status` sichtbar macht. Kapitel 5 vertieft dieses Modell; hier lernst du bereits, es praktisch zu beobachten.

### Zustand nach einem Commit und weiteren Änderungen

Nach dem ersten Commit (siehe folgender Abschnitt dieses Kapitels) ändert sich die Ausgabe erneut. Bearbeitest du `index.php` danach weiter, zeigt `git status` beispielsweise:

```text
Auf Branch main
Änderungen, die nicht zum Commit vorgemerkt sind:
  (benutze "git add <Datei>..." zum Aktualisieren, was committet werden soll)
  (benutze "git restore <Datei>..." zum Verwerfen von Änderungen im Arbeitsverzeichnis)
        geändert:       index.php

keine Änderungen zum Commit vorgemerkt (benutze "git add" und/oder "git commit -a")
```

Beachte den Unterschied zur vorherigen Ausgabe: Es fehlt der Hinweis *„Noch keine Commits“*, da bereits ein Commit existiert. Zudem erscheint jetzt die Kategorie *geändert* statt *neue Datei*, weil Git die Datei bereits aus einem früheren Commit kennt.

### Kurzform mit `git status -s`

Für den täglichen Gebrauch ist die ausführliche Ausgabe oft zu lang. Die Kurzform liefert dieselben Informationen kompakt:

```bash
git status -s
```

```text
 M index.php
?? notizen.txt
```

Die beiden Buchstaben links stehen jeweils für den **Index-Status** und den **Arbeitsverzeichnis-Status** einer Datei. Die wichtigsten Codes im Überblick:

| Code | Bedeutung |
|---|---|
| `??` | Unversionierte Datei |
| ` M` | Geändert, aber nicht vorgemerkt |
| `M ` | Geändert und vorgemerkt |
| `A ` | Neu hinzugefügt und vorgemerkt |
| `D ` | Gelöscht und vorgemerkt |
| `UU` | Merge-Konflikt in dieser Datei |

Diese Kurzform ist besonders nützlich, wenn du `git status` in eigene Aliase oder Skripte einbindest (siehe Kapitel 26).

### Branch- und Tracking-Informationen

`git status` zeigt zusätzlich an, wie dein lokaler Branch im Vergleich zu seinem Remote-Gegenstück steht – sobald ein Remote-Tracking existiert (Kapitel 13 und 14 behandeln dies ausführlich):

```text
Auf Branch main
Ihr Branch ist auf demselben Stand wie 'origin/main'.
```

Oder, falls du bereits lokale Commits hast, die noch nicht veröffentlicht wurden:

```text
Auf Branch main
Ihr Branch ist 2 Commits vor 'origin/main'.
  (benutze "git push", um lokale Commits zu veröffentlichen)
```

Diese Information bewahrt dich davor, versehentlich unveröffentlichte Arbeit zu verlieren oder zu überschreiben.

### `git status` in PhpStorm

PhpStorm zeigt denselben Zustand grafisch an, ohne dass du die Kommandozeile öffnen musst:

- Im **Projektbaum** werden Dateien farblich markiert: Blau für geänderte, Grün für neue (unversionierte) und Grau für ignorierte Dateien.
- Das **Commit-Werkzeugfenster** (`Alt` + `0`) listet alle geänderten und unversionierten Dateien strukturiert nach Changelists auf.
- Die **Statusleiste** unten zeigt den aktuellen Branch sowie die Anzahl ausstehender Änderungen.

```mermaid
flowchart LR
    A["Arbeitsverzeichnis"] -->|unversioniert / geändert| B["git status Ausgabe"]
    C["Staging Area / Index"] -->|vorgemerkt| B
    D["Letzter Commit"] -->|Vergleichsbasis| B
    B --> E["Entscheidung: add, restore, commit"]
```

Die farbliche Kennzeichnung in PhpStorm ist letztlich nichts anderes als eine visuelle Aufbereitung derselben Informationen, die `git status` textuell liefert. Wer beide Darstellungen kennt, kann flexibel zwischen grafischer Übersicht und präziser Kommandozeilenkontrolle wechseln.

### Praktische Gewohnheit etablieren

Für den weiteren Kursverlauf empfiehlt sich folgende Routine, die du ab jetzt konsequent anwenden solltest:

1. **Vor** jeder Aktion: `git status`, um den Ausgangszustand zu kennen.
2. **Nach** jeder Aktion (`add`, `commit`, `checkout`, `merge` etc.): erneut `git status`, um die Wirkung zu bestätigen.
3. Bei unklaren oder unerwarteten Meldungen: die Hinweistexte in der Ausgabe genau lesen, bevor du einen Befehl aus dem Gedächtnis ausführst.

Diese Disziplin verhindert die meisten Anfängerfehler, die in Abschnitt 1.8 bereits angesprochen wurden – etwa das versehentliche Committen unfertiger Dateien oder das Verwerfen von Änderungen, die eigentlich behalten werden sollten. `git status` ist damit nicht nur ein Informationsbefehl, sondern dein wichtigstes Sicherheitsnetz im gesamten Git-Alltag.

# Dateien mit git add vormerken

## Dateien mit `git add` vormerken

Nachdem du mit `git status` den Zustand deines Projekts eingeordnet hast, folgt der nächste logische Schritt: Du entscheidest bewusst, *welche* Änderungen Teil des nächsten Commits werden sollen. Genau das ist die Aufgabe von `git add` – dem Befehl, mit dem Dateien in die sogenannte *Staging Area* (auch *Index* genannt) aufgenommen werden.

### Vom Arbeitsverzeichnis in den Index

Git trennt bewusst zwischen dem, was in deinen Dateien steht, und dem, was tatsächlich im nächsten Commit landen soll. Diese Trennung ist kein technisches Detail, sondern eines der zentralen Konzepte von Git überhaupt – sie wird in Kapitel 5 vertieft. An dieser Stelle reicht folgendes Modell:

```mermaid
flowchart LR
    A["Arbeitsverzeichnis"] -->|git add| B["Staging Area Index"]
    B -->|git commit| C["Repository .git"]
```

`git add` kopiert also nicht einfach eine Datei, sondern merkt den *aktuellen Inhalt* dieser Datei für den nächsten Commit vor. Änderst du die Datei danach erneut, musst du sie erneut hinzufügen – ein Verhalten, das anfangs oft verwundert, aber sehr präzise Kontrolle ermöglicht.

### Der Grundbefehl

Am einfachsten fügst du eine einzelne Datei hinzu:

```bash
git add index.php
```

Mehrere Dateien lassen sich in einem Aufruf übergeben:

```bash
git add index.php composer.json README.md
```

Auch Wildcards funktionieren, sofern deine Shell sie unterstützt:

```bash
git add src/*.php
```

### Ganze Verzeichnisse und das Projekt komplett stagen

Für PHP-Projekte mit mehreren Verzeichnissen – etwa `src/`, `tests/` und `public/` – ist es oft praktischer, ganze Ordner vorzumerken:

```bash
git add src
git add tests
```

Willst du *alle* Änderungen im aktuellen Verzeichnis und dessen Unterverzeichnissen erfassen, verwendest du:

```bash
git add .
```

Wichtig: Der Punkt bezieht sich auf das aktuelle Arbeitsverzeichnis. Führst du den Befehl aus einem Unterordner aus, werden auch nur dessen Inhalte berücksichtigt – nicht das gesamte Repository.

### `git add .` vs. `git add -A` vs. `git add -u`

Diese drei Varianten werden häufig verwechselt, unterscheiden sich aber in einem entscheidenden Punkt: dem Umgang mit **gelöschten** Dateien.

| Befehl | Neue Dateien | Geänderte Dateien | Gelöschte Dateien | Bereich |
|---|---|---|---|---|
| `git add .` | ✔️ | ✔️ | ✔️ *(moderne Git-Versionen)* | Aktuelles Verzeichnis abwärts |
| `git add -A` | ✔️ | ✔️ | ✔️ | Gesamtes Repository |
| `git add -u` | ❌ | ✔️ | ✔️ | Gesamtes Repository, nur verfolgte Dateien |

*Hinweis:* Seit Git 2.x verhält sich `git add .` im gesamten Repository-Kontext praktisch identisch zu `git add -A`, sofern du dich im Wurzelverzeichnis befindest. In älteren Versionen gab es hier Unterschiede – solltest du auf ein Legacy-System stoßen, prüfe das Verhalten sicherheitshalber mit `git status`.

### Den Effekt kontrollieren

`git add` verändert nichts sichtbar an deinen Dateien – der Effekt zeigt sich ausschließlich im Status:

```bash
git status
```

Vor dem Staging:

```
Untracked files:
  (use "git add <file>..." to include in what will be committed)
        src/Calculator.php
```

Nach `git add src/Calculator.php`:

```
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        new file:   src/Calculator.php
```

Diese farbliche und textuelle Unterscheidung zwischen *„Changes not staged“* und *„Changes to be committed“* ist eine der wichtigsten Orientierungshilfen im täglichen Git-Alltag.

### Ein praktisches Beispiel

Angenommen, du arbeitest an einem kleinen PHP-Projekt und hast folgende Änderungen vorliegen:

- eine neue Klasse `src/Calculator.php`
- eine geänderte `composer.json`
- eine gelöschte, nicht mehr benötigte Datei `legacy.php`

```bash
git status
```

```
Changes not staged for commit:
        modified:   composer.json
        deleted:    legacy.php

Untracked files:
        src/Calculator.php
```

Möchtest du **alles** in den nächsten Commit übernehmen:

```bash
git add -A
```

Möchtest du hingegen nur die neue Klasse vormerken und die anderen Änderungen bewusst für einen späteren, separaten Commit zurückhalten:

```bash
git add src/Calculator.php
```

`git status` zeigt danach exakt, was gestaged ist und was noch offen bleibt – ein zentrales Werkzeug, um Commits klein und thematisch sauber zu halten (siehe Kapitel 6).

### Ein häufiges Missverständnis

Ein weit verbreiteter Irrtum lautet: *„git add speichert meine Datei.“* Das ist nicht korrekt. `git add` verändert **nur den Index**, nicht das Repository. Erst `git commit` überführt den Inhalt des Index dauerhaft in die Historie. Bis dahin lässt sich jede Vormerkung problemlos wieder zurücknehmen – etwa mit:

```bash
git restore --staged <datei>
```

Diese Rücknahme wird in Kapitel 5 ausführlich behandelt; wichtig ist an dieser Stelle nur das Bewusstsein, dass Staging ein **reversibler Zwischenschritt** ist.

### Selektives Vorgehen als Gewohnheit

Auch wenn `git add -A` in vielen Situationen bequem erscheint, lohnt es sich, frühzeitig ein bewussteres Vorgehen einzuüben:

1. Änderungen mit `git status` und `git diff` sichten.
2. Nur thematisch zusammengehörige Dateien stagen.
3. Bei Bedarf mit `git status` erneut prüfen, ob wirklich nur das Gewünschte vorgemerkt ist.
4. Erst dann committen.

Diese Reihenfolge verhindert eines der häufigsten Anfängerprobleme: Commits, die versehentlich unfertigen Code, temporäre Debug-Ausgaben oder unabsichtlich geänderte Konfigurationsdateien enthalten.

### Ausblick

Der hier vorgestellte Grundmechanismus reicht für den Einstieg vollkommen aus. Im weiteren Kursverlauf – insbesondere in Kapitel 5 – vertiefst du das Staging deutlich: interaktives Hinzufügen einzelner Codeblöcke mit `git add -p`, das gezielte Entfernen aus dem Index sowie die Diagnose komplexer Zustände. Zunächst genügt es, den zentralen Grundsatz verinnerlicht zu haben:

> *Nichts gelangt in einen Commit, das nicht zuvor bewusst mit `git add` vorgemerkt wurde.*

Damit ist die Grundlage gelegt, um im nächsten Abschnitt den ersten echten Commit zu erstellen.

# Den ersten Commit erstellen

## Vom Index zum Commit

Nachdem du Dateien mit `git add` in die *Staging Area* aufgenommen hast, liegt der nächste Schritt nahe: Aus den vorgemerkten Änderungen wird ein **Commit** – ein unveränderlicher Schnappschuss deines Projekts zu einem bestimmten Zeitpunkt. Anders als der Name „Speichern“ vermuten lässt, erzeugt ein Commit keine einzelne Momentaufnahme einer Datei, sondern einen vollständigen, in sich geschlossenen Zustand des gesamten Repositorys.

Technisch betrachtet geschieht dabei Folgendes:

1. Git erstellt aus dem Inhalt der Staging Area einen sogenannten *Tree*, der die aktuelle Verzeichnisstruktur abbildet.
2. Ein neues *Commit-Objekt* verweist auf diesen Tree, auf den vorherigen Commit (den *Parent*) sowie auf Autor, Zeitstempel und Nachricht.
3. Der aktuelle Branch-Zeiger – meist `main` – wird auf dieses neue Commit-Objekt verschoben.

Diese internen Zusammenhänge vertiefst du später in Kapitel 22 „Git unter der Haube“. Für den praktischen Einstieg reicht es, den Commit als bewussten, benannten Kontrollpunkt in der Projektgeschichte zu verstehen.

---

## Voraussetzung: Ein saubere Staging Area

Bevor du committest, lohnt sich ein kurzer Blick mit `git status`:

```bash
git status
```

```text
Auf Branch main

Zum Commit vorgemerkte Änderungen:
  (benutze "git restore --staged <Datei>..." zum Entfernen aus der Staging Area)
        neue Datei:     README.md
```

Nur was hier unter *„Zum Commit vorgemerkte Änderungen“* aufgeführt ist, wird tatsächlich Teil des Commits. Dateien im Arbeitsverzeichnis, die noch nicht mit `git add` vorgemerkt wurden, bleiben unberührt – ein wichtiger Sicherheitsmechanismus, den du bereits in Kapitel 5 kennengelernt hast.

---

## Den Commit erstellen

### Mit einer kurzen Nachricht direkt in der Kommandozeile

Der schnellste und im Alltag häufigste Weg verwendet die Option `-m`:

```bash
git commit -m "Initiale Projektstruktur hinzufügen"
```

Git bestätigt den Vorgang mit einer kurzen Zusammenfassung:

```text
[main (Root-Commit) a1b2c3d] Initiale Projektstruktur hinzufügen
 1 file changed, 12 insertions(+)
 create mode 100644 README.md
```

Diese Ausgabe enthält bereits drei wichtige Informationen:

- den **Branch**, auf dem der Commit liegt (`main`),
- den Hinweis **Root-Commit**, da es sich um den allerersten Commit im Repository handelt,
- die ersten Zeichen des **Commit-Hashes** (`a1b2c3d`), über den sich der Commit später eindeutig identifizieren lässt.

### Mit dem konfigurierten Editor

Lässt du `-m` weg, öffnet Git den in Kapitel 2 festgelegten Standard-Editor:

```bash
git commit
```

Das ist besonders bei umfangreicheren Änderungen sinnvoll, da sich im Editor eine mehrzeilige Nachricht mit Betreff, Leerzeile und ausführlicher Beschreibung formulieren lässt:

```text
Formular zur Benutzerregistrierung hinzufügen

Implementiert Validierung für E-Mail und Passwort.
Bezieht sich auf Issue #12.
```

Speicherst du die Datei und schließt den Editor, wird der Commit erstellt. Ein leerer Editorinhalt bricht den Vorgang dagegen ab – eine bewusste Schutzmaßnahme gegen Commits ohne Nachricht.

> 💡 **Hinweis für Windows 11:** Falls sich kein Editor öffnet oder Git Bash mit einer Fehlermeldung wie `error: cannot spawn` reagiert, wurde der Editor in `core.editor` vermutlich falsch konfiguriert. Kapitel 2 zeigt, wie du das korrigierst.

---

## Anforderungen an eine gute Commit-Nachricht

Eine ausführliche Behandlung von Commit-Konventionen folgt in Kapitel 6. Für den Einstieg gelten drei einfache Regeln:

| Regel | Beispiel |
|---|---|
| Im Imperativ formulieren | „Login-Validierung hinzufügen“ statt „Habe Validierung hinzugefügt“ |
| Kurz und aussagekräftig | Erste Zeile idealerweise unter 50–72 Zeichen |
| Eine Änderung, eine Absicht | Nicht mehrere unabhängige Themen in einem Commit vermischen |

Eine unpräzise Nachricht wie `"update"` oder `"fix"` mag im Moment praktisch erscheinen, erschwert aber jede spätere Auswertung mit `git log` oder `git blame` erheblich.

---

## Wer steckt hinter einem Commit?

Jeder Commit speichert automatisch Autor und Zeitstempel – basierend auf den Werten, die du in Kapitel 2 mit `git config` gesetzt hast:

```bash
git config user.name
git config user.email
```

Diese Angaben lassen sich für einen einzelnen Commit auch gezielt überschreiben, etwa bei Pair-Programming oder Testcommits:

```bash
git commit -m "Testcommit" --author="Testperson <test@example.com>"
```

Der Unterschied zwischen *Autor* und *Committer* – relevant etwa bei Rebase oder Cherry-Pick – wird in Kapitel 6 vertieft.

---

## Den Commit überprüfen

Direkt nach dem Erstellen solltest du dir zur Gewohnheit machen, das Ergebnis zu kontrollieren.

**Historie ansehen:**

```bash
git log
```

```text
commit a1b2c3d4e5f67890abcdef1234567890abcdef1
Author: Max Mustermann <max@example.com>
Date:   Mon Jan 8 10:15:32 2025 +0100

    Initiale Projektstruktur hinzufügen
```

**Inhalt des Commits im Detail prüfen:**

```bash
git show a1b2c3d
```

Dieser Befehl zeigt sowohl die Metadaten als auch den vollständigen Diff der im Commit enthaltenen Änderungen – nützlich, um zu bestätigen, dass tatsächlich nur die gewünschten Anpassungen erfasst wurden.

**Arbeitsverzeichnis erneut prüfen:**

```bash
git status
```

```text
Auf Branch main
nichts zu committen, Arbeitsverzeichnis unverändert
```

Diese Meldung zeigt an, dass alle vorgemerkten Änderungen erfolgreich in die Historie übernommen wurden.

---

## Typische Stolperfallen

- **„Nothing to commit“ trotz Änderungen:** Die Dateien wurden verändert, aber nicht mit `git add` vorgemerkt. Ein Blick auf `git status` klärt sofort, ob Änderungen noch als *„nicht vorgemerkt“* geführt werden.
- **Leerer Commit gewünscht:** In seltenen Fällen – etwa um einen CI-Lauf auszulösen – lässt sich ein Commit ohne Inhaltsänderung mit `git commit --allow-empty -m "..."` erzwingen.
- **Falsche Nachricht direkt nach dem Commit:** Kein Grund zur Sorge – Kapitel 6 zeigt, wie sich der letzte Commit mit `git commit --amend` sauber korrigieren lässt, solange er noch nicht veröffentlicht wurde.
- **Zeilenenden-Warnungen unter Windows:** Meldungen wie `warning: LF will be replaced by CRLF` sind normal und resultieren aus der in Kapitel 2 behandelten `core.autocrlf`-Konfiguration. Sie verhindern den Commit nicht.

---

## Ausblick

Damit besitzt dein Repository seinen ersten dokumentierten Zustand. Im weiteren Verlauf dieses Kapitels lernst du, wie sich diese Historie mit `git log` gezielt lesen lässt, wie Änderungen zwischen Commits mit `git diff` sichtbar werden – und wie sich exakt derselbe Ablauf komfortabel über die Commit-Oberfläche von PhpStorm abbilden lässt, ohne die Kommandozeile zu verlassen.

# Commit-Historie mit git log lesen

## Commit-Historie mit git log lesen

Ein Repository ist nur so wertvoll wie die Geschichte, die es erzählt. Mit jedem Commit wächst ein Protokoll, das dokumentiert, *wer* *wann* *welche* Änderung vorgenommen hat und *warum*. Der Befehl `git log` ist das zentrale Werkzeug, um dieses Protokoll zu lesen – und wer ihn beherrscht, kann sich in jedem Projekt schnell orientieren, unabhängig davon, wie alt oder komplex es ist.

### Die Grundform verstehen

Ohne weitere Optionen zeigt `git log` die Historie in umgekehrter chronologischer Reihenfolge an – der neueste Commit steht oben:

```bash
git log
```

Die Ausgabe sieht typischerweise so aus:

```
commit 8f3c1a9b2e4d5f6a7b8c9d0e1f2a3b4c5d6e7f8a
Author: Anna Beispiel <anna@beispiel.de>
Date:   Mon Mar 4 14:22:07 2024 +0100

    Formular-Validierung hinzugefügt

commit 1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b
Author: Anna Beispiel <anna@beispiel.de>
Date:   Mon Mar 4 13:05:41 2024 +0100

    Erste Projektstruktur angelegt
```

Jeder Eintrag besteht aus vier festen Bestandteilen:

- **Commit-Hash** – die eindeutige, vierzig Zeichen lange SHA-1-Kennung des Commits.
- **Author** – Name und E-Mail-Adresse der Person, die den Inhalt erstellt hat.
- **Date** – Zeitstempel inklusive Zeitzone.
- **Commit-Nachricht** – der erklärende Text, den du beim Commit vergeben hast.

Da lange Hashes unhandlich sind, genügt fast immer ein *eindeutiges Präfix* von sechs bis acht Zeichen, um einen Commit später zu referenzieren.

### Kompakte Ansichten mit --oneline

Bei größeren Historien wird die ausführliche Ansicht schnell unübersichtlich. Die Option `--oneline` reduziert jeden Commit auf eine einzige Zeile:

```bash
git log --oneline
```

```
8f3c1a9 Formular-Validierung hinzugefügt
1a2b3c4 Erste Projektstruktur angelegt
```

Diese verkürzte Form ist der Standard für einen schnellen Überblick und wird häufig mit weiteren Optionen kombiniert.

### Den Verlauf begrenzen

Nicht immer wird die gesamte Historie benötigt. Mit `-n` beschränkst du die Ausgabe auf eine bestimmte Anzahl von Commits:

```bash
git log -n 5
```

Alternativ lässt sich der Zeitraum eingrenzen:

```bash
git log --since="2 weeks ago"
git log --until="2024-03-01"
git log --since="2024-01-01" --until="2024-02-01"
```

### Nach Inhalt und Person filtern

`git log` erlaubt gezielte Suchen innerhalb der Historie, ohne dass du die Ausgabe manuell durchsuchen musst.

| Ziel | Befehl |
|---|---|
| Nach Autor filtern | `git log --author="Anna"` |
| Nach Nachrichtentext suchen | `git log --grep="Validierung"` |
| Commits einer Datei anzeigen | `git log -- pfad/zur/datei.php` |
| Nur Merge-Commits anzeigen | `git log --merges` |
| Merge-Commits ausblenden | `git log --no-merges` |

Diese Filter lassen sich beliebig kombinieren, etwa um alle Commits einer bestimmten Person innerhalb eines Zeitraums zu einer bestimmten Datei zu finden.

### Änderungen direkt mitanzeigen

Manchmal reicht die Nachricht allein nicht aus – du willst sehen, *was* sich tatsächlich geändert hat.

- `git log -p` zeigt zu jedem Commit den vollständigen Patch (Diff) an.
- `git log --stat` zeigt stattdessen eine kompakte Statistik mit geänderten Dateien und der Anzahl hinzugefügter beziehungsweise entfernter Zeilen.

```bash
git log --stat
```

```
8f3c1a9 Formular-Validierung hinzugefügt
 src/Validator.php | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)
```

Diese Übersicht eignet sich gut, um schnell einzuschätzen, wie umfangreich ein Commit war, ohne den gesamten Patch lesen zu müssen.

### Eigene Formate mit --pretty und --format

Für individuelle Ansichten bietet Git das Format `--pretty=format:"…"`, mit dem du festlegst, welche Informationen in welcher Reihenfolge erscheinen.

```bash
git log --pretty=format:"%h – %an, %ar : %s"
```

```
8f3c1a9 – Anna Beispiel, 2 hours ago : Formular-Validierung hinzugefügt
1a2b3c4 – Anna Beispiel, 3 hours ago : Erste Projektstruktur angelegt
```

Die wichtigsten Platzhalter:

| Platzhalter | Bedeutung |
|---|---|
| `%h` | Kurzer Commit-Hash |
| `%H` | Vollständiger Commit-Hash |
| `%an` | Autorenname |
| `%ae` | Autoren-E-Mail |
| `%ad` / `%ar` | Datum absolut / relativ |
| `%s` | Betreffzeile der Commit-Nachricht |

Da solche Formate schnell lang werden, lohnt es sich, sie später als Git-Alias zu speichern – ein Thema, das in einem eigenen Kapitel zu fortgeschrittenen Werkzeugen vertieft wird.

### Verzweigungen sichtbar machen

Sobald ein Projekt mehrere Branches enthält, hilft eine grafische Darstellung, Zusammenhänge zu erkennen:

```bash
git log --oneline --graph --all
```

```
* 8f3c1a9 (HEAD -> main) Formular-Validierung hinzugefügt
* 1a2b3c4 Erste Projektstruktur angelegt
```

Die Option `--graph` zeichnet die Commit-Struktur mit Zeichen wie `*`, `|` und `\`, während `--all` sämtliche Branches statt nur den aktuellen einbezieht. In einem reinen lokalen Repository mit nur einem Branch wirkt diese Ansicht noch schlicht – ihr Nutzen zeigt sich erst, sobald mehrere Branches parallel existieren, wie in einem späteren Kapitel ausführlich behandelt wird.

### Relative Referenzen im Log verwenden

Anstelle vollständiger Hashes kannst du Commits relativ zum aktuellen Stand ansprechen:

```bash
git log HEAD~1
git log HEAD~2..HEAD
```

`HEAD~1` bezeichnet den Elternteil des aktuellen Commits, `HEAD~2` den Großelternteil und so weiter. Der Bereichsoperator `..` zeigt alle Commits zwischen zwei Punkten an – eine Notation, die in späteren Kapiteln zu Branches und Vergleichen regelmäßig wiederkehrt.

### Ausblick: Historie in PhpStorm

Alles, was hier über die Kommandozeile erarbeitet wurde, lässt sich auch grafisch im **Git-Werkzeugfenster** von PhpStorm nachvollziehen – inklusive Filterung, Diff-Ansicht und Graphdarstellung per Mausklick. Da dieser Kurs bewusst Kommandozeile und IDE parallel vermittelt, wird der identische Workflow am Ende dieses Kapitels vollständig in PhpStorm wiederholt.

### Checkliste für den Alltag

- 📜 `git log --oneline` für einen schnellen Überblick.
- 🔍 `git log --grep` oder `--author`, um gezielt zu suchen.
- 📊 `git log --stat`, um den Umfang von Änderungen einzuschätzen.
- 🌳 `git log --graph --all`, sobald mehrere Branches im Spiel sind.
- ✂️ `HEAD~n`, um relativ zum aktuellen Stand zu navigieren.

Wer diese Grundtechniken verinnerlicht, verfügt über das Handwerkszeug, um sich in jedem – auch fremden – Git-Repository zügig zurechtzufinden, bevor im nächsten Abschnitt mit `git diff` der inhaltliche Vergleich von Änderungen im Detail folgt.

# Änderungen mit git diff untersuchen

## Änderungen mit `git diff` untersuchen

Ein Commit fasst nur zusammen, *was* sich verändert hat – doch bevor du überhaupt vormerkst oder committest, willst du genau wissen, *welche* Zeilen betroffen sind. Genau dafür ist `git diff` gedacht: Es macht Unterschiede zwischen zwei Zuständen deines Projekts sichtbar, ohne selbst irgendetwas zu verändern. `git diff` ist damit ein reines *Lesewerkzeug* – ideal, um vor jedem `git add` und jedem Commit einen letzten Kontrollblick zu werfen.

### Drei Bereiche, drei Vergleiche

Erinnere dich an das Drei-Bereiche-Modell aus dem vorherigen Kapitel: Arbeitsverzeichnis, Index (Staging Area) und Repository. `git diff` vergleicht standardmäßig genau zwei dieser Bereiche – je nach Aufruf unterschiedliche.

| Befehl | Vergleicht | Beantwortet die Frage |
|---|---|---|
| `git diff` | Arbeitsverzeichnis ↔ Index | „Was habe ich verändert, aber noch nicht vorgemerkt?“ |
| `git diff --staged` (oder `--cached`) | Index ↔ letzter Commit | „Was würde ein Commit jetzt genau festhalten?“ |
| `git diff HEAD` | Arbeitsverzeichnis ↔ letzter Commit | „Was unterscheidet sich insgesamt vom letzten Commit – egal ob vorgemerkt oder nicht?“ |

Diese Unterscheidung ist der Schlüssel zum Verständnis: `git status` sagt dir nur, *dass* etwas verändert wurde, `git diff` zeigt dir *wie*.

### Der Standardfall: Arbeitsverzeichnis gegen Index

Nimm an, du hast eine Datei `index.php` bearbeitet, aber noch nichts mit `git add` vorgemerkt:

```bash
git diff
```

Die Ausgabe könnte so aussehen:

```diff
diff --git a/index.php b/index.php
index e69de29..f2c1a3d 100644
--- a/index.php
+++ b/index.php
@@ -1,3 +1,5 @@
 <?php
-echo "Hallo Welt";
+echo "Hallo, Git!";
+
+// Neue Zeile für die Begrüßung
```

Diese Ausgabe folgt dem sogenannten **Unified-Diff-Format**, das nicht nur Git, sondern auch viele andere Werkzeuge verwenden. Es lohnt sich, jeden Bestandteil einmal genau zu lesen:

- **`diff --git a/... b/...`** – kennzeichnet die verglichenen Dateien; `a` steht für die alte, `b` für die neue Version.
- **`index e69de29..f2c1a3d`** – zeigt die betroffenen Objekt-Hashes (dazu mehr im Kapitel über Git-Interna).
- **`---` / `+++`** – markieren die alte bzw. neue Dateiversion.
- **`@@ -1,3 +1,5 @@`** – der sogenannte *Hunk-Header*. Er bedeutet: „Ab Zeile 1 wurden in der alten Datei 3 Zeilen, in der neuen Datei 5 Zeilen betrachtet.“
- **Zeilen mit `-`** wurden entfernt, Zeilen mit **`+`** wurden hinzugefügt, unveränderte Zeilen erscheinen ohne Präfix als Kontext.

Diese Kontextzeilen sind wichtig: Sie helfen dir, die Änderung im umgebenden Code einzuordnen, ohne die ganze Datei öffnen zu müssen.

### Vorgemerkte Änderungen prüfen: `--staged`

Sobald du `git add` ausgeführt hast, zeigt der einfache `git diff` nichts mehr an – die Änderung liegt jetzt im Index, nicht mehr nur im Arbeitsverzeichnis. Um zu sehen, was genau ein Commit übernehmen würde, verwendest du:

```bash
git diff --staged
```

`--cached` ist ein reines Synonym und liefert dasselbe Ergebnis:

```bash
git diff --cached
```

Diese Unterscheidung zwischen *unstaged* und *staged* Diffs ist besonders bei selektivem Staging wertvoll (siehe Kapitel 5), wenn du bewusst nur einen Teil deiner Änderungen committen möchtest.

### Alles auf einen Blick: `git diff HEAD`

Willst du unabhängig vom Staging-Status wissen, was sich seit dem letzten Commit insgesamt verändert hat – egal ob vorgemerkt oder nicht – hilft:

```bash
git diff HEAD
```

`HEAD` ist dabei ein Zeiger auf den aktuellen Commit, mit dem du später noch viel intensiver arbeiten wirst.

### Einzelne Dateien oder Verzeichnisse vergleichen

`git diff` lässt sich immer auf konkrete Pfade einschränken. Das ist besonders bei größeren Projekten hilfreich, um den Fokus zu behalten:

```bash
git diff index.php
git diff src/
```

Mehrere Pfade lassen sich einfach aneinanderhängen:

```bash
git diff README.md composer.json
```

### Kompakte Übersichten statt vollständiger Diffs

Manchmal willst du nicht jede Zeile sehen, sondern nur wissen, *welche* Dateien betroffen sind und *wie stark*:

```bash
git diff --stat
```

```
 index.php | 4 ++--
 README.md | 2 ++
 2 files changed, 4 insertions(+), 2 deletions(-)
```

Für eine reine Auflistung der geänderten Dateinamen eignen sich:

```bash
git diff --name-only
git diff --name-status
```

`--name-status` ergänzt zusätzlich ein Kürzel wie `M` (modified), `A` (added) oder `D` (deleted) – praktisch für Skripte oder einen schnellen Überblick.

### Wortweise statt zeilenweise vergleichen

Bei Prosatexten, Dokumentation oder Konfigurationsdateien ist eine zeilenbasierte Darstellung oft unübersichtlich, wenn nur ein einzelnes Wort geändert wurde. Hier hilft der Wortmodus:

```bash
git diff --word-diff
```

Er markiert nicht ganze Zeilen, sondern einzelne geänderte Wortfolgen mit `[-alt-]` und `{+neu+}` – deutlich präziser für kleinteilige Textänderungen.

### Vorausblick: Commits und Branches vergleichen

`git diff` beschränkt sich nicht auf die drei lokalen Bereiche. Es lassen sich ebenso zwei beliebige Commits, Branches oder Tags gegenüberstellen, etwa mit:

```bash
git diff main feature/login
```

Diese Fähigkeit wird im Kapitel „Historie lesen, durchsuchen und vergleichen“ ausführlich vertieft – an dieser Stelle reicht es, zu wissen, dass `git diff` dafür dieselbe Syntax und dieselbe Ausgabe-Logik verwendet wie beim Vergleich von Arbeitsverzeichnis und Index.

### Diff-Ausgaben besser lesbar machen

Auf vielen Windows-Terminals lohnt es sich, farbige Ausgaben zu aktivieren, falls sie nicht bereits standardmäßig aktiv sind:

```bash
git config --global color.diff auto
```

Für sehr lange Diffs kann zusätzlich ein Pager wie `less` hilfreich sein, den Git unter Windows über Git Bash automatisch mitbringt. Falls die Ausgabe im Terminal umbricht oder unübersichtlich wirkt, ist das ein guter Moment, um zur grafischen Diff-Ansicht in PhpStorm zu wechseln – dort erscheinen alte und neue Version übersichtlich nebeneinander, farblich hervorgehoben und mit Navigationspfeilen zwischen den Änderungsblöcken. Wie dieser Workflow konkret aussieht, zeigt der letzte Abschnitt dieses Kapitels.

### Zusammenfassung

`git diff` ist dein wichtigstes Werkzeug, um Änderungen *vor* dem Staging und *vor* dem Commit kritisch zu prüfen. Die zentrale Faustregel lautet:

- **Kein Argument** → Arbeitsverzeichnis gegen Index (unstaged Änderungen).
- **`--staged`/`--cached`** → Index gegen letzten Commit (was der nächste Commit enthält).
- **`HEAD`** → Arbeitsverzeichnis gegen letzten Commit (alles zusammen).

Wer diese drei Varianten sicher unterscheidet, vermeidet eine der häufigsten Anfängerverwirrungen in Git: die Frage, *warum* eine erwartete Änderung im Diff plötzlich nicht mehr auftaucht, obwohl die Datei sichtbar verändert wurde. 🔍

# Dateien umbenennen und verschieben

## Dateien umbenennen und verschieben

Anders als viele Entwickler zunächst erwarten, speichert Git *keine* expliziten Umbenennungsinformationen. Es gibt in der internen Datenstruktur kein Attribut „diese Datei wurde umbenannt“. Git arbeitet stattdessen mit Snapshots ganzer Verzeichnisbäume und **erkennt** Umbenennungen nachträglich, indem es Dateiinhalte zwischen zwei Commits auf Ähnlichkeit vergleicht. Dieses Verständnis ist wichtig, um das Verhalten von `git status`, `git diff` und `git log` bei verschobenen oder umbenannten Dateien richtig einzuordnen.

### Der Komfortbefehl `git mv`

Für den Alltag stellt Git den Befehl `git mv` bereit, der zwei Schritte in einem einzigen Kommando zusammenfasst: das physische Umbenennen im Dateisystem und das Vormerken der Änderung im Index.

```bash
git mv alt.txt neu.txt
```

Dieser Aufruf entspricht exakt der folgenden Sequenz:

```bash
mv alt.txt neu.txt
git add alt.txt neu.txt
```

`git mv` ist also reine Bequemlichkeit – kein eigenständiger Git-Mechanismus. Ein Blick auf `git status` nach einem `git mv` zeigt den erwarteten Zustand:

```
renamed:    alt.txt -> neu.txt
```

### Manuelles Umbenennen

Wer eine Datei über den Windows-Explorer, PhpStorm oder ein beliebiges anderes Werkzeug umbenennt, erzielt am Ende dasselbe Ergebnis. Git registriert zunächst zwei getrennte Änderungen:

```
deleted:    alt.txt
new file:   neu.txt
```

Erst beim Erstellen des Commits – beziehungsweise beim Anzeigen von `git status` mit Ähnlichkeitserkennung – interpretiert Git diese Kombination als Umbenennung. Sofern der Inhalt der Datei weitgehend unverändert bleibt, ist es **funktional gleichwertig**, ob `git mv` verwendet wird oder Löschen und Neuanlegen manuell erfolgen. Für die Übersichtlichkeit im Arbeitsalltag ist `git mv` jedoch vorzuziehen, da es Missverständnisse vermeidet und die Absicht sofort klar kommuniziert.

### Wie Git Umbenennungen erkennt

Die Erkennung basiert auf einem Ähnlichkeitsvergleich, keiner festen Zuordnung. Git betrachtet eine gelöschte und eine neu hinzugekommene Datei als „umbenannt“, wenn ihr Inhalt zu einem konfigurierbaren Prozentsatz übereinstimmt. Der Standardwert liegt bei **50 %**.

```bash
git status -M          # zeigt Umbenennungen mit Standardschwelle
git diff -M50%          # explizite Schwelle angeben
git log --follow neu.txt
```

Der Parameter `--follow` ist besonders wertvoll: Er sorgt dafür, dass `git log` die Historie einer Datei über Umbenennungen hinweg verfolgt, statt an dem Punkt zu stoppen, an dem der alte Dateiname verschwindet.

> **Hinweis:** Wird eine Datei beim Umbenennen zusätzlich stark inhaltlich verändert, kann Git die Beziehung nicht mehr erkennen. In diesem Fall erscheinen zwei unabhängige Einträge – eine Löschung und eine Neuanlage – und die Historie „reißt“ an dieser Stelle ab.

### Dateien in andere Verzeichnisse verschieben

Das Prinzip gilt unverändert für Verschiebungen zwischen Verzeichnissen:

```bash
git mv src/Helper.php src/Utils/Helper.php
```

Auch hier merkt Git die neue Position im Index vor. Fehlt das Zielverzeichnis, muss es zuvor angelegt werden, da Git – im Gegensatz zu vielen anderen Werkzeugen – keine leeren Verzeichnisse verwaltet, sondern ausschließlich Dateien.

### Umbenennungen als eigenständige Commits

Für eine nachvollziehbare Projektgeschichte empfiehlt es sich, Umbenennungen **getrennt** von inhaltlichen Änderungen zu committen:

```bash
git mv OldClassName.php NewClassName.php
git commit -m "refactor: Klasse in NewClassName umbenennen"
```

Werden Umbenennung und Codeänderung im selben Commit vermischt, sinkt die Wahrscheinlichkeit einer korrekten automatischen Erkennung erheblich, und spätere Reviews sowie `git blame`-Analysen werden unnötig erschwert.

### Kontrolle nach dem Umbenennen

Zur Absicherung sollte der Zustand vor dem Commit stets überprüft werden:

```bash
git status
git diff --staged
```

`git status` bestätigt die erkannte Umbenennung, während `git diff --staged` zeigt, ob neben dem neuen Namen unbeabsichtigt auch Inhalte verändert wurden.

### Ausblick

Der hier beschriebene Kommandozeilen-Workflow bildet die Grundlage. Wie sich Umbenennungen und Verschiebungen komfortabel und mit visueller Rückmeldung direkt in PhpStorm durchführen lassen, zeigt der folgende Abschnitt *„Derselbe Workflow in PhpStorm“* 🧭 – inklusive automatischer Referenzanpassung im PHP-Code, die die IDE zusätzlich übernimmt.

# Dateien aus Git entfernen

Das Löschen einer Datei ist in Git ein eigenständiger, protokollierter Vorgang – kein Nebeneffekt des Dateisystems. Wer eine Datei einfach im Explorer oder in PhpStorm löscht, hat Git davon zunächst nichts mitgeteilt. Dieser Abschnitt zeigt, wie Löschvorgänge korrekt vorgemerkt, committet und in unterschiedlichen Varianten durchgeführt werden.

### Löschen im Dateisystem versus Löschen in Git

Wenn du eine Datei manuell löschst, meldet `git status` sie als *geänderte, aber nicht vorgemerkte* Datei:

```bash
del beispiel.txt
git status
```

```
Changes not staged for commit:
  deleted:    beispiel.txt
```

Git erkennt zwar, dass die Datei fehlt, hat die Löschung aber noch nicht in den Index übernommen. Erst ein zusätzlicher `git add` – oder besser gleich `git rm` – macht die Löschung Teil des nächsten Commits.

### `git rm`: Löschen und Vormerken in einem Schritt

Der saubere Weg führt über `git rm`. Der Befehl entfernt die Datei gleichzeitig aus dem Arbeitsverzeichnis *und* aus dem Index:

```bash
git rm beispiel.txt
```

```
rm 'beispiel.txt'
```

Ein anschließendes `git status` zeigt die Datei bereits als *vorgemerkt zum Löschen* (`staged: deleted`). Ein Commit schließt den Vorgang ab:

```bash
git commit -m "Entferne veraltete Datei beispiel.txt"
```

### Nur aus der Versionskontrolle entfernen, Datei behalten

Häufig soll eine Datei nicht mehr von Git verfolgt werden, aber weiterhin lokal existieren – etwa eine Konfigurationsdatei mit lokalen Einstellungen oder eine versehentlich committete `.env`-Datei. Dafür gibt es die Option `--cached`:

```bash
git rm --cached config.local.php
```

Dieser Befehl entfernt die Datei ausschließlich aus dem Index. Im Arbeitsverzeichnis bleibt sie unverändert erhalten, taucht danach aber als *nicht verfolgt* auf. In Kombination mit einem passenden Eintrag in `.gitignore` verschwindet sie danach dauerhaft aus zukünftigen Vorschlägen von `git status`.

> **Praxistipp:** Diese Kombination – `git rm --cached` gefolgt von einem `.gitignore`-Eintrag – ist der Standardweg, um versehentlich eingecheckte Zugangsdaten oder generierte Dateien nachträglich aus der Nachverfolgung zu entfernen. Die vollständige Entfernung aus der *Historie* erfordert dagegen weiterführende Werkzeuge, die in späteren Kapiteln behandelt werden.

### Bereits gelöschte Dateien nachträglich stagen

Wurde eine Datei bereits klassisch gelöscht, bevor du an `git rm` gedacht hast, musst du das Repository nicht zurücksetzen. `git add` merkt auch Löschungen korrekt vor:

```bash
git add beispiel.txt
```

Git erkennt, dass die Datei fehlt, und merkt diesen Zustand als Löschung vor – der Effekt ist identisch zu `git rm`.

### Verzeichnisse rekursiv entfernen

Soll ein ganzes Verzeichnis samt Inhalt entfernt werden, ist die Option `-r` erforderlich:

```bash
git rm -r temp/
```

Ohne diese Option verweigert Git die Operation, um versehentliches Löschen ganzer Verzeichnisbäume zu verhindern.

### Löschung erzwingen

Enthält eine Datei nicht committete Änderungen, verweigert `git rm` standardmäßig die Löschung, um Datenverlust zu vermeiden:

```
error: the following file has local modifications:
    beispiel.txt
```

Mit der Option `-f` (force) wird die Löschung dennoch durchgeführt:

```bash
git rm -f beispiel.txt
```

Diese Schutzmechanik ist bewusst restriktiv gestaltet – ein typisches Beispiel für Gits generelle Haltung, lieber einen expliziten zusätzlichen Schritt zu verlangen, als Arbeit unwiderruflich zu verwerfen.

### Übersicht der wichtigsten Varianten

| Befehl | Wirkung auf Arbeitsverzeichnis | Wirkung auf Index |
|---|---|---|
| `git rm datei` | Datei wird gelöscht | Löschung vorgemerkt |
| `git rm --cached datei` | Datei bleibt erhalten | Löschung vorgemerkt |
| `git rm -r verzeichnis/` | Verzeichnis wird gelöscht | Löschung vorgemerkt |
| `git rm -f datei` | Datei wird trotz Änderungen gelöscht | Löschung vorgemerkt |
| Manuelles Löschen + `git add` | Datei bereits gelöscht | Löschung nachträglich vorgemerkt |

### Ausblick auf PhpStorm

PhpStorm bildet diese Vorgänge grafisch nach: Ein Löschen einer Datei im *Project*-Werkzeugfenster fragt automatisch, ob die Löschung auch in Git vorgemerkt werden soll, und übernimmt intern denselben `git rm`-Mechanismus. Wie dieser Ablauf konkret aussieht und sich in die übrige IDE-Bedienung einfügt, zeigt der letzte Abschnitt dieses Kapitels, in dem der gesamte bisherige Workflow noch einmal vollständig innerhalb von PhpStorm nachvollzogen wird.

# Derselbe Workflow in PhpStorm

Die vorherigen Abschnitte dieses Kapitels haben den kompletten Weg von `git init` bis zum Entfernen einzelner Dateien ausschließlich über die Kommandozeile beschritten. Das war kein Zufall: Wer die Befehle einmal *bewusst* eingegeben hat, versteht später jede grafische Schaltfläche, die im Hintergrund exakt denselben Befehl auslöst. Dieser Abschnitt wiederholt nun den identischen Workflow – Repository anlegen, Zustand prüfen, Dateien vormerken, committen, Historie lesen, Diffs betrachten, umbenennen und entfernen – vollständig über die Oberfläche von PhpStorm.

Das Ziel ist nicht, die Kommandozeile zu ersetzen, sondern eine bewusste **Übersetzungstabelle** im Kopf zu verankern: „Wenn ich diesen Button klicke, passiert intern dieser Befehl.“

---

### Vom Übungsprojekt zum versionierten Verzeichnis

Öffne das Übungsprojekt aus den vorherigen Abschnitten in PhpStorm, sofern es noch nicht als Repository initialisiert wurde. Der Menüpfad dafür lautet:

> `VCS → Enable Version Control Integration…`

PhpStorm fragt anschließend nach dem gewünschten Versionskontrollsystem und bietet *Git* als Option an. Nach Bestätigung führt die IDE im Hintergrund exakt den Befehl aus, den du bereits kennst:

$$
\texttt{git init}
$$

Ein neues `.git`-Verzeichnis entsteht, unsichtbar für den Datei-Explorer, aber sichtbar im PhpStorm-Projektbaum, sofern versteckte Dateien angezeigt werden. Die Statusleiste am unteren Bildschirmrand zeigt ab sofort den aktuellen Branch-Namen an – ein erstes visuelles Signal, dass Versionskontrolle aktiv ist.

---

### Den Zustand prüfen: Local Changes statt `git status`

Anstelle von `git status` nutzt PhpStorm das Werkzeugfenster **Commit** (früher „Local Changes“ genannt), erreichbar über:

> `View → Tool Windows → Commit`

Hier erscheinen alle veränderten, neuen und gelöschten Dateien in einer strukturierten Liste, farblich unterschieden:

- **Grün** – neue, noch nicht verfolgte Dateien
- **Blau** – bereits verfolgte, aber veränderte Dateien
- **Rot** – gelöschte Dateien

Diese Darstellung liefert dieselbe Information wie `git status`, jedoch dauerhaft aktualisiert und ohne erneuten Befehlsaufruf. Ein Klick auf eine Datei öffnet sofort die Diff-Ansicht – ein Komfort, den die reine Kommandozeile nicht bietet.

---

### Dateien vormerken: Checkboxen statt `git add`

Im Commit-Fenster besitzt jede Datei eine Checkbox. Ist sie aktiviert, wird die Datei beim nächsten Commit einbezogen – funktional entspricht das exakt:

$$
\texttt{git add <datei>}
$$

Wichtig zu verstehen: Das reine *Anhaken* einer Datei löst in PhpStorm **noch nicht sofort** einen `git add`-Befehl aus. Stattdessen merkt sich die IDE die Auswahl und führt das eigentliche Staging erst beim Commit-Vorgang durch. Für Nutzer, die den exakten Zeitpunkt des Stagings kontrollieren möchten, lässt sich dieses Verhalten in den Einstellungen anpassen unter:

> `Settings → Version Control → Commit`

Wer gezielt nur Teile einer Datei vormerken möchte, öffnet über einen Rechtsklick den Diff-Viewer und aktiviert dort einzelne Änderungsblöcke – das grafische Äquivalent zu `git add -p`, das im nächsten Kapitel vertieft wird.

---

### Den ersten Commit erstellen

Mit ausgewählten Dateien öffnest du das Commit-Fenster über `Strg + K` (unter Windows 11 die gebräuchliche Tastenkombination in PhpStorm) oder über die Schaltfläche **Commit** in der Werkzeugleiste. Ein Textfeld erwartet die Commit-Nachricht – dieselbe Nachricht, die bei der Kommandozeile über

$$
\texttt{git commit -m "Nachricht"}
$$

übergeben würde. PhpStorm bietet zusätzlich:

- Eine **Kommentarvorlage**, sofern im Projekt konfiguriert
- Automatische **Rechtschreibprüfung**
- Optionale **Vor-Commit-Prüfungen** (z. B. Codeanalyse, TODO-Kommentare), die sich einzeln aktivieren oder deaktivieren lassen

Die Schaltfläche **Commit** entspricht einem einfachen Commit; **Commit and Push…** führt zusätzlich sofort einen Push aus – ein Vorgriff auf spätere Kapitel, der hier bewusst noch nicht verwendet werden sollte.

---

### Historie lesen: Das Git-Log-Fenster statt `git log`

Die textbasierte Ausgabe von `git log` findet ihre grafische Entsprechung im Werkzeugfenster **Git**, Reiter **Log**:

> `View → Tool Windows → Git`

Dort erscheint jeder Commit als Zeile in einem Graphen, ergänzt um Autor, Zeitstempel und vollständige Nachricht im Detailbereich. Ein Klick auf einen Commit zeigt sofort dessen Änderungen an – ohne zusätzlichen Befehl wie `git show`. Die Filterleiste oberhalb des Logs ermöglicht Suchen nach Autor, Branch oder Nachricht, was in der Kommandozeile erst mit Optionen wie `--author` oder `--grep` möglich wäre.

---

### Änderungen untersuchen: Der integrierte Diff-Viewer

Statt `git diff` in der Konsole zu lesen, öffnet ein Doppelklick auf eine geänderte Datei im Commit-Fenster den **Diff-Viewer** von PhpStorm. Er stellt alte und neue Version einer Datei Seite an Seite dar, farblich markiert, mit Navigationspfeilen zwischen den einzelnen Änderungsblöcken. Diese Darstellung ist inhaltlich identisch mit der textuellen Diff-Ausgabe, jedoch erheblich leichter lesbar – besonders bei umfangreichen Änderungen oder verschachtelten Codeblöcken.

---

### Dateien umbenennen und verschieben

Ein einfacher Rechtsklick im Projektbaum mit der Option **Refactor → Rename** bzw. **Move** genügt. PhpStorm erkennt, dass die Datei unter Versionskontrolle steht, und führt automatisch die passende Git-Operation aus – intern entspricht dies:

$$
\texttt{git mv <alt> <neu>}
$$

Der entscheidende Vorteil gegenüber einer manuellen Umbenennung im Windows-Explorer: PhpStorm passt zugleich alle Codeverweise auf die Datei an, etwa `require`- oder `use`-Anweisungen in PHP – eine Funktion, die reines Git nicht kennt.

---

### Dateien aus Git entfernen

Löschst du eine Datei über den Projektbaum (`Entf`-Taste) oder direkt im Datei-Explorer, erkennt PhpStorm die Löschung im Commit-Fenster als rote Zeile. Beim anschließenden Commit wird sie regulär aus der Versionsverwaltung entfernt – gleichbedeutend mit:

$$
\texttt{git rm <datei>}
$$

Möchtest du eine Datei zwar physisch behalten, aber aus der Nachverfolgung entnehmen, bietet der Rechtsklick im Commit-Fenster die Option **Rollback** oder **Ignore**, was Kapitel 7 vertieft.

---

### Gegenüberstellung: Befehl und Oberfläche

| Aufgabe | Kommandozeile | PhpStorm |
| --- | --- | --- |
| Repository anlegen | `git init` | `VCS → Enable Version Control Integration` |
| Zustand prüfen | `git status` | Werkzeugfenster *Commit* |
| Datei vormerken | `git add` | Checkbox im Commit-Fenster |
| Commit erstellen | `git commit -m "…"` | Schaltfläche *Commit* |
| Historie ansehen | `git log` | Werkzeugfenster *Git → Log* |
| Änderungen vergleichen | `git diff` | Integrierter Diff-Viewer |
| Datei umbenennen | `git mv` | *Refactor → Rename* |
| Datei entfernen | `git rm` | Löschen \+ Commit |

---

### Einordnung: Wann welches Werkzeug?

Die grafische Oberfläche punktet bei **Übersicht, Diff-Lesbarkeit und Refactoring-Integration** – besonders wertvoll bei umfangreichen PHP-Projekten mit vielen Abhängigkeiten zwischen Dateien. Die Kommandozeile bleibt unschlagbar bei **Automatisierung, Skripten, Fernzugriffen über SSH** und in Situationen, in denen kein grafisches Werkzeug zur Verfügung steht.

Ein erfahrener Git-Anwender wechselt bewusst zwischen beiden Welten, statt sich auf eine einzige Methode zu versteifen. 🧭 Genau dieses flexible Zusammenspiel bildet die Grundlage für alle folgenden Kapitel, in denen Branching, Merging und Teamarbeit sowohl über die Kommandozeile als auch über PhpStorm demonstriert werden.

# Die drei Bereiche von Git sicher beherrschen

Git arbeitet mit Arbeitsverzeichnis, Index und Repository. Dieses Kapitel macht das zentrale Drei-Bereiche-Modell anschaulich und zeigt, wie Änderungen zwischen diesen Zuständen bewegt werden. Du lernst selektives Staging, Patch-Modus, Wiederherstellung und den Umgang mit versehentlichen Änderungen.

# Arbeitsverzeichnis, Index und Repository

Wer Git wirklich verstehen will, muss zunächst ein einziges Modell verinnerlichen: Git verwaltet Änderungen nicht in *einem* Speicherort, sondern in **drei klar getrennten Bereichen**. Fast jede Verwirrung im Umgang mit Git – „Warum sieht `git status` das nicht?“, „Wo ist meine Änderung hin?“, „Warum wird das committet, obwohl ich es nicht wollte?“ – lässt sich auf ein unklares Verständnis dieser drei Bereiche zurückführen. Dieses Kapitel schafft die gedankliche Grundlage für alles Weitere.

## Die drei Bereiche im Überblick

Git unterscheidet zwischen:

1. **Arbeitsverzeichnis** *(Working Directory / Working Tree)* – die Dateien, wie du sie im Explorer oder in PhpStorm siehst und bearbeitest.
2. **Index** *(Staging Area, auch „Cache“ genannt)* – ein Zwischenspeicher, der festlegt, was in den *nächsten* Commit aufgenommen wird.
3. **Repository** *(genauer: die Objektdatenbank in `.git`)* – die dauerhafte, unveränderliche Historie aller bisherigen Commits.

$$
\text{Arbeitsverzeichnis} \xrightarrow{\text{git add}} \text{Index} \xrightarrow{\text{git commit}} \text{Repository}
$$

Diese drei Stationen bilden eine Art Förderband: Änderungen entstehen im Arbeitsverzeichnis, werden bewusst für den nächsten Commit ausgewählt (Index) und schließlich dauerhaft in der Historie verankert (Repository).

```mermaid
flowchart LR
    A["Arbeitsverzeichnis<br/>bearbeitete Dateien"] -->|git add| B["Index<br/>Staging Area"]
    B -->|git commit| C["Repository<br/>.git Objektdatenbank"]
    C -->|git restore --staged| B
    C -->|git checkout / restore| A
    B -->|git restore| A
```

*Hinweis:* In Mermaid-Labels sind keine `<br/>`-Zeilenumbrüche erlaubt – im tatsächlichen Diagramm werden Zeilenumbrüche daher durch Kommas oder kurze Beschriftungen ersetzt.

## Das Arbeitsverzeichnis

Das Arbeitsverzeichnis ist der Ort, an dem die eigentliche Arbeit passiert. Es enthält die aktuelle Momentaufnahme deines Projekts als reale Dateien auf der Festplatte – genau das, was PhpStorm im Projektbaum anzeigt und was du mit einem Editor öffnest.

Wichtig ist: Das Arbeitsverzeichnis ist **nicht** die Historie. Es zeigt immer nur den Zustand, der aktuell ausgecheckt ist – meist der letzte Commit des aktiven Branches, plus alle Änderungen, die du seither vorgenommen hast.

```bash
# Zeigt den aktuellen Zustand des Arbeitsverzeichnisses
git status
```

Git vergleicht dabei den Inhalt der Dateien auf der Festplatte mit dem, was im Index bzw. im letzten Commit gespeichert ist. Aus diesem Vergleich ergeben sich die bekannten Kategorien: *unverändert*, *verändert*, *nicht verfolgt* (untracked) und *ignoriert*.

## Der Index als Steuerzentrale

Der Index ist konzeptionell der wichtigste – und zugleich am häufigsten missverstandene – Bereich. Er ist **kein** Verzeichnis auf der Festplatte, sondern eine einzelne binäre Datei unter `.git/index`, die eine Liste von Dateipfaden mit zugehörigen Metadaten und Objekt-Hashes enthält.

Man kann sich den Index als **Entwurf des nächsten Commits** vorstellen. Erst wenn eine Änderung explizit mit `git add` in den Index übernommen wurde, „weiß“ Git, dass sie beim nächsten `git commit` berücksichtigt werden soll.

```bash
# Änderung im Arbeitsverzeichnis vornehmen
echo "Neue Zeile" >> beispiel.txt

# Änderung für den nächsten Commit vormerken
git add beispiel.txt

# Den Index einsehen
git status
```

Diese Zwischenstufe erlaubt eine entscheidende Fähigkeit, die viele andere Werkzeuge nicht bieten: **selektives Committen**. Du kannst zehn geänderte Dateien im Arbeitsverzeichnis haben und trotzdem nur drei davon – oder sogar nur einen Teil einer einzelnen Datei – in den nächsten Commit übernehmen. Diesem Thema widmet sich das weitere Kapitel im Detail (Abschnitte zu selektivem und interaktivem Staging).

> 💡 **Merksatz:** Der Index beschreibt nicht, was du geändert hast, sondern was du *committen willst*.

## Das Repository als Objektdatenbank

Das Repository – technisch der Inhalt von `.git` – ist die dauerhafte Ablage aller jemals erstellten Commits, Bäume und Dateiinhalte. Sobald ein Commit erstellt wurde, ist er **unveränderlich**: Jede „Änderung“ eines bestehenden Commits erzeugt in Wahrheit einen neuen Commit mit neuer Prüfsumme.

```bash
# Den Index als neuen Commit im Repository verankern
git commit -m "Beispieländerung hinzufügen"

# Die Commit-Historie im Repository einsehen
git log --oneline
```

Nach einem `git commit` sind Arbeitsverzeichnis, Index und Repository für die betroffenen Dateien wieder **synchron** – bis die nächste Änderung im Arbeitsverzeichnis vorgenommen wird und der Zyklus erneut beginnt.

## Zustände im Zusammenspiel

Die folgende Tabelle fasst zusammen, wie sich derselbe Dateiinhalt je nach Bereich unterscheiden kann:

| Bereich | Enthält | Verändert sich durch |
|---|---|---|
| Arbeitsverzeichnis | reale Dateien auf der Festplatte | Bearbeiten, Speichern, Löschen |
| Index | Entwurf des nächsten Commits | `git add`, `git restore --staged`, `git reset` |
| Repository | vollständige, unveränderliche Historie | `git commit`, `git merge`, `git rebase` |

Ein praktisches Beispiel verdeutlicht das Zusammenspiel:

```bash
# 1. Datei im Arbeitsverzeichnis ändern
echo "Zeile A" >> datei.txt

# 2. Zustand prüfen: Änderung ist "not staged"
git status

# 3. Änderung in den Index übernehmen
git add datei.txt

# 4. Zustand prüfen: Änderung ist jetzt "staged"
git status

# 5. Änderung dauerhaft im Repository verankern
git commit -m "Zeile A hinzufügen"

# 6. Zustand prüfen: Arbeitsverzeichnis, Index und Repository sind wieder synchron
git status
```

Der letzte `git status`-Aufruf zeigt typischerweise „nothing to commit, working tree clean“ – ein klares Signal dafür, dass alle drei Bereiche denselben Stand widerspiegeln.

## Warum dieses Modell zentral ist

Ohne dieses Drei-Bereiche-Modell wirken viele Git-Befehle willkürlich. Mit ihm werden sie **logisch vorhersehbar**:

- `git diff` vergleicht standardmäßig **Arbeitsverzeichnis mit Index**.
- `git diff --staged` vergleicht **Index mit dem letzten Commit**.
- `git restore` bewegt Inhalte **vom Repository oder Index zurück ins Arbeitsverzeichnis**.
- `git restore --staged` bewegt Inhalte **vom letzten Commit zurück in den Index**.
- `git reset` verändert, wie weit der Index und optional das Arbeitsverzeichnis dem Repository „nachgezogen“ werden.

Wer diese drei Bereiche als feste Landkarte im Kopf hat, kann jeden Git-Befehl anhand einer einzigen Frage einordnen: *„Zwischen welchen zwei Bereichen bewegt dieser Befehl etwas – und in welche Richtung?“*

Die folgenden Abschnitte dieses Kapitels vertiefen genau diese Bewegungen: das Unterscheiden verfolgter und unverfolgter Dateien, selektives und interaktives Staging, das gezielte Verwerfen von Änderungen sowie die Darstellung dieser Zustände direkt in PhpStorm.

# Commits professionell gestalten

Ein Commit ist mehr als ein Speicherpunkt. Du lernst, logisch getrennte und nachvollziehbare Änderungen zu erstellen, gute Commit-Nachrichten zu formulieren und fehlerhafte Commits zu korrigieren. Konventionen, Signaturen, Autorenangaben und PhpStorm-Prüfungen sorgen für belastbare Historien.

# Dateien ignorieren und Repository-Hygiene

Nicht jede Projektdatei gehört in Git. Dieses Kapitel erklärt globale und projektspezifische Ignore-Regeln, Negationen, Verzeichnismuster und bereits verfolgte Dateien. Der Fokus liegt auf PHP-, Composer- und PhpStorm-Projekten sowie dem sicheren Ausschluss von Zugangsdaten und Build-Artefakten.

# Historie lesen, durchsuchen und vergleichen

Wer Git beherrschen will, muss Projektgeschichte gezielt auswerten können. Du lernst Log-Formate, Graphdarstellungen, Diffs, Dateihistorien und Suchoptionen kennen. PhpStorms Git Log, Annotate-Funktion und Vergleichsansichten helfen dabei, Änderungen und Verantwortlichkeiten schnell zu verstehen.

# Branches von Grund auf verstehen

Branches ermöglichen parallele Entwicklung ohne teure Kopien. Dieses Kapitel erklärt Branch-Zeiger, HEAD, Wechsel und Zusammenführung. Du erstellst, benennst und löschst Branches, arbeitest mit Detached HEAD und lernst, wie PhpStorm lokale und entfernte Branches visualisiert.

# Änderungen mit Merge zusammenführen

Dieses Kapitel behandelt Fast-Forward-, Drei-Wege- und Merge-Commits. Du lernst, Branches kontrolliert zusammenzuführen, Merge-Konflikte zu analysieren und mit Kommandozeile oder PhpStorm zu lösen. Strategien und Optionen werden nicht nur angewendet, sondern anhand ihrer Auswirkungen erklärt.

# Historien mit Rebase überarbeiten

Rebase überträgt Commits auf eine neue Basis und ermöglicht lineare Historien. Du lernst einfachen und interaktiven Rebase, das Umordnen, Zusammenfassen, Bearbeiten und Entfernen von Commits sowie die sichere Konfliktlösung. Klare Regeln zeigen, wann Rebase sinnvoll oder gefährlich ist.

# Fehler rückgängig machen und Arbeit retten

Von einer falschen Codezeile bis zum versehentlich gelöschten Branch: Dieses Kapitel zeigt passende Rettungswege für jeden Git-Zustand. Du unterscheidest restore, reset, revert und checkout, nutzt Stashes und findest verloren geglaubte Commits über Reflogs wieder, ohne Schäden zu vergrößern.

# GitHub-Konto, Remotes und Authentifizierung

Nun wird das lokale Repository mit GitHub verbunden. Du richtest Konto, Profil und Authentifizierung ein, vergleichst HTTPS und SSH und verstehst Remote-Namen, URLs sowie Tracking-Beziehungen. Sicherheitsaspekte wie Tokens, Passphrases und Zwei-Faktor-Authentifizierung sind fest integriert.

# Clone, Fetch, Pull und Push

Dieses Kapitel erklärt den vollständigen Datenaustausch mit entfernten Repositories. Du klonst Projekte, lädst Referenzen und Objekte, integrierst Änderungen und veröffentlichst Commits. Tracking-Branches, Refspecs, Pull-Varianten und sichere Alternativen zum erzwungenen Push werden gründlich behandelt.

# Zusammenarbeit über Forks und Pull Requests

Pull Requests bilden das Herz vieler GitHub-Workflows. Du forkst Repositories, hältst Forks aktuell und entwickelst Änderungen in eigenen Branches. Danach erstellst, diskutierst und aktualisierst du Pull Requests, bearbeitest Reviews und wählst die passende Merge-Methode.

# Code Reviews auf professionellem Niveau

Gute Reviews verbessern Qualität, Wissenstransfer und Sicherheit. Dieses Kapitel behandelt kleine Review-Einheiten, konstruktives Feedback, GitHub-Vorschläge, Threads und Freigaben. Du lernst zugleich, automatisierte Prüfungen einzubeziehen und menschliche Verantwortung nicht an Werkzeuge abzugeben.

# GitHub Issues, Projects und Diskussionen

Dieses Kapitel verbindet Quellcode mit Planung und Kommunikation. Du strukturierst Issues, Vorlagen, Labels, Milestones und Abhängigkeiten, verknüpfst Commits und Pull Requests und automatisierst Projektboards. GitHub Discussions und nachvollziehbare Entscheidungsprotokolle ergänzen den Teamprozess.

# Tags, Versionen und Releases

Versionen markieren stabile Punkte in der Historie. Du vergleichst leichtgewichtige und annotierte Tags, signierst und überträgst sie und setzt Semantic Versioning praktisch um. GitHub Releases, Changelogs, Vorabversionen und Hotfix-Abläufe führen zu reproduzierbaren Veröffentlichungen.

# Team-Workflows und Branching-Modelle

Unterschiedliche Teams benötigen unterschiedliche Abläufe. Dieses Kapitel vergleicht Feature Branching, GitHub Flow, Git Flow, Trunk-Based Development und Release-Branches. Du bewertest Integrationsfrequenz, Freigaben, Hotfixes und Branch-Schutz statt ein Modell unkritisch zu übernehmen.

# GitHub Actions und kontinuierliche Integration

Du automatisierst Tests, Qualitätsprüfungen, Builds und Releases mit GitHub Actions. Das Kapitel erklärt Workflows, Events, Jobs, Runner, Matrizen, Artefakte, Caches und Secrets. Ein praxisnaher PHP-Workflow bindet Composer, PHPUnit und statische Analyse in Pull Requests ein.

# GitHub-Sicherheit und Lieferkettenschutz

Dieses Kapitel schützt Konto, Repository und Abhängigkeiten. Du arbeitest mit Berechtigungen nach dem Least-Privilege-Prinzip, Dependabot, Secret Scanning, Code Scanning und geschützten Umgebungen. Auch kompromittierte Schlüssel, versehentlich veröffentlichte Secrets und Security Advisories werden behandelt.

# Git unter der Haube

Hier wird Git vom Bedienwerkzeug zum verständlichen Datenmodell. Du untersuchst Blobs, Trees, Commits, Tags, Hashes und Referenzen direkt im Objektbestand. Plumbing-Befehle zeigen, wie aus Dateiinhalten unveränderliche Objekte und daraus die gerichtete Commit-Struktur entstehen.

# Referenzen, Index und Reflogs intern

Dieses Kapitel zerlegt die beweglichen Bestandteile von Git. Du erforschst Branch- und Tag-Referenzen, HEAD, packed-refs, den binären Index und Reflogs. Dadurch werden Branch-Wechsel, Staging, Reset und Wiederherstellung nicht mehr als Magie, sondern als konkrete Zeiger- und Zustandsänderungen verständlich.

# Speicherung, Packfiles und Wartung

Git komprimiert ältere Objekte in Packfiles und nutzt Indizes, Delta-Kompression und Graphdateien für Geschwindigkeit. Du analysierst lose und gepackte Objekte, führst Wartung aus und verstehst Erreichbarkeit sowie Garbage Collection. So kannst du große oder beschädigte Repositories fundiert untersuchen.

# Netzwerkprotokolle und Datentransfer

Fetch und Push werden technisch bis zur Protokollebene erklärt. Du lernst Referenzwerbung, Objektverhandlung, Packfile-Übertragung, Thin Packs und serverseitige Prüfungen kennen. HTTPS, SSH und Git-Protokoll werden hinsichtlich Authentifizierung, Sicherheit und Einsatzgebiet verglichen.

# Fortgeschrittene Werkzeuge für den Alltag

Git bietet mächtige Werkzeuge jenseits des Standard-Workflows. Du überträgst einzelne Commits, suchst Fehler per Bisektion, nutzt Worktrees und erzeugst Patches. Hooks, Aliase und bedingte Konfigurationen helfen, wiederkehrende Aufgaben zu automatisieren und mehrere Projekte sauber zu verwalten.

# Große Repositories und besondere Dateitypen

Große Binärdateien, Monorepos und umfangreiche Historien benötigen spezielle Verfahren. Dieses Kapitel behandelt Git LFS, flache und partielle Klone, Sparse Checkout, Submodule und Subtrees. Du lernst Nutzen, Grenzen und Migrationsrisiken kennen und vermeidest typische Performance-Fallen.

# Historien bereinigen und Repositories migrieren

Manchmal müssen Geheimnisse, große Dateien oder falsche Autorenangaben aus der gesamten Historie entfernt werden. Du planst invasive Umschreibungen, setzt git filter-repo ein und koordinierst Force Pushes. Import, Export, Repository-Aufteilung und die Folgen für Klone und Pull Requests werden erklärt.

# Konfiguration, Attribute und plattformübergreifende Projekte

Dieses Kapitel vertieft systemweite, globale, lokale und Worktree-bezogene Einstellungen. Mit .gitattributes steuerst du Zeilenenden, Binärdateien, Diffs, Merges und Exporte. Besonderes Augenmerk gilt Windows 11, Linux-Servern, Groß-/Kleinschreibung und stabilen Teamstandards.

# Fehlersuche und Diagnose

Statt Befehle blind zu wiederholen, lernst du einen systematischen Diagnoseprozess. Status, Logs, Referenzen, Konfiguration, Trace-Ausgaben und Netzwerkprotokolle liefern belastbare Hinweise. Typische Windows-, PhpStorm-, Authentifizierungs-, Merge- und Synchronisationsprobleme werden reproduzierbar gelöst.

# GitHub-Organisationen und Administration

Für professionelle Teams reicht ein persönliches Konto nicht aus. Dieses Kapitel behandelt Organisationen, Teams, Rollen, Repository-Vorlagen, Regeln und Audit-Protokolle. Du gestaltest Zugriffe, Standardrichtlinien und Wiederverwendbarkeit so, dass Wachstum, Sicherheit und Compliance unterstützt werden.

# Open Source auf GitHub

Dieses Kapitel führt durch die technischen und sozialen Aspekte offener Projekte. Du wählst eine Lizenz, erstellst Community-Dateien, definierst Beitragsregeln und pflegst Releases. Zudem lernst du, fremde Projekte respektvoll zu unterstützen und Beiträge effizient zu prüfen und zu betreuen.

# Professioneller Praxisworkflow mit PHP und PhpStorm

In einem durchgängigen Projekt kombinierst du alle Kernkompetenzen: Repository-Einrichtung, Composer, Branches, Tests, Reviews, CI und Release. Jeder Arbeitsschritt wird in PhpStorm und auf der Kommandozeile nachvollzogen, sodass Werkzeugverständnis und Routine gemeinsam wachsen.

# Vom sicheren Anwender zum Git-Profi

Das Abschlusskapitel führt Wissen, Denkmodelle und Diagnosefähigkeiten zusammen. Du entwickelst persönliche Checklisten, Teamkonventionen und Übungsstrategien, lernst Dokumentation effizient zu lesen und kannst unbekannte Git-Situationen selbstständig analysieren, testen und sicher lösen.