Zum Inhalt springen

Git & GitHub - Komplette Referenz

SAP Implementation Consulting & ERP - Startupistan Deutschland · Block I · Lernnotizen zur Wiederholung.


Die selbstgebastelte Variante davon hat jeder schon gemacht: report-final.docx, report-final2.docx, report-FINAL-really.docx. Es funktioniert so halb, bis ich mich nicht mehr erinnere, welche Kopie die neueste ist, nicht mehr sehe, was sich zwischen zwei davon eigentlich geändert hat, und die falsche lösche - ohne Rückgängig. Im Team wird es schlimmer: Zwei Leute bearbeiten dieselbe Datei, und das zweite Speichern überschreibt klammheimlich das erste.

Versionskontrolle ist genau dieser Instinkt, nur richtig gemacht. Sie beobachtet einen Ordner und hält, sobald ich es sage, einen Snapshot von allem fest, der Reihe nach, jeweils mit einer Notiz und einem Zeitstempel. Im Gegenzug bekomme ich vier Dinge:

  • Verlauf - jeder Speicherpunkt bleibt erhalten, sodass sich das Projekt wie ein Tagebuch dessen liest, was sich wann und warum geändert hat.
  • Rückgängig - jede Datei, oder das ganze Projekt, kann auf einen früheren Speicherpunkt zurückgehen. Nichts, was ich festgehalten habe, geht durch eine spätere Änderung verloren.
  • Paralleles Arbeiten - mehrere Leute (oder auch nur ich, der zwei Ideen ausprobiert) arbeiten gleichzeitig, ohne sich gegenseitig in die Quere zu kommen.
  • Nachvollziehbarkeit - jede Änderung ist signiert, sodass „wer hat das angefasst, und warum?” immer eine Antwort hat.

Es ist kein reines Werkzeug für große Teams. Allein arbeitend verdienen sich schon das Rückgängig und der Verlauf ihren Platz - das Ich von nächstem Monat hat alles vergessen, und der Verlauf ist die Art, wie ich mich erinnere.


Git vs. GitHub - die eine Unterscheidung, die man im Kopf behalten muss

Abschnitt betitelt „Git vs. GitHub - die eine Unterscheidung, die man im Kopf behalten muss“

Die beiden Namen werden so oft in einem Atemzug genannt, dass Einsteiger sie für eine Sache halten. Es sind zwei Dinge, von verschiedenen Leuten gemacht, und das erste funktioniert vollständig ohne das zweite.

GitGitHub
Was es istEin Programm, das auf meinem Rechner installiert istEine Website und ein Cloud-Dienst
Wo es läuftLokal, auf meinem RechnerIm Internet
Seine AufgabeZeichnet Verlauf auf, stellt Versionen wieder her, verwaltet BranchesHostet Git-Projekte, damit andere sie sehen und mitwirken können
Braucht Internet?Nein - funktioniert komplett offlineJa
Braucht einen Account?NeinJa
Entstanden20052008

Eine Frage hält es auseinander: „Wo passiert es?” Verlauf aufzeichnen passiert auf meinem Rechner, mit Git, offline. Diesen Verlauf teilen und Änderungen besprechen passiert in der Cloud, auf GitHub. Würde das Internet morgen verschwinden, liefe Git weiter und GitHub nicht.

GitHub ist nicht der einzige Anbieter - GitLab, Bitbucket und Azure DevOps machen dieselbe Arbeit. Jeder Befehl weiter unten funktioniert bei allen identisch, weil die Befehle zu Git gehören, nicht zur Website. Git zu lernen ist die übertragbare Fähigkeit; GitHub ist nur der Treffpunkt, den diese Notizen verwenden.


Das ist das eine Stück Theorie, auf dem das ganze Werkzeug ruht. Jeder Befehl, den ich lerne, bewegt Arbeit zwischen drei (eigentlich vier) Orten, immer in dieselbe Richtung.

Working Directorydie Dateien, die ich bearbeite
→
Staging Areawas in den nächsten Speicherpunkt kommt
→
Repositorydauerhafter Verlauf (.git)
→
Remoteder Zwilling in der Cloud (GitHub)
Arbeit fließt in eine Richtung: bearbeiten → stagen, was zusammengehört → in den Verlauf committen → in die Cloud pushen.
  • Working Directory (Arbeitsverzeichnis) - der Ordner, den ich sehe; meine tatsächlichen Dateien in ihrem aktuellen Zustand. Hier bearbeite ich. Ab hier verwende ich den englischen Begriff Working Directory.
  • Staging Area - ein Warteraum zwischen meinen Änderungen und dem Verlauf. Hier sammle ich genau die Änderungen, die in den nächsten Speicherpunkt gehören. Nichts hier ist bisher dauerhaft.
  • Repository - der aufgezeichnete Verlauf, aufbewahrt in einem versteckten .git-Ordner. Sobald eine Änderung hier committet ist, ist sie ein dauerhafter Speicherpunkt. (Ein Repository, oder Repo, ist einfach ein Ordner plus sein vollständiger aufgezeichneter Verlauf.)
  • Remote - eine Kopie des Repositorys, die anderswo gehostet wird (GitHub). Weiter unten behandelt.

Warum zwei Schritte zum Speichern, nicht einer? Die Staging Area ist Gits bestes Feature in Verkleidung: Sie lässt mich auswählen, was in jeden Speicherpunkt kommt. Wenn ich in einer Datei einen Tippfehler behoben und eine andere halb neu geschrieben habe, kann ich die fertige Tippfehler-Korrektur jetzt committen und die unfertige Umschreibung aus dem Verlauf heraushalten, bis sie bereit ist. Speicherpunkte bleiben sauber und ehrlich beschriftet.

Jede Datei befindet sich in genau einem von vier Zuständen und durchläuft sie im Lauf der Arbeit: untracked (brandneu, Git wurde nie gesagt, dass es sich darum kümmern soll), unmodified (getrackt, identisch mit dem letzten Speicherpunkt), modified (getrackt, seit dem letzten Speicherpunkt geändert, noch nicht gestaget), staged (im Karton, bereit für den nächsten Commit).


Erstmalige Einrichtung - ein Handschlag pro Rechner

Abschnitt betitelt „Erstmalige Einrichtung - ein Handschlag pro Rechner“

Jeder Speicherpunkt wird für immer mit einem Autorennamen und einer E-Mail signiert. Git weigert sich, diese zu erraten, also sage ich es ihm einmal, und es merkt es sich für jedes Projekt auf diesem Rechner. --global bedeutet „für jedes Projekt auf diesem Computer”.

Terminal-Fenster
# Meine Commits signieren (dieselbe E-Mail wie mein GitHub-Account verwenden)
git config --global user.name "My Name"
git config --global user.email "me@example.com"
# Jedes neue Repo auf einem Branch namens "main" starten lassen (passt zu GitHub)
git config --global init.defaultBranch main
# Eine Einstellung überprüfen, indem ich sie beim Namen abfrage
git config user.name

Keine Ausgabe bedeutet, es hat funktioniert. Die E-Mail ist nicht geheim - sie wird im Verlauf des Projekts sichtbar, sobald ich veröffentliche, und genau so wird Arbeit meinem Profil zugerechnet. Etwas falsch getippt? Dieselbe Zeile noch einmal mit dem richtigen Wert ausführen; die neue Antwort ersetzt die alte.


Das ist der Rhythmus jedes Arbeitstags: bearbeiten → status → add → commit, mit log, diff und restore als Lese- und Rettungswerkzeugen drum herum.

  1. Das Repository erstellen - einmal pro Projekt. init ist die Kurzform von initialize („zum ersten Mal einrichten”). Einmal ausführen, im obersten Ordner des Projekts.

    Terminal-Fenster
    cd my-project
    git init
    Initialized empty Git repository in /home/me/my-project/.git/

    Dieser versteckte .git-Ordner ist das Repository - jeder Speicherpunkt liegt darin, und er reist mit dem Ordner mit, wenn ich ihn kopiere oder verschiebe. Niemals von Hand bearbeiten oder löschen.

  2. Den Zustand prüfen - vor und nach allem. git status meldet, was untracked, modified oder staged ist und auf welchem Branch ich bin. Es ändert nichts, kostet eine Sekunde und macht Gits unsichtbare Buchführung sichtbar.

    Terminal-Fenster
    echo "The Corner Bakery" > notes.txt
    git status
    On branch main
    No commits yet
    Untracked files:
    (use "git add <file>..." to include in what will be committed)
    notes.txt
  3. Stagen, was zusammengehört. git add kopiert den aktuellen Inhalt einer Datei in die Staging Area. Schweigen bedeutet Erfolg - mit status bestätigen (die Datei wechselt von rot/untracked zu grün/staged).

    Terminal-Fenster
    git add notes.txt # eine Datei - der bewusste Standardfall
    git add notes.txt menu.txt # mehrere Dateien
    git add . # alles unterhalb hiervon - bequem, aber vorher status prüfen

    Stagen macht einen Snapshot der Datei so, wie sie genau jetzt ist. Wenn ich sie danach erneut bearbeite, ist diese neuere Änderung nicht im Karton - status listet dieselbe Datei dann als staged und modified auf. Lösung: erneut git add.

  4. Den Snapshot festhalten. git commit -m "message" versiegelt alles Gestagete zu einem dauerhaften Speicherpunkt. -m ist die message (Commit-Message), in Anführungszeichen direkt dahinter.

    Terminal-Fenster
    git commit -m "Add bakery notes file"
    [main (root-commit) f4a2c1e] Add bakery notes file
    1 file changed, 1 insertion(+)
    create mode 100644 notes.txt

    Dieses f4a2c1e ist der kurze Bezeichner des Commits (seine Adresse). Ein Commit ist ein dauerhafter, adressierbarer Snapshot, signiert mit meinem Namen und meiner E-Mail, mit der Zeit gestempelt, mit meiner Commit-Message beschriftet. Er geht nie klammheimlich verloren oder wird überschrieben - der Stapel wächst nur.

  5. Den Verlauf lesen. git log läuft die Commits neueste zuerst ab; --oneline ist die kompakte Story-Ansicht.

    Terminal-Fenster
    git log --oneline
    7b9e0d2 (HEAD -> main) Add Saturday opening hours
    f4a2c1e Add bakery notes file

    HEAD ist Gits Wort für „wo ich gerade stehe” - normalerweise die Spitze des aktuellen Branches. Wenn der Log mehr als einen Bildschirm füllt, öffnet er sich in einem Pager: q drücken zum Beenden (der klassische „mein Terminal hängt fest”-Moment, vorab gelöst).

  6. Die genauen Änderungen sehen. git diff zeigt Zeile für Zeile, was sich seit dem letzten Commit im Working Directory geändert hat und noch nicht gestaget ist. +-Zeilen wurden hinzugefügt, --Zeilen entfernt, schlichte Zeilen sind unveränderter Kontext. Dieses Diff-Format ist die universelle Sprache des Code Reviews.

    Terminal-Fenster
    git diff
    diff --git a/notes.txt b/notes.txt
    @@ -1,2 +1,3 @@
    The Corner Bakery
    Open Saturdays from 8:00
    +Closed on public holidays
  7. Eine Datei retten - der Lohn des Committens. Eine Datei beschädigt (geleert, einen Absatz gelöscht, eine Stunde Änderungen, die ich weghaben will)? git restore wirft die nicht committeten Änderungen weg und bringt die Datei auf ihren letzten Speicherpunkt zurück.

    Terminal-Fenster
    git status # bestätigt, dass die Datei "modified" ist - die Arbeit ist im letzten Commit sicher
    git restore notes.txt # den Schaden verwerfen, zurück zum letzten Speicherpunkt
    git restore --staged menu.txt # eine Datei wieder AUS dem Karton nehmen (Inhalt unangetastet)

    Die ehrliche Warnung: restore verwirft aktuelle, nicht committete Änderungen - das ist seine ganze Aufgabe. Im Zweifel vorher kurz einen Blick auf git diff werfen. Es rührt niemals committeten Verlauf an; Commits sind das, woraus es rettet. Je öfter ich committe, desto näher ist mein nächster Speicherpunkt immer.

Die Message ist für Menschen, die später mitlesen - meistens das zukünftige Ich, drei Wochen später, das alles vergessen hat. Die Konventionen der Branche:

  • Imperativ - „Add weekend specials”, „Fix Saturday opening time”, nicht „added” oder „adding”. Lies sie, als vollende sie den Satz „dieser Commit wird…”.
  • Sag was, und warum, wenn nützlich - „Increase espresso price to match supplier costs” schlägt „change price” schlägt „stuff”.
  • Kurze erste Zeile - unter ~50 Zeichen; es ist die Zeile, die jede Verlaufsansicht zeigt.

Und committe klein und oft: eine logische Änderung pro Commit (ein Bug behoben, ein Abschnitt geschrieben), nicht „alles, was ich heute gemacht habe”. Ein Verlauf aus kleinen, beschrifteten Schritten ist eine lesbare Geschichte, ermöglicht chirurgisch genaues Rückgängigmachen und ist wirklich überprüfbar; ein tausend Zeilen langer „did stuff”-Commit wird überflogen und durchgewunken.


.gitignore - Dateien, die aus dem Verlauf herausbleiben

Abschnitt betitelt „.gitignore - Dateien, die aus dem Verlauf herausbleiben“

Nicht alles in einem Projektordner gehört in seinen Verlauf. Eine .gitignore ist eine reine Textdatei im obersten Ordner des Repos, die Muster auflistet, die Git niemals tracken soll - ein Muster pro Zeile. Ignorierte Dateien tauchen einfach nicht mehr als untracked auf; Git behandelt sie als unsichtbar (sie bleiben unangetastet auf der Festplatte).

.gitignore
# Generierte Dateien - regenerierbar, also ist ihr Aufzeichnen nur Rauschen
*.log
dist/
temp/
# Abhängigkeiten - aus der Rezeptdatei des Projekts neu installierbar
node_modules/
# Geheimnisse - der Verlauf ist dauerhaft und, einmal veröffentlicht, öffentlich
.env

Die .gitignore-Datei selbst wird getrackt und committet, sodass das ganze Team dieselben Regeln teilt:

Terminal-Fenster
git add .gitignore
git commit -m "Add gitignore for logs, build output and secrets"

Alles bisher war lokal. Ein Remote Repository ist eine Kopie meines Repos, die anderswo gehostet wird - für uns auf GitHub. Die beiden sind Zwillinge, die ich bewusst synchron halte: Push schickt meine lokalen Commits hoch, Pull holt Remote-Commits herunter. Nichts synchronisiert sich von selbst, niemals.

Ein Repo bezieht sich auf seine Remotes über einen Spitznamen, und der nahezu universelle Spitzname für das Haupt-Remote eines Projekts ist origin - nichts weiter als eine gespeicherte Adresse mit einem kurzen Namen, wie ein Kontakt in meinem Telefon. git push origin main liest sich als „pushe Branch main zum Remote mit dem Spitznamen origin”.

  1. Ein leeres Repo auf GitHub erstellen. Auf github.com: das +-Menü → New repository. Gib ihm einen kurzen, kleingeschriebenen, mit Bindestrichen getrennten Namen (bakery-notes, nicht test123). Wähle Public. Lass jede Initialisierungs-Checkbox leer - kein README, keine .gitignore, keine Lizenz.

  2. Die Adresse des Remotes unter dem Spitznamen origin speichern. Kopiere die SSH-Adresse von der Einrichtungsseite des Repos (sie beginnt mit git@github.com:, nicht https://). Das schreibt nur eine Zeile in die lokalen Einstellungen - kein Netzwerk, kein Upload, noch keine Prüfung.

    Terminal-Fenster
    git remote add origin git@github.com:my-username/bakery-notes.git
    git remote -v # überprüfen - listet die gespeicherten Remotes (-v = verbose)
    origin git@github.com:my-username/bakery-notes.git (fetch)
    origin git@github.com:my-username/bakery-notes.git (push)
  3. Einen Push versuchen - und ihm beim Scheitern zusehen (mit Absicht). Der erste Push stößt auf eine verschlossene Tür:

    Terminal-Fenster
    git push -u origin main
    git@github.com: Permission denied (publickey).
    fatal: Could not read from remote repository.

    Das ist nicht kaputt - es ist verweigert. GitHub sagt: „Ich weiß nicht, wer du bist, und ich erwarte, dass du es mit einem Public Key beweist, den du mir nicht gezeigt hast.” GitHub akzeptiert seit 2021 keine Account-Passwörter mehr von Git - ein Passwort, das bei jedem Push getippt wird, ist ein Passwort, das ständig exponiert ist. Pushen braucht eine maschinentaugliche Zugangsberechtigung: einen SSH-Key.

  4. Einen SSH-Key einrichten - einmal pro Rechner. Ein SSH-Schlüsselpaar sind zwei zusammengehörige Dateien: ein Private Key, der meinen Rechner nie verlässt, und ein Public Key, den ich GitHub einmal übergebe. Von da an kann GitHub überprüfen, dass Anfragen von dem Rechner kommen, der den privaten Zwilling hält, ohne dass ein Geheimnis über die Leitung geht.

    Terminal-Fenster
    # 1. Das Paar erzeugen (bei allen Abfragen Enter drücken:
    # den Standard-Speicherort akzeptieren, die Passphrase leer lassen)
    ssh-keygen -t ed25519 -C "me@example.com"
    # 2. Den PUBLIC Key ausgeben (die .pub-Datei - die EINZIGE, die den Rechner je verlässt)
    cat ~/.ssh/id_ed25519.pub

    Kopiere diese ganze Zeile (beginnt mit ssh-ed25519 …). Auf github.com: Profilbild → Settings → SSH and GPG keys → New SSH key, benenne ihn nach dem Rechner, einfügen, Add SSH key. Dann testen:

    Terminal-Fenster
    ssh -T git@github.com
    Hi my-username! You've successfully authenticated, but GitHub does not provide shell access.

    Die Zeile „successfully authenticated” ist das Ziel. (Beim ersten Kontakt die einmalige Echtheitsfrage mit yes beantworten. Den Standard-Dateinamen in Schritt 1 beizubehalten ist das, was Git den Schlüssel von selbst finden lässt, ganz ohne zusätzliche Konfiguration.)

  5. Jetzt wirklich pushen. Derselbe Befehl funktioniert nun. -u (für upstream) wird einmal pro Branch benötigt, bei dessen erstem Push - es merkt sich die Paarung, sodass spätere Pushes auf ein Wort schrumpfen.

    Terminal-Fenster
    git push -u origin main
    To github.com:my-username/bakery-notes.git
    * [new branch] main -> main
    branch 'main' set up to track 'origin/main'.

    Ab dem zweiten Push einfach nur:

    Terminal-Fenster
    git push # schickt committete Arbeit hoch; nicht committete Änderungen bleiben zu Hause
  6. Pullen, um aktuell zu bleiben. git pull holt neue Commits vom gepaarten Branch des Remotes und merged sie in meinen lokalen. Fast-forward bedeutet den einfachen Fall: Das Remote war einfach voraus und mein Branch hat aufgeholt, nichts zu verweben.

    Terminal-Fenster
    git pull

    Die professionelle Klammer um jede Arbeitssitzung: pullen, bevor ich anfange (auf dem neuesten Stand aufbauen), pushen, wenn ich aufhöre (teilen, sichern, sichtbar machen).

git clone lädt eine vollständige Kopie eines Remote-Repos herunter - alle Dateien, den gesamten Verlauf, mit bereits verdrahtetem origin (kein git remote add nötig). Es ist der Standard-Erstbefehl auf einem neuen Rechner, in einem neuen Team, in einem neuen Job.

Terminal-Fenster
git clone git@github.com:my-username/bakery-notes.git
cd bakery-notes

Ein Branch ist eine eigenständige Entwicklungslinie innerhalb eines Repositorys. Commits auf einem Branch berühren keinen anderen Branch; jede Linie lässt ihren eigenen Verlauf wachsen, bis ich sie bewusst merge. Jedes Repo startet mit einem Branch, main.

Die universelle Konvention: main ist die stabile Linie - was darauf ist, funktioniert, es ist die Version, die ich jedem jederzeit zeigen würde. Änderungen werden auf kurzlebigen Branches gemacht - neue Arbeit, Experimente, Fixes bekommen jeweils ihren eigenen Branch, einen sicheren Arbeitsraum, in dem nichts, was ich tue, main stören kann. Fertig und geprüft → hineinmergen. Sackgasse → den Branch löschen, und main hat nie davon erfahren.

Terminal-Fenster
git branch # Branches auflisten; der * markiert, wo ich bin
git switch -c weekend-specials # einen neuen Branch erstellen UND darauf wechseln (-c = create)
git switch main # zu einem bestehenden Branch wechseln

Das Wechseln verwandelt das Working Directory an Ort und Stelle - die Dateien in meinem Ordner ändern sich passend zu dem Branch, auf dem ich lande. Ein Ordner, viele parallele Zustände. Commits landen immer auf dem Branch, auf dem ich stehe, also ist die mit Abstand nützlichste Angewohnheit, die erste Zeile von git status (On branch …) zu lesen, bevor ich arbeite und bevor ich committe.

Die alltägliche Branch-Schleife ist dasselbe bearbeiten → add → commit → push, das ich schon kenne; -u beim ersten Push des Branches:

Terminal-Fenster
git switch -c add-contact-info
# ...Dateien bearbeiten...
git add bakery-notes.txt
git commit -m "Add phone number to notes"
git push -u origin add-contact-info # erster Push DIESES Branches

Ein Pull Request (PR) ist eine auf GitHub gestellte Anfrage, einen Branch in einen anderen zu mergen - fast immer meinen Branch in main. Aber der Merge ist nur das Ende; die Mitte ist der Punkt. Ein PR öffnet einen Raum, in dem die Änderung als lesbares Diff zur Ansicht steht, und Leute können lesen, was sich genau ändern würde, es diskutieren (Kommentare an genauen Zeilen verankert) und freigeben - oder es erst für eine weitere Runde zurückschicken. Das ist Code Review, wie die Branche es praktiziert.

Den Namen einmal entschlüsseln: Ich bitte (request) darum, dass das Projekt die Änderungen meines Branches hereinzieht (pull). (GitLab nennt es Merge Request - dieselbe Mechanik.)

  1. Den Branch pushen, dann den PR öffnen - über den Link, den Git in der Push-Ausgabe druckt, das Compare & pull request-Banner oder den Pull requests-Tab → New pull request (Basis main, Vergleich my-branch).

  2. Titel und Beschreibung schreiben - Commit-Message-Disziplin, eine Ebene höher. Titel: was es tut, im Imperativ, eine Zeile. Beschreibung: was und warum, ehrlich, plus alles, was der Reviewer wissen sollte.

  3. Prüfen im Tab Files changed - die ganze Änderung als ein Diff. Über jede Zeile fahren, um ein blaues + für einen genau dort verankerten Kommentar zu erhalten. Nützliche Kommentare sind konkret und freundlich: auf die Zeile zeigen, sagen was und warum, vorschlagen statt befehlen.

  4. Mergen mit dem grünen Merge pull request → Confirm merge. Die Commits meines Branches schließen sich main auf dem Remote an; der PR wird als gemerged geschlossen, seine Unterhaltung für immer als Dokumentation aufbewahrt. Nimm den Delete branch-Button - der Branch war ein Gerüst, seine Commits leben jetzt in main.

  5. Die Schleife lokal schließen - der Merge passierte auf dem Remote, also erfährt mein lokales main davon durch Pullen:

    Terminal-Fenster
    git switch main
    git pull

Der Merge-Button ist keine Magie; er führt git merge aus. Die Grammatik bringt jeden einmal ins Straucheln: Ich stehe auf dem empfangenden Branch und nenne den Branch, der hereingebracht wird.

Terminal-Fenster
git switch main # auf dem Empfänger stehen
git merge weekend-specials # die Commits dieses Branches hereinbringen
Updating 9c2d7e1..5d3a9f2
Fast-forward
bakery-notes.txt | 1 +

Wieder Fast-forward: main hatte sich seit der Erstellung des Branches nicht bewegt, also hat Git einfach das Label von main nach vorne geschoben - kein Verweben. Wenn sich beide Branches bewegt haben, verwebt Git sie zu einem Merge Commit (ein Speicherpunkt mit zwei Eltern). In der Praxis benutze ich den Button - er hält den Review-Schritt angehängt - und den Befehl zu kennen bedeutet, dass der Button eine Bequemlichkeit ist, die ich verstehe, keine Abhängigkeit, die ich nicht erklären kann.

Ein Merge Conflict passiert in genau einer Situation: beide Branches haben dieselben Zeilen unterschiedlich geändert. Git weigert sich zu erraten, welche Version gewünscht ist, also hält es an und fragt. Das ist das ganze Ereignis - kein Defekt, kein Verlust; eine Maschine, die eine Ermessensentscheidung ablehnt, die meine zu treffen ist. (Unterschiedliche Dateien, oder unterschiedliche Teile derselben Datei, mergen still und korrekt.)

  1. Der Merge hält an. Git markiert die strittige Stelle innerhalb der Datei.

    Terminal-Fenster
    git switch main
    git merge price-update
    Auto-merging bakery-notes.txt
    CONFLICT (content): Merge conflict in bakery-notes.txt
    Automatic merge failed; fix conflicts and then commit the result.
  2. Die Datei öffnen und die Conflict-Marker lesen. Zwischen <<<<<<< HEAD und ======= steht die Version des Branches, auf dem ich bin (HEAD - hier main). Zwischen ======= und >>>>>>> steht die Version des hereinkommenden Branches. Git zeigt mir beide Antworten und fragt: welche?

    The Corner Bakery
    <<<<<<< HEAD
    Espresso: 2.60
    =======
    Espresso: 2.80
    >>>>>>> price-update
  3. Entscheiden - das Entscheiden ist die Lösung. Die Datei so bearbeiten, dass sie genau das enthält, was wahr sein soll, und alle drei Marker-Zeilen löschen.

    The Corner Bakery
    Espresso: 2.80
  4. Git mitteilen, dass die Frage beantwortet ist - dieselbe add- + commit-Schleife, die ich schon beherrsche. Der Merge wird abgeschlossen; der Verlauf hält beide Zeilen fest und die menschliche Entscheidung, die sie zusammengeführt hat.

    Terminal-Fenster
    git add bakery-notes.txt
    git commit -m "Merge price-update, keeping new espresso price"

Conflicts sind selten, wenn ich die Anti-Conflict-Gewohnheiten einhalte: kurzlebige Branches, kleine, fokussierte Änderungen und pullen, bevor ich anfange. Auch VS Code erkennt die Marker und zeigt über ihnen Buttons zum Übernehmen der jeweiligen Version an.


GitHub Pages ist kostenloses Website-Hosting, das in jedes GitHub-Repo eingebaut ist: Sag GitHub, es soll die Dateien des Repos als Website ausliefern, und es tut es, unter einer Adresse wie https://my-username.github.io/repo-name/. Wenn jemand vorbeischaut, sucht GitHub nach einer Datei namens index.html - die Web-Konvention für „die Eingangstür einer Website”.

Der Workflow ist genau die Branch-Schleife von oben, plus ein Einstellungsschritt:

  1. Auf einem Branch eine index.html hinzufügen im obersten Ordner des Repos - schon ein Platzhalter reicht, um live zu gehen:

    <!DOCTYPE html>
    <html>
    <body>
    <h1>The Corner Bakery</h1>
    <p>Fresh bread, honest coffee.</p>
    </body>
    </html>
  2. Committen, pushen, PR, mergen und main zurückpullen - die Schleife, die inzwischen Reflex ist.

    Terminal-Fenster
    git switch -c add-homepage
    git add index.html
    git commit -m "Add homepage placeholder"
    git push -u origin add-homepage
  3. Pages aktivieren. Auf der Repo-Seite: Settings → Pages → unter Build and deployment Source auf Deploy from a branch setzen, Branch main und Ordner / (root) wählen, Save.

  4. Ein, zwei Minuten warten, aktualisieren, und ein Banner zeigt Your site is live at https://my-username.github.io/bakery-notes/. Sie öffnet sich von jedem Telefon der Welt.

Von hier an ist es bearbeiten → committen → pushen → live: index.html ändern, durch die Schleife pushen, eine Minute warten, aktualisieren - die Änderung ist da. Diese selbstgebaute Pipeline hat dieselbe Form wie jedes echte Deployment; die professionelle Version fügt nur den Teilen, die ich jetzt von Hand mache, Automatisierung hinzu.


Jeder Befehl aus diesen Notizen, an einem Ort, gruppiert nach der Arbeitsphase, zu der er gehört.

Setup - einmal pro Rechner

BefehlWas er tutTypische Nutzung
git --versionBestätigen, dass Git installiert istgit --version
git config --global user.name "…"Den Namen setzen, der Commits signiertEinmal, bei der Ersteinrichtung
git config --global user.email "…"Die E-Mail setzen, die Commits signiert (an GitHub angleichen)Einmal, bei der Ersteinrichtung
git config --global init.defaultBranch mainNeue Repos auf main starten lassenEinmal, bei der Ersteinrichtung
git config user.nameEine Einstellung zur Kontrolle zurücklesenJederzeit
ssh-keygen -t ed25519 -C "email"Ein SSH-Schlüsselpaar erzeugenEinmal pro Rechner
ssh -T git@github.comTesten, ob GitHub diesen Rechner erkenntNach dem Hinzufügen des Public Keys

Snapshotting - die alltägliche Speicherschleife

BefehlWas er tutTypische Nutzung
git initDen aktuellen Ordner zu einem Repository machenEinmal, im obersten Ordner eines Projekts
git add <file>Eine Datei für den nächsten Commit stagenNach dem Bearbeiten, vor dem Committen
git add .Alles unterhalb des aktuellen Ordners stagenNachdem man vorher git status geprüft hat
git commit -m "message"Gestagete Änderungen zu einem dauerhaften Speicherpunkt versiegelnEinmal pro logischer Änderung
.gitignoreDateimuster auflisten, die Git niemals tracken sollEinmal committet, bei Bedarf aktualisiert

Inspizieren - schauen ohne zu ändern

BefehlWas er tutTypische Nutzung
git statusZeigen, was untracked, modified, staged ist und den BranchVor und nach allem
git logCommits auflisten, neueste zuerst, mit vollem DetailVerlauf durchsehen (q beendet den Pager)
git log --onelineKompakter Verlauf, eine Zeile pro CommitSchneller Überblick
git diffUngestagete Zeile-für-Zeile-Änderungen seit dem letzten Commit zeigenVor dem Stagen / vor dem Restore
git remote -vDie gespeicherten Remotes und ihre Adressen auflistenDie origin-Verbindung prüfen
git branchBranches auflisten (* markiert den aktuellen)Prüfen, wo ich bin

Rückgängig machen - sichere Wiederherstellung

BefehlWas er tutTypische Nutzung
git restore <file>Nicht committete Änderungen verwerfen, zurück zum letzten CommitEine beschädigte Datei retten
git restore --staged <file>Eine Datei unstagen, ohne ihren Inhalt zu ändernDas Falsche gestaget
git branch -m master mainDen aktuellen Branch umbenennenEin auf master festhängendes Repo reparieren

Remotes - mit der Cloud teilen

BefehlWas er tutTypische Nutzung
git remote add origin <ssh-url>Die Adresse eines Remotes unter dem Spitznamen origin speichernEin lokales Repo mit GitHub verbinden
git remote set-url origin <ssh-url>Die Adresse eines bestehenden Remotes überschreibenEin vertipptes Remote reparieren
git push -u origin <branch>Einen Branch veröffentlichen und die Paarung merkenErster Push eines Branches
git pushCommittete Arbeit zum Remote hochschickenJeder Push nach dem ersten
git pullRemote-Commits holen und in den lokalen mergenBeginn jeder Arbeitssitzung
git clone <ssh-url>Eine vollständige Kopie eines Remote-Repos herunterladenNeuer Rechner / neues Projekt

Branching & Merging - paralleles Arbeiten

BefehlWas er tutTypische Nutzung
git switch -c <name>Einen Branch erstellen und darauf wechselnEin neues Arbeitsstück beginnen
git switch <name>Zu einem bestehenden Branch wechselnÄndern, was auf meinem Schreibtisch liegt
git merge <branch>Die Commits eines anderen Branches in den aktuellen bringenLokal mergen (der PR-Button macht das remote)

Symptom / MeldungWas es bedeutetDie Lösung
nothing to commit / no changes added to commitIch habe bearbeitet, aber nie gestaget - der Karton war leergit add <file>, dann erneut committen
Nach git commit in einem seltsamen Texteditor festgesteckt-m vergessen, also hat Git vim für die Message geöffnetEsc drücken, :q! tippen, Enter - dann mit -m "message" erneut committen
Commits mit dem falschen Namen/E-Mail signiertgit config war falsch oder übersprungenDie beiden git config --global-Zeilen erneut ausführen; neue Commits tragen die Korrektur
On branch master (alle anderen sagen main)Das Repo wurde erstellt, bevor init.defaultBranch gesetzt wargit branch -m master main
Permission denied (publickey)GitHub erkennt den Rechner nicht (Key-Handschlag fehlgeschlagen)ssh -T git@github.com ausführen; wenn es mich nicht begrüßt, die SSH-Key-Schritte erneut durchgehen
remote origin already existsEin origin ist bereits gespeichert; Spitznamen sind eindeutiggit remote -v zum Prüfen, dann git remote set-url origin <url>
Updates were rejected / fetch first (non-fast-forward)Das Remote hat Commits, die ich nicht gepullt habegit pull, dann git push - die Pull-zuerst-Gewohnheit verhindert es ganz
Auf dem falschen Branch committetstatus wurde übersprungen; der Commit landete auf der falschen LinieWenn vor dem Committen bemerkt: git switch -c the-branch-I-meant (nicht committete Arbeit reist mit mir). Wenn schon committet: mit Hilfe verschieben - nichts geht verloren
There isn't anything to compare auf GitHubDer Branch wurde lokal committet, aber nie gepushtgit push -u origin <branch>, dann die Vergleichsseite aktualisieren
Merge Conflict (CONFLICT (content))Beide Branches haben dieselben Zeilen unterschiedlich geändertDie Datei auf die gewünschte Wahrheit bearbeiten, die Marker <<<<<<< ======= >>>>>>> löschen, dann git add + git commit

KernpunktKurz gemerkt
Git vs. GitHubGit = lokales Werkzeug, das Verlauf aufzeichnet; GitHub = Cloud-Dienst, der ihn hostet
Drei BereicheWorking Directory → Staging Area → Repository (→ Remote)
Warum es Staging gibtUm auszuwählen, was genau in jeden Speicherpunkt kommt
Erstmalige Einrichtunggit config --global Name, E-Mail und init.defaultBranch main - einmal pro Rechner
Alltägliche Schleifebearbeiten → status → add → commit → push
Gute Commit-MessageImperativ, kurze erste Zeile, sagt was und warum
Commit-GewohnheitEine logische Änderung pro Commit; klein und oft
.gitignoreListet Muster, die Git nie trackt; die Datei selbst wird committet
originDer übliche Spitzname für das Haupt-Remote eines Projekts
Push vs. PullPush schickt Commits hoch; Pull bringt sie herunter; nichts synchronisiert sich von selbst
SSH-KeyDer Private Key bleibt zu Hause, der Public Key wird GitHub einmal gegeben - keine Passwörter über Git
-u-FlagEinmal pro erstem Push eines Branches nötig; setzt die Remote-Paarung
BranchEigenständige Verlaufslinie; main bleibt stabil, Arbeit passiert auf kurzlebigen Branches
HEAD„Wo ich gerade stehe” - die Spitze des aktuellen Branches
Pull RequestSchlägt vor, einen Branch in main zu mergen, und öffnet eine Review-Unterhaltung
git merge-GrammatikAuf dem Empfänger stehen, den Branch nennen, der hereingebracht wird
Merge ConflictBeide Seiten haben dieselben Zeilen geändert; auf die Wahrheit bearbeiten, Marker entfernen, add + commit
GitHub PagesLiefert ein Repo als Website aus; braucht index.html; bearbeiten → committen → pushen → live
Jeder FehlerLies Gits Meldung - sie benennt das Problem und meist die Lösung