
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
git merge $intended_parent_1 $intended_parent_2
git checkout $original_commit -- .
git commit --amend -a -C $original_commit
git replace --graft $original_commit \
$(git show --pretty=%P $original_commit) \
$additional_parent
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.

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 --orphan
wie 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.
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 --amend
und 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.)
@rumpel hat die richtige Antwort gegeben. Erlauben Sie mir, die Snippets zu teilen, die ich verwende.
Zuerst habe ich orphan erstellt master
Zweig:
git checkout --orphan master
git commit --allow-empty -m 'Init'
Mein Anwendungsfall ist etwas anders, die Website, die ich möchte, ist in _site
Verzeichnis an develop
Zweig. Deshalb mache ich:
git checkout master
git rm -rf .
git read-tree develop^{tree}:_site
git checkout -- .
git commit -m "Update from develop SHA1:$(git rev-parse --short develop) ($(git log -1 --format=%cd develop))"
git replace --graft @ $(git show --pretty=%P @ | head -n1) develop
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.
10170000cookie-checkWie füge ich alten Git-Commits zusätzliche Eltern hinzu?yes