Befehl:
$ git checkout -b feauture/fix_code_quality
# (Hinweis: hatte ursprünglich den Tippfehler!)
Nach dem Erstellen des Branches:
feauture/fix_code_quality erstelltmain (beaea6c)Wichtige Erkenntnis: Das Erstellen eines Branches ist günstig - es ist nur das Erstellen eines Zeigers (ein paar Bytes)!
Den ersten Commit erstellen:
$ vim main.py # Code-Formatierung reparieren
$ git add main.py
$ git commit -m "fix code formatting using ruff format"
Vor dem Commit:
Nach dem Commit (032f36c):
Was ist passiert:
032f36c erstelltfeauture/fix_code_quality-Zeiger vorwärts zu 032f36c bewegtmain-Zeiger blieb bei beaea6c (unverändert!)feauture/fix_code_qualityNur der aktuelle Branch-Zeiger bewegt sich, wenn Sie commiten.
Andere Branches bleiben, wo sie sind!
So bieten Feature-Branches Isolation - Ihre Arbeit auf dem Feature-Branch beeinflusst main nicht.
Weitere Commits erstellen:
$ git commit -m "lasse ruff check laufen..." # e341990
$ git commit -m "style: fix code quality..." # 1ff0a77
Finaler Zustand nach 3 Commits auf dem Branch:
Was Sie sehen:
main ist immer noch bei beaea6c (wo Sie abgezweigt sind)feauture/fix_code_quality ist durch 3 Commits vorwärts gegangenZurück zu main wechseln:
$ git checkout main
Vor dem Checkout:
Nach dem Checkout:
Nur HEAD hat sich bewegt!
beaea6c zu zeigenfeauture/fix_code_quality zeigt immer noch auf 1ff0a77Das ist alles, was git checkout macht - es bewegt den HEAD-Zeiger!
Wenn Sie den Feature-Branch mergen:
$ git checkout main
$ git merge feauture/fix_code_quality
# (Oder merge über GitHub PR)
Ergebnis: Fast-Forward-Merge
Nach dem Merge (Fast-Forward):
Was ist passiert:
main-Zeiger vorwärts zu 1ff0a77 bewegtmain als auch feauture/fix_code_quality zeigen jetzt auf denselben CommitIm Beispiel oben war es einfach — main hatte sich nicht bewegt. In echten Teams arbeiten mehrere Entwickler parallel: während Sie am Feature waren, hat jemand anderes seinen PR gemergt.
main und Ihr Feature sind divergiert — ein Fast-Forward ist nicht mehr möglich. Frage an Sie: Wie bringen Sie die drei Commits jetzt sauber zurück in main?
$ git checkout main
$ git merge --no-ff feature/fix_code_quality
# Erstellt einen Merge-Commit M3 mit zwei Eltern: M2 und C3
M3 ist ein neuer Commit mit zwei Eltern: M2 (von main) und C3 (vom feature-Branch). Die Feature-Commits behalten ihre Original-Hashes — sie werden nicht kopiert, sondern sind über M3 jetzt auch von main aus erreichbar.
Vorteile
git log --graph lesbar Nachteile
Typischer Einsatz: Teams, die Feature-Lineage bewusst sichtbar halten wollen — jeder Merge ist ein erkennbarer Integrationspunkt im git log --graph.
Was steht im Merge-Commit?
Git generiert eine Default-Message und öffnet Ihren Editor:
Merge branch 'feature/fix_code_quality' into main
Direkt setzen oder anpassen:
$ git merge --no-ff feature/... \
-m "Merge: code quality (PR #42)"
Auf GitHub via PR — automatisch:
Merge pull request #42 from user/feature/fix_code_quality
<PR-Beschreibung als Body>
Was passiert mit dem Feature-Branch?
In der Praxis nach dem Merge löschen:
$ git branch -d feature/fix_code_quality
$ git push origin --delete feature/fix_code_quality
Sind Ihre Commits damit weg? Nein. C1, C2, C3 bleiben über M3 erreichbar:
git log zeigt sie weiterhingit blame findet ihre Autorengit checkout C2 springt direkt dorthinEin Branch ist nur ein Zeiger — den Zeiger zu löschen löscht keine Commits.
$ git checkout main
$ git merge --squash feature/fix_code_quality
$ git commit -m "Fix code quality (PR #42)"
# Auf GitHub: der "Squash and merge"-Button
S1 ist ein neuer Commit, der alle Änderungen aus C1, C2, C3 als einen Diff zusammenfasst. C1, C2, C3 selbst sind nicht in der Historie von main — der feature-Branch wird typischerweise gelöscht.
Vorteile
main Nachteile
main verlorengit bisect weniger granularTypischer Einsatz: GitHub-Repos mit "Squash and merge"-Default — Feature-Autor macht beliebig viele kleine Commits, die beim Merge zu einem sauberen main-Commit verschmelzen.
$ git checkout feature/fix_code_quality
$ git rebase main # C1, C2, C3 werden auf M2 "umgehängt"
$ git push --force-with-lease
$ git checkout main
$ git merge feature/fix_code_quality # Jetzt Fast-Forward möglich!
C1', C2', C3' haben neue Hashes — sie sind umgehängte Kopien der ursprünglichen C1, C2, C3. Die Originale existieren nur noch im Reflog.
Vorteile
git log liest sich wie eine Geschichte Nachteile
Goldene Regel: Nur Branches rebasen, an denen sonst niemand arbeitet — sonst zerstören Sie die Historie der Kolleg:innen.
| Strategie | Historie auf main |
Wann sinnvoll |
|---|---|---|
| Fast-Forward | Linear, keine Merge-Spuren | Solo-Projekte, main hat sich nicht bewegt |
Merge-Commit (--no-ff) |
Verzweigt, vollständig | Teams, die Feature-Lineage sehen wollen |
| Squash & Merge | Linear, ein Commit pro PR | Viele kleine "WIP"-Commits; saubere main |
| Rebase + FF | Linear, alle Commits | Feature-Branch lokal aktualisieren vor PR |
In der Praxis: Teams entscheiden sich pro Repo, nicht pro PR. GitHub-Repos werden oft auf Squash-only oder Merge-Commit-only konfiguriert. Rebase bleibt meist ein lokales Werkzeug, um den eigenen Feature-Branch sauber zu halten.
Wichtig: Nicht die "perfekte" Strategie wählen — sondern eine, die zum Team passt und konsequent durchhalten.
Den lecture-04 Tag erstellen:
$ git tag -a lecture-04 -m "End of Chapter 02 (Refactoring): Code quality fixes"
Aktueller Zustand mit Tag:
Alle vier Zeiger zeigen auf den GLEICHEN Commit 1ff0a77!
Tags sind genau wie Branches - sie sind Zeiger auf Commits!
Der Unterschied:
Beide sind nur Referenzen auf Commits - keine Kopien von Commits.
Den Tippfehler korrigieren:
$ git branch -m feauture/fix_code_quality feature/fix_code_quality
Was ist passiert:
Vor dem Umbenennen:
Nach dem Umbenennen:
Der Commit 1ff0a77 hat sich nie geändert!
Sie haben nur:
Deshalb:
lecture-04 funktioniert immer noch (zeigt auf Commit, nicht auf Branch-Namen)Ohne Branches (direkt auf main):
main: A → B → C → D(kaputt) → E(fix) → F(fix) → G(ok)
↑
Alle sehen kaputten Code
Andere Devs blockiert
Rückgängig machen schwer
Mit Feature-Branches:
main: A → B → C ────────────→ M (merge)
feature: D → E → F → G (getestet)
↑
Nur Sie sehen das
Sicher zu experimentieren
Einfach zu löschen
5 Vorteile: Isolation · Sicherheit · Experimentieren · Review · leichtes Rollback
Branches anzeigen:
$ git branch
main
* feature/fix-code-quality ← Sie sind hier (*)
feature/improve-road-curve
Branch erstellen:
$ git branch feature/new-feature # Erstellen, auf aktuellem Branch bleiben
$ git checkout -b feature/new-feature # Erstellen UND wechseln (klassisch)
$ git switch -c feature/new-feature # Erstellen UND wechseln (modern)
Zwischen Branches wechseln:
$ git checkout feature/fix-code-quality # klassisch
$ git switch feature/fix-code-quality # modern
# Branch löschen
$ git branch -d feature/old-feature # Sicher — nur wenn gemerged
$ git branch -D feature/old-feature # Erzwingen — auch wenn nicht gemerged
# Branches inspizieren
$ git branch # Lokale Branches
$ git branch -a # Alle Branches (inkl. Remote)
$ git branch --merged main # In main gemergte Branches
$ git branch --no-merged # Noch nicht gemergte Branches
Nach dem Mergen löschen hält das Repo sauber. Branches sind günstig — erstelle einen frischen für das nächste Feature.
main pushenmain gemergedGoldene Regel: Niemals direkt auf main pushen. Immer Feature-Branches verwenden.
(Das erzwingen Sie gleich mit Branch-Schutz.)
Gut — beschreibend, mit Präfix
feature/improve-road-curve
fix/intersection-calculation
refactor/ray-calculation
docs/add-usage-instructions
fix/42-intersection-bug
Schlecht — nichtssagend, vage
branch1
test
dominik-stuff
fix
new
Best Practices:
kebab-case)feature/, fix/, refactor/, docs/main erstellenmain mergenSchritte 1–3: lokal · Schritte 4–9: kollaborativ · Schritt 10: Aufräumen
# 1. Feature-Branch vom aktualisierten main erstellen
$ git checkout main
$ git pull origin main
$ git checkout -b feature/fix-code-quality
# 2. Implementieren — kleine, logische Commits
$ vim main.py
$ git add main.py
$ git commit -m "Fix PEP8: imports auf verschiedene Zeilen aufteilen"
$ vim main.py
$ git add main.py
$ git commit -m "Fix PEP8: Spacing um Operatoren"
# 3. Zu GitHub pushen (erstes Mal: -u verknüpft lokal
remote)
$ git push -u origin feature/fix-code-quality
Gute Commits: klein, fokussiert, beschreibend · referenziere den Standard (PEP8) · Checks vorher laufen lassen.
Ein Pull Request bittet: "Bitte review meine Änderungen und merge sie."
Auf GitHub:
main · Compare: feature/fix-code-qualityDer PR ist jetzt für das ganze Team sichtbar — sie können kommentieren, reviewen und approven.
5. Automatische Checks (GitHub Actions)
Ruff check passed
Ruff format check passed
Pyright type check passed
Tests pass
Alle Checks grün — bereit zum Merge!
Check rot → lokal fixen → pushen → PR läuft automatisch neu.
6. Code-Review — Reviewer achten auf:
7. Feedback einarbeiten — weitere Commits pushen, PR aktualisiert sich automatisch.
8. Mergen (auf GitHub, drei Strategien):
| Strategie | Was sie macht |
|---|---|
| Merge commit | Alle Commits + neuer Merge-Commit (Standard) |
| Squash and merge | Alle Commits zu einem kombiniert |
| Rebase and merge | Commits linear auf main replayed |
9. Feature-Branch löschen — auf GitHub "Delete branch" klicken, dann lokal:
$ git checkout main
$ git pull origin main
$ git branch -d feature/fix-code-quality
Trotz des Namens ist ein Pull Request eigentlich ein Merge Request.
Sie bitten die Maintainer, Ihre Änderungen in ihren Branch zu ziehen. Historischer Begriff; moderne Bedeutung:
"Bitte review und merge meine Änderungen."
Warum PRs wichtig sind:
main erreichtJeder Teil hat einen eigenen Tab in der GitHub-UI — Reviewer arbeiten sie der Reihe nach durch.
Größe zählt
Guter PR — 50–300 Zeilen
Schlechter PR — 2.000+ Zeilen
Beschreibungs-Template
## Was
Ein-Satz-Zusammenfassung.
## Warum
Motivation, Link zum Issue.
## Wie
Wichtige Entwurfsentscheidungen.
## Testing
Welche Befehle, welches Ergebnis.
## Checklist
- [ ] Tests aktualisiert
- [ ] Docs aktualisiert
Wenn der PR zu groß ist — in mehrere kleinere PRs aufteilen.
# Code im PR
def generate_road_profile(num_points=100, x_max=80):
x = np.linspace(0, x_max, num_points)
x_norm = x / x_max
y = 0.015 * x_norm**3 * x_max + 0.3 * np.sin(2 * np.pi * x_norm) + 0.035 * x_norm * x_max
y = y - y[0]
return x, y
Reviewer-Kommentare:
-> tuple[np.ndarray, np.ndarray]num_points > 0 und x_max > 0?0.015, 0.3, 0.035) — als benannte Konstanten extrahieren?Autor antwortet: einen Folge-Commit pushen; der PR aktualisiert sich automatisch.
| Zustand | Bedeutung |
|---|---|
| Open | Unter Review, kann noch geändert werden, noch nicht gemerged |
| Merged | Akzeptiert und in den Ziel-Branch gemerged — Branch kann gelöscht werden |
| Closed | Abgelehnt oder aufgegeben — kann bei Bedarf wieder geöffnet werden |
| Draft | Work in progress, noch nicht reif für Review — gut für frühes Feedback |
Tipp: Sie öffnen Ihren PR früh als Draft, wenn Sie Feedback zur Richtung wollen, bevor Sie mehr Zeit investieren.
Das Problem: technisch hindert Sie nichts daran, das hier zu tun —
$ git checkout main
$ git commit -m "Quick fix"
$ git push origin main # Umgeht den PR-Prozess!
Die Lösung: Branch Protection auf GitHub konfigurieren (Settings → Branches):
$ git push origin main
remote: error: GH006: Protected branch update failed for refs/heads/main.
remote: error: Cannot push directly to main. Use a pull request.
To github.com:yourname/yourrepo.git
! [remote rejected] main -> main (protected branch hook declined)
error: failed to push some refs to 'github.com:yourname/yourrepo.git'
Vorteile:
main ohne ReviewIn Teil 2 fügen Sie GitHub Actions hinzu, die bei jedem PR Checks laufen lassen:
# .github/workflows/quality.yml
name: Code Quality
on:
pull_request: # Trigger bei PRs (nicht bei direkten Pushes)
branches: [main]
jobs:
quality:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v4
- run: uv sync --dev
- run: uv run ruff check .
Beim Öffnen eines PR läuft GitHub automatisch alles durch und blockiert den Merge bei Fehlern.
1. Feature-Branch von main erstellen
2. Feature implementieren (kleine Commits)
3. Branch zu GitHub pushen
4. Pull Request öffnen
↓
5. Automatische Checks laufen (GitHub Actions)
Ruff linter ·
Ruff format ·
Pyright ·
Tests
↓
6. Checks rot → fixen → pushen → Checks laufen erneut
↓
7. Review anfragen → Feedback einarbeiten → Approval holen
↓
8. In main mergen (nur möglich, wenn Checks grün + approved)
9. Feature-Branch löschen
So liefern professionelle Teams Code in hoher Qualität aus.
Ziel: Ein echtes Code-Quality-Problem im Road Profile Viewer mit dem vollständigen Feature-Branch-Workflow fixen.
Das Ziel: die ungenutzte HelperFunction in main.py entfernen — einer der 14 Ruff-Fehler aus Kapitel 02.
# Unused function entfernen oder auskommentieren:
# def HelperFunction(val):
# """Unused helper function that violates naming convention"""
# result=val*2
# return result
Sie erstellen einen Branch, machen den Fix, öffnen einen PR, mergen und räumen auf.
# 1. Von aktualisiertem main starten
$ git checkout main
$ git pull origin main
# 2. Feature-Branch erstellen
$ git checkout -b feature/remove-unused-helper
# 3. Änderung machen
$ vim main.py # HelperFunction auskommentieren oder löschen
# 4. Fix lokal verifizieren
$ uv run ruff check main.py
# → Sollte EINEN Fehler weniger zeigen
# 5. Committen
$ git status
$ git add main.py
$ git commit -m "Fix PEP8: unused HelperFunction entfernen"
# 6. Zu GitHub pushen (erstes Mal: -u)
$ git push -u origin feature/remove-unused-helper
7. Auf GitHub → Pull Request öffnen
Fix PEP8: unused HelperFunction entfernen8. Eigenen PR reviewen im "Files changed"-Tab
# 9. Auf GitHub mergen — "Merge pull request" → "Confirm merge" → "Delete branch"
# 10. Lokal aufräumen
$ git checkout main
$ git pull origin main
$ git branch -d feature/remove-unused-helper
# 11. Verifizieren
$ git log --oneline
# → Sie sollten sehen: "Fix PEP8: unused HelperFunction entfernen"
$ uv run ruff check main.py
# → Ein Fehler weniger!
Challenge: wiederhole diesen Prozess für jeden der verbleibenden 13 Ruff-Fehler — ein Branch, ein PR pro Fix.
Haben Sie:
main gestartet?Bei „Ja" zu allem → Sie denken wie professionelle Entwickler.
Feature starten
git checkout main
git pull origin main
git checkout -b feature/my-feature
Während der Arbeit
git status
git diff
git add <file>
git commit -m "Message"
Pushen
git push -u origin feature/my-feature # erstes Mal
git push # danach
Abschluss (nach PR-Merge)
git checkout main
git pull origin main
git branch -d feature/my-feature
Information
git status
git log --oneline --graph --all
git branch
git diff
git diff --staged
git show <commit-hash>
Rückgängig machen
git restore <file> # Arbeitsverzeichnis-Änderung verwerfen
git restore --staged <file> # Unstagen (Änderung behalten)
git reset HEAD~1 # Letzten Commit zurücknehmen (Dateien bleiben)
git commit --amend # Letzte Commit-Message ändern
Auf den falschen Branch committet (noch nicht gepusht)
git reset HEAD~1
git checkout correct-branch
git add .
git commit -m "Message"
Feature-Branch mit neuestem main aktualisieren
git checkout feature/my-feature
git pull origin main # Konflikte ggf. auflösen
git push
Vergessen, einen Feature-Branch zu erstellen
git stash
git checkout -b feature/new-feature
git stash pop
git add . && git commit -m "Message"
Neu anfangen bei einer Datei
git checkout <file>
Vorher — Cowboy-Coding
$ git add .
$ git commit -m "stuff"
$ git push origin main
#
Hoffen, dass nichts bricht!
Nachher — professioneller Workflow
$ git checkout main
$ git pull origin main
$ git checkout -b feature/fix-code-quality
# ... arbeiten ...
$ git add main.py
$ git commit -m "Fix PEP8: imports trennen..."
$ git push -u origin feature/fix-code-quality
# PR öffnen · Review · Merge
$ git checkout main && git pull
$ git branch -d feature/fix-code-quality
main pushen — immer Feature-Branches verwendenmain starten — immer pull vor dem Branchgit status ist Ihr Freund — ständig ausführen