Forum: Compiler & IDEs Github Probleme


von Rudolph R. (rudolph)


Lesenswert?

Github frustriert mich gerade stark, seit Tagen komme ich damit nicht 
weiter und schlage mich damit rum anstatt mich mit dem Code an sich 
beschäftigen zu können.

Was mache ich falsch?

Okay, ganz von Anfang, mehrere Probleme.

Ich habe ein Repository mit einem Branch dem ich zuarbeiten möchte.
Da ich auf das Repository keinen direkten Zugriff habe erstelle ich 
einen Fork in meinen Account.
Das erste was ich gemacht habe ist den Branch zu clonen, zu bearbeiten 
und schliesslich einen Pull-Request zu stellen.
Soweit alles gut.

Nun hat der Autor aber den Branch selber verändert, ohne das er meinen 
Pull-Request vorher bearbeitet hätte.
Wie bekomme ich meinen Fork auf den aktuellen Stand?
Nach einigen Stunden habe ich schlieslich meinen Fork gelöscht und einen 
neuen Fork erstellt.
Aber das kann ja wohl kaum die Lösung sein?

In dem neuen Fork habe ich diesmal einen neuen Branch erstellt, weil ich 
grundsätzlich auch Dateien bearbeiten muss die ich nicht per 
Pull-Request in das Projekt zurück spielen will, lokale Änderungen die 
nur für mich relevant sind.

Wie bekomme ich jetzt gezielt einzelne Dateien von einem Branch in den 
anderen um letztlich gegen das Original-Repository einen Pull-Request 
stellen zu können?
Nachdem ich da mit der Github Webseite und TortoiseGit nicht weiter 
gekommen bin habe ich die "GitHub Desktop" angeworfen und "Merge into 
current branch" ausprobiert.
Mit dem Ergebnis das ohne jedes Feedback oder Rückfragen alle Dateien in 
dem Ziel-Branch überschrieben wurden, obwohl ich nur eine Datei ändern 
wollte.
Damit bin ich gerade an dem Punkt das ich im Grunde genommen nur wieder 
den Fork löschen und von vorne anfangen kann.

Kann ich wirklich nur von Hand die gewünschten Dateien in den Branch 
kopieren?

von Sven B. (scummos)


Lesenswert?

Du solltest dich erstmal mit den Grundkonzepten von git (!= github) 
vertraut machen, bevor du zwanzig Tools darauf wirfst die irgendwelche 
Dinge tun die du dann nicht nachvollziehen kannst.

Generell, wenn es Upstream (="von anderen Leuten") Änderungen gibt, die 
du in deinen eigenen Branch übernehmen möchtest, "git pull" oder "git 
pull --rebase".

Einzelne Dateien von einem Branch in einen anderen zu kopieren geht mit 
einer bestimmten Syntax von "git checkout", aber das ist auch nicht die 
Operation die du machen willst, oder? Du willst z.B. einen einzelnen 
Commit importieren; das geht mit "git cherry-pick".

: Bearbeitet durch User
von derElf (Gast)


Lesenswert?

Du wirst dich wohl oder übel mit den Grundlegenden Operationen von git 
beschäftigen müssen: merge, rebase und commit

Wie man das genau mit deinem jeweiligen GUI umsetzt kann ich dir nicht 
sagen, aber unter 
https://git-scm.com/book/en/v2/Getting-Started-Git-Basics findest du 
einen Einstieg.

von TestX (Gast)


Lesenswert?

1. Fork Upstream Sync: https://help.github.com/articles/syncing-a-fork/
2. Git Branching, Rebasing: 
https://git-scm.com/book/de/v1/Git-Branching-Rebasing
3. Pull Requests nach Möglichkeit immer in einem eigenen Branch 
erstellen der dann vom Maintainer gemerged werden kann.

Manchmal ist es allerdings einfacher seinen Fork zu syncen und danach 
die Dateien manuell zu kopieren...kommt auf das Projekt drauf an

von Rudolph R. (rudolph)


Lesenswert?

Nachdem ich inzwischen fünf Mal oder so den Fork gelöscht und neu 
erstellt habe ist das ja auf dem gleichen Stand für den Moment.
Mit einem abweichenden Stand habe ich git nicht dazu bringen können den 
Branch aus dem übergeordneten Repository mit den neuen Daten zu 
überschreiben.
Wie auch immer, das kann ich gerade nicht neu ausprobieren.

Bleibt im Moment das andere Problem, wie bekomme ich mit Git einzelne 
Dateien von einem Branch in den anderen?

TestX schrieb:
> 3. Pull Requests nach Möglichkeit immer in einem eigenen Branch
> erstellen der dann vom Maintainer gemerged werden kann.

Okay, geht natürlich auch, bringt aber die gleichen Probleme mit sich.
Dafür muss ich also einen neuen Branch von dem ableiten zu dem ich einen 
Pull-Request erstellen will - easy.
Und dann aus meinem Arbeits-Branch das in den Branch überführen was ich 
per Pull-Request ins Projekt bringen will.

Wie macht man das geschickt?
Auf Github selber gibt es kein Cherry-Picking, das fällt also aus, alles 
oder nichts, was anderes geht nicht.

Und für "git cherry-pick" muss ich wohl vorher selber wissen und dann da 
festelegen was ich haben will.
Wobei mich der Hilfstext von "git cherry-pick" gerade überhaupt nicht 
vorwärts bringt, keine Ahnung wie man da von einem Branch in einen 
anderen kommen soll.
Ich vermute gerade eher, das geht damit gar nicht, ich will ja keinen 
Commit kopieren, sondern bestimmte Dateien die vielleicht oder auch 
nicht Teil von dem einen oder anderen Commit waren.

Dann kann ich aber auch gleich die Dateien von Hand kopieren und per 
Commit/Push in den Branch schieben.

von Sven B. (scummos)


Lesenswert?

Hä? Dateien die Teil eines Commits sind? Wovon sprichst du?

Ich denke, das ist ein typischer Fall von "XY-Problem". 
https://en.wikipedia.org/wiki/XY_problem

von Gituser (Gast)


Lesenswert?

Rudolph R. schrieb:
> Bleibt im Moment das andere Problem, wie bekomme ich mit Git einzelne
> Dateien von einem Branch in den anderen?

Git ist nicht dateibasiert. Git ist commit- (changeset-) basiert.
Wenn du z.B. 'master' hast, dann einen 'branch' machst und auf 'master' 
weiter commits machst, kannst du diese entweder mit git-pull alle in 
'branch' reinziehen, oder mit git-cherry-pick einzelne commits 
reinziehen.

Wenn du "einzelne Dateien" reinziehen willst, musst du das entweder 
manuell eben so machen und einen neuen commit erstellen, oder ein commit 
pro Datei erstellen und den dann mit cherry-pick übernehmen.

von Sven B. (scummos)


Lesenswert?

Gituser schrieb:
> Rudolph R. schrieb:
>> Bleibt im Moment das andere Problem, wie bekomme ich mit Git einzelne
>> Dateien von einem Branch in den anderen?
>
> Git ist nicht dateibasiert. Git ist commit- (changeset-) basiert.

Naja wenn du dir anschaust wie es intern funktioniert ist eigentlich 
genau das Gegenteil der Fall, aber es verhält sich nach außen eher so, 
ja.

von Gituser (Gast)


Lesenswert?

Sven B. schrieb:
> Naja wenn du dir anschaust wie es intern funktioniert ist eigentlich
> genau das Gegenteil der Fall,

Was meinst du damit?
Nur weil die .git Datenbank in Dateien gespeichert wird, ist git nicht 
dateibasiert.
Es ist ein gewolltes Designmerkmal von git, dass commits 
dateiübergreifend sind.

von Rudolph R. (rudolph)


Lesenswert?

Gituser schrieb:
> Git ist nicht dateibasiert. Git ist commit- (changeset-) basiert.

Na bitte, dann habe ich das mit dem Cherry-Pick und Commits doch nicht 
so falsch verstanden in meinem letzten Kommentar.
Mein Fehler war jetzt, das ich inital zu viele Änderungen auf einmal 
gemacht und in einen Commit gepackt habe, das wird dann nichts.
Da muss man auch erstmal drauf kommen, dass eine Revisions-Verwaltung 
nicht Datei-basiert ist.

Also kleinere Schritte, verschiedene Änderungen getrennt Einchecken.

Danke!

von Sven B. (scummos)


Lesenswert?

Gituser schrieb:
> Sven B. schrieb:
>> Naja wenn du dir anschaust wie es intern funktioniert ist eigentlich
>> genau das Gegenteil der Fall,
>
> Was meinst du damit?
> Nur weil die .git Datenbank in Dateien gespeichert wird, ist git nicht
> dateibasiert.
> Es ist ein gewolltes Designmerkmal von git, dass commits
> dateiübergreifend sind.

Ein "commit" in git ist aber kein Patch oder Diff zu irgendeinem anderen 
Zustand, sondern im Gegenteil ein Archiv mit dem kompletten 
Verzeichnisbaum in einem bestimmten Zustand zusammen mit ein paar 
Metainformationen. Die mehr oder wenige einzige Relation zu anderen 
Zuständen entsteht dadurch, dass zu den Metainformationen ein 
"parent"-Commit dazugehört.

Die Diffs werden dann nur auf Anfrage berechnet, ein Diff ist kein 
Objekt in git, was irgendwo abgespeichert wird oder für die 
Funktionsweise des Tools irgendwie elementar wäre. Außer für ein paar 
spezielle Operationen (rebase, diff, cherry-pick etc) kommen Diffs 
eigentlich gar nicht vor.

Die Aussage "git ist changeset-basiert" ist aus diesem Blickpunkt 
deshalb ziemlich irreführend.

: Bearbeitet durch User
von René H. (Gast)


Lesenswert?

https://xkcd.com/1597/

Hol Dir eines der unzähligen GIT Cheat Sheet im Netz. Dann beschäftige 
Dich mit GIT. Wenn man es mal begriffen hat, ist es trivial und man 
weiss die Vorteile zu schätzen.

Grüsse,
René

von Gituser (Gast)


Lesenswert?

Sven B. schrieb:
> Die Aussage "git ist changeset-basiert" ist aus diesem Blickpunkt
> deshalb ziemlich irreführend.

Nö. Es ist auch aus diesem Blickwinkel ziemlich richtig. Du sagst doch 
selbst, dass ein commit ein snapshot des gesamten Repositories und nicht 
einzelner Dateien ist.

von Christopher J. (christopher_j23)


Lesenswert?


von René H. (Gast)


Lesenswert?

Christopher J. schrieb:
> René H. schrieb:
>> https://xkcd.com/1597/
>
> http://ohshitgit.com/

Den kannte ich noch nicht, thx :-D

Grüsse,
René

von Sven B. (scummos)


Lesenswert?

Gituser schrieb:
> Sven B. schrieb:
>> Die Aussage "git ist changeset-basiert" ist aus diesem Blickpunkt
>> deshalb ziemlich irreführend.
>
> Nö. Es ist auch aus diesem Blickwinkel ziemlich richtig. Du sagst doch
> selbst, dass ein commit ein snapshot des gesamten Repositories und nicht
> einzelner Dateien ist.

Ein Changeset ist aber kein Set von Dateien, sondern ein Set von 
Änderungen. Sagt schon der Name.

von Gituser (Gast)


Lesenswert?

Sven B. schrieb:
> Ein Changeset ist aber kein Set von Dateien, sondern ein Set von
> Änderungen. Sagt schon der Name.

Habe ich etwas anderes behauptet?
Genau das ist doch der Punkt. Git verwaltet keine Dateiversionen, 
sondern nur Änderungen im Branch als eine Einheit: Das Changeset.

von ~Mercedes~ (Gast)


Lesenswert?

Das ist ein Ding!  ;-O

Vater hat mir gerade das Buch

Rene Preißel / Bjorn Stachmann
Dezentrale Versionsverwaltung im Team
Grundlagen und Workflows

ISBN 978-3-86490-130-0

in die Hängematte geworfen,
vielleicht interessiert es einen,
das Teil ist in Deutsch.

mfg

von Rudolph R. (rudolph)


Lesenswert?

Okay, I habe einen Commit-Branch erstellt, die Änderungen gegenüber dem 
Original Branch im Original Repository da drin gemacht, committet, 
gepusht, einen Pull-Request erstellt und der Maintainer hat meinen 
Pull-Request akzeptiert und gemerged.
Soweit alles schick.

Damit war mein Branch in meinem Fork allerdings um die entsprechenden 
Commits zurück.
Das hier: https://help.github.com/articles/syncing-a-fork/
Hilft bei dem Problem überhaupt nicht.
"git fetch upstream" gab nur die Fehlermeldung das es keinen Branch 
"upstream" gibt.
Also mindestens ist das unvollständig.

Ich bin dann hier nach vorgegangen:
https://webapps.stackexchange.com/questions/28998/how-do-you-update-a-github-repo-fork-in-the-web-interface/58140#58140

Also ich habe einen Pull-Request von dem anderen Repository auf mein 
eigenes erstellt und verarbeitet.
Jetzt ist das wieder im Grunde auf dem gleichen Stand, allerdings meldet 
Github nun, das der Branch in meinem Repository einen Commit Ahead wäre.

Dann habe ich zusätzlich mal das hier probiert:
https://superuser.com/questions/456145/how-can-i-resync-a-fork-from-original

git remote add upstream 
https://github.com/upstream-username/projectname.git
git pull upstream master
git push

Nachdem ich denn herausgefunden hatte wie ich aus VIM raus komme für die 
commit-message (:wq ENTER ...) hat das auch funktioniert soweit.
Nur ist mein Fork jetzt 2 commits ahead...

Meine Fresse, ich möchte doch nur, dass der Branch im meinem Fork auf 
dem gleichen Stand ist wie der entsprechende Branch im 
Original-Repository.
Keinen Commit ahead oder zurück, 1:1 der Stand.

Und der einzige Weg bisher das zu erreichen war den Fork zu löschen und 
neu zu erstellen -> das kann es ja wohl nicht sein.

Soweit ist Git oder eher Github eigentlich nur zum kotzen beim Arbeiten 
mit zwei Repositories.

von Sven B. (scummos)


Lesenswert?

Gituser schrieb:
> Sven B. schrieb:
>> Ein Changeset ist aber kein Set von Dateien, sondern ein Set von
>> Änderungen. Sagt schon der Name.
>
> Habe ich etwas anderes behauptet?
> Genau das ist doch der Punkt. Git verwaltet keine Dateiversionen,
> sondern nur Änderungen im Branch als eine Einheit: Das Changeset.

Und das genau ist falsch. Git verwaltet Versionen von Dateien, keine 
Changesets.

Ein "commit" in git ist eine Liste von Objekten, und jede Version jeder 
Datei ist ein Objekt. Wenn du eine Datei änderst und einen neuen Commit 
mit dieser Änderung erstellst, legt git ein neues Objekt an für die neue 
Datei, in der es einfach den Inhalt der neuen Datei komprimiert (völlig 
unabhängig vom alten Zustand), und dann einen Commit, der einfach nur 
eine Liste von Objekten (=Datei in einem bestimmten Zustand) ist. In die 
Metadaten des Commits wird der Name des vorherigen Commits notiert. Mit 
Diff oder Changeset hat das gar nichts zu tun.

Das Diff wird dann wenn du danach fragst anhand der Angabe des 
vorherigen Commits berechnet.

Schau dir zum Beispiel mal "git ls-tree HEAD" an, da bekommst du eine 
Liste mit Objects im HEAD des Repos, und daneben steht immer ein 
sha1-Hash. Diese Liste ist im Wesentlichen ein Commit. Die Dateien in 
den Versionen, die dort aufgelistet sind, sind in 
.git/objects/ab/cdefgh... wobei ab die ersten 2 Buchstaben des 
sha1-Hashs sind.

Deshalb ändert sich auch zwangsläufig der sha1-Hash eines Commits, wenn 
man irgendwo in der Historie etwas ändert: weil der Hash nicht das 
Changeset identifiziert, was durch diesen Commit eingeführt wird (das 
gibt's nämlich nicht), sondern den Zustand des Repositories bei diesem 
Commit.

: Bearbeitet durch User
von Experte (Gast)


Lesenswert?

Sven B. schrieb:
> Gituser schrieb:
>> Sven B. schrieb:
>>> Ein Changeset ist aber kein Set von Dateien, sondern ein Set von
>>> Änderungen. Sagt schon der Name.
>>
>> Habe ich etwas anderes behauptet?
>> Genau das ist doch der Punkt. Git verwaltet keine Dateiversionen,
>> sondern nur Änderungen im Branch als eine Einheit: Das Changeset.
>
> Und das genau ist falsch. Git verwaltet Versionen von Dateien, keine
> Changesets.

Alles nicht komplett falsch, aber auch nicht komplett richtig.

Git verwaltet eben weder Dateiversionen noch Changesets.

Git verwaltet commits. Ein commit besteht aus einem Kommtar und einem 
Snapshot; ein Snapshot wie ein Image einer Festplatte. Nur dass kein 
Image einer Festplatte gemacht wird, sondern eben ein "Image", aka 
Snapshot, eines kompletten Verzeichnisbaums.

Wie bei einem Festplatten-Image-Tool kann man auch einzelne Dateien aus 
dem commit (Snapshot) extrahieren, wenn man möchte. Oder man kann sich 
die Unterschiede von commits anschauen.

Wie Git intern die commits verwaltet, ob es gleiche Dateien nur einmal 
speichert oder nicht, ob es Diffs speichert oder nicht, spielt keine 
Rolle.

Der Punkt ist: Ein Commit ist ein Snapshot eines Verzeichnisbaums mit 
einer Commit-Nachricht und noch ein paar anderen Metadaten.

von Gituser (Gast)


Lesenswert?

Sven B. schrieb:
> Und das genau ist falsch. Git verwaltet Versionen von Dateien, keine
> Changesets.
>
> Ein "commit" in git ist eine Liste von Objekten, ...

Was git intern in seiner Datenbank macht
- weiß ich sehr wohl
- interessiert hier nicht. Wir arbeiten hier mit dem offiziellen git 
user-Interface. Und dort gibt es keine Versionen von Dateien. Ende der 
Diskussion. Wenn du das willst, gehe zurück zu CVS.

von Gituser (Gast)


Lesenswert?

Rudolph R. schrieb:
> "git fetch upstream" gab nur die Fehlermeldung das es keinen Branch
> "upstream" gibt.
> Also mindestens ist das unvollständig.

Lies einfach mal ein Grundlagenbuch
https://git-scm.com/book/en/v2

Es bringt nichts, wenn wir dir hier den Befehl nennen. Du kennst die 
Grundlagen von git offensichtlich nicht.
Und die sind nicht so schwer. Also lies die ersten paar Abschnitte des 
Buchs.

von Rudolph (Gast)


Lesenswert?

Gituser schrieb:
> Es bringt nichts, wenn wir dir hier den Befehl nennen. Du kennst die
> Grundlagen von git offensichtlich nicht.

Dafür komme ich aber schon gut klar.
Innerhalb eines Repositories habe ich ja erstmal kein Problem mehr.

> Und die sind nicht so schwer. Also lies die ersten paar Abschnitte des
> Buchs.

Und die ersten paar Abschnitte bringen mich jetzt wie weiter bei der 
Arbeit mit zwei verschiedenen Repositories?
Oder welcher der Kommentare dazu hier bisher?

Was nützt mir ein Re-Sync mit dem Upstream Repository wenn hinterher 
mein Branch einen Commit weiter ist als das Original, obwohl das 
inhaltlich dann auf dem gleichen Stand ist?

So wie es sich bisher darstellt werde ich wohl regelmäßig den Fork 
löschen und neu erstellen müssen.
Das ist deutlich weniger Aufwand und im Ergebnis sauberer.
Nachdem der Pull-Request aus meinem Fork durch ist brauche ich das 
Repository ja auch nicht mehr.

von Sven B. (scummos)


Lesenswert?

Gituser schrieb:
> Sven B. schrieb:
>> Und das genau ist falsch. Git verwaltet Versionen von Dateien, keine
>> Changesets.
>>
>> Ein "commit" in git ist eine Liste von Objekten, ...
>
> Was git intern in seiner Datenbank macht
> - weiß ich sehr wohl
> - interessiert hier nicht. Wir arbeiten hier mit dem offiziellen git
> user-Interface. Und dort gibt es keine Versionen von Dateien. Ende der
> Diskussion. Wenn du das willst, gehe zurück zu CVS.

Naja, das gesamte Verhalten macht halt keinen Sinn, wenn du das so 
betrachtest, aber bitteschön. Warum gibt es zum Beispiel einen 
Merge-Commit wenn ich Commits von einem Remote pulle, aber schon selbst 
einen Commit gemacht habe, nicht aber, wenn es in der umgekehrten 
Reihenfolge passiert? Das ist mit deiner Darstellung nicht schlüssig 
erklärbar, und ist bei Versionskontrollsystemen wie svn (die tatsächlich 
mit Deltas arbeiten) auch nicht der Fall.

von Gituser (Gast)


Lesenswert?

Rudolph schrieb:
> Dafür komme ich aber schon gut klar.
> Innerhalb eines Repositories habe ich ja erstmal kein Problem mehr.

Genau deshalb solltest du die Grundlagen lesen.
Es spielt nämlich kaum eine Rolle, wo die Repositories liegen und wie 
viele es sind.

Die entsprechenden Kapitel sind "2. Git Basics" und insbesondere "3. Git 
Branching".

von Gituser (Gast)


Lesenswert?

Sven B. schrieb:
> Naja, das gesamte Verhalten macht halt keinen Sinn, wenn du das so
> betrachtest, aber bitteschön. Warum gibt es zum Beispiel einen
> Merge-Commit wenn ich Commits von einem Remote pulle, aber schon selbst
> einen Commit gemacht habe, nicht aber, wenn es in der umgekehrten
> Reihenfolge passiert? Das ist mit deiner Darstellung nicht schlüssig
> erklärbar

Was du schreibst ergibt überhaupt keinen Sinn.
Was haben merge-commits denn bitte mit der angeblichen Dateibasiertheit 
von git zu tun?

git commits sind eine Kette. Wenn diese Kette beim pull/merge verlängert 
wird, ist es ein fast-forward. Wenn sich die Kette nicht verlängern 
lässt, ist ein ein merge-commit. Das hat mit einzelnen Dateien überhaupt 
gar nichts zu tun.

von Sven B. (scummos)


Lesenswert?

Egal, das führt zu nichts. Du weißt ja offenbar wie es funktioniert und 
möchtest es trotzdem anders erklären, sind wir halt verschiedener 
Meinung. Ich hätte es lieber näher an dem erklärt wie git es intern tut, 
weil das meiner Meinung nach dann leichter nachvollziehbar ist und eher 
erlaubt zu extrapolieren wie sich das Tool in anderen Situationen 
verhält.

von Nico W. (nico_w)


Lesenswert?

Mein größtes Problem als ich mit git angefangen habe war zu begreifen, 
dass git pull, anders als der Befehl aussieht, zwei unterschiedliche 
Verhalten hat und eigentlich auch intern zwei Befehle hintereinander 
verknüpft.


Zunächst einmal allgemein ein git fetch. Abrufen vom verknüpften Remote. 
Und dann, was tückisch ist, je nach Zustand bzw. Delta von lokalen und 
remote Branch, ein git merge oder einen git rebase.


Ich für meinen Teil entscheide sowas gerne selbst und verzichte daher 
auf git pull, wenn ich in einem Repository arbeite, gänzlich.


Für ein Rebase nutze ich ein kleines Script* welches den rebase Commit 
für Commit durchgeht um Konflikte Recht einfach zu beheben.

* 
https://github.com/Traumflug/Teacup_Firmware/blob/master/tools/git-step-rebase

: Bearbeitet durch User
von Gituser (Gast)


Lesenswert?

Nico W. schrieb:
> Zunächst einmal allgemein ein git fetch. Abrufen vom verknüpften Remote.
> Und dann, was tückisch ist, je nach Zustand bzw. Delta von lokalen und
> remote Branch, ein git merge oder einen git rebase.

Was meinst du mit rebase an der Stelle?
Ein fast forward ist kein rebase.

> Für ein Rebase nutze ich ein kleines Script* welches den rebase Commit
> für Commit durchgeht um Konflikte Recht einfach zu beheben.

Warum nicht einfach git rebase --interactive?

von Nico W. (nico_w)


Lesenswert?

Fast-forward ist aber auch kein merge...

Das Script geht jeden Commit einzeln durch und macht einen rebase drauf. 
Wenn man das ganze Packet auf einmal einem Rebase unterzieht, dann 
bekommst du zum Teil Konflikte die man nicht mehr so einfach überblicken 
kann.

Wenn du also in deinem Master branch bist und einen rebase auf dein 
Experimental machen möchtest und dieser 2 Commits ahead ist, dann macht 
das Script:

git rebase experimental~1
git rebase experimental

Sobald ein Konflikt aufkommt, bricht das Script ab. Den Konflikt muss 
man dann natürlich lösen. Anschließend ein git rebase --continue. Danach 
kann man das Script wieder ausführen, bis alle Commits im master sind. 
Dadurch bekommt man eine schöne lineare History ohne Merge.

von Gituser (Gast)


Lesenswert?

Ich sehe jetzt keinen Unterschied zu einem normalen git rebase 
--interactive.
Auch dort kann man stoppen, umsortieren und editieren.

von Nico W. (nico_w)


Lesenswert?

Klar kann man auch per Hand alle Commits bis auf einen einzigen raus 
löschen um dann Schritt für Schritt alles durchzuarbeiten. Oder man 
nimmt das Script.


Dabei geht es nicht ums umsortieren sondern einem kompletten Rebase auf 
den eigentlichen Branch um eine lineare History zu bekommen.


Wenn ich mit git arbeite möchte ich keinen merge commit. Und wenn dann 
doch mal 20 oder mehr Commits ahead sind, dann wirst du dir bei einem 
normalen rebase schnell ins Knie schießen.

von Gituser (Gast)


Lesenswert?

Nico W. schrieb:
> Klar kann man auch per Hand alle Commits bis auf einen einzigen raus
> löschen um dann Schritt für Schritt alles durchzuarbeiten.

Hast du --interactive mal probiert?
Das ist eben nicht alles per Hand durchgehen.

> Wenn ich mit git arbeite möchte ich keinen merge commit.

Der entsteht beim rebase ja auch gar nicht.

von Gituser (Gast)


Lesenswert?

Nico W. schrieb:
> Wenn du also in deinem Master branch bist und einen rebase auf dein
> Experimental machen möchtest

übrigens halte ich diese Arbeitsweise auch für sehr merkwürdig.
Warum machst du kein rebase deines Branches auf master (also umgekehrt)? 
Danach ist das pull von branch nach master nur ein fast forward.
Du hast keine merge commits und vor allem brauchst du auch kein 
force-push für master auf dein origin (und falls es weitere Clones gibt, 
machst damit auch diese nicht kaputt. Wenn du einen rebase von master 
machst, zwingst du deine clones ja auch so einem rebase, statt einem 
einfachen ff-pull).

von Nico W. (nico_w)


Lesenswert?

Wir reden lediglich ein wenig aneinander vorbei.


Wenn ich im Master einen rebase mit dem experimental mache, dann gehen 
die Commits vom experimental aufs Master drauf. Nicht dazwischen oder 
sonst wo hin.


Und ich habe mir das interaktive rebase angesehen. Nutze ich auch um 
Commits zusammen zu fassen oder in einem Testbranch zu löschen. Manchmal 
auch um sie umzusortieren.


Hast du dir denn das Script mal angesehen? Speziell wenn der Master 
durch einen früheren rebase von einem anderen Branch ahead und behind 
ist?

von Gituser (Gast)


Lesenswert?

Nico W. schrieb:
> Wir reden lediglich ein wenig aneinander vorbei.
>
> Wenn ich im Master einen rebase mit dem experimental mache, dann gehen
> die Commits vom experimental aufs Master drauf. Nicht dazwischen oder
> sonst wo hin.

Das befürchte ich allerdings auch.

> Hast du dir denn das Script mal angesehen?

Ja.

> Speziell wenn der Master
> durch einen früheren rebase von einem anderen Branch ahead und behind
> ist?

Gleichzeitig ahead und behind? Was ist das?
Kannst du vielleicht mal den Fall, in dem das script nützlich ist, 
aufzeichnen?

von Nico W. (nico_w)


Lesenswert?

Du machst einen neuen Branch A aus dem master.
Nun fügst du dort ein paar Änderungen ein.
Jemand anderes arbeitet an einem Branch B.

Nun bist du mit A fertig und kannst diesen recht einfach mit dem Master 
vereinen.

Der Andere mit Branch B möchte nun diese Änderungen zunächst einmal in 
seinen Branch einarbeiten, da er zum Teil im gleichen Bereich Änderungen 
vollzogen hat. Jetzt kann er jeden einzelnen Commit der zwischen Master 
und A enstanden ist einzeln einarbeiten.
1
       --- A1 -- A2 -- A3 
2
      /
3
master
4
      \
5
       --- B1 -- B2
6
7
git checkout master
8
git rebase A
9
10
master - A1 - A2 - A3
11
12
git checkout B
13
git-step-rebase master
14
15
1. master - A1 - B1' - B2'
16
2. master - A1 - A2 - B1'' - B2''
17
3. master - A1 - A2 - A3 - B1''' - B2'''

Grob wäre das in etwa der Aufbau.

Wenn das ganze nur ein oder zwei, meinetwegen auch ein paar mehr, 
Commits sind, geht das mit einem normalen Rebase meist noch recht 
Problemlos. Aber wenn es mehr wird, kann es schnell zu Problemen kommen.

Ich habe zum Beispiel vor zwei Jahren einen Port erstellt von einer 
Firmware. Hier war zunächst ein Master mit AVR und LPC Support. Diesen 
habe ich hergenommen um meinen STM-Port draufzupacken. Nach ca. einem 
Jahr war ich fertig (War alles Neuland für mich und einfach auch nur ein 
kleines Hobby) und in der Zeit sind ca. 100 Commits im Master 
entstanden. Um dort eine lineare History auch mit dem Script zu 
erstellen ist eine kleine Herausforderung. Ohne fast kaum zu händeln.

von Gituser (Gast)


Lesenswert?

Nico W. schrieb:
> git checkout master
> git rebase A

Ok, das habe ich befürchtet.
Das ist eine völlig unübliche Nutzung von rebase.

Üblicher wäre eher sowas wie

git checkout master
git pull . A  #Das ist ein FF
git checkout B
git rebase master #eventuell --interactive
git checkout master
git pull . B #Das ist ein FF

von Nico W. (nico_w)


Lesenswert?

Völlig unüblich? Glaube ich kaum. Nen local pull habe ich bisher noch 
nie gesehen.


Aber ist in dem Bereich auch völlig egal, da das Ergebnis identisch ist.


Ich würde bei deinen git pull . A noch ein -ff-only dran setzen.

: Bearbeitet durch User
von Gituser (Gast)


Lesenswert?

Nico W. schrieb:
> Aber ist in dem Bereich auch völlig egal, da das Ergebnis identisch ist.

Na dann sehe ich die Notwendigkeit für das Script immer noch nicht.

Ich würde das Script auch alleine deshalb in Frage stellen, weil alle 
git-Nutzer, außer du, ohne dieses script gut auskommen.
Also musst du einen Spezialfall haben. Wenn du keinen Spezialfall 
hättest, wäre diese Funktionalität schon lange in git drin.

> Nen local pull habe ich bisher noch nie gesehen.

Lokale pulls waren schon immer ganz normal.
In frühen Versionen ging es auch gar nicht anders.

von Nico W. (nico_w)


Lesenswert?

Die meisten Gituser nutzen Rebase selten bis nie, arbeiten eher mit nem 
Merge bzw. pull-Requests. Ich möchte keinen Merge. Ich möchte eine 
komplette lineare History.

Wenn du einen Arbeits-Branch hast mit 100 commits, der Master 100 
commits ahead ist, dann wirst du schnell mit einem normalen rebase 
Probleme bekommen.

Vielleicht hast du selten so einen großen Unterschied zwischen einem 
Arbeits-Branch und dem eigentlichen Master. Dann mag das kaum einen 
Unterschied machen.

Hinter der Hütte macht das Script in etwa:
1
git checkout issue-67
2
---- git-step-rebase ----
3
git rebase experimental^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4
git rebase experimental^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5
git rebase experimental^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6
git rebase experimental^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
7
git rebase experimental^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
8
[...]
9
git rebase experimental^^
10
git rebase experimental^
11
git rebase experimental

Wenn du das nicht benötigst ist es ja auch gut. Ich für meinen Teil habe 
das bei größeren Geschichten immer gerne dabei.

von Hater (Gast)


Lesenswert?

Nico W. schrieb:
> Die meisten Gituser nutzen Rebase selten bis nie, arbeiten eher mit nem
> Merge bzw. pull-Requests. Ich möchte keinen Merge. Ich möchte eine
> komplette lineare History.

Falsch. Aber so richtig.

Mit rebase sorgst du dafür, das dein Branch problemlos in den Master 
gemergt werden kann. Das ist oftmals sehr viel eleganter, als von einem 
völlig weggetrifteten Zweig abertausende Konflikte bei einem direkten 
Merge zu beheben.

Wie die Historie in meinem lokalen Brach aussieht, ist völlig 
irrelevant.

Es ist DEINE Aufgabe, das es nicht zu Konflikten kommt - nicht 
derjenigen Person, welche den Merge durchführen will.

Man sieht leider an vielen Stellen, das Git wie SVN oder jedes beliebig 
zentrale Versionsmanagement Tool verwendet wird. Davon muss man sich 
einfach lösen.

von Gituser (Gast)


Lesenswert?

Hater schrieb:
> Man sieht leider an vielen Stellen, das Git wie SVN oder jedes beliebig
> zentrale Versionsmanagement Tool verwendet wird. Davon muss man sich
> einfach lösen.

Das sehe ich auch so.

Ich kenne die beschriebenen Probleme nicht. Wenn man ständig 
merge-Konflikte hat, dann ist etwas im Entwicklungsmodell falsch. Die 
Entwickler sprechen sich nicht ab. Oder wenn es nur einen Entwickler 
gibt, dann zieht er seine Nebenbranches zu spät nach.
Wenn ich in master etwas tue, von dem ich weiß, dass es Konflikte in 
einem Branch verursachen wird, dann mache ich natürlich schnellstmöglich 
einen rebase des Branches.
Und genau das macht ja dieses Script. Nur eben viel später. Also dann, 
wenn ich gar nicht mehr weiß, wie dieser Konflikt aufzulösen ist. Für 
mich ist dieses Vorgehen nicht sinnvoll.

Für mich gibt es nur zwei Arten von Branches:
1) Tote Branches. Diese werden natürlich auch nicht mehr rebased.
2) Aktive Branches. Diese ziehe ich natürlich regelmäßig per Rebase nach 
und warte nicht, bis hunderte Konflikte aufgelaufen sind. Ich sehe nur 
Nachteile darin einen Branch nie zu rebasen und dann am Ende beim 
Merge/Rebase nach master alle Konflikte aufzulösen.

von tictactoe (Gast)


Lesenswert?

Rudolph R. schrieb:
> git remote add upstream
> https://github.com/upstream-username/projectname.git
> git pull upstream master
> git push
>
> Nachdem ich denn herausgefunden hatte wie ich aus VIM raus komme für die
> commit-message (:wq ENTER ...) hat das auch funktioniert soweit.
> Nur ist mein Fork jetzt 2 commits ahead...

Wenn alles nach Plan gelaufen wäre, sollte VIM hier gar nicht ins Bild 
kommen. Und tatsächlich: 2 Commits ahead? Einer davon ist wohl ein 
Merge-commit (dessetwegen VIM gekommen ist). Dann ist da noch ein 
weiterer Commit. Das muss einer sein, den du zusätzlich zu denen von 
"upstream" und deinem Pull Request in deinem Repository gehabt hast. 
Klingelt da was?

BTW, ich verwende gitk, um mir einen Überblick über die Branches zu 
verschaffen. Versuche mal
1
gitk --branches --remotes=upstream HEAD
Kann sein, dass da viel Kram auftaucht, aber man sollte sehen, wo man 
sich befindet (gelber Knoten) und auf welchen Bahnen sich der/die 
Branches von "upstream" bewegen.

Es könnte auch passiert sein, dass "upstream" deinen Pull Request 
abgeändert hat. Dann würde man das in gitk relativ leicht erkennen 
können.

von Rudolph R. (rudolph)


Lesenswert?

Na, ich habe schon Stuss mit dem Repository gemacht, erst den 
Merge-Request über die Webseite und dann noch mal den Sync über die 
Kommando-Zeile.
Einfach mal Ausprobieren das ganze schadet ja erstmal nicht.

Beim Merge-Request über die Webseite kommt halt heraus, dass die 
Branches in den Repositories zwar identisch sind, der Branch in meinem 
Repository aber dennoch einen Commit ahead ist.

Und beim Sync über die Kommando-Zeile mit den ohnehin schon identischen 
Repositories wurde ein Commit generiert den ich zu kommentieren 
automatisch aufgefordert wurde. Der zweite Commit sollte eigentlich leer 
sein, ist es aber gar nicht.
Und wohl gemerkt, den Branch habe ich selber gar nicht in dem Sinne 
angefasst als das ich da drin irgendwelche Dateien manipuliert hätte.

Inzwischen ist der Branch den ich dann bearbeiten will gegenüber meinem 
Repository um 5 Commits zurück und ich habe immer noch keine Antwort auf 
die Frage wie ich das Synchronisiert bekomme.
Ausser jetzt mein Repository zu löschen und neu zu erstellen.

Ich will nur, dass auf Github steht: "This branch is even with ..."
Und das nehme ich dann als Arbeitsgrundlage, zweige einen Branch ab zum 
Rumspielen und einen weiteren in den ich die für einen Pull-Request 
relevanten Änderungen einspielen kann.
Und wenn dann da steht "This branch is x commits behind...", dann möchte 
ich das schlicht nur so re-synchroniseren, dass da wieder steht "This 
branch is even with..." und nicht etwa "This branch is 1 commit 
ahead...".

Statt dessen wird hier nur sinnlos am Thema vorbei diskutiert.
Eine Anwort auf die Fragestellung könnte auch sein, dass das so gar 
nicht funktioniert mit Git.
Okay, wenn das so ist werde ich wohl nicht drum herum kommen mein 
Repository immer wieder zu löschen und einen frischen Fork zu erstellen.
Aber irgendwie klingt das schon reichlich beknackt.

von Gituser (Gast)


Lesenswert?

Rudolph R. schrieb:
> Inzwischen ist der Branch den ich dann bearbeiten will gegenüber meinem
> Repository um 5 Commits zurück und ich habe immer noch keine Antwort auf
> die Frage wie ich das Synchronisiert bekomme.

git fetch origin
git rebase origin/master

Wenn dein remote origin und der branch master heißen.

von Gituser (Gast)


Lesenswert?

Wenn du alles verbastelt hast, geht natürlich auch immer git reset.

von Rudolph R. (rudolph)


Lesenswert?

Wieso Origin?
Es geht doch darum das Repository mit dem Upstream-Repository zu 
synchronisieren.

Es ging nie darum die lokale Kopie mit dem Repository auf Github zu 
synchronisieren.

Gituser schrieb:
> Wenn du alles verbastelt hast, geht natürlich auch immer git reset.

Schön, das setzt aber nur den Fork zurück und nicht etwa auf den 
aktuellen Stand des Upstream Repositories.

: Bearbeitet durch User
von Gituser (Gast)


Lesenswert?

Rudolph R. schrieb:
> Wieso Origin?
> Es geht doch darum das Repository mit dem Upstream-Repository zu
> synchronisieren.
>
> Es ging nie darum die lokale Kopie mit dem Repository auf Github zu
> synchronisieren.

Du kannst nicht direkt ein remote modifizieren.
Das ist nicht vorgesehen und auch nie sinnvoll.

Es wird immer alles lokal gemacht und dann per push/pull mit dem remote 
synchronisiert. Stichwort: Dezentrale Versionsverwaltung.

Deshalb checke den Branch, den du modifizieren willst, lokal aus 
(nachdem du lokal synchronisiert hast mit git fetch) und mache was du 
machen willst. Dann pushe mit git push (-f).
Fertig.

Wichtig: Vorher die genannten Grundlagenkapitel im Buch lesen.

von Gituser (Gast)


Lesenswert?

Rudolph R. schrieb:
> Schön, das setzt aber nur den Fork zurück und nicht etwa auf den
> aktuellen Stand des Upstream Repositories.

Hast du dein upstream nicht als remote eingetragen?

git remote add upstream URL_VON_UPSTREAM
git reset upstream/master
alternativ auch: git rebase upstream/master
git push -f

von Rudolph R. (rudolph)


Lesenswert?

Okay, mal mit git clone den Branch frisch lokal auf die Platte gezogen.

git remote -v

Okay, origin ist gesetzt und die URL anders als ich dachte.

git remote add upstream https://github.com/marcio-ao/Marlin.git

git remote -v

sieht okay aus

git reset upstream
git reset upstream/master
git reset upstream/bugfix-2.0.x-with-ftdi-eve-touchscreen

-> fatal: ambignous argument '...' unknown revision or path in the 
working tree.

git rebase upstream/bugfix-2.0.x-with-ftdi-eve-touchscreen
git rebase upstream/master

-> fatal Needed a single revision invalid upstream

na denn.

git fetch upstream
git rebase upstream/bugfix-2.0.x-with-ftdi-eve-touchscreen

Jetzt ist was passiert und es sieht so aus als ob die lokale Kopie auf 
dem Stand von dem Upstream-Repository wäre.

git push
-> error: failed to push some refs to ...
hint: Updates were rejected beause the tip of your current branch is 
behind its remote counterpart. Integrate the remote changes (e.g. 'git 
pull ...') befor pushing again.

git pull
-> VIM Eingabe für Commit-Kommentar
"Merge made by the 'recursive' strategy.

git push

Die lokale Kopie landet auf Github und sieht so aus als ob die identisch 
ist mit dem Branch im Upstream Repository.

Allerdings: This branch is 3 commits ahead of 
marcio-ao:bugfix-2.0.x-with-ftdi-eve-touchscreen.

Schön, jetzt sind die Dateien scheinbar *möglichwerweise* vielleicht 
wieder synchron mit dem Upstream Repository, weil das so aussieht und 
trotzdem drei Commits weiter.

Wenn ich davon jetzt einen Branch ableite für den Pull-Request ist 
Github zurecht erstmal verwirrt da es den Branch im Upstream-Repository 
nicht gibt und zeigt an wie weit das weg ist vom Master-Branch, macht ja 
nichts.
Aber wenn ich dafür einen Pull-Request erstelle gegen den Ziel-Branch 
ohne wirklich was geändert zu haben, dann will Github die inzwischen 
drei Commits ansetzen mit denen ich lediglich die Repositories 
synchronisiert habe -> unlustig.

Also unterm Strich immer noch, es funktioniert nicht zwei Repositories 
sauber zu Synchronisieren.

von Gituser (Gast)


Lesenswert?

Rudolph R. schrieb:
> git fetch upstream
> git rebase upstream/bugfix-2.0.x-with-ftdi-eve-touchscreen
>
> Jetzt ist was passiert

Es ist nicht einfach nur "was passiert". Mit dem fetch hast du erst alle 
Daten von Upstream lokal geladen und bekannt gemacht.

Bitte bitte die Kapitel aus dem Buch lesen.
Git ist ein dezentrales System.
Das zu verstehen ist wichtig.

>git push
>-> error: failed to push some refs to ...

git push -f

>git pull

Falsch!

>trotzdem drei Commits weiter.

Weil du einen git pull gemacht hast.
Bitte Buch lesen und verstehen.

>Also unterm Strich immer noch, es funktioniert nicht zwei Repositories sauber zu 
Synchronisieren.

Kein pull machen, sondern nur reset/rebase. Dann push -f.

von Rudolph R. (rudolph)


Lesenswert?

Gituser schrieb:
>>git push
>>-> error: failed to push some refs to ...
>
> git push -f

Verlixt, ja, ein forced-push, macht Sinn und hatte ich überlesen.
Danke!
Nach einem erneuten git rebase und git push -f steht da jetzt endlich 
"This branch is even with 
marcio-ao:bugfix-2.0.x-with-ftdi-eve-touchscreen.".

Geht also doch, super, das macht die Geschichte etwas leichter.

>>git pull
>
> Falsch!

Nur weil git das vorgeschlagen hat...

>>trotzdem drei Commits weiter.
>
> Weil du einen git pull gemacht hast.
> Bitte Buch lesen und verstehen.

Zumindest für den Moment habe ich jetzt alles zusammen was ich brauche 
und weiss mehr über Git als ich je wissen wollte.

von Gituser (Gast)


Lesenswert?

Rudolph R. schrieb:
> Nur weil git das vorgeschlagen hat...

Die Vorschläge von git passen meistens.
Aber git kann eben auch keine Gedanken lesen.

Generell nimmt git an, dass man eher kein rebase machen will, oder sonst 
irgendwie die history modifizieren will. Das ist einfach ein "safe 
default", mit dem man sich am wenigsten kaputt macht.

Sollte man sich doch mal was kaputt machen, gibts aber auch noch Tools 
zum Retten, wie z.B. git reflog. Ein komplett neues clone ist nie 
notwendig. Auch wenn es zugegeben für Anfänger oft der einfachere Weg 
ist. :)
Aber wenn man einmal verstanden hat, wie git funktioniert, kommt man auf 
solche Ideen nicht mehr.

von Nico W. (nico_w)


Lesenswert?

Hater schrieb:
> Nico W. schrieb:
>> Die meisten Gituser nutzen Rebase selten bis nie, arbeiten eher mit nem
>> Merge bzw. pull-Requests. Ich möchte keinen Merge. Ich möchte eine
>> komplette lineare History.
>
> Falsch. Aber so richtig.

Nichts anderes wollte ich damit aussagen. Das ist nicht meine 
Vorgehensweise, sondern eine, die ich häufig gesehen habe.

Ich sorge dafür das mein Arbeitsbranch mit dem Master/Experimental in 
einem linearen Zusammenhang steht. Meine Commits sollen am Ende on top 
auf das Master passen können. Hierzu nutze ich das angegebene Script, da 
es mir die Arbeit erleichtert.

Bisher habe ich meistens nur gehört das ich 'alles Verkehrt' mache, 
allerdings vermisse ich stark, was genau der 'richtige' Weg ist.

Mein normaler Workflow:
1
git checkout master/experimental
2
git fetch
3
git pull
4
git checkout -b work_on_feature_xy
5
git add -u
6
git commit -m "my new feature"
7
git rebase master/experimental
8
git checkout master/experimental
9
git rebase work_on_feature_xy (oder git pull . work_on_feature_xy, beim rebase wird automatisch hier ein fast forward erzeugt)
10
git push

von Gituser (Gast)


Lesenswert?

Nico W. schrieb:
> git rebase work_on_feature_xy

Ich finde es sehr merkwürdig, dass du hier rebase verwendest.
Ich habe das auch sonst noch nie gesehen.
Warum nicht git merge oder eben einen lokalen pull?
Das bewahrt dich auch vor Fehlern, falls du vergisst den branch vorher 
auf master zu rebasen.
Wenn du git merge --ff-only verwendest, kannst du auch den Abbruch 
forcieren, falls kein FF möglich ist. Mit rebase tappst du stattdessen 
in die Falle.

von Nico W. (nico_w)


Lesenswert?

Bewahren muss mich nichts bei git. Es ist ja nie was verloren. Reflog, 
Reset und co sei Dank. Und wenn ich nen rebase verkehrt setze breche ich 
ihn ab.


Jedoch der einzige Grund warum ich keinen lokalen Pull gemacht habe, ich 
kannte es bisher einfach nicht. Aber ich bin nicht lernresistent. Ich 
werde Mal ein wenig damit arbeiten.

Beitrag #5437242 wurde von einem Moderator gelöscht.
Beitrag #5437275 wurde von einem Moderator gelöscht.
Beitrag #5437331 wurde von einem Moderator gelöscht.
Beitrag #5437373 wurde von einem Moderator gelöscht.
Beitrag #5437408 wurde von einem Moderator gelöscht.
Beitrag #5437410 wurde von einem Moderator gelöscht.
Beitrag #5437413 wurde von einem Moderator gelöscht.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.