Wie überschreibe ich einen Zweig in einem anderen Zweig in Git, anstatt ihn zusammenzuführen?


257

Ich habe zwei Zweige emailund staging. stagingist die neueste und ich brauche die alten Änderungen im emailZweig nicht mehr, möchte sie aber nicht löschen.

Ich möchte also nur den gesamten Inhalt von stagingin emailspeichern, damit beide auf dasselbe Commit verweisen. Ist das möglich?


Antworten:


196

Sie können die Zusammenführungsstrategie "Unsere" verwenden:

$ git checkout staging
$ git merge -s ours email # Merge branches, but use our branch head

26
Ich habe es versucht, und es scheint mir rückwärts? Setzt dies nicht den Inhalt von E-Mails in die Inszenierung und nicht umgekehrt?
Max

27
@ Max Ich hatte die gleiche Verwirrung und es hat mir viel Ärger gemacht. Sie müssen diesen Befehl vom neueren Zweig aus (Staging) ausführen und dann eine normale Zusammenführung / PR für Ihren alten Zweig (E-Mail) durchführen.
MrGlass

7
Warum ;am Ende eines jeden Befehls? Ich habe auf das verzichtet ;und es scheint zu funktionieren. Auch diese Antwort ist unvollständig. Der dritte Schritt besteht darin, den alten Zweig (E-Mail) auszuchecken und dann erneut mit dem Staging zusammenzuführen.
Rosdi Kasim

4
git rebase -s theirs <oldbranc> <newbranch> funktioniert auch (egal welcher Zweig Sie sind). Beachten Sie, dass in Rebase "ihre" tatsächlich die neue Branche ist, da "unsere" der Kopf ist, auf den wir derzeit die Commits anwenden.
Rolf

4
@Rolf: Aber Rebase wird die Zusammenführungsinformationen entfernen und den Verlauf abflachen. Nicht unbedingt das, wonach Sie suchen. Auch keine gute Idee, wenn Sie mit bereits veröffentlichtem Verlauf arbeiten.
Knittl

99

Wenn Sie nur möchten, dass die beiden Zweige "E-Mail" und "Staging" identisch sind, können Sie den Zweig "E-Mail" mit einem Tag versehen und dann den Zweig "E-Mail" auf den Zweig "Staging" zurücksetzen:

$ git checkout email
$ git tag old-email-branch
$ git reset --hard staging

Sie können den Zweig "Staging" auch im Zweig "E-Mail" neu einrichten. Das Ergebnis enthält jedoch die Änderung der beiden Zweige.


1
Sie meinen wahrscheinlich git checkout, git checkexistiert meines Wissens nicht
knittl

4
Sie haben Recht, ich bin es so gewohnt, die Ausführung des Git-Befehls so zu tabulieren, dass ich immer "Git Check <TAB>" schreibe, um "Git Checkout" zu schreiben! Korrigiert.
Sylvain Defresne

17
Git Reset bricht das Repo anderer Leute, die Ihr Repo geklont haben
Geoffrey De Smet

Ich glaube, das ist die richtige Antwort. emailDer Zweig des Zweigs sollte nur auf den gleichen Kopf von zeigen, stagingund beide haben die gleichen Commits, die gleiche Geschichte.
Cicerocamargo

76

Ich habe mehrere Antworten gesehen und das ist das einzige Verfahren, mit dem ich das ohne Konflikte beheben kann.

Wenn Sie alle Änderungen von branch_new in branch_old wünschen, dann:

git checkout branch_new
git merge -s ours branch_old
git checkout branch_old
git merge branch_new

Sobald Sie diese vier Befehle angewendet haben, können Sie den branch_old problemlos drücken


5
Ihre Antwort passte wirklich am besten zu meinem Problem, da ich den HEAD nicht zurücksetzen wollte. Geben Sie einfach eine Präferenz für die neueren Dateien im neueren Zweig an, wenn Sie Dinge in den älteren zusammenführen, und arbeiteten Sie ohne Probleme! +1
Öfen

Ich habe mein branch_new nach dem "Zusammenführen" auf "remote" verschoben, und diese Methode hat bei mir funktioniert. War es notwendig für mich zu pushen? Oder hätte es ohne geklappt? (War nicht sicher, ob es den lokalen Zweig oder die Fernbedienung verwenden würde). Vielen Dank!
AspergillusOryzae

Warum können Sie nicht einfach das Folgende tun? git checkout branch_old git merge -s ihre branch_new Hinweis aus stackoverflow.com/questions/14275856/…
Ripu Daman

Es heißt, konnte keine Zusammenführungsstrategie "ihre" finden.
Arango_86

Funktioniert perfekt für mich, hat den Vorteil, nichts zurückzusetzen
Romain

68

Die anderen Antworten gaben mir die richtigen Hinweise, aber sie halfen nicht ganz.

Folgendes hat bei mir funktioniert:

$ git checkout email
$ git tag old-email-branch # This is optional
$ git reset --hard staging
$
$ # Using a custom commit message for the merge below
$ git merge -m 'Merge -s our where _ours_ is the branch staging' -s ours origin/email
$ git push origin email

Ohne den vierten Schritt der Verschmelzung mit unserer Strategie wird der Push als nicht schnelles Vorwärts-Update betrachtet und abgelehnt (von GitHub).


Das macht die Merge-Commit-Nachricht falsch, aber ja, es funktioniert großartig.
cdunn2001

cdunn2001, ich bin neugierig. Was war die Merge-Commit-Nachricht, die Sie erwartet hatten, und wie wurde das durcheinander gebracht?
Shyam Habarakada

Es heißt "Remote-Tracking-Zweig 'Ursprung / E-Mail' in E-Mail zusammenführen". Inszenierung wird nicht erwähnt. Keine große Sache. Ändern Sie einfach das Commit oder verwenden Sie es merge -m 'This is not my beautiful house.' -s ours origin/email.
cdunn2001

@ShyamHabarakada, ich mache, was du sagst, und ich bekomme das Problem mit dem Update ohne schnellen Vorlauf. weil nichts passiert, wenn ich den 4. Schritt mache.
kommradHomer

Im vierten Schritt müssen Sie origin / email verwenden. Dies funktioniert nicht nur mit lokalen E-Mails.
Travis Reeder

45

Wenn Sie wie ich sind und sich nicht mit dem Zusammenführen befassen möchten, können Sie die obigen Schritte ausführen, außer dass Sie Gewalt anstelle von Zusammenführen anwenden, da dies eine ablenkende Protokollpapierspur erzeugt:

git checkout email
git reset --hard staging
git push origin email --force

Hinweis: Dies ist nur möglich, wenn Sie das Material WIRKLICH nie wieder in E-Mails sehen möchten.


1
git push origin email --force hat bei mir nicht funktioniert, da Step2 die Zweige verlassen hat. Also nach Schritt 2, das ist, was ich getan habe: Git zurücksetzen Ursprung / E-Mail und dann Git Push
Benutzer 3505394

2
Dies ist genau das, was in Frage gestellt wurde - "wie man überschreibt, anstatt zusammenzuführen". Sollte als Antwort akzeptiert werden.
jozols

17

Ich wollte zwei Zweige zusammenführen, damit alle Inhalte old_branchmit den Inhalten von aktualisiert werdennew_branch

Für mich hat das wie ein Zauber gewirkt:

$ git checkout new_branch
$ git merge -m 'merge message' -s ours origin/old_branch
$ git checkout old_branch
$ git merge new_branch
$ git push origin old_branch

10

Wie wäre es mit:

git branch -D email
git checkout staging
git checkout -b email
git push origin email --force-with-lease

@emptywalls, weil es einen Force-Push ausführt, ohne den Benutzer zu warnen, dass er vom Server abgelehnt werden kann, und auch nicht erklärt, warum er benötigt wird. Das heißt, es ist eine praktikable Option für ein Ein-Entwickler-Projekt
David Costa

@ DavidCosta warum sollte dies vom Server abgelehnt werden? Dies ist ein einfacher Vorgang zum Löschen von E-Mail-Zweigen und zum Kopieren von Staging in E-Mail. Ich möchte also nur den gesamten Inhalt von "Staging" in "E-Mail" speichern, damit beide auf dasselbe Commit verweisen. Genau das passiert Hier.
Arek S

@ArekS kann von einem serverseitigen Hook abgelehnt werden, wenn der Zweig als "geschützt" festgelegt ist, z. B. in GitLab. Problem ist, dass, wenn jemand anderes seinen Zweig vor dieser Operation von E-Mail abgeleitet hat und dann versucht zu pushen, die Referenzen nicht mehr übereinstimmen (weil einige Commits einfach verschwunden sind)
David Costa

1
Ich habe das Original von --force zu --force-with-lease bearbeitet, das den Trick auf zerstörungsfreie Weise erledigt.
frandroid

1
Dies ist der beste Weg, wenn Sie nur einen Zweig wegblasen und ihn sauber vom Quellzweig aus starten möchten.
Shane

6

Andere Antworten sahen unvollständig aus.
Ich habe es unten vollständig versucht und es hat gut funktioniert.

HINWEIS:
1. Erstellen Sie eine Kopie Ihres Repositorys, bevor Sie es unten versuchen, um auf der sicheren Seite zu sein.

Details:
1. Die gesamte Entwicklung findet im Dev-Zweig statt.
2. Der Qa-Zweig ist genau dieselbe Kopie von Dev.
3. Von Zeit zu Zeit muss der Dev-Code in den Qa-Zweig verschoben / überschrieben werden

Also müssen wir den qa-Zweig vom dev-Zweig überschreiben

Teil 1:
Mit den folgenden Befehlen wurde das alte qa auf ein neueres dev aktualisiert:

git checkout dev
git merge -s ours qa
git checkout qa
git merge dev
git push

Automatischer Kommentar für den letzten Push gibt unten:

// Output:
//  *<MYNAME> Merge branch 'qa' into dev,*  

Dieser Kommentar sieht umgekehrt aus, da die obige Reihenfolge auch umgekehrt aussieht

Teil 2:

Im Folgenden finden Sie unerwartete, neue lokale Commits in dev, die unnötigen,
also müssen wir sie wegwerfen und dev unberührt lassen.

git checkout dev

// Output:
//  Switched to branch 'dev'  
//  Your branch is ahead of 'origin/dev' by 15 commits.  
//  (use "git push" to publish your local commits)


git reset --hard origin/dev  

//  Now we threw away the unexpected commits

Teil 3:
Überprüfen Sie, ob alles wie erwartet ist:

git status  

// Output:
//  *On branch dev  
//  Your branch is up-to-date with 'origin/dev'.  
//  nothing to commit, working tree clean*  

Das ist alles.
1. altes qa wird jetzt durch neuen dev-verzweigungscode überschrieben
2. local ist sauber (remote origin / dev ist unberührt)


6

Der einfachste Weg, dies zu tun:

//the branch you want to overwrite
git checkout email 

//reset to the new branch
git reset --hard origin/staging

// push to remote
git push -f

Jetzt sind der E-Mail-Zweig und die Bereitstellung identisch.


2
Warnung: Dadurch werden alle Commits in der emailVerzweigung gelöscht . Es ist so, als würde man den emailZweig löschen und am Kopf des stagingZweigs neu erstellen .
Cameron Hudson

2
git checkout email
git merge -m "Making email same as staging disregarding any conflicts from email in the process" -s recursive -X theirs staging

1
Diese Antwort wäre für mich klarer gewesen, wenn der Kommentar vom zusammengeführten Kommentar im Befehl getrennt worden wäre. Erklären Sie kurz, was -X tut und wie sich dies auf diese Zusammenführung auswirkt. Trotzdem danke. Ich musste nachschlagen :)
Noelicus

@noelicus danke für den Kommentar und du hast recht. Ich könnte die Antwort in Zukunft bearbeiten.
Willa

0

Dieser ändert den ursprünglichen neueren Zweig nicht und gibt Ihnen die Möglichkeit, vor dem endgültigen Festschreiben weitere Änderungen vorzunehmen.

git checkout new -b tmp
git merge -s ours old -m 'irrelevant'
git checkout old
git merge --squash tmp
git branch -D tmp
#do any other stuff you want
git add -A; git commit -m 'foo' #commit (or however you like)
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.