Jak całkowicie zastąpić oddział lokalny oddziałem zdalnym w Git?

777

Mam dwa oddziały:

  1. oddział lokalny (ten, z którym pracuję)
  2. oddział zdalny (publiczny, tylko dobrze przetestowane commity tam)

Ostatnio poważnie popsułem mój lokalny oddział.

Jak całkowicie zastąpić oddział lokalny oddziałem zdalnym, aby móc kontynuować pracę z miejsca, w którym znajduje się teraz oddział zdalny?

Już przeszukałem SO i lokalne sprawdzenie w oddziale zdalnym nie ma żadnego efektu.

YemSalat
źródło
1
Wiem, że zaakceptowana odpowiedź ma 1280 głosów oddanych, ale naprawdę powinieneś rozważyć zmianę zaakceptowanej odpowiedzi na jedną przez @TTT.
Jamie

Odpowiedzi:

1286
  1. Upewnij się, że sprawdziłeś gałąź, którą zastępujesz (na podstawie komentarza Zoltána ).
  2. Zakładając, że master jest lokalną gałęzią, którą zastępujesz, a „origin / master” to gałąź zdalna, którą chcesz zresetować:

    git reset --hard origin/master
    

Spowoduje to zaktualizowanie lokalnej gałęzi HEAD do tej samej wersji co origin / master i --hardzsynchronizuje tę zmianę również z indeksem i obszarem roboczym.

araqnid
źródło
4
Dziękuję za twoją sugestię, boję się już użycia --hard i - force już, więc właśnie wybrałem rozwiązanie, które ich nie używa.
YemSalat
13
@KonstantinLevin: ah tak, nazywanie tych opcji jest raczej irytujące. git resetdomyślnie przemieści bieżącą gałąź i zsynchronizuje indeks. --softpominie aktualizację indeksu, --hardzsynchronizuje również przestrzeń roboczą. Moje własne doświadczenie wykorzystuje --hardwiększość czasu, z wyjątkiem sytuacji, gdy chcę cofnąć ostatnie zatwierdzenie (co jest po prostu git reset HEAD^)
araqnid
9
Dzięki większemu doświadczeniu z git jestem przekonany, że to lepsze rozwiązanie, dzięki.
YemSalat,
24
prawdopodobnie będziesz musiał najpierw pobrać:git fetch origin remote_branch
b1r3k
53
Należy pamiętać, że zastąpi to dowolną gałąź, w której aktualnie się znajdujesz, zawartością master . Więc jeśli jesteś np. W gałęzi funkcji, zastąpi ona wszystkie swoje zatwierdzenia master, więc upewnij się, że najpierw sprawdziłeś gałąź, którą zastępujesz.
Zoltán
218

To tak proste, jak trzy kroki:

  1. Usuń swój lokalny oddział: git branch -d local_branch
  2. Pobierz najnowszą zdalną gałąź: git fetch origin remote_branch
  3. Odbuduj oddział lokalny na podstawie zdalnego: git checkout -b local_branch origin/remote_branch
Adam Smith
źródło
7
Właściwie to, co powiedział @araqnid, jest słuszne i bardziej zwięzłe. Przetestowałem to i ty też możesz spróbować.
adamsmith
Wow, git Checkout -b local_branch origin / remote_branch jest świetny! Zawsze robiłem to w dwóch osobnych poleceniach. dzięki!
kendepelchin
11
Może być konieczne wykonanie git branch -D local_branchpierwszego kroku, jeśli Twój oddział nie zostanie scalony.
szeryf
dzięki, miałem trudności z korzystaniem z gitflow, po opublikowaniu gałęzi, a następnie jej zakończeniu, chciałem przejść do usuniętej gałęzi, a twoje rozwiązanie było jedyne, które działało, pull nie wydaje się działać .. lub mam wątpliwości nie używam go dobrze -
Decebal
2
powinniśmy upewnić się, że bieżąca gałąź nie jest tą, która ma zostać usunięta.
a_secenthusiast
43
git branch -D <branch-name>
git fetch <remote> <branch-name>
git checkout -b <branch-name> --track <remote>/<branch-name>
Sailesh
źródło
Co robi część --track?
eonist
3
@GitSync, o tym git help branchmówi --track. When creating a new branch, set up branch.<name>.remote and branch.<name>.merge configuration entries to mark the start-point branch as "upstream" from the new branch. This configuration will tell git to show the relationship between the two branches in git status and git branch -v. Furthermore, it directs git pull without arguments to pull from the upstream when the new branch is checked out. Naprawiłem to polecenie w odpowiedzi. Dzięki za podniesienie punktu.
Sailesh
Mówiąc w skrócie: dodaje zdalny adres URL do nowego oddziału. Więc są zsynchronizowane na zawsze. Że tak powiem.
eonist
2
Można powiedzieć, że to tylko dla wygody. Jeśli to zrobisz git status, zgłosi, czy oddział lokalny znajduje się przed, czy za oddziałem zdalnym, jeśli masz je powiązane. Dodatkowo możesz zrobić git pull(lub push) zamiast pełnego, git pull <remote> <branch>jeśli już ustawiłeś swój oddział do śledzenia <remote/branch>.
Sailesh
22

Zastąp wszystko zdalnym oddziałem; ale tylko z tego samego zatwierdzenia, w którym działa Twój oddział lokalny:

git reset --hard origin/some-branch

LUB uzyskaj najnowsze informacje ze zdalnego oddziału i zamień wszystko:

git fetch origin some-branch
git reset --hard FETCH_HEAD

Na bok, w razie potrzeby, możesz usunąć nieśledzone pliki i katalogi, których jeszcze nie dopuściłeś:

git clean -fd
nieco mniej
źródło
git cleanKomenda zrobił to dla mnie. git reset hard origin/masternie usuwaj nieśledzonych plików. Dzięki!
Mornor,
9

Najbezpieczniejszy i najbardziej kompletny sposób zastąpienia obecnego oddziału lokalnego pilotem:

git stash
git merge --abort
git rebase --abort
git branch -M yourBranch replaced_yourBranch
git fetch origin yourBranch:yourBranch
git checkout yourBranch

stashLinia zapisuje zmiany, które nie zostały popełnione. branchLinia przenosi swój oddział do innej nazwy, zwalniając oryginalną nazwę. fetchLinia pobiera najnowszą kopię pilocie. checkoutLinia odtwarza oryginalny oddział jako oddział śledzenia.

Lub jako funkcja bash:

replaceWithRemote() {
    yourBranch=${1:-`git rev-parse --abbrev-ref HEAD`}
    git stash
    git merge --abort
    git rebase --abort
    git branch -M ${yourBranch} replaced_${yourBranch}_`git rev-parse --short HEAD`
    git fetch origin ${yourBranch}:${yourBranch}
    git checkout ${yourBranch}
}

która zmienia nazwę bieżącej gałęzi na coś takiego jak replace_master_98d258f.

Joshua S.
źródło
Może chcesz uwzględnić git stash popw tym przepływie pracy. Jeśli chcesz ponownie zastosować ukryte pliki.
eonist
Co robisz z ukrytą gałęzią? Obawiam się, że pojawi się gdzieś w przyszłości na długo po tym, jak zapomnę, po co.
Scott Biggs,
1
@ScottBiggs Jeśli chcesz usunąć ukrytą gałąź, użyj „git stash clear”.
Mark A. Durham
4

Jestem trochę zaskoczony, że nikt jeszcze o tym nie wspominał; Używam go prawie codziennie:

git reset --hard @{u}

Zasadniczo @{u}jest to tylko skrót dla gałęzi upstream, którą śledzi twoja obecna gałąź. Na przykład zwykle jest to równe origin/[my-current-branch-name]. To miłe, ponieważ jest agnostyczne dla gałęzi.

git fetchNajpierw upewnij się, aby uzyskać najnowszą kopię zdalnego oddziału.

TTT
źródło
1
to wygląda naprawdę ładnie, miałem już dość kopiowania i wklejania nazwy oddziału, aby zresetować!
pedroct92
1
Miałem kilka przypadków, w których dodawałem odpowiedzi na stare pytania, a moje odpowiedzi dotarły do ​​tabeli liderów. Mam nadzieję, że tak.
Jamie
3

Można to zrobić na wiele sposobów, kontynuując edycję tej odpowiedzi w celu rozpowszechnienia lepszej perspektywy wiedzy.

1) Zresetuj mocno

Jeśli pracujesz ze zdalnej gałęzi rozwoju, możesz zresetować HEAD do ostatniego zatwierdzenia na zdalnej gałęzi, jak poniżej:

git reset --hard origin/develop

2) Usuń bieżącą gałąź i ponownie dokonaj płatności ze zdalnego repozytorium

Biorąc pod uwagę, że pracujesz nad rozwojem oddziału w lokalnym repozytorium, który synchronizuje się ze zdalnym / develop oddziału, możesz wykonać następujące czynności:

git branch -D develop
git checkout -b develop origin/develop

3) Przerwij scalanie

Jeśli znajdujesz się pomiędzy złym scaleniem (błędnie zrobionym z niewłaściwą gałęzią) i chciałeś uniknąć scalenia, aby wrócić do gałęzi najpóźniej jak poniżej:

git merge --abort

4) Przerwij wycofanie

Jeśli jesteś pomiędzy złym rebase, możesz przerwać żądanie rebase, jak poniżej:

git rebase --abort
Amit Kaneria
źródło
2

Możesz zrobić, jak powiedział @ Hugo z @Laurent, lub możesz użyć git rebasedo usunięcia zatwierdzeń, które chcesz się pozbyć, jeśli wiesz, które. Zazwyczaj używam git rebase -i head~N(gdzie N jest liczbą, umożliwiającą manipulowanie ostatnimi N zatwierdzeniami) do tego rodzaju operacji.

ksol
źródło
Właściwie to polecenie „git rebase” zawiodło sprawę, potem wymuszone scalenia i twarde resetowania. W każdym razie, to, czego szukałem, to po prostu prosty sposób na wyciągnięcie całego repo ze zdalnego serwera bez scalania.
YemSalat
2

Wybrana odpowiedź jest absolutnie poprawne , jednakże nie zostawił mnie ostatni commit / naciska ...

Więc dla mnie:

git reset --hard dev/jobmanager-tools
git pull  ( did not work as git was not sure what branch i wanted)

Ponieważ wiem, że chcę tymczasowo ustawić moją gałąź nadrzędną na kilka tygodni na konkretną gałąź (taką samą jak ta, którą przełączyłem / wylogowałem wcześniej i dokonałem twardego resetu)

Więc PO zresetowaniu

git branch --set-upstream-to=origin/dev/jobmanager-tools
git pull
git status    ( says--> on branch  dev/jobmanager-tools 
Tom Stickel
źródło
1

Jeśli chcesz zaktualizować gałąź, która nie jest obecnie wyewidencjonowana, możesz:

git fetch -f origin rbranch:lbranch
kqr
źródło
0

Jak podano w wybranym objaśnieniu, git reset jest dobry. Ale obecnie często używamy podmodułów: repozytoriów w repozytoriach. Na przykład, jeśli używasz ZF3 i jQuery w swoim projekcie, najprawdopodobniej chcesz, aby zostały one sklonowane z ich oryginalnych repozytoriów. W takim przypadku reset git nie wystarczy. Musimy zaktualizować submoduły do ​​dokładnie tej wersji, która jest zdefiniowana w naszym repozytorium:

git checkout master
git fetch origin master
git reset --hard origin/master
git pull

git submodule foreach git submodule update

git status

jest to to samo, co rekursywnie będziesz wchodził (cd) do katalogu roboczego każdego podmodułu i będzie działał:

git submodule update

I to bardzo różni się od

git checkout master
git pull

ponieważ podmoduły wskazują nie rozgałęzienie, ale zatwierdzenie.

W takich przypadkach, gdy ręcznie wyewidencjonujesz jakiś oddział dla 1 lub więcej submodułów, możesz uruchomić

git submodule foreach git pull
Eugene Kaurov
źródło
Podaj wyjaśnienie, zwłaszcza w przypadku odpowiedzi na tak stare pytania. Twoja odpowiedź nie jest pomocna w obecnej postaci.
Erik A,
Przyjęta odpowiedź już proponuje git reset --hard. Daje to niewielką wartość.
florisla
0
git reset --hard
git clean -fd

To działało dla mnie - clean pokazał także wszystkie pliki, które usunął. Jeśli powie ci, że stracisz zmiany, musisz się schować.

Travis Heeter
źródło
-6

Brzydki, ale prostszy sposób: usuń folder lokalny i ponownie sklonuj zdalne repozytorium.

Hugo
źródło
10
Lub po prostu usuń gałąź i sprawdź ponownie.
laurent
Tak, chyba to zrobię, jeśli nie znajdę, jak to zrobić w mniej „brzydki” sposób
YemSalat,
2
Brzydki czasem bywa przydatny. Chciałbym, żeby ludzie nie głosowali na rzeczy tylko dlatego, że nie są to konwencjonalne sposoby: musi istnieć bardziej racjonalny powód, by głosować niżej ... i należy to podać. Git to rzecz, która osiąga wyniki. To nie jest jakiś święty tekst.
Mike gryzoń
3
Nie rozumiem negatywnych opinii :-( Tak, to nieeleganckie itp., Ale w niektórych przypadkach może działać najlepiej ... przepraszam @Hugo
silverdr
@Hugo, uzgodnione. Coś tajemniczego i śmierdzącego przydarzyło się mojemu lokalnemu oddziałowi, a zarówno Kierownik Zespołu, jak i Menedżer ds. Inżynierii zasugerowali, wśród bardziej eleganckich rozwiązań, po prostu (skompresowanie, skopiowanie i zapisanie mojej pracy nad funkcjami, a następnie) zaatakowanie lokalnego repozytorium i ponowne wygenerowanie.
AmitaiB