Wie kann ich all meine lokalen Git-Zweige (und -Tags) umbuchen, wenn der Upstream den Verlauf neu geschrieben hat?

9

Der Betreuer eines bestimmten (eingebetteten) Linux-Kernel-Repos hat eine Reihe alter Commits modifiziert, um den Verlauf zu bereinigen. Als Folge haben alle Commits eine andere SHA.

Wenn ich von diesem neu geschriebenen Verlauf abhole, bin ich in der Notwendigkeit, meine lokalen Zweige zu dem lokalen Verfolgungszweigeintrittspunkt zu rebasieren, der dem Punkt in dem lokalen Baum entspricht, wo meine eigenen Zweige beginnen. Standardlösung:

%Vor%

(SHAxx entspricht c2 von Fernbedienungen / Ursprung / Master in der folgenden Grafik).

Wenn ich jedoch mehrere eigene Zweige habe, die einen einzigen Vorfahren im Master haben, muss ich eine Rebase für jeden einzelnen Zweig anlegen. Stattdessen möchte ich alle Zweige mit allen zugehörigen Tags in einer Aktion auf den neuen Einstiegspunkt im abgerufenen Verfolgungszweig übertragen.

Grafisch, Zustand nach dem Fetch, vor jeder Aktion (vereinfacht - dahinter ist der Master-Verlauf):

%Vor%

Um genau zu sein: Wenn meine eigene Arbeit mit master commit c2 beginnt, möchte ich meinen eigenen Teilbaum mit all seinen Tags (wenn vorhanden) in einer Aktion auf c2 'von remotes / origin / master (mit seiner eigenen SHA verglichen) zu master's c2).

Zu dieser Zeit kann ich den Meister komplett entfernen und mit meiner eigenen Arbeit Fernbedienungen / Ursprung / Meister des neuen Meisters machen:

%Vor%

Dann würde ich testen, ob der Build-Prozess das gleiche Ergebnis liefert wie zuvor und wenn OK: fortfahren, Master-Aktualisierungen inkrementell (zB pro Subindex nn Schritt in 2.6.nn) in meinen eigenen (boardspezifischen) Zweig zu integrieren.

Oder gibt es einen anderen / besseren Ansatz, um das gleiche Ergebnis zu erzielen?

Eine mögliche Lösung wird vorgestellt unter Rebasing einer Filiale mit allen Kindern , aber Tags werden nicht verschoben.

    
Rob 12.07.2011, 00:14
quelle

2 Antworten

3

Nachfolgend wird eine Abfolge von Schritten vorgestellt, die einen relativ neuen Befehl git replace verwenden. Wenn Sie diesen Befehl anstelle von rebase --onto ... verwenden, treten keine Probleme aufgrund von eigenen Zusammenführungen mit dem Master auf - Zusammenführungen, die eine Konfliktlösung erfordern könnten, da die Rebase tatsächlich "commits" wiederholt.

Bemerkung: Es scheint besser zu sein, das entfernte Repo zu klonen, wo der Verlauf neu geschrieben wird, und hier eigene Verzweigungen einzufügen, anstatt dieses entfernte Repo "wie immer" in Ihr lokales Repo zu holen und dann Ihre eigenen Zweige neu zu erstellen. Der Hauptvorteil: Jedes alte Zeug, das nicht Ihr eigenes ist, ist in einem neu geklonten Repo nicht vorhanden, wenn es im umgeschriebenen Repo gelöscht oder umbenannt wird. Beim Abrufen des umgeschriebenen Repos in Ihr lokales Repo würden Zweige, die in dem neuen Verlauf umbenannt werden, zu einer weiteren Existenz von Verzweigungen mit altem Namen führen.

VORGESCHLAGENES VERFAHREN

  • Klonen Sie das entfernte Repo mit seiner neu geschriebenen Geschichte, vermutlich nur die Zweige, die mit Ihrer Arbeit in Verbindung stehen - dies hilft bei der Überprüfung der nächsten Operationen.
  • Geben Sie eine remote add tmp an, die den Pfad Ihres aktuellen lokalen Repos angibt.
  • im lokalen Repo: Fügen Sie ein Tag (z. B. ownstart ) an den Startpunkten Ihrer Zweige hinzu (der Punkt, der mit dem Master geteilt wird).
  • Holen Sie Ihre eigenen Zweige von diesem tmp remote (einige git fetch tmp <branch>:<branch> ). Viele (doppelte) Commits parallel zum Branch Master können unter dem Tag ownstart erscheinen. Dies wird nach dem nächsten Schritt verschwinden; alternativ können Sie eine neue Wurzel an Ihrem eigenen Branch-Tag über Grafts & amp; git filter-branch vor dem Fetch).
  • suche den neuen entsprechenden Startpunkt, an dem ownstart seinen Äquivalent-Commit in der neu geschriebenen Historie hat, und wende seinen SHA wie folgt an: git replace ownstart SHA . Dies erzeugt eine falsche Verbindung aller Ihrer lokalen Arbeit von diesem Punkt zu dem entsprechenden Eintrag in der neuen Geschichte und lässt den Rest der Geschichte "unter" ownstart verschwinden, weil eine Referenz fehlschlägt.

Hinweis 1 : Alle Protokolle nach diesen Vorgängen sollten bereits die gewünschte Commit-Kette aufweisen (z. B. mit gitk). Die ersetzten Commits werden jedoch nicht zusammengeschmolzen: Sie sind noch getrennt und haben nun einen gemeinsamen Vorfahren aus der neu geschriebenen Geschichte. Dies ist konstruktionsbedingt und beeinflusst nicht die (korrekte) Gesamtintegration Ihrer eigenen Arbeit. Es ist möglich (und sogar empfohlen - siehe Hinweis 2), diese Doppelungen zu entfernen, indem git filter-branch -- --master..ownstart --all ausgeführt wird (dies kann zeitaufwendig sein). Es wird die SHAs aller Ihrer eigenen Arbeit ändern, aber die Upstream-Commit-Kette ist nicht betroffen. Die git filter-branch -Operation erstellt Backup-Zweige. Das Ende der Hilfeseite filter-branch schlägt eine Clone-Operation vor, um ohne diese Backups ein neues Repo zu erhalten (verwenden Sie - wenn Sie lokal klonen - keine Hardlinks). Aber dies würde alle eigenen Zweige in Tracking-Fernbedienungen verwandeln, während sie einen anderen Upstream-Ursprung zuweisen.

Anmerkung 2 : Bei einer Testsequenz, die ausgeführt wurde, wurde jede Zusammenführung eines bestimmten Commits in meinem eigenen Zweig (von einem Master-Commit) automatisch mit dem entsprechenden neu geschriebenen History-Commit neu verknüpft den Befehl git filter-branch wie beschrieben ausgeführt haben. Dies ist perfekt. Bei einem anderen Test wurde diese Zusammenführung jedoch getrennt. Es kann an den neu geschriebenen Verlauf gebunden werden, indem git replace -Befehle mit SHAs ausgegeben werden, wobei master-seitige Eltern von Zusammenführungen den entsprechenden Commits des Master-Zweigs entsprechen. Dann muss ein git-filter-branch wiederholt werden.

    
Rob 13.07.2011, 00:58
quelle
1

Ja, das ist möglich. Sie sollten 2 Commits mit dem gleichen Datum und Benutzer sehen, wenn Sie ein Git Log --all - - beschreiben. Sie können ein Skript erstellen, das alle Zweige einzeln auf die neuen Orte zurücksetzt.

Mit Tags können Sie sie löschen und neu erstellen

Hoffe, das hilft

    
Adam Dymitruk 12.07.2011 03:28
quelle

Tags und Links