Benennen Sie den Hauptzweig für lokale und entfernte Git-Repositorys um

820

Ich habe den Zweig, masterder den entfernten Zweig verfolgt origin/master.

Ich möchte sie master-oldsowohl lokal als auch auf der Fernbedienung umbenennen . Ist das möglich?

Was würde für andere Benutzer, die nachverfolgt haben origin/master(und die ihren lokalen masterZweig immer über aktualisiert haben git pull), passieren, nachdem ich den Remote-Zweig umbenannt habe?
Würde ihr git pullnoch funktionieren oder würde es einen Fehler auslösen, den es nicht origin/mastermehr finden konnte?

Anschließend möchte ich einen neuen masterZweig erstellen (sowohl lokal als auch remote). Was würde jetzt wieder passieren, wenn die anderen Benutzer dies tun git pull?

Ich denke, all dies würde zu viel Ärger führen. Gibt es einen sauberen Weg, um das zu bekommen, was ich will? Oder sollte ich einfach so bleiben masterwie es ist und eine neue Niederlassung gründen master-newund dort einfach weiterarbeiten?

Albert
quelle
2
Das Rezept in der akzeptierten Antwort gegeben hat zu einem Zweig eines beliebigen Namen gilt, aber die Einschränkungen (wie bereits erwähnt) nicht, aufgrund der (Standard) besonderen Rolle der Master - Niederlassung in Git.
Kynan
3
@kynan: Ich glaube ich verstehe nicht. Welche Einschränkungen gelten für Master und nicht für andere Branchen? Wenn es sich um einen Zweig namens xy handeln würde und andere Personen diesen Zweig verfolgt hätten, wie wäre das anders?
Albert
4
Die Einschränkung, dass Sie den Remote-Master normalerweise nicht löschen können. Dies gilt jedoch nicht für Aristoteles 'Antwort. Sie sollten dies daher als akzeptierte Antwort markieren. Sie haben Recht, jeder git push -fbeeinträchtigt die Fähigkeit pullvon jedem Remote-Tracking-Zweig.
Kynan
Sie können einen neuen Zweig erstellen master-old, der auf dasselbe Commit wie der vorherige masterZweig verweist . Anschließend können Sie den masterZweig mit Ihren neuen Änderungen überschreiben, indem Sie eine mergemit der oursStrategie ausführen. Das Zusammenführen funktioniert, wenn die Fernbedienung keine nicht schnellen Änderungen zulässt. Das bedeutet auch, dass andere Benutzer keine erzwungenen Updates haben.
dnozay
1
@kynan masterist nur etwas Besonderes, solange es der einzige existierende Zweig ist. Sobald Sie mehr als einen haben, sind alle Zweige gleichberechtigt.
jub0bs

Antworten:

614

Das Umbenennen kommt dem Löschen und erneuten Erstellen auf der Fernbedienung am nächsten. Zum Beispiel:

git branch -m master master-old
git push remote :master         # delete master
git push remote master-old      # create master-old on remote

git checkout -b master some-ref # create a new local master
git push remote master          # create master on remote

Dies hat jedoch viele Einschränkungen. Erstens wissen keine vorhandenen Kassen über die Umbenennung Bescheid - git versucht nicht , die Umbenennung von Zweigen zu verfolgen. Wenn das neue masternoch nicht existiert, wird git pull einen Fehler verursachen. Wenn das neue mastererstellt wurde. Der Pull versucht zu verschmelzen masterund master-old. Daher ist es im Allgemeinen eine schlechte Idee, es sei denn, Sie arbeiten mit allen zusammen, die das Repository zuvor ausgecheckt haben.

Hinweis: In neueren Versionen von git können Sie den Hauptzweig standardmäßig nicht remote löschen. Sie können dies überschreiben, indem Sie den receive.denyDeleteCurrentKonfigurationswert auf warnoder ignoreim Remote- Repository festlegen. Wenn Sie andernfalls sofort einen neuen Master erstellen möchten, überspringen Sie den git push remote :masterSchritt und fahren Sie --forcemit dem git push remote masterSchritt fort. Beachten Sie, dass Sie den Hauptzweig nicht vollständig löschen können, wenn Sie die Konfiguration der Fernbedienung nicht ändern können!

Diese Einschränkung gilt nur für den aktuellen Zweig (normalerweise den masterZweig). Jeder andere Zweig kann wie oben gelöscht und neu erstellt werden.

bdonlan
quelle
2
Zweige sind nur ein (Name, Hash) Paar - nicht mehr und nicht weniger. Es gibt das Reflog für Zweige, das jedoch niemals Remoteclients ausgesetzt ist.
Bdonlan
122
Ich würde Master-Old auf Remote erstellen, bevor Master auf Remote gelöscht wird. Ich bin nur paranoid.
Adam Dymitruk
6
Die Antwort von Aristoteles unten ermöglicht es Ihnen, dies zu tun, ohne den Master zu löschen, daher würde ich das für vorzuziehen halten.
Clay Bridges
13
Es wäre klar und SICHER, wenn Sie new-branch-nameund old-branch-nameanstelle von master/ verwenden könnten master-old, daher ist dies ein allgemeines Problem.
Jaider
2
Wenn der gelöschte Zweig (hier: master) nicht von anderen Zweigen referenziert wird, sammelt git möglicherweise alle Commits für diesen ... nun ... "Zweig". - Einige Git-Porzellan-Befehle lösen eine Speicherbereinigung aus. - Deshalb: Erstellen Sie zuerst den neuen Namen (zeigen Sie auf dasselbe Commit) und löschen Sie dann den alten Namen.
Robert Siemer
257

Angenommen, Sie befinden sich derzeit auf master:

git push origin master:master-old        # 1
git branch master-old origin/master-old  # 2
git reset --hard $new_master_commit      # 3
git push -f origin                       # 4
  1. Erstellen Sie zunächst eine master-oldVerzweigung im originRepository, basierend auf dem masterCommit im lokalen Repository.
  2. Erstellen Sie einen neuen lokalen Zweig für diesen neuen origin/master-oldZweig (der automatisch ordnungsgemäß als Tracking-Zweig eingerichtet wird).
  3. masterZeigen Sie nun mit Ihrem lokalen Standort auf das Commit, auf das es verweisen soll.
  4. Erzwingen Sie schließlich eine Änderung masterim originRepository, um Ihre neue lokale Position widerzuspiegeln master.

(Wenn Sie dies auf eine andere Weise tun, benötigen Sie mindestens einen weiteren Schritt, um sicherzustellen, dass master-olddie Nachverfolgung ordnungsgemäß eingerichtet ist origin/master-old. Keine der anderen zum Zeitpunkt dieses Schreibens veröffentlichten Lösungen enthält dies.)

Aristoteles Pagaltzis
quelle
11
Dies ist eine bessere Antwort als "die Antwort", stimme ich zu, aber für Leute, die hierher gekommen sind, um nur einen Zweig umzubenennen (nicht explizit Master), macht der dritte Schritt nicht viel Sinn.
Knocte
Es macht absolut keinen Unterschied für die Antwort, ob Sie sich in einem masteroder einem anderen Zweig befinden. Die Frage hatte jedoch einen schlechten Titel und fragt nach einer Aufgabe, die komplexer ist als nur das Umbenennen eines Zweigs.
Aristoteles Pagaltzis
3
Dies stellte sich als die Lösung heraus, die für mich funktionierte. Ich habe versucht, den Master durch einen anderen Zweig zu ersetzen. Ich habe ein Git-Protokoll -1 origin / what_i_want_as_new_master erstellt, um den $ new_master_commit für Schritt 3 zu erhalten. Nach dem Push (Schritt 4) haben andere Entwickler Nachrichten abgerufen und erhalten, dass "Ihr Zweig 295 Commits vor dem Master liegt". Um dies zu beheben, habe ich eine E-Mail verschickt, in der sie über jeden Lauf informiert wurden: git pull; git checkout some_random_branch; Git Branch -D Master; Git Pull; Git Checkout Master; Grundsätzlich müssen sie ihren lokalen Master entfernen und die neue Version ziehen, sonst sind sie lokal am falschen Ort.
Nairbv
Sie hätten das viel einfacher tun können: Angenommen, sie sind bereits eingeschaltet, masterdann könnten sie einfach tun git fetch && git reset --hard origin/master, um ihre lokale Position so zu erzwingen master, dass sie mit der eingeschaltet ist origin. Ich habe dies sowie den komplexeren Fall, in dem Sie zusätzlich lokale Commits haben master, die Sie behalten möchten, in stackoverflow.com/q/4084868
Aristoteles Pagaltzis
Stellen Sie sicher, dass die Remote-Konfigurationsdatei "leugnenNonFastforwards = false" enthält. Andernfalls wird "remote: Fehler: Verweigern von Refs / Heads / Master mit nicht schnellem Vorlauf (Sie sollten zuerst ziehen)"
angezeigt
160

Mit Git v1.7 hat sich das meiner Meinung nach leicht geändert. Das Aktualisieren des Tracking-Verweises Ihrer lokalen Niederlassung auf die neue Fernbedienung ist jetzt sehr einfach.

git branch -m old_branch new_branch         # Rename branch locally    
git push origin :old_branch                 # Delete the old branch    
git push --set-upstream origin new_branch   # Push the new branch, set local branch to track the new remote
Excalibur
quelle
10
Eine Alternative zu --set-upstreamist wie folgt: Sobald Sie Ihren Zweig lokal umbenannt und am Ursprung gelöscht haben, tun Sie einfach: git push -u --all
lucifurious
4
Dies funktioniert nicht mit dem Master-Zweig, da Sie mit git den Remote-Master nicht löschen können.
Alexandre Neto
4
@AlexandreNeto In diesem Fall können Sie die 3. Zeile vor der 2. ausführen, den Standardzweig auf setzen new_branchund schließlich die Fernbedienung mastermit der 2. Zeile löschen .
Tristan Jahier
3
Erstaunlich einfache Schritte. Dies ist die beste Antwort auf die Frage
Siddhusingh
13
Das Löschen des Remote-Zweigs git push origin --delete old_branchist etwas besser lesbar.
ThomasW
35
git checkout -b new-branch-name
git push remote-name new-branch-name :old-branch-name

Möglicherweise müssen Sie new-branch-namevor dem Löschen manuell zu wechselnold-branch-name

Treken
quelle
Löscht irgendein Teil dieser Lösung den lokalen alten Zweignamen oder ist das eine serparate Übung?
GreenAsJade
4
Ich denke am Ende muss ausgeführt werden, git branch -d old-branch-nameum den lokalen alten Zweig zu löschen.
Nabi KAZ
Sie können Änderungen mit nur einem Befehl übertragen : git push remote-name new-branch-name :old-branch-name.
Sigod
Auf diese Weise werden Sie die Git-Geschichte nicht komplizieren? Weil Sie stattdessen einen neuen Zweig eröffnen und nur den aktuellen umbenennen.
Androidevil
1
@androider Nr. Zweige in Git ist eine einfache Referenz .
Sigod
29

Es gibt viele Möglichkeiten, die Niederlassung umzubenennen, aber ich werde mich auf das größere Problem konzentrieren: "Wie können Kunden einen schnellen Vorlauf durchführen und müssen sich nicht lokal mit ihren Niederlassungen herumschlagen?" .

Zuerst ein kurzes Bild: Umbenennen des Hauptzweigs und Ermöglichen des schnellen Vorlaufs von Clients

Das ist eigentlich ganz einfach; aber missbrauche es nicht. Die ganze Idee hängt von Zusammenführungsverpflichtungen ab. da sie einen schnellen Vorlauf ermöglichen und die Historien eines Zweigs mit einem anderen verknüpfen.

Umbenennen des Zweigs:

# rename the branch "master" to "master-old"
# this works even if you are on branch "master"
git branch -m master master-old

Erstellen des neuen "Master" -Zweigs:

# create master from new starting point
git branch master <new-master-start-point>

Erstellen eines Zusammenführungs-Commits für einen Eltern-Kind-Verlauf:

# now we've got to fix the new branch...
git checkout master

# ... by doing a merge commit that obsoletes
# "master-old" hence the "ours" strategy.
git merge -s ours master-old

und voila.

git push origin master

Dies funktioniert, da durch das Erstellen eines mergeCommits der Zweig schnell zu einer neuen Revision weitergeleitet werden kann.

Verwenden einer sinnvollen Merge-Commit-Nachricht:

renamed branch "master" to "master-old" and use commit ba2f9cc as new "master"
-- this is done by doing a merge commit with "ours" strategy which obsoletes
   the branch.

these are the steps I did:

git branch -m master master-old
git branch master ba2f9cc
git checkout master
git merge -s ours master-old
dnozay
quelle
3
Vielen Dank! git merge -s ours master-oldist das entscheidende Stück, das die anderen Antworten vermissen. Auch "leicht zu machen" bedeutet nicht "leicht zu verstehen oder herauszufinden", was bei viel Git der Fall zu sein scheint, aber ich schweife ab.
Martin Vidner
3
Ich liebe die Tatsache, dass keine Löschungen erwähnt werden und dass der Übergang für diejenigen, die mit Klonen von Upstream arbeiten, "nahtlos" ist. Vielen Dank!
Piotrek
12

Ich gehe davon aus, dass Sie immer noch nach der gleichen Situation wie in Ihrer vorherigen Frage fragen . Das heißt, Master-New enthält Master-Old nicht in seinem Verlauf. * ​​Wenn Sie Master-New als "Master" bezeichnen, haben Sie den Verlauf effektiv neu geschrieben. Es spielt keine Rolle, wie Sie in einen Zustand gelangen, in dem der Meister kein Nachkomme einer früheren Position des Meisters ist, sondern nur, dass er sich in diesem Zustand befindet.

Bei anderen Benutzern, die versuchen zu ziehen, während der Master nicht vorhanden ist, schlagen ihre Pulls einfach fehl (keine solche Referenz auf der Fernbedienung). Sobald sie an einem neuen Ort erneut vorhanden sind, müssen ihre Pulls versuchen, ihren Master mit dem neuen Remote-Master zusammenzuführen. als ob Sie Master-Alt und Master-Neu in Ihrem Repository zusammengeführt hätten. Angesichts dessen, was Sie hier versuchen, würde die Zusammenführung Konflikte verursachen. (Wenn sie behoben würden und das Ergebnis zurück in das Repository verschoben würde, wären Sie in einem noch schlechteren Zustand - beide Versionen des Verlaufs dort.)

Um Ihre Frage einfach zu beantworten: Sie sollten akzeptieren, dass es manchmal Fehler in Ihrer Geschichte gibt. Das ist okay Es passiert jedem. Es gibt zurückgesetzte Commits im git.git-Repository. Wichtig ist, dass jeder, dem wir die Geschichte veröffentlichen, vertrauen kann.

* Wenn dies der Fall wäre, würde dies bedeuten, einige Änderungen auf den Master zu übertragen und dann einen neuen Zweig dort zu erstellen, wo er sich früher befand. Kein Problem.

Cascabel
quelle
Ja, es ist das gleiche Problem, es war nur eine Idee, wie man es löst. Aber selbst wenn ich diese Umbenennung nicht durchführen würde, war ich interessant, ob dies möglich wäre. Ich dachte, solche Refs wie "Master" sind nur Verweise auf bestimmte Commits. Ich möchte wirklich keine Geschichte ändern. Ich dachte, ich würde den Master-Verweis nur auf einen anderen Kopf verweisen. Dies bedeutet auch, dass ich nie wieder einen Filialnamen verwenden kann, wenn ich ihn jemals zuvor verwendet habe?
Albert
In der Tat sind Zweige Verweise auf Commits. Die Sache ist, wir erwarten, dass sich der Leiter einer Niederlassung auf eine bestimmte Art und Weise entwickelt (nämlich immer schnell vorwärts). Aus der Sicht einer anderen Person entspricht das Verschieben eines Zweigs in Ihrem öffentlichen Repo dem Umschreiben des Verlaufs des Zweigs. Es zeigt nicht mehr auf ein Commit, das alles enthält, was es früher war.
Cascabel
8

Die ausgewählte Antwort ist fehlgeschlagen, als ich es versucht habe. Es wird ein Fehler ausgegeben : refusing to delete the current branch: refs/heads/master. Ich denke, ich werde posten, was für mich funktioniert:

git checkout master             # if not in master already

git branch placeholder          # create placeholder branch
git checkout placeholder        # checkout to placeholder
git push remote placeholder     # push placeholder to remote repository

git branch -d master            # remove master in local repository
git push remote :master         # remove master from remote repository.

Der Trick besteht darin, den Platzhalter direkt vor dem Verschieben in das Remote-Repository auszuchecken. Der Rest ist selbsterklärend. Das Löschen des Hauptzweigs und das Verschieben in das Remote-Repository sollten jetzt funktionieren. Auszug von hier .

Hendra Uzia
quelle
Auf git push remote: master würde dies fehlschlagen, wenn dies auf der Remote-Seite aktiviert ist. In den Fehlerprotokollzeilen wird "remote: error:" als Präfix angezeigt.
Rafalmag
2

Gut. Meine 2 Cent. Wie wäre es, wenn Sie sich am Server anmelden, in das Git-Verzeichnis wechseln und den Zweig im Bare-Repository umbenennen. Dies hat nicht alle Probleme, die mit dem erneuten Hochladen desselben Zweigs verbunden sind. Tatsächlich erkennen die 'Clients' automatisch den geänderten Namen und ändern ihre Fernreferenz. Danach (oder vorher) können Sie auch den lokalen Namen des Zweigs ändern.


quelle
8
Ich habe die Anmeldeinformationen für die Anmeldung am Github-Server vergessen. Jeder mit Anmeldeinformationen da draußen :-P
Daniel Fisher Lennybacon
1

Wie wäre es mit:

git checkout old-branch-name
git push remote-name new-branch-name
git push remote-name :old-branch-name
git branch -m new-branch-name
Hannes Tydén
quelle
Probleme mit der Filialverfolgung - Benutzer müssen ihre Filiale möglicherweise lokal reparieren?
dnozay
1

Dies ist der einfachste und am besten lesbare Weg, den ich kenne:

Lokalen Zweig mit -m 'verschieben'

git branch -m my_old_branch_name my_new_branch_name

Schieben Sie den 'verschobenen' Zweig auf die Fernbedienung und stellen Sie '-stream' mit -u ein

git push origin -u my_new_branch_name

(Wenn Sie "Upstream" einstellen, wird Ihr lokaler Zweig im Wesentlichen mit der Fernbedienung verbunden, sodass Dinge wie Abrufen, Ziehen und Drücken funktionieren.)

Löschen Sie den alten Zweig von der Fernbedienung

git push origin -D <old_name>

(Ihre lokale Niederlassung ist bereits weg, weil Sie sie im ersten Schritt "verschoben" haben.)

Chris Halcrow
quelle
1

OK , Umbenennen eines Zweigs sowohl lokal als auch auf der Fernbedienung ist ziemlich einfach! ...

Wenn Sie in der Branche sind, können Sie ganz einfach Folgendes tun:

git branch -m <branch>

oder wenn nicht, müssen Sie Folgendes tun:

git branch -m <your_old_branch> <your_new_branch>

Drücken Sie dann die Löschung wie folgt auf die Fernbedienung:

git push origin <your_old_branch>

Wenn Sie beim Pushen einen Upstream-Fehler erhalten, tun Sie einfach Folgendes:

git push --set-upstream origin <your_new_branch>

Ich erstelle auch das Bild unten, um die Schritte in der realen Befehlszeile zu zeigen. Befolgen Sie einfach die Schritte und Sie wären gut:

Geben Sie hier die Bildbeschreibung ein

Alireza
quelle
0

Sie können Folgendes tun:

git -m master master-old #rename current master
git checkout -b master   #create a new branch master
git push -f origin master #force push to master

Force Push ist jedoch eine schlechte Idee, wenn andere Personen dieses Repository gemeinsam nutzen. Force Push führt dazu, dass ihre Revisionshistorie mit der neuen in Konflikt steht.

Riyafa Abdul Hameed
quelle
0

Folgendes kann im Shell-Skript gespeichert werden, um die Aufgabe auszuführen:

Zum Beispiel:

remote="origin"

if [ "$#" -eq 0 ] # if there are no arguments, just quit
then
    echo "Usage: $0 oldName newName or $0 newName" >&2
    exit 1
elif
    [ "$#" -eq 1 ] # if only one argument is given, rename current branch
then 
    oldBranchName="$(git branch | grep \* | cut -d ' ' -f2)" #save current branch name
    newBranchName=$1
else
    oldBranchName=$1
    newBranchName=$2
fi

git branch -m $oldBranchName $newBranchName

git push $remote :$oldBranchName #delete old branch on remote
git push --set-upstream $remote $newBranchName # add new branch name on remote and track it

Bitte beachten Sie, dass hier der Standard-Remote-Name "Ursprung" fest codiert ist. Sie können das Skript erweitern, um es zu konfigurieren!

Dann kann dieses Skript mit Bash-Aliasen, Git-Aliasen oder beispielsweise in benutzerdefinierten Quellenbaumaktionen verwendet werden.

Neu machen
quelle
-1

Ich glaube, der Schlüssel ist die Erkenntnis, dass Sie eine doppelte Umbenennung durchführen: masterzu master-oldund auch master-newzumaster .

Aus all den anderen Antworten habe ich Folgendes zusammengefasst:

doublerename master-new master master-old

wo wir zuerst die doublerenameBash-Funktion definieren müssen:

# doublerename NEW CURRENT OLD
#   - arguments are branch names
#   - see COMMIT_MESSAGE below
#   - the result is pushed to origin, with upstream tracking info updated
doublerename() {
  local NEW=$1
  local CUR=$2
  local OLD=$3
  local COMMIT_MESSAGE="Double rename: $NEW -> $CUR -> $OLD.

This commit replaces the contents of '$CUR' with the contents of '$NEW'.
The old contents of '$CUR' now lives in '$OLD'.
The name '$NEW' will be deleted.

This way the public history of '$CUR' is not rewritten and clients do not have
to perform a Rebase Recovery.
"

  git branch --move $CUR $OLD
  git branch --move $NEW $CUR

  git checkout $CUR
  git merge -s ours $OLD -m $COMMIT_MESSAGE

  git push --set-upstream --atomic origin $OLD $CUR :$NEW
}

Dies ähnelt einer Änderung der Historie git rebase, da der Zweiginhalt sehr unterschiedlich ist, unterscheidet sich jedoch darin, dass die Clients dennoch sicher schnell vorspulen können git pull master.

Martin Vidner
quelle
-5
git update-ref newref oldref
git update-ref -d oldref newref
Dlamotte
quelle
2
Dies scheint nicht für mich zu funktionieren, ich bekomme: Git Update-Ref Trunk Trunk2 fatal: Trunk2: kein gültiger SHA1
Gregg Lind