Wie füge ich alten Git-Commits zusätzliche Eltern hinzu?
Lesezeit: 7 Minuten
Quuxplusone
Ich habe ein Projekt mit zwei Zweigen: Master- und GH-Seiten. Es handelt sich im Wesentlichen um zwei verschiedene Projekte, wobei das gh-pages-Projekt vom Master-Projekt abhängt (und nicht umgekehrt). Stellen Sie sich vor, “master enthält den Quellcode, gh-pages enthält die aus diesen Quelldateien erstellte Binärdatei”. In regelmäßigen Abständen nehme ich die Änderungen, die sich im Master angesammelt haben, und mache einen neuen Commit zum gh-pages-Zweig mit der Commit-Nachricht „In Übereinstimmung mit Master-Commit xxxxxxxx bringen“.
Nach einer Weile wurde mir klar, dass es schön wäre, wenn der gh-pages-Commit „In Einklang mit Master-Commit xxxxxxxx bringen“ tatsächlich xxxxxxxx als Elternteil im Git-Repository hätte. So (schlechte MSPaint-Kunst):
Gibt es eine Möglichkeit, das Repository wie das zweite Bild oben aussehen zu lassen? Ich weiß, wie man neue Commits nach diesem Muster erstellt: Ich kann “git merge -s ours master” (was die Eltern eines ansonsten leeren Commits festlegt) gefolgt von “git commit –amend adv550.z8” (wobei adv550.z8 ist die Binärdatei, die sich tatsächlich ändert). Aber macht es Git einfach, in der Zeit zurückzureisen und alten Commits neue Eltern hinzuzufügen?
Ich bin durchaus bereit, “git push -f” zu verwenden und den aktuellen Verlauf meines Github-Repositorys wegzublasen, sobald mein lokales Repo richtig aussieht. Die Frage ist, kann Ich sehe mein lokales Repo richtig?
BEARBEITET JAHRE SPÄTER, UM HINZUZUFÜGEN: Ich habe schließlich meine Versuche aufgegeben, die Git-Geschichte zu schreiben gh-pages Sieht danach aus; Ich entschied, dass es zu viel Arbeit für null Gewinn war. Meine neue Praxis besteht darin, Commits aggressiv zu quetschen gh-pages, weil das Speichern dieser Commit-Nachrichten in meinem Fall wirklich keine Rolle spielt. (Es ist nur eine lange Reihe von „Mit Master-Commit in Einklang bringen …“, von denen keines historisch interessant ist.) Wenn ich dies jedoch noch einmal tun müsste, würde ich mir die Antworten anhören, die besagten
Erläuterung: git replace –graft ermöglicht es, neu anzugeben, welche die Eltern eines bestimmten Commits sind. Dies funktioniert, indem ein neuer Commit mit den entsprechenden Änderungen geschrieben wird und eine Ersetzungsreferenz geschrieben wird, die git veranlasst, bei jedem Zugriff nach dem neuen Commit anstelle des ursprünglichen zu suchen.
git show --pretty=%P $original_commit listet nur die ursprünglichen Eltern auf.
Das ist [nearly] die richtige Antwort. Fast, denn ich musste gebrauchen git show --pretty=%P $original_commit | head -n1 – mein Git (2.11.1) hat viel mehr ausgegeben als nur die übergeordnete Zeile.
– kgadek
13. Februar 2017 um 1:08 Uhr
dies ist eine Nachricht aus der apokalyptischen Zukunft, die besagt, dass Sie beide mein Leben um einiges einfacher gemacht haben und ich Ihnen sehr dankbar bin
– das richtige Zeug
24. März 2020 um 17:19 Uhr
Verwenden git show --pretty="format:%P" --no-abbrev-commit --no-patch ${original_commit} vermeiden head -n 1
– Maddes
31. Dezember 2020 um 1:10 Uhr
Beachten Sie, dass auf diese Weise hinzugefügte Eltern nicht auf Github angezeigt werden
– falscher Benutzername
10. Januar 2021 um 23:48 Uhr
@wrongusername Weißt du, ob es eine Möglichkeit gibt, sie in Github anzuzeigen?
– Emon
16. September 2021 um 12:06 Uhr
krlmlr
Das sind Ihre Zauberworte:
git merge origin/master --strategy ours
Führen Sie diese in der aus gh-pages Filiale, um die Beziehung zu erfassen master ohne wirklich etwas zu ändern. Dies funktionierte für mich, als ich die erstellte gh-pages Zweig als --orphanwie in dieser Antwort.
Du kannst sogar --amend diesen leeren Merge-Commit hinterher, um die Änderungen einzuführen, die Sie tatsächlich an Ihren “Seiten” vornehmen möchten. Sehen https://github.com/krlmlr/pdlyr/network für ein aktuelles Beispiel auf GitHub.
Dies, kombiniert mit Informationen, die der Frage in einer Bearbeitung hinzugefügt wurden (z git commit --amend -a -C ..., etc.) hat sich für mich als nützlich erwiesen. Vielen Dank.
– Linde
20. Januar 2016 um 19:45 Uhr
Das braucht ein --allow-unrelated-histories -Flag nun funktioniert, da Git seit Git 2.9 standardmäßig nicht mehr zulässt, dass nicht zusammenhängende Historien zusammengeführt werden
– jitin
20. April um 8:22 Uhr
Sie können nicht in der Zeit zurückgehen und bestehende Commits ändern. Auch wenn Sie so etwas tun git commit --amend, Sie ändern den Commit nicht wirklich; Sie erstellen an derselben Stelle im Baum ein neues mit dem gesamten Inhalt des Originals (plus Ihren Änderungen). Sie werden feststellen, dass sich der Commit-Hash nach dem ändert --amendund das Original ist immer noch in Ihrem Repo vorhanden – Sie können mit darauf zurückgreifen git reflog.
Andererseits du kann Reise in die Vergangenheit und erschaffe ein alternatives Universum. Im Wesentlichen würden Sie zu Ihrem zurückkehren gh-pages Verzweigungspunkt und erstelle das Ganze neu (mit zB git cherry-pick oder so) als Parallelzweig. Die Hashes würden sich ändern, weil die Commits unterschiedliche Objekte sind.
(Ich bin neugierig, warum Sie Ihr Repo als separate Zweige eingerichtet haben, anstatt als separate Verzeichnisse im selben Zweig. Es scheint, als würde der Code -> Build-Prozess langweilig werden.)
“Sie werden feststellen, dass sich der Commit-Hash nach dem –amend ändert”: Aber nur, wenn sich der Inhalt ändert, richtig? Das Ändern der Commit-Log-Nachricht scheint den Hash nicht zu ändern, und ich hoffe, dass das Ändern der Eltern auch nicht der Fall sein wird. “warum separate Branches”: Genau so macht GitHub ihre “GitHub Pages” -Funktion, die ich zum Hosten verwende quuxplusone.github.com/Advent/play-550.html. Sie erstellen einen neuen Zweig mit dem Namen “gh-pages”, und alles, was sich darin befindet, wird automatisch auf die Live-Webseite gespiegelt. Es ist irgendwie seltsam, aber ich denke, es macht unter den Umständen einen gewissen Sinn.
– Quuxplusone
30. Mai 2012 um 1:15 Uhr
“Im Wesentlichen würden Sie zu Ihrem gh-pages-Verzweigungspunkt zurückkehren und das Ganze neu erstellen”: Ich wäre damit einverstanden. Aber wie erhalte ich die Zeitstempel der ursprünglichen Commits? Ich will sie nicht verlieren. Deshalb habe ich gefragt, wie man in der Zeit zurückgeht.
– Quuxplusone
30. Mai 2012 um 1:20 Uhr
Ich bekomme einen neuen Hash auch mit a commit --amend -C mit leerem Index.
– ellotheth
30. Mai 2012 um 2:16 Uhr
Nun, da ich genauer darüber nachdenke, wäre es sinnvoll, wenn Sie nur versuchen, die Herkunftsinformationen beizubehalten, die Idee des Zusammenführens der Eltern zu überspringen und stattdessen Tags zu verwenden? Sie könnten kommentierte Tags auf die werfen gh-pages Zweig mit der master Commit-Eltern für alte Commits und verwenden Sie in Zukunft Ihr Zusammenführungs-/Änderungs-System.
– ellotheth
30. Mai 2012 um 2:18 Uhr
Der Commit-Hash deckt alles ab, was mit diesem Commit zu tun hat. Der Inhalt, die übergeordnete Referenz, der Kommentar, das Datum/die Uhrzeit. Wenn Sie ein einzelnes Bit in einem Commit ändern, wird ein neuer Hash generiert.
– Wattwelt
30. Mai 2012 um 16:03 Uhr
@rumpel hat die richtige Antwort gegeben. Erlauben Sie mir, die Snippets zu teilen, die ich verwende.
Beachten Sie, dass ich im letzten Befehl filtern musste | head -n1 seit mein git Ausgabe viel mehr als nur Eltern.
Sie können die Commits neu schreiben, aber es erfordert das Neuschreiben des gesamten Zweigs, beginnend mit dem ersten Commit, das ein zusätzliches übergeordnetes Element benötigt, bis zur Spitze des Zweigs. Es ist (wie bei Rebases) ein neuer Zweig, der nur den gleichen Inhalt hat.
Der Trick besteht darin, den Commit-Baum zu verwenden, der alles übernimmt (Committer/Autor-Informationen, Zeitstempel, Commit-Nachricht, Liste der Eltern), wenn auch auf ziemlich unpraktische Weise. Ein bisschen Scripting erledigt dann den Job.
Sie würden positiv bewertet, wenn Ihr zweiter Absatz nicht so bizarr vage wäre.
– Quuxplusone
26. Februar 2014 um 4:26 Uhr
Ich weiss. Aber es ist ein bisschen Arbeit, und ich brauche dieses Skript jetzt nicht.
– Andreas Krey
28. März 2014 um 14:33 Uhr
Sie würden positiv bewertet, wenn Ihr zweiter Absatz nicht so bizarr vage wäre.
– Quuxplusone
26. Februar 2014 um 4:26 Uhr
Ich weiss. Aber es ist ein bisschen Arbeit, und ich brauche dieses Skript jetzt nicht.
– Andreas Krey
28. März 2014 um 14:33 Uhr
10170000cookie-checkWie füge ich alten Git-Commits zusätzliche Eltern hinzu?yes