Ustaw bieżącą gałąź Git jako gałąź główną

1657

Mam repozytorium w Git. Zrobiłem gałąź, a następnie dokonałem pewnych zmian zarówno w systemie głównym, jak i w gałęzi.

Potem, kilkadziesiąt zatwierdzeń później, zdałem sobie sprawę, że gałąź jest w znacznie lepszym stanie niż master, więc chcę, aby gałąź „stała się” master i zignorowała zmiany w master.

Nie mogę tego scalić, ponieważ nie chcę zachować zmian na poziomie głównym. Co powinienem zrobić?

Dodatkowo : w tym przypadku „stary” wzorzec został już przeniesiony pushdo innego repozytorium, takiego jak GitHub. Jak to zmienia rzeczy?

Karel Bílek
źródło
2
Sprawdź odpowiedzi na bardzo podobne pytanie stackoverflow.com/q/2862590/151641
mloskot
4
Miałem ten sam problem, jednak po prostu usunąłem master i
zmieniłem
10
@jayarjo powinieneś tego unikać, jeśli to możliwe, ponieważ spowoduje to przepisanie historii i spowoduje problemy dla wszystkich innych, gdy będą próbowali pobrać master.
joelittlejohn,
3
Właśnie dlatego uwielbiam odpowiedź @Jefromi. Nie dzieje się dekonstrukcja historii archiwum.
froggythefrog

Odpowiedzi:

2134

Problem z pozostałymi dwiema odpowiedziami polega na tym, że nowy mistrz nie ma starego mistrza jako przodka, więc kiedy go popchniesz, wszyscy inni zostaną pomieszani. Oto co chcesz zrobić:

git checkout better_branch
git merge --strategy=ours master    # keep the content of this branch, but record a merge
git checkout master
git merge better_branch             # fast-forward master up to the merge

Jeśli chcesz, aby twoja historia była trochę jaśniejsza, polecam dodanie informacji do komunikatu zatwierdzenia scalania, aby wyjaśnić, co zrobiłeś. Zmień drugą linię na:

git merge --strategy=ours --no-commit master
git commit          # add information to the template merge message
Cascabel
źródło
25
Uwaga na temat „strategii” scalania gita: --strategy=oursróżni się od --strategy=recursive -Xours. Tj. „Nasza” może być strategią samą w sobie (wynik będzie aktualną gałęzią bez względu na wszystko) lub przekazana jako opcja strategii „rekurencyjnej” (wprowadzaj zmiany innych gałęzi i automatycznie preferuj zmiany bieżącej gałęzi, gdy wystąpi konflikt ).
Kelvin
5
Musiałem zrobić drugą linię git merge --strategy=ours master -m "new master", żeby to zadziałało.
incandescentman
5
@Johsm Właśnie o tym mówi pierwsze zdanie mojej odpowiedzi. Jeśli to zrobisz, nowy mistrz nie będzie miał takiej samej historii jak stary mistrz, co jest bardzo złe, jeśli chcesz pchać / ciągnąć. Musisz mieć wspólne pochodzenie, aby działało poprawnie; jeśli zamiast tego zrobisz to, co mówisz, to kiedy spróbujesz go popchnąć, po prostu się nie powiedzie, chyba że go zmusisz (ponieważ jest to zły i próbuje cię powstrzymać), a jeśli to zrobisz, to każdy, kto następnie pociągnie spróbuje połączyć starego mistrza i nowego mistrza, który prawdopodobnie będzie wrakiem pociągu.
Cascabel,
4
Jeśli pojawi się edytor vi podczas scalania, wpisz: w (w celu zapisania): q (w celu wyjścia z vi)
Tomas Kubes 27.10.16
9
Ta odpowiedź działa świetnie. Chciałem tylko dodać (dla osób, które mogą być nowe lub niepewne), że będziesz musiał zrobić to git pushzaraz, jeśli chcesz, aby Twój kod został przekazany zdalnie. Może pojawić się ostrzeżenie: Your branch is ahead of 'origin/master' by 50 commits.To jest oczekiwane. Po prostu go popchnij! : D
chapeljuice
387

Upewnij się, że wszystko jest wypychane do Twojego zdalnego repozytorium (GitHub):

git checkout master

Nadpisz „master” słowem „better_branch”:

git reset --hard better_branch

Wymuś wypchnięcie do zdalnego repozytorium:

git push -f origin master
Brandon Howard
źródło
81
Jest to prawdopodobnie odpowiedź, której szuka większość ludzi. Wszystkie pozostałe odpowiedzi ze scalenia strategii BS nie zastępują gałęzi całkowicie. To sprawiło, że wszystko tak, jak chciałem, po prostu zastąp gałąź i popchnij ją do góry.
Gubatron
31
chociaż tego właśnie szuka wielu, należy zauważyć, że wszelkie inne lokalne kopie repozytorium będą musiały git reset --hard origin/masternastępnym razem, gdy będą chcieli je pobrać, w przeciwnym razie git spróbuje scalić zmiany w ich (teraz) rozbieżnym lokalnym. Niebezpieczeństwa związane z tym wyjaśniono bardziej w tej odpowiedzi
7yl4r
3
należy również pamiętać, że należy zezwolić na wymuszenie wypychania do repozytorium - np. w środowisku biznesowym to nie zadziała
inetphantom
Zaletą tutaj może być również wada w zależności od tego, czego ludzie chcą. Jeśli chcesz posunąć się do zastąpienia historii mistrza historią drugiej gałęzi, oto twoja odpowiedź.
b15
75

Edycja: Nie powiedziałeś, że przeszedłeś na publiczne repozytorium! To robi różnicę.

Istnieją dwa sposoby: „brudny” i „czysty”. Załóżmy, że nazwa twojego oddziału new-master. To jest czysty sposób:

git checkout new-master
git branch -m master old-master
git branch -m new-master master
# And don't do this part.  Just don't.  But if you want to...
# git branch -d --force old-master

Spowoduje to zmianę plików konfiguracyjnych, aby pasowały do ​​gałęzi o zmienionych nazwach.

Możesz to również zrobić w brudny sposób, który nie zaktualizuje plików konfiguracyjnych. To jest coś, co dzieje się pod maską powyższego ...

mv -i .git/refs/new-master .git/refs/master
git checkout master
Dietrich Epp
źródło
2
Dziękuję Ci. Jeszcze jedno pytanie. Pcham to do github. Co się tam stanie, jeśli to zrobię?
Karel Bílek
3
@Karel: To stworzy bałagan dla innych użytkowników; będą musieli zresetować swojego mistrza do mistrza github. Jeśli chcesz uniknąć powodowania im kłopotów, spójrz na moją odpowiedź.
Cascabel
6
@Dietrick Epp: Nie jestem pewien, czy dobrym pomysłem jest nawet sugerowanie brudnej drogi. Będzie to popsuło zdalne śledzenie, ponowne rejestrowanie ... nie mogę wymyślić żadnego powodu, dla którego byś to zrobił.
Cascabel
2
Ach, to dobra uwaga. Możesz mieć to w obie strony, ale: git branch old-master master; git branch -f master new-master. Utwórz gałąź kopii zapasowej na świeżo, a następnie bezpośrednio przenieś master do new-master. (I przepraszam, że źle napisałeś swoje imię, właśnie to zauważyłem)
Cascabel
2
@FakeName Nie doszedłem do wniosku, że nie ma powodu, aby to robić, tylko że nie ma powodu, aby robić to w brudny sposób . Możesz to zrobić za pomocą normalnych poleceń (jak w moim poprzednim komentarzu) i uzyskać ten sam wynik, z wyjątkiem nienaruszonych dzienników logowania i bez szans na rozwarcie. Gwarantuje to, że zadziała, ponieważ nie zajmujesz się szczegółami implementacji.
Cascabel
46

Zmień nazwę oddziału na master:

git branch -M branch_name master
Alan Haggai Alavi
źródło
11
Niestety git nie śledzi zmian nazw gałęzi, więc jeśli już przekazałeś repozytorium do pilota, a inni mają lokalne zmiany w swojej starej lokalnej gałęzi głównej, będą mieli kłopoty.
thSoft
czy jest jakaś różnica między tym a git checkout master&&git reset --hard better_branch?
wotanii
26

Z tego, co rozumiem, możesz rozgałęzić bieżącą gałąź w istniejącą gałąź. Zasadniczo zastąpi to masterwszystko, co masz w bieżącym oddziale:

git branch -f master HEAD

Gdy to zrobisz, możesz zwykle wypchnąć masteroddział lokalny , prawdopodobnie wymagając również tutaj parametru force :

git push -f origin master

Bez scalania, bez długich poleceń. Po prostu branchi push- ale tak, to będzie przepisać historię z masterbranży, więc jeśli pracujesz w zespole masz wiedzieć, co robisz.




Alternatywnie odkryłem, że możesz wypchnąć dowolną gałąź do dowolnej gałęzi zdalnej, więc:

# This will force push the current branch to the remote master
git push -f origin HEAD:master

# Switch current branch to master
git checkout master

# Reset the local master branch to what's on the remote
git reset --hard origin/master
fregante
źródło
Bardzo prosty i działał idealnie! Dwa proste i łatwe do zrozumienia polecenia git. Moje repozytorium git zostało zapisane i wygląda teraz super czyste. Dzięki!
thehelix
16

Odpowiedzi znalazłem w poście na blogu Zamień gałąź główną na inną gałąź w git :

git checkout feature_branch
git merge -s ours --no-commit master
git commit      # Add a message regarding the replacement that you just did
git checkout master
git merge feature_branch

Jest to w zasadzie to samo co odpowiedź Cascabela . Tyle że „opcja”, którą dodał poniżej swojego rozwiązania, jest już osadzona w moim głównym bloku kodu.

Łatwiej jest znaleźć w ten sposób.

Dodaję to jako nową odpowiedź, ponieważ jeśli będę potrzebować tego rozwiązania później, chcę mieć cały kod, którego zamierzam użyć w jednym bloku kodu.

W przeciwnym razie mogę skopiować i wkleić, a następnie przeczytać szczegóły poniżej, aby zobaczyć wiersz, który powinienem zmienić - po jego wykonaniu.

SherylHohman
źródło
14

Podane tutaj rozwiązania (zmiana nazwy gałęzi na „master”) nie kładą nacisku na konsekwencje dla zdalnego repozytorium (GitHub):

    -fa
    --siła

Zwykle polecenie odmawia aktualizacji zdalnego odwołania, które nie jest przodkiem lokalnego odwołania, którego użyto do zastąpienia. Ta flaga wyłącza czek. Może to spowodować utratę zatwierdzeń przez zdalne repozytorium; używaj go ostrożnie.

Jeśli inni wyciągnęli już twoje repozytorium, nie będą w stanie wyciągnąć nowej historii master bez zastąpienia własnego master przez tę nową gałąź master GitHub (lub radzenie sobie z wieloma połączeniami).
Istnieją alternatywy dla git push - force dla publicznych repozytoriów .
Odpowiedź Jefromiego (połączenie odpowiednich zmian z powrotem do pierwotnego mistrza) jest jedną z nich.

VonC
źródło
14

Znalazłem tę prostą metodę, która działa najlepiej. Nie przepisuje historii, a wszystkie poprzednie zameldowania w oddziale zostaną dołączone do wzorca. Nic nie jest stracone i możesz wyraźnie zobaczyć, co się wydarzyło w dzienniku zatwierdzeń.

Cel: uczynienie obecnego stanu „gałęzi” „mistrzem”

Pracując w oddziale, zatwierdzaj i wypychaj zmiany, aby upewnić się, że lokalne i zdalne repozytoria są aktualne:

git checkout master      # Set local repository to master
git reset --hard branch  # Force working tree and index to branch
git push origin master    # Update remote repository

Następnie twój master będzie dokładnie w stanie twojego ostatniego zatwierdzenia oddziału, a twój główny dziennik zatwierdzeń pokaże wszystkie zameldowania w oddziale.

Mark Dietel
źródło
10

Można również pobrać wszystkie pliki z drugiej gałęzi do głównego:

git checkout master
git checkout better_branch -- .

a następnie zatwierdzić wszystkie zmiany.

użytkownik2064284
źródło
5

Aby dodać do odpowiedzi Jefromiego, jeśli nie chcesz umieszczać bezsensownego scalenia w historii sourceoddziału, możesz utworzyć tymczasową gałąź dla oursscalenia, a następnie wyrzucić:

git checkout <source>
git checkout -b temp            # temporary branch for merge
git merge -s ours <target>      # create merge commit with contents of <source>
git checkout <target>           # fast forward <target> to merge commit
git merge temp                  # ...
git branch -d temp              # throw temporary branch away

W ten sposób zatwierdzenie scalania będzie istniało tylko w historii target oddziału.

Alternatywnie, jeśli w ogóle nie chcesz tworzyć scalenia, możesz po prostu pobrać zawartość sourcei użyć ich do nowego zatwierdzenia target:

git checkout <source>                          # fill index with contents of <source>
git symbolic-ref HEAD <target>                 # tell git we're committing on <target>
git commit -m "Setting contents to <source>"   # make an ordinary commit with the contents of <source>
staafl
źródło
3

Dla mnie chciałem, aby mój diabeł wrócił do mistrza po tym, jak był przed nami.

Podczas opracowywania:

git checkout master
git pull

git checkout develop
git pull

git reset --hard origin/master
git push -f
Braden Borman
źródło
2

Mój sposób robienia rzeczy jest następujący

#Backup branch
git checkout -b master_backup
git push origin master_backup
git checkout master
#Hard Reset master branch to the last common commit
git reset --hard e8c8597
#Merge
git merge develop
ar-g
źródło
2

Jeśli używasz eGit w Eclipse :

  • Kliknij prawym przyciskiem myszy węzeł projektu.
  • Wybierz Zespół → następnie Zaawansowane → następnie Zmień nazwę gałęzi
  • Następnie rozwiń folder zdalnego śledzenia .
  • Wybierz gałąź o niewłaściwej nazwie, a następnie kliknij przycisk Zmień nazwę i zmień nazwę na dowolną nową nazwę.
  • Wybierz nowego wzorca, a następnie zmień jego nazwę na wzorca.
Junchen Liu
źródło
Zrobiłem to, ale nie jestem pewien, czy to zadziałało. Na github nic się nie zmieniło, ale na rozszerzeniach git widzę, że nazwa gałęzi została zmieniona.
Pramod
0

Poniższe kroki są wykonywane w przeglądarce Git obsługiwanej przez Atlassian (serwer Bitbucket)

Wykonanie {current-branch} jako master

  1. Zrób gałąź master i nazwij ją „master-duplicate”.
  2. Utwórz gałąź z {current-branch} i nazwij ją „{current-branch} -copy”.
  3. W ustawieniach repozytorium (Bitbucket) zmień „Default Branch” na „master-duplicate” (bez tego kroku nie będzie można usunąć master - „W następnym kroku”).
  4. Usuń gałąź „master” - zrobiłem ten krok z drzewa źródłowego (możesz to zrobić z poziomu interfejsu CLI lub przeglądarki Git)
  5. Zmień nazwę „{current-branch}” na „master” i wypchnij do repozytorium (spowoduje to utworzenie nowej gałęzi „master”, ale nadal będzie istnieć „{current-branch}”).
  6. W ustawieniach repozytorium zmień „Default Branch”, aby wskazywało „master”.
Purushothaman
źródło