Zmień nazwę gałęzi głównej dla lokalnych i zdalnych repozytoriów Git


820

Mam gałąź, masterktóra śledzi gałąź zdalną origin/master.

Chcę zmienić ich nazwę na master-oldlokalną i zdalną. czy to możliwe?

W przypadku innych użytkowników, którzy śledzili origin/master(i którzy zawsze aktualizowali swój masteroddział lokalny za pośrednictwem git pull), co stałoby się po zmianie nazwy oddziału zdalnego?
Czy git pullnadal będą działać, czy wygeneruje błąd, którego nie będzie w stanie znaleźć origin/master?

Następnie chcę utworzyć nowy masteroddział (lokalnie i zdalnie). Ponownie, po zrobieniu tego, co stałoby się teraz, gdyby zrobili to inni użytkownicy git pull?

Myślę, że to wszystko spowodowałoby wiele problemów. Czy istnieje czysty sposób na uzyskanie tego, czego chcę? A może powinienem po prostu odejść bez masterzmian, utworzyć nowy oddział master-newi popracować nad tym?


2
Przepis podany w zaakceptowanej odpowiedzi dotyczy gałęzi o dowolnej nazwie, ale zastrzeżenia (jak wspomniano) nie mają zastosowania, ze względu na (domyślnie) specjalną rolę gałęzi master w Git.
kynan

3
@kynan: Myślę, że nie rozumiem. Jakie zastrzeżenia dotyczą mistrza i nie dotyczą innych gałęzi? Jeśli byłaby to gałąź o nazwie xy, a inni ludzie śledziliby tę gałąź, jak by to było inaczej?
Albert

4
Zastrzeżenie, że normalnie nie można usunąć zdalnego urządzenia nadrzędnego. Nie dotyczy to jednak odpowiedzi Arystotelesa, więc możesz zaznaczyć to jako odpowiedź zaakceptowaną. Masz rację, każda git push -fwpływa na zdolność pulldowolnego oddziału zdalnego śledzenia.
kynan

możesz utworzyć nową gałąź, master-oldktóra wskazuje na to samo zatwierdzenie, co poprzednia mastergałąź. Następnie można zastąpić masteroddział z nowymi zmianami wykonując mergeze oursstrategią. Wykonanie scalenia działa, gdy pilot nie zezwala na zmiany inne niż szybkie. Oznacza to również, że inni użytkownicy nie będą wymuszać aktualizacji.
dnozay

1
@kynan masterjest wyjątkowy, o ile jest to jedyna istniejąca gałąź. Gdy masz więcej niż jeden, wszystkie gałęzie są na równi.
jub0bs

Odpowiedzi:


614

Najbliższą rzeczą do zmiany nazwy jest usunięcie, a następnie ponowne utworzenie na pilocie. Na przykład:

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

Ma to jednak wiele zastrzeżeń. Po pierwsze, żadne istniejące kasy nie będą wiedziały o zmianie nazwy - git nie próbuje śledzić nazw gałęzi. Jeśli nowy masterjeszcze nie istnieje, git pull spowoduje błąd. Jeśli nowy masterzostał utworzony. pull spróbuje połączyć masteri master-old. Jest to więc ogólnie zły pomysł, chyba że współpracujesz z każdym, kto wcześniej sprawdził repozytorium.

Uwaga: nowsze wersje git domyślnie nie pozwalają na zdalne usunięcie gałęzi master. Możesz to zmienić, ustawiając receive.denyDeleteCurrentwartość konfiguracji na warnlub ignorew zdalnym repozytorium. W przeciwnym razie, jeśli jesteś gotowy, aby od razu utworzyć nowego mistrza, pomiń git push remote :masterkrok i przejdź --forcedo git push remote masterkroku. Pamiętaj, że jeśli nie możesz zmienić konfiguracji pilota, nie będziesz w stanie całkowicie usunąć gałęzi master!

To zastrzeżenie dotyczy tylko bieżącej gałęzi (zazwyczaj mastergałęzi); każdy inny oddział można usunąć i odtworzyć jak wyżej.


2
gałęzie to tylko para (nazwa, skrót) - nic więcej, nic mniej. Na gałęziach znajduje się dziennik logowania, ale nigdy nie jest on narażony na zdalnych klientów.
bdonlan,

122
Chciałbym utworzyć master-old na zdalnym przed usunięciem master na zdalnym. Jestem tylko paranoikiem.
Adam Dymitruk,

6
Odpowiedź Arystotelesa poniżej pozwala ci to zrobić bez usuwania mistrza, więc uważam, że lepiej.
Clay Bridges

13
byłoby jasne i BEZPIECZNE, jeśli możesz używać new-branch-namei old-branch-namezamiast master/ master-old, więc jest to ogólny problem.
Jaider

2
Jeśli do usuniętej gałęzi (tutaj: master) nie odwołują się inne gałęzie, git może odrzucić wszystkie zatwierdzenia na tej ... cóż ... „gałęzi”. - Niektóre polecenia git z porcelany powodują zbieranie śmieci. - Dlatego: najpierw stwórz nową nazwę (wskazując na to samo zatwierdzenie), a następnie usuń starą nazwę.
Robert Siemer

257

Zakładając, że aktualnie jesteś na 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. Najpierw utwórz master-oldgałąź w originrepozytorium, na podstawie masterzatwierdzenia w lokalnym repozytorium.
  2. Utwórz nowy oddział lokalny dla tego nowego origin/master-oldoddziału (który zostanie automatycznie skonfigurowany poprawnie jako oddział śledzenia).
  3. Teraz wskaż lokalnemu masterto, co chcesz zatwierdzić.
  4. Na koniec wymuś zmianę masterw originrepozytorium, aby odzwierciedlić nowy lokalny master.

(Jeśli zrobisz to w jakikolwiek inny sposób, potrzebujesz co najmniej jednego kroku, aby upewnić się, że master-oldjest odpowiednio skonfigurowany do śledzenia origin/master-old. Żadne z innych rozwiązań opublikowanych w momencie pisania tego tekstu nie obejmuje tego.)


11
To lepsza odpowiedź niż „odpowiedź”, zgadzam się, ale dla ludzi, którzy przybyli tutaj, aby zmienić nazwę gałęzi (nie wprost mistrza), trzeci krok nie ma większego sensu.
knocte

Nie ma absolutnie żadnej różnicy w odpowiedzi na pytanie, czy jesteś w masterinnym oddziale. Pytanie zostało źle zatytułowanych choć prosi o zadanie bardziej skomplikowane niż tylko zmiana nazwy oddziału.
Arystoteles Pagaltzis

3
To okazało się rozwiązaniem, które działało dla mnie. Próbowałem zastąpić master innym oddziałem. Zrobiłem dziennik git -1 origin / what_i_w_ant_as_new_master, aby uzyskać $ new_master_commit dla kroku 3. Po wypchnięciu (krok 4), inni deweloperzy wyciągali wiadomości i otrzymywali wiadomości „twoja gałąź wyprzedza master o 295 zatwierdzeń”. Aby to naprawić, wysłałem wiadomość e-mail z informacją o każdym uruchomieniu: git pull; git checkout some_random_branch; gałąź git -D master; git pull; Git Checkout Master; Zasadniczo muszą usunąć lokalnego administratora i pobrać nową wersję, w przeciwnym razie lokalnie znajdą się w niewłaściwym miejscu.
nairbv

Mógłbyś to zrobić o wiele łatwiej: zakładając, że są już włączone master, mogliby po prostu git fetch && git reset --hard origin/masterzmusić swojego lokalnego masterdo bycia takim samym jak ten origin. Udokumentowałem to, a także bardziej złożony przypadek, w którym masz lokalne zatwierdzenia master
oprócz

Upewnij się, że zdalny plik konfiguracyjny ma „denyNonFastforwards = false”, albo dostaniesz „zdalny: błąd: odmawianie ref / non-przewijania do przodu / heads / master (powinieneś najpierw pociągnąć)”
gjcamann

159

W przypadku Git v1.7 myślę, że to się nieco zmieniło. Aktualizacja referencji śledzenia lokalnego oddziału do nowego pilota jest teraz bardzo łatwa.

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

10
Alternatywa --set-upstreamjest następująca: po zmianie nazwy oddziału lokalnie i usunięciu źródła, po prostu zrób: git push -u --all
lucifurious

4
Nie będzie to działać z gałęzią master, ponieważ git nie pozwoli ci usunąć zdalnego mistrza.
Alexandre Neto

4
@AlexandreNeto W tym przypadku możesz wykonać 3. linię przed 2. linią, ustawić domyślną gałąź na, new_brancha następnie ostatecznie usunąć pilota masterza pomocą 2. linii.
Tristan Jahier

3
Niezwykle proste kroki. To najlepsza odpowiedź na pytanie
siddhusingh

13
Usunięcie zdalnej gałęzi git push origin --delete old_branchjest nieco bardziej czytelne.
ThomasW

35
git checkout -b new-branch-name
git push remote-name new-branch-name :old-branch-name

new-branch-namePrzed usunięciem może być konieczne ręczne przełączenie naold-branch-name


Czy jakakolwiek część tego rozwiązania usuwa lokalną nazwę starej gałęzi, czy też jest to ćwiczenie oddzielne?
GreenAsJade

4
Myślę, że na końcu należy uruchomić, git branch -d old-branch-nameaby usunąć lokalną starą gałąź.
Nabi KAZ

Można przekazać zmian przez tylko jedno polecenie: git push remote-name new-branch-name :old-branch-name.
Sigod

W ten sposób nie komplikujesz historii gitów? Ponieważ otwierasz nowy oddział, po prostu zmieniając nazwę bieżącego.
androidevil

1
@ androider Nie. Oddziały w git to proste odniesienia .
sigod

29

Istnieje wiele sposobów zmiany nazwy oddziału, ale zamierzam skupić się na większym problemie: „jak pozwolić klientom na szybkie przewijanie do przodu i nie musieć lokalnie zadzierać z oddziałami” .

Najpierw szybki obrazek: zmiana nazwy gałęzi głównej i umożliwienie klientom szybkiego przewijania do przodu

To jest naprawdę łatwe do zrobienia; ale nie nadużywaj tego. Cały pomysł opiera się na zobowiązaniach do scalania; ponieważ umożliwiają szybkie przewijanie do przodu i łączą historie gałęzi z inną.

zmiana nazwy oddziału:

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

utworzenie nowej gałęzi „master”:

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

utworzenie scalenia zatwierdzenia, aby mieć historię rodzic-dziecko:

# 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

i voila.

git push origin master

Działa to, ponieważ utworzenie mergezatwierdzenia umożliwia szybkie przekierowanie gałęzi do nowej wersji.

za pomocą sensownego komunikatu zatwierdzenia scalania:

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

3
Dzięki! git merge -s ours master-oldjest kluczowym elementem, którego brakuje innym odpowiedziom. Również „łatwe do zrobienia” nie oznacza „łatwe do zrozumienia lub dowiedzenia się”, co wydaje się mieć miejsce w przypadku większości gitów, ale zaczynam dygresję.
Martin Vidner

3
Uwielbiam fakt, że nie wspomniano o żadnych usunięciach i że przejście dla osób pracujących z klonami upstream jest „bezproblemowe”. Dziękuję Ci!
Piotrek

12

Zakładam, że wciąż pytasz o tę samą sytuację, co w poprzednim pytaniu . Oznacza to, że master-new nie będzie zawierał master-old w swojej historii. * Jeśli nazwiesz master-new „master”, skutecznie przepisasz historię. Nie ma znaczenia, jak wejdziesz w stan, w którym mistrz nie jest potomkiem poprzedniej pozycji mistrza, po prostu że jest w tym stanie.

Inni użytkownicy próbujący wyciągnąć, gdy master nie istnieje, po prostu nie będą mogli wyciągnąć swoich ściągów (brak takiego odwołania na zdalnym), a gdy ponownie pojawi się w nowym miejscu, ich ściągnięcia będą musiały spróbować połączyć swojego mistrza z nowym zdalnym masterem, tak jakbyś połączył master-old i master-new w swoim repozytorium. Biorąc pod uwagę to, co próbujesz tutaj zrobić, scalenie miałoby konflikty. (Gdyby zostały rozwiązane, a wynik zostałby zepchnięty z powrotem do repozytorium, byłbyś w jeszcze gorszym stanie - obie wersje historii tam.)

Aby odpowiedzieć na twoje pytanie po prostu: powinieneś zaakceptować fakt, że czasami w twojej historii będą błędy. To jest w porządku. Zdarza się każdemu. Przywrócono zatwierdzenia w repozytorium git.git. Ważne jest to, że po opublikowaniu historii jest to coś, czemu każdy może zaufać.

* Gdyby tak było, byłoby to równoznaczne z wypchnięciem niektórych zmian na master, a następnie utworzeniem nowej gałęzi tam, gdzie kiedyś była. Nie ma problemu.


Tak, to ten sam problem, tylko jeden pomysł, jak go rozwiązać. Ale nawet gdybym nie dokonał zmiany nazwy gałęzi, interesowałbym się, czy byłoby to możliwe. Myślałem, że takie referencje jak „master” są tylko odniesieniami do konkretnych zatwierdzeń. Naprawdę nie chcę zmieniać żadnej historii. Myślałem, że po prostu wskażę wzorzec odniesienia innej głowie. Oznacza to również, że nigdy nie będę mógł użyć nazwy oddziału, jeśli kiedykolwiek go użyłem?
Albert,

Rzeczywiście, gałęzie są odniesieniami - wskaźnikami do zatwierdzeń. Chodzi o to, że oczekujemy, że szef oddziału będzie ewoluował w określony sposób (a mianowicie zawsze szybkie przewijanie do przodu). Z punktu widzenia kogoś innego przeniesienie gałęzi w publicznym repozytorium jest tym samym, co przepisanie historii oddziału. Nie wskazuje już na zatwierdzenie zawierające wszystko, co kiedyś.
Cascabel

8

Wybrana odpowiedź nie powiodło się, gdy próbowałem go. Zgłasza błąd: refusing to delete the current branch: refs/heads/master. Chyba opublikuję to, co dla mnie działa:

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.

Sztuką jest wykupienie symbolu zastępczego tuż przed wypchnięciem go do zdalnego repozytorium. Reszta jest oczywista, usunięcie gałęzi master i przekazanie jej do zdalnego repozytorium powinno już działać. Fragment stąd .


Nie powiedzie się na git push remote: master, jeśli jest zaznaczone po stronie zdalnej - zobaczysz „remote: error:” jako prefiks w wierszach dziennika błędów.
rafalmag

2

Dobrze. Moje 2 centy. Co powiesz na zalogowanie się na serwerze, przejście do katalogu git i zmianę nazwy gałęzi w czystym repozytorium. Nie ma to wszystkich problemów związanych z ponownym ładowaniem tego samego oddziału. W rzeczywistości „klienci” automatycznie rozpoznają zmodyfikowaną nazwę i zmienią swoje zdalne odwołanie. Następnie (lub wcześniej) możesz również zmodyfikować lokalną nazwę oddziału.


8
Zapomniałem danych logowania do serwera github. Każdy,
kto

1

Co powiesz na:

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

nie zgadza się ze śledzeniem gałęzi - użytkownicy mogą być zmuszeni naprawić lokalnie gałąź?
dnozay

1

To najprostszy i najbardziej „czytelny” sposób, jaki znam:

„Przenieś” oddział lokalny za pomocą -m

git branch -m my_old_branch_name my_new_branch_name

Wciśnij gałąź „przeniesiona” do pilota, ustaw „upstream” za pomocą -u

git push origin -u my_new_branch_name

(ustawienie „upstream” zasadniczo „łączy” lokalny oddział ze zdalnym, tak aby działały takie jak pobieranie, ściąganie i wypychanie)

Usuń starą gałąź ze zdalnego

git push origin -D <old_name>

(Twój lokalny oddział już nie istnieje, ponieważ „przeniosłeś” go w pierwszym kroku)


1

OK , zmiana nazwy gałęzi zarówno lokalnie, jak i zdalnie jest dość prosta! ...

Jeśli jesteś w oddziale, możesz łatwo zrobić:

git branch -m <branch>

lub jeśli nie, musisz:

git branch -m <your_old_branch> <your_new_branch>

Następnie wciśnij usuwanie do pilota w następujący sposób:

git push origin <your_old_branch>

Teraz gotowe, jeśli podczas próby wypychania wystąpi błąd wysyłania, po prostu wykonaj:

git push --set-upstream origin <your_new_branch>

Tworzę również poniższy obrazek, aby pokazać kroki w prawdziwej linii poleceń, po prostu wykonaj kroki, a będziesz dobrze:

wprowadź opis zdjęcia tutaj


0

Możesz wykonać następujące czynności:

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

Ale forsowanie jest złym pomysłem, jeśli inne osoby współużytkują to repozytorium. Force push spowoduje konflikt historii zmian z nową wersją.


0

W celu wykonania zadania można zapisać w skrypcie powłoki:

Na przykład:

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

Pamiętaj, że tutaj domyślna zdalna nazwa „origin” jest zakodowana na stałe, możesz rozszerzyć skrypt, aby był konfigurowalny!

Następnie ten skrypt może być używany z aliasami bash, aliasami git lub, na przykład, w niestandardowych akcjach sourcetree.


-1

Uważam, że kluczem jest uświadomienie sobie, że dokonujesz podwójnej zmiany nazwy: masterna master-oldi również master-newna master.

Ze wszystkich innych odpowiedzi zsyntetyzowałem to:

doublerename master-new master master-old

gdzie najpierw musimy zdefiniować funkcję doublerenameBash:

# 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
}

Jest to podobne do zmiany historii git rebase, ponieważ zawartość gałęzi jest zupełnie inna, ale różni się tym, że klienci nadal mogą bezpiecznie przewijać do przodu git pull master.


-5
git update-ref newref oldref
git update-ref -d oldref newref

2
Wydaje mi się, że to nie działa, otrzymuję: git update-ref trunk trunk2 fatal: trunk2: niepoprawny SHA1
Gregg Lind
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.