Git-Konflikt lösen¶
Ziel¶
Nach einem abgelehnten Push oder einem Konflikt beim Pull sind deine Commits ohne Datenverlust auf Codeberg, und der Server passt wieder zum Repo.
Voraussetzungen¶
- dein Rechner ist eingerichtet, vor allem
pull.rebase(Arbeitsrechner einrichten) - gelesen: Git-Workflow, vor allem Rebase statt Merge
- du kannst eine plan-Ausgabe lesen (Änderung ausrollen, Schritt 6)
Nie git push --force auf main
Ein Force-Push überschreibt die Commits der anderen auf Codeberg.
Ihre Änderungen sind danach aus dem Repo verschwunden, laufen aber weiter auf dem Server.
Schlägt ein normaler git push fehl, geh nach dieser Anleitung vor.
Schritte¶
Du kommst hierher, weil git push mit rejected abgelehnt wurde oder weil git pull --rebase einen Konflikt gemeldet hat.
Ein abgelehnter Push sieht so aus:
1. Neuesten Stand holen¶
Im Repo-Ordner:
| Bash | |
|---|---|
Erwartet, wenn die anderen andere Stellen geändert haben als du:
| Text Only | |
|---|---|
Notiere dir die beiden Commit-Kennungen aus der Zeile mit -> (hier b3ffca9..671dedc); du brauchst sie in Schritt 5.
Weiter mit Schritt 5.
Haben die anderen dieselben Zeilen geändert wie du, meldet Git einen Konflikt und hält mitten im Rebase an:
Dann weiter mit Schritt 2.
Meldet Git stattdessen error: cannot pull with rebase: You have unstaged changes., hast du noch Änderungen, die nicht committet sind.
Roll sie aus und committe sie nach Änderung ausrollen oder verwirf sie mit git restore <datei>, dann fang hier noch einmal an.
2. Konflikt finden¶
| Bash | |
|---|---|
Erwartet: You are currently rebasing branch 'main' und unter Unmerged paths: die Dateien mit Konflikt, etwa:
| Text Only | |
|---|---|
Steht dort eine Datei terraform.tfstate, löse den Konflikt nicht selbst.
Brich mit git rebase --abort ab (Erwartet: git status zeigt wieder On branch main) und frag in Signal nach, wer gerade Terraform ausgeführt hat; was der State ist, steht in Terraform.
Bist du an irgendeiner Stelle unsicher, gilt dasselbe: git rebase --abort setzt dein Repo auf den Stand vor dem Pull zurück, ohne etwas zu verlieren.
Frag dann in Signal nach, bevor du weitermachst.
3. Konflikt auflösen¶
Öffne jede Datei unter Unmerged paths: in deinem Editor.
Git hat an der Konfliktstelle beide Fassungen eingefügt, getrennt durch Konfliktmarker:
| Text Only | |
|---|---|
- zwischen
<<<<<<< HEADund=======: der Stand auf Codeberg, also die Änderung der anderen - zwischen
=======und>>>>>>>: deine Änderung, dahinter dein Commit und seine Message
Ersetze den ganzen Block durch die Fassung, die gelten soll, und lösche alle drei Markerzeilen.
Welche Fassung gilt, siehst du mit git log -3 --format='%h %an %ar %s' origin/main -- <datei>: Dort steht, wer die andere Änderung gemacht hat und warum.
Ist nicht eindeutig, welche Fassung richtig ist, sprich dich mit dieser Person in Signal ab.
Prüfe danach, dass keine Marker übrig sind, und formatiere die CUE-Dateien im Ordner der Datei:
Erwartet: beide Befehle geben nichts aus.
Meldet git diff --check leftover conflict marker, steht in der Zeile davor die Datei und die Zeilennummer eines vergessenen Markers.
4. Rebase fortsetzen¶
Nur wenn es in Schritt 2 einen Konflikt gab:
Erwartet: all conflicts fixed: run "git rebase --continue".
| Bash | |
|---|---|
Es öffnet sich dein Editor mit der Commit-Message deines Commits; lass sie, wie sie ist, speichere und schließe den Editor.
Erwartet: Successfully rebased and updated refs/heads/main.
Hast du mehrere Commits noch nicht gepusht, kann Git beim nächsten Commit wieder mit einem Konflikt anhalten; dann wiederhole die Schritte 2 bis 4, bis Successfully rebased erscheint.
5. Prüfen, was dazugekommen ist¶
Mit den beiden Commit-Kennungen aus Schritt 1:
| Bash | |
|---|---|
Erwartet: die Commits der anderen mit den Dateien, die sie geändert haben.
Merke dir, welche Ordner betroffen sind (syslet/werner/, syslet/containerhost/, desec/, apps/authentik/…); in diesen und in den Ordnern deiner eigenen Änderung führst du die nächsten Schritte aus.
6. plan erneut ausführen¶
Hast du deine Änderung schon ausgerollt, lief auf dem Server ein Stand ohne die Commits der anderen. Führe deshalb in jedem Ordner aus Schritt 5 plan aus, wie in Änderung ausrollen, Schritt 2 und 3, für Authentik wie in Terraform für Authentik ausführen:
| Bash | |
|---|---|
Erwartet: entweder „No changes“ oder nur Änderungen, die zu deinen Commits oder zu den Commits aus Schritt 5 gehören.
Ein Beispiel: Du hast Discourse aktualisiert und ausgerollt, während jemand HedgeDoc von 1.12.0 auf 1.12.1 gehoben hat.
Dann zeigt plan in syslet/werner, dass HedgeDoc von old: …:1.12.0 auf new: …:1.12.1 gesetzt wird, weil dein apply die Änderung der anderen Person zurückgedreht hat.
Zeigt plan etwas, das zu keinem dieser Commits passt, roll nicht aus, sondern geh nach plan zeigt unerwartete Änderungen vor.
Hast du noch nicht ausgerollt, mach stattdessen in der Anleitung weiter, aus der du gekommen bist.
7. Ausrollen¶
Nur wenn plan in Schritt 6 Änderungen gezeigt hat, in jedem betroffenen Ordner:
| Bash | |
|---|---|
Erwartet: dieselbe Ausgabe wie bei plan, dann Continue? (yes/no); tippe yes.
8. Pushen¶
| Bash | |
|---|---|
Erwartet: am Ende eine Zeile main -> main.
Wird der Push wieder abgelehnt, hat in der Zwischenzeit noch jemand gepusht; fang wieder mit Schritt 1 an.
Prüfen¶
git statuszeigtYour branch is up to date with 'origin/main'.undnothing to commit, working tree clean.git log --oneline -5zeigt die Commits der anderen und darüber deine eigenen, ohne Merge-Commit.cue cmd planzeigt in jedem Ordner aus Schritt 5 „No changes“.
Wenn etwas schiefgeht¶
- Du hast dich beim Auflösen vertan und noch nicht gepusht:
git rebase --abort, solange der Rebase läuft; ist er schon abgeschlossen, frag in Signal nach, bevor du etwas anderes versuchst. - plan zeigt Änderungen, die zu keinem Commit passen: plan zeigt unerwartete Änderungen
- Ein Container läuft nach dem apply nicht: Container-Status und Logs ansehen
- Allgemeines zu Konflikten: Git-Buch, Einfaches Branching und Merging und Rebasing