Umbenennen von Zweigen aus der Ferne in Git

407

Wenn es ein Repository gibt, auf das ich nur git://Zugriff habe (und das normalerweise nur Push + Pull ist), gibt es eine Möglichkeit, Zweige in diesem Repository auf die gleiche Weise umzubenennen, wie ich es lokal tun würde git branch -m?

kdt
quelle
48
In der verknüpften Frage "Duplizieren" wird gefragt, ob ein Zweig "lokal und remote" umbenannt werden soll. Bei dieser Frage wird jedoch nur gefragt, wie Zweige remote umbenannt werden sollen, was eine Vereinfachung ermöglicht. Dies ist, was ich tue, um einen Zweig auf dem Server umzubenennen, ohne einen lokalen Zweig auschecken und / oder erstellen zu müssen : git push origin origin/old_name:refs/heads/new_name && git push origin :old_name.
sschuberth
1
@sschuberth: Sie können beide Befehle auf einmal geben. Und das sollte wirklich die Antwort auf diese Frage sein.
Joachim Breitner
2
@ JoachimBreitner Du hast recht, ich habe diese Optimierung bereits in meinem Skript durchgeführt .
Sschuberth
1
@sschuberth, du solltest deinen Kommentar als Antwort posten, da er mir besser gefällt als die anderen unten.
Phatmann
Fertig .
sschuberth

Antworten:

480

Sie müssen nur einen neuen lokalen Zweig mit dem gewünschten Namen erstellen, ihn auf Ihre Fernbedienung übertragen und dann den alten Fernzweig löschen:

$ git branch new-branch-name origin/old-branch-name
$ git push origin --set-upstream new-branch-name
$ git push origin :old-branch-name

Um den alten Zweigstellennamen zu sehen, müsste jeder Client des Repositorys Folgendes tun:

$ git fetch origin
$ git remote prune origin

HINWEIS: Wenn Ihr alter Zweig Ihr Hauptzweig ist, sollten Sie Ihre Einstellungen für den Hauptzweig ändern. Andernfalls wird beim Ausführen $ git push origin :old-branch-namedie Fehlermeldung "Löschen des aktuellen Zweigs verboten" angezeigt .

Sylvain Defresne
quelle
8
Nun, wenn der alte und der neue Name gleich sind, bedeutet dies, dass Sie den Zweig nicht umbenennen müssen, sodass es keinen Sinn macht, den Befehl überhaupt
auszuführen ;-)
9
Sicher. Ich meine nur, wenn Sie dies auf automatisierte Weise aufrufen (als Funktionsteil eines anderen Skripts), können Sie es genauso gut nicht falsch machen lassen, wenn Sie es vermeiden können.
Geheimnisvoller Dan
9
Dans Weg: Ordne die Befehle neu an, damit sie immer nur funktionieren. Der Weg der Erdmaschine: Denken Sie immer daran, dies zu überprüfen, sonst verlieren Sie Daten. Ich weiß, welches ich auswählen würde.
Doradus
2
Die Benutzer können einfach Folgendes ausführen: git fetch origin --prune(um die neuen Zweige effektiv abzurufen und auch die Referenzen zu entfernen, die nicht mehr auf der Fernbedienung vorhanden sind).
DolphinDream
2
Kann -doder --deleteanstelle von :in neueren Versionen von Git verwenden.
Zitrax
285

Wenn Sie Zweige wirklich nur remote umbenennen möchten, ohne gleichzeitig lokale Zweige umzubenennen , können Sie dies mit einem einzigen Befehl tun:

git push <remote> <remote>/<old_name>:refs/heads/<new_name> :<old_name>

Ich habe dieses Skript ( git-rename-remote-branch ) geschrieben, das eine praktische Verknüpfung bietet, um die oben genannten Aufgaben einfach auszuführen.

Als Bash-Funktion:

git-rename-remote-branch(){
  if [ $# -ne 3 ]; then
    echo "Rationale : Rename a branch on the server without checking it out."
    echo "Usage     : $(basename $0) <remote> <old name> <new name>"
    echo "Example   : $(basename $0) origin master release"
    exit 1 
  fi

  git push $1 $1/$2:refs/heads/$3 :$2
}

So integrieren Sie den Kommentar von @ ksrb : Grundsätzlich werden zwei Pushs in einem einzigen Befehl ausgeführt, um zuerst git push <remote> <remote>/<old_name>:refs/heads/<new_name>einen neuen Remote-Zweig basierend auf dem alten Remote-Tracking-Zweig zu pushen und dann git push <remote> :<old_name>den alten Remote-Zweig zu löschen.

sschuberth
quelle
10
Für diejenigen, die einen Alias ​​dieses Befehls wünschen: rename = "! F () {git push origin origin / $ 1: refs / Heads / $ 2: $ 1;}; f" kann dies als> git rename <old_name> <verwendet werden neuer_name>
Jonathan Schmidt
33
Für diejenigen, die neugierig sind, was dieser Befehl tatsächlich bedeutet, bedeutet es im Wesentlichen, dass 2 Pushs git push <remote>/<old_name>:refs/heads/<new_name>eine neue Fernbedienung drücken, die die alte Fernbedienung als src verwendet, und dann git push [space]:<old_name> die alte Fernbedienung löschen
ksrb
3
Warum müssen Sie verwenden refs/heads/name? Können Sie nicht einfach namedirekt den ersten Befehl ausführen git push <remote> <remote>/<old_name>:<new_name>?
Drew Noakes
6
Nein, da der Remote-Zweig <new_name>noch nicht vorhanden ist. Wenn der Zweig nicht vorhanden ist, müssen Sie bei Git den vollständigen Namen verwenden, da er sich sonst <new_name>auch auf einen Tag-Namen beziehen könnte.
Sschuberth
3
Wir verwenden diesen Ansatz in unserem Build-System. Die einzige Einschränkung, auf die wir stoßen, ist, wenn sie refs/heads/<new_name> bereits vorhanden ist. Das Löschen ist weiterhin erfolgreich und wird <remote>/<old_name>nur gelöscht. Einige Überprüfungen vor der Hand können dies leicht vermeiden.
Apeiron
172

Erste Kasse zu dem Zweig, den Sie umbenennen möchten:

git branch -m old_branch new_branch
git push -u origin new_branch

So entfernen Sie einen alten Zweig aus remote:

git push origin :old_branch
Shashank Hegde
quelle
12
Wenn Sie den umbenannten Zweig (new_branch) auf remote (origin) verschieben, sollten Sie auch den Upstream so einstellen, dass der Zweig mit dem neuen Namen verfolgt wird (z. B. git push -u origin new_branch). Andernfalls verfolgt der umbenannte Zweig (new_branch) weiterhin den Ursprung / old_branch. Und sobald Sie die entfernte alte_Zweige löschen, verfolgt die neue_Zweig weiterhin den Ursprung / die alte_Zweigstelle, obwohl dieser Zweig jetzt weg ist.
DolphinDream
@DolphinDream Ich habe die Antwort so bearbeitet, dass sie Ihre nützliche vorgelagerte Änderung enthält.
MVChr
10

Sicher. Benennen Sie den Zweig einfach lokal um, verschieben Sie den neuen Zweig und löschen Sie den alten.

Das einzige wirkliche Problem ist, dass andere Benutzer des Repositorys keine lokalen Tracking-Zweige umbenennen.

Lily Ballard
quelle
1
Wenn ich also versuche, den Master zu löschen, habe ich versucht, $ git zu klonen refspec stimmt weder mit einer vorhandenen Referenz auf der Fernbedienung überein, noch beginnt sie mit refs /, und wir können kein Präfix basierend auf der Quellreferenz erraten. Fehler: Fehler beim Verschieben einiger Refs auf '../alpha/' Die Fernbedienung hat wirklich einen Zweig namens master
kdt
2

TL; DR

Das "Umbenennen" eines Remote-Zweigs ist eigentlich ein zweistufiger Prozess (nicht unbedingt bestellt):

  • Löschen des alten Remote-Zweigs ( git push [space]:<old_name>wie ksrb erklärt );
  • Push in einen neuen Remote-Zweig (Unterschied zwischen einigen Antwortbefehlen unten).

Löschen

Ich benutze TortoiseGit und als ich zum ersten Mal versuchte, den Zweig über die Befehlszeile zu löschen, bekam ich Folgendes:

$ git push origin :in
  • fatal: 'origin' scheint kein Git-Repository zu sein

  • fatal: Konnte nicht aus dem Remote-Repository lesen.

Stellen Sie sicher, dass Sie über die richtigen Zugriffsrechte verfügen und das Repository vorhanden ist.

Dies war wahrscheinlich darauf zurückzuführen, dass bei einem Festzug der private Schlüssel nicht geladen war (den TortoiseGit automatisch in den Festzug lädt ). Außerdem ist mir aufgefallen, dass TortoiseGit- Befehle nicht den originRef enthalten (z git.exe push --progress "my_project" interesting_local:interesting. B. ).

Ich verwende auch Bitbucket und konnte als andere webbasierte Online-Git-Manager dieser Art (GitHub, GitLab) den Remote-Zweig direkt über die Benutzeroberfläche (Zweig-Seite) löschen:

Zweig Bitbucket löschen

In TortoiseGit können Sie jedoch auch entfernte Zweige über Verweise durchsuchen löschen :

Menü Referenzen durchsuchen

Mit einem Rechtsklick auf einer entfernten Zweig (Fernbedienungen Liste) die Delete Remotezweig Option zeigt nach oben:

TortoiseGit Remote-Zweig löschen

Schieben

Nach dem Löschen des alten Remote-Zweigs habe ich über TortoiseGit direkt in einen neuen Remote-Zweig verschoben, indem ich den neuen Namen in das Feld Remote: des Push- Fensters eingegeben habe . Dieser Zweig wurde automatisch erstellt und in Bitbucket angezeigt .

Wenn Sie es dennoch lieber manuell machen möchten, ist ein Punkt, der in diesem Thread noch nicht erwähnt wurde, -u= --set-upstream.

Von git pushdocs , -uist nur ein Alias --set-upstream, so dass die Befehle in den Antworten von Sylvain ( -set-upstream new-branch) und Shashank ( -u origin new_branch) äquivalent sind, da die Remote - ref standardmäßigorigin , wenn keine andere ref vorher definiert wurden:

  • git push origin -u new_branch= git push -u new_branch aus der Dokumentbeschreibung :

    Wenn die Konfiguration fehlt, wird standardmäßig verwendet origin.

Am Ende habe ich keinen der Befehle, die in den anderen Antworten hier vorgeschlagen wurden, manuell eingegeben oder verwendet, sodass dies in einer ähnlichen Situation möglicherweise für andere nützlich sein könnte.

CPHPython
quelle
Das Problem ist, dass Ihre Fernbedienung nicht aufgerufen wird origin. Sie müssen Ihre Fernbedienung benennen, wenn Sie den Befehl ausführen git remote. Git arbeitet mit dem, sshwas impliziert, dass Sie öffentliche + private Schlüssel verwenden. Ich Autoload Putty keysgehe davon aus, dass TortoiseGit nur die erforderlichen Schlüssel automatisch lädt, damit Sie mit Ihrer Fernreferenz überhaupt etwas tun können. Das Letzte ist, dass git push -ues sich nicht um einen Alias ​​zum Verschieben in einen Remote-Zweig handelt, sondern um einen Alias ​​zum Verschieben in einen Remote-Zweig , der lokal erstellt wurde und dessen Remote-Referenz diesen Zweig noch nicht hat .
Juanecabellob
1
@juancab -uist ein Alias ​​von --set-upstreamund "Wenn die Konfiguration fehlt, wird standardmäßigorigin " verwendet. Sylvain und Shashank verwenden dies, um in einen neu erstellten Remote-Zweig zu gelangen . Der Schlüssel Problem möglicherweise aufgrund gewesen Festzug nicht mit dem Laden , als ich versuchte , git push origin :inauf der Schale. Damit ich Ihre Ablehnung nicht verstehe, habe ich in anderen Antworten nur auf meine und nicht angesprochenen Details hingewiesen, sie erklärt und gelöst.
CPHPython
Sie geben falsche Dinge an und ein Großteil dieser Antwort hat nichts mit der Frage selbst zu tun. Wenn Sie darauf hinweisen, was für Sie funktioniert hat, empfehle ich Ihnen, die Antwort auf das zu beschränken, was funktioniert hat. Wenn Sie wirklich eine Erklärung geben möchten, informieren Sie sich bitte besser. Übrigens: -uist ein Alias ​​für, --set-upstreamaber das ist kein Alias ​​für das Verschieben in einen Remote-Zweig, wie Sie sagten. Um in einen Remote-Zweig zu pushen, den Sie eindeutig benötigen git push <remote>, und wenn er sich noch nicht in der Remote befindet, fügen Sie hinzu git push -u <remote>. Wird -udaher verwendet, um eine Referenz des Zweigs in der Fernbedienung zu erstellen.
Juanecabellob
1
@juancab Vielleicht war das, was Sie für falsch hielten, hauptsächlich die Alias- Formulierung oder die Wortwahl. Ich habe meine Antwort umstrukturiert und neu formuliert, um eine vollständige Erklärung der Lösung (en) zu erhalten, die ich gefunden habe, um einen Remote-Zweig umzubenennen .
CPHPython
Ich würde es weiter umformulieren. Es macht jetzt mehr Sinn, aber es ist immer noch zu lang. Ich würde spezifischer auf das Problem eingehen, dh angeben, dass für TortoiseGit-Benutzer die vorgeschlagenen Lösungen nicht funktionieren. Sie erzählen eine Geschichte und das ist verwirrend und lässt Benutzer das Lesen vermeiden. Ich werde Ihre Antwort mit einem Vorschlag bearbeiten.
Juanecabellob
1

Ich weiß nicht warum, aber die Antwort von @Sylvain Defresne funktioniert bei mir nicht.

git branch new-branch-name origin/old-branch-name
git push origin --set-upstream new-branch-name
git push origin :old-branch-name

Ich muss den Upstream deaktivieren und dann kann ich den Stream wieder einstellen. Das Folgende ist, wie ich es gemacht habe.

git checkout -b new-branch-name
git branch --unset-upstream
git push origin new-branch-name -u
git branch origin :old-branch-name
Arthur Bryant
quelle
0

Ich weiß nicht, ob dies richtig oder falsch ist, aber ich habe den "alten Namen" des Zweigs in den "neuen Namen" des Zweigs verschoben und dann den alten Zweig vollständig mit den folgenden zwei Zeilen gelöscht:

git push origin old_branch:new_branch
git push origin :old_branch
EpicPandaForce
quelle
Soweit ich das beurteilen kann, ist dies genau das, was alle anderen Antworten tun. Ihre Antwort ist nur prägnanter.
Klarer
-1

Sie können einen neuen Zweig basierend auf einem Zweig mit altem Namen erstellen. Einfach so, dann lösche den alten Zweig, vorbei !!!Geben Sie hier die Bildbeschreibung ein

Pober Wong
quelle
Das ist GitHub, nicht Git. ;)
Bouncner
-4

Zusätzlich zu den bereits gegebenen Antworten finden Sie hier eine Version, die zunächst prüft, ob der neue Zweig bereits vorhanden ist (damit Sie ihn sicher in einem Skript verwenden können).

if git ls-remote --heads "$remote" \
    | cut -f2 \
    | sed 's:refs/heads/::' \
    | grep -q ^"$newname"$; then
    echo "Error: $newname already exists"
    exit 1
fi
git push "$oldname" "$remote/$oldname:refs/heads/$newname" ":$oldname"

(Der Scheck stammt aus dieser Antwort )

myzzzl
quelle
Ich hätte git show-ref --quiet --verify -- refs/heads/$new_namestatt verwendet ls-remote | cut | sed | grep.
Andy