[erledigt] Git (rebase): Konflikt nach abgelehntem Pull Request

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
Benutzeravatar
paedubucher
Beiträge: 855
Registriert: 22.02.2009 16:19:02
Lizenz eigener Beiträge: GNU Free Documentation License
Wohnort: Schweiz
Kontaktdaten:

[erledigt] Git (rebase): Konflikt nach abgelehntem Pull Request

Beitrag von paedubucher » 25.09.2021 14:33:22

Ich habe folgendes Szenario auf einem Git-Server:
  • Ein Benutzer namens alice hat ein Repository namens tasks, nennen wir es alice/repo
  • Ein Benutzer namens bob erstellt einen Fork daraus, nennen wir es bob/repo
  • Ein Benutzer namens mallory erstellt ebenfalls einen Fork daraus, nennen wir es mallory/repo
Wir bezeichnen das Repository von alice als das "zentrale" Repository, bzw. den upstream.

Nun passiert folgendes:
  1. mallory nimmt eine Änderung am Fork vor (Datei: tasks.txt) und pusht diese auf sein origin unter mallory/repo.
  2. bob nimmt ebenfalls eine Änderung an seinem Fork vor (Datei: tasks.txt), welche er auf sein origin unter bob/repo pusht.
  3. mallory erstellt einen Pull Request von mallory/repo auf alice/repo, welcher von alice aus inhaltlichen Gründen abgeleht wird.
  4. bob erstellt einen Pull Request von bob/repo auf alice/repo, welcher von alice angenommen wird.
Nun haben alice und bob den gleichen Stand. mallory hingegen hat einen Stand, der mit den anderen beiden Repositories im Konflikt steht. Mallory möchte nun die divergierenden Repositories wieder inhaltlich auf den gleichen Stand bringen und spielt darum die Commit History vom upstream lokal nach:

Code: Alles auswählen

$ git remote add upstream https://my-git-server.com/alice/repo
$ git fetch upstream
$ git rebase upstream/master

Dadurch entsteht ein Konflikt in der Datei tasks.txt. mallory löst diesen durch die Übernahme von bobs Änderungen auf. Weiter geht es folgendermassen:

Code: Alles auswählen

$ git add tasks.txt
$ git rebase --continue
$ git commit -m 'resolved merge conflict'
$ git push origin
Nun entsteht ein weiterer Konflikt, da die Spitze des lokalen Repositories weiter ist als diejenige von mallory/origin. Dieser muss also ein zweites Mal aufgelöst werden:

Code: Alles auswählen

$ git add tasks.txt
$ git commit -m 'resolved merge conflict'
$ git push origin
Jetzt ist mallory/tasks wieder synchron mit alice/tasks.

Nun meine Frage: Geht das nicht einfacher? Der gleiche Konflikt muss bei diesem Workflow zweimal aufgelöst werden.
Zuletzt geändert von paedubucher am 25.09.2021 20:40:17, insgesamt 1-mal geändert.
Habe nun, ach! Java
Python und C-Sharp,
Und leider auch Visual Basic!
Durchaus programmiert mit heissem Bemühn.
Da steh' ich nun, ich armer Tor!
Und bin so klug als wie zuvor.

Benutzeravatar
Meillo
Moderator
Beiträge: 8813
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Git (rebase): Konflikt nach abgelehntem Pull Request

Beitrag von Meillo » 25.09.2021 16:16:10

Ich versuche es mal.

Mallory hat ja zwei Repos, eines lokal und eines auf dem Server. Er arbeitet lokal und macht dort die Merges. Das sollte man sich bewusst machen.

Was du machst ist folgendes:

Mit dem Rebase setzt du die master-Commits von mallory auf alice/master drauf. Es entstehen dabei neue Commits. D.h. im lokalen Repo von mallory ist die master-History umgeschrieben worden. Sie besteht nun aus dem gemeinsamen Anfang, dann den weiteren alice-Commits und dann den neu aufgespielten Commits von mallory. Diese neu aufgespielten Commits von mallory sind *nicht* mehr die gleichen, die dort frueher auf mallory/master waren.

Wenn du nun mallory-lokal auf mallory-master pushst, dann gibt es auf beiden Seiten unterschiedliche Commits, weil nach dem Rebase von mallory/master dessen Commits zu *neuen* Commits geworden sind. Das ist der Grund, weshalb du ein zweites Mal mergen musst.

Ich moechte behaupten, wenn du statt dem Rebase einen Merge machst, dann musst du das nur einmal machen, weil die mallory-Commits erhalten bleiben und du damit konfliktfrei pushen kannst.

(Zudem sollte man vorsichtig sein wenn man Commits rebaset, die schon veroeffentlicht sind, zumal hier sogar master gerebaset wird. Manche wuerden auch sagen, dass man das *nie* tun sollte.)
Use ed once in a while!

Benutzeravatar
paedubucher
Beiträge: 855
Registriert: 22.02.2009 16:19:02
Lizenz eigener Beiträge: GNU Free Documentation License
Wohnort: Schweiz
Kontaktdaten:

Re: Git (rebase): Konflikt nach abgelehntem Pull Request

Beitrag von paedubucher » 25.09.2021 20:36:13

Meillo hat geschrieben: ↑ zum Beitrag ↑
25.09.2021 16:16:10
Mit dem Rebase setzt du die master-Commits von mallory auf alice/master drauf. Es entstehen dabei neue Commits. D.h. im lokalen Repo von mallory ist die master-History umgeschrieben worden. Sie besteht nun aus dem gemeinsamen Anfang, dann den weiteren alice-Commits und dann den neu aufgespielten Commits von mallory. Diese neu aufgespielten Commits von mallory sind *nicht* mehr die gleichen, die dort frueher auf mallory/master waren.
Klingt schon einmal einleuchtend.
Meillo hat geschrieben: Wenn du nun mallory-lokal auf mallory-master pushst, dann gibt es auf beiden Seiten unterschiedliche Commits, weil nach dem Rebase von mallory/master dessen Commits zu *neuen* Commits geworden sind. Das ist der Grund, weshalb du ein zweites Mal mergen musst.

Ich moechte behaupten, wenn du statt dem Rebase einen Merge machst, dann musst du das nur einmal machen, weil die mallory-Commits erhalten bleiben und du damit konfliktfrei pushen kannst.

(Zudem sollte man vorsichtig sein wenn man Commits rebaset, die schon veroeffentlicht sind, zumal hier sogar master gerebaset wird. Manche wuerden auch sagen, dass man das *nie* tun sollte.)
Mit git merge geht es tatsächlich in einem Schritt. :THX:

Noch zum Hintergrund: Ich verwende dieses Setup in der Schule, wo ca. 50 Leute auf dem gleichen Repository arbeiten, und dort kleine Pull Requests machen. Meine Idee hinter rebase war eben, dass anschliessend alle sehen, wer welchen Commit gemacht hat. Aber das verursacht mehr Ärger als es Nutzen stiftet.

Von daher werde ich ab sofort wohl git merge empfehlen.
Habe nun, ach! Java
Python und C-Sharp,
Und leider auch Visual Basic!
Durchaus programmiert mit heissem Bemühn.
Da steh' ich nun, ich armer Tor!
Und bin so klug als wie zuvor.

Benutzeravatar
Meillo
Moderator
Beiträge: 8813
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Git (rebase): Konflikt nach abgelehntem Pull Request

Beitrag von Meillo » 26.09.2021 08:51:26

paedubucher hat geschrieben: ↑ zum Beitrag ↑
25.09.2021 20:36:13
Meillo hat geschrieben: ↑ zum Beitrag ↑
25.09.2021 16:16:10
Mit dem Rebase setzt du die master-Commits von mallory auf alice/master drauf. Es entstehen dabei neue Commits. D.h. im lokalen Repo von mallory ist die master-History umgeschrieben worden. Sie besteht nun aus dem gemeinsamen Anfang, dann den weiteren alice-Commits und dann den neu aufgespielten Commits von mallory. Diese neu aufgespielten Commits von mallory sind *nicht* mehr die gleichen, die dort frueher auf mallory/master waren.
Klingt schon einmal einleuchtend.
Wenn es nicht so aufwaendig waere, wuerde ich standardmaessig empfehlen: Vergleicht die Commithashes und nicht die Commitmessages wenn ihr wissen wollt was ein Commit (Identitaet) ist. In der Praxis ist man nur meist zu faul dafuer.

In den Manpages ist das schoen mit A und A' notiert, das finde ich gut. Man sieht, dass es inhaltlich weiter A ist, aber nicht mehr identisch zu A.

Noch zum Hintergrund: Ich verwende dieses Setup in der Schule, wo ca. 50 Leute auf dem gleichen Repository arbeiten, und dort kleine Pull Requests machen. Meine Idee hinter rebase war eben, dass anschliessend alle sehen, wer welchen Commit gemacht hat. Aber das verursacht mehr Ärger als es Nutzen stiftet.

Von daher werde ich ab sofort wohl git merge empfehlen.
Rebase sollte nur von Personen verwendet werden, die wirklich verstehen wie git funktioniert. Und noch mehr: Es sollte besser auch nur in Teams verwendet werden, wo *alle* verstehen wie git funktioniert. Solange man nur ganz fuer sich persoenlich ausschliesslich lokal erstellte und zuvor nie gepushte Commits rebaset, merken das die anderen nicht. Nur dieser Fall sollte vorkommen. Alles andere ist advanced und erfordert viel git-Wissen auf allen Seiten, weil es zu vielen Schwierigkeiten fuehrt, die die Beteiligten selber loesen koennen sollten.

Solange alle mergen, kommen diese Probleme gar nicht auf und es kann viel weniger kaputt gehen, weil Commits nicht veraendert werden. Das ist die sauberere Art von Versionskontrolle, bei der alles Bestehende erhalten bleibt. Mit Anfaengern nur mergen!

Rebase ist maechtig, aber ebenso schwierig handzuhaben, wenn man nicht genau weiss was man tut.

Darum ja: empfehle ausschliesslich merge zu verwenden. Einzelnen Personen, die sich auskennen, kannst du dann zeigen wie sie ihre lokalen Commits vor dem Pushen mit `rebase -i' ueberarbeiten koennen, bzw. wie sie ihren noch nie gepushten Feature-Branch mit rebase auf die Entwicklungen von master hochschieben koennen (damit es danach ein FF-Merge wird). Dafuer sollten sie aber zuerst verstehen wie git funktioniert und warum man das alles nicht mit bereits gepushten Commits machen soll.
Use ed once in a while!

Benutzeravatar
Meillo
Moderator
Beiträge: 8813
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: [erledigt] Git (rebase): Konflikt nach abgelehntem Pull Request

Beitrag von Meillo » 27.09.2021 09:40:05

Hier mal noch praegnanter in Linus Torvalds' Worten:
https://yarchive.net/comp/linux/git_rebase.html hat geschrieben: In other words, you really shouldn't rebase stuff that has been exposed
anywhere outside of your own private tree. But *within* your own private
tree, and within the commits that have never seen the light of day,
rebasing is fine.
Use ed once in a while!

Benutzeravatar
paedubucher
Beiträge: 855
Registriert: 22.02.2009 16:19:02
Lizenz eigener Beiträge: GNU Free Documentation License
Wohnort: Schweiz
Kontaktdaten:

Re: [erledigt] Git (rebase): Konflikt nach abgelehntem Pull Request

Beitrag von paedubucher » 27.09.2021 11:26:22

Vielen Dank für die Erläuterungen. rebase ist wirklich das falsche für dieses Setup. Ich hätte mich an merge halten sollen.

Ich kann mich noch an meinen ersten Kontakt mit Git erinnern, wo ein Dozent an der Fachhochschule uns damit ins Chaos getrieben hat. Somit habe ich meine Schäden an andere weitergegeben :wink:
Habe nun, ach! Java
Python und C-Sharp,
Und leider auch Visual Basic!
Durchaus programmiert mit heissem Bemühn.
Da steh' ich nun, ich armer Tor!
Und bin so klug als wie zuvor.

Benutzeravatar
Meillo
Moderator
Beiträge: 8813
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: [erledigt] Git (rebase): Konflikt nach abgelehntem Pull Request

Beitrag von Meillo » 27.09.2021 11:38:45

Das Schoene ist ja, dass Dozenten auch Menschen sind, die (hoffentlich!) dazu lernen. Das darf man gerne den Schuelern/Studenten/Azubis auch zeigen. Man denke sich nur, was fuer eine praegende Erfahrung es fuer sie sein wird, wenn sie dazu beigetragen haben, dem Dozenten etwas zu lehren oder seinen Lernprozess zu begleiten! Das sollte in der Lehre mehr beruecksichtigt werden.

Zudem kann man hierbei auch einen anderen, positiveren Umgang mit Fehlern aufzeigen, als er in unserer Gesellschaft ueblich ist. Das waere von weitreichendem Nutzen.

Du kannst dich also ueber diese tolle Gelegenheit freuen, anhand der du eine Menge vermitteln kannst. :THX:
Use ed once in a while!

Benutzeravatar
paedubucher
Beiträge: 855
Registriert: 22.02.2009 16:19:02
Lizenz eigener Beiträge: GNU Free Documentation License
Wohnort: Schweiz
Kontaktdaten:

Re: [erledigt] Git (rebase): Konflikt nach abgelehntem Pull Request

Beitrag von paedubucher » 27.09.2021 22:54:04

Meillo hat geschrieben: ↑ zum Beitrag ↑
27.09.2021 11:38:45
Das Schoene ist ja, dass Dozenten auch Menschen sind, die (hoffentlich!) dazu lernen. Das darf man gerne den Schuelern/Studenten/Azubis auch zeigen. Man denke sich nur, was fuer eine praegende Erfahrung es fuer sie sein wird, wenn sie dazu beigetragen haben, dem Dozenten etwas zu lehren oder seinen Lernprozess zu begleiten! Das sollte in der Lehre mehr beruecksichtigt werden.

Zudem kann man hierbei auch einen anderen, positiveren Umgang mit Fehlern aufzeigen, als er in unserer Gesellschaft ueblich ist. Das waere von weitreichendem Nutzen.

Du kannst dich also ueber diese tolle Gelegenheit freuen, anhand der du eine Menge vermitteln kannst. :THX:
Das ist pädagogisch tatsächlich wertvoll. Ich habe jetzt ein Beispiel geskriptet, womit man das Problem veranschaulichen kann:

Code: Alles auswählen

#!/usr/bin/bash

# Zak: Preparation
git init --bare repo

git clone repo zak
pushd zak
git config user.name zak
git config user.email zak@host

echo '1' > numbers.txt
git add numbers.txt
git commit -m 'initial commit'
git push origin
git log --pretty=format:"%h [%ci] <%an, %ae>: %s"

popd
read

# Alice
git clone repo alice
pushd alice
git config user.name alice
git config user.email alice@host

git checkout -b topic-alice
echo '2' >> numbers.txt
git add numbers.txt
git commit -m 'second commit'
git push --set-upstream origin topic-alice
git log --pretty=format:"%h [%ci] <%an, %ae>: %s"

popd
read

# Bob
git clone repo bob
pushd bob
git config user.name bob
git config user.email bob@host

git checkout topic-alice
git checkout -b topic-bob
echo '3' >> numbers.txt
git add numbers.txt
git commit -m 'third commit'
git push --set-upstream origin topic-bob
git log --pretty=format:"%h [%ci] <%an, %ae>: %s"

popd
read

# Mallory
git clone repo mallory
pushd mallory
git config user.name mallory
git config user.email mallory@host

git checkout topic-alice
git checkout -b topic-mallory
echo '3' >> numbers.txt
echo '4' >> numbers.txt
git add numbers.txt
git commit -m 'helping out'
git push --set-upstream origin topic-mallory
git log --pretty=format:"%h [%ci] <%an, %ae>: %s"

popd
read

# Alice (performing the problematic rebase)
pushd alice
git fetch origin
git rebase origin/topic-mallory
git push
git log --pretty=format:"%h [%ci] <%an, %ae>: %s"

popd
read

# Bob (suffering the consequences)
pushd bob
git fetch origin
git merge origin/topic-alice # XXX: this will cause a merge conflict

popd
read

rm -rf repo alice bob mallory zak
Das kann ich dann gleich vor der Klasse demonstrieren.
Habe nun, ach! Java
Python und C-Sharp,
Und leider auch Visual Basic!
Durchaus programmiert mit heissem Bemühn.
Da steh' ich nun, ich armer Tor!
Und bin so klug als wie zuvor.

Antworten