Jak „wyciągnąć” do gałęzi, która nie jest obecna?


126

Kiedy biegniesz git pullpo mastergałęzi, zwykle ciągnie origin/master. Jestem w innej gałęzi o nazwie newbranch, ale muszę uruchomić polecenie, które wykonuje polecenie git pullod origin/masterdo, masterale nie mogę uruchomić git checkoutzmiany wybranej gałęzi, dopóki nie zakończy się ściąganie. Czy jest na to sposób?

Aby dać trochę informacji, repozytorium przechowuje witrynę internetową. Dokonałem pewnych zmian newbranchi wdrożyłem je, przełączając witrynę na newbranch. Teraz te zmiany zostały włączone do mastergałęzi, próbuję również przełączyć witrynę z powrotem do mastergałęzi. W tym momencie, newbranchi origin/mastersą identyczne, ale masterpozostaje w tyle origin/masteri musi zostać zaktualizowana. Problem w tym, że jeśli robię to w tradycyjny sposób:

$ git checkout master
   # Uh oh, production website has now reverted back to old version in master
$ git pull
   # Website is now up to date again

Muszę osiągnąć to samo, co powyżej ( git checkout master && git pull), ale bez zmiany katalogu roboczego na wcześniejszą wersję podczas procesu.


@phi: Nie sądzę, żeby to zadziałało, ponieważ jestem w newbranchśrodku i nie ma tam nic do ukrycia!
Malvineous

Klonowałbym do nowego katalogu, łączyłbym newbranch z master, łączył mastera z powrotem w newbranch, a następnie git pull z miejsca, w którym się znajdujesz. Mistrz i nowa gałąź będą takie same.
AET

@aet Mógłby to zrobić teraz w swoim bieżącym katalogu, robiąc to git fetch; git merge origin/masterod wewnątrz newbranch. Sklonowanie całej drugiej kopii repozytorium nie przynosi żadnych korzyści.
meagar


Odpowiedzi:


5

Masz drzewo robocze, którego nie chcesz dotykać, więc użyj innego. Clone jest tani, jest do tego stworzony.

git fetch origin master       # nice linear tree
git clone . ../wip -b master  # wip's `origin/master` is my `master`
cd ../wip                     # .
git pull origin origin/master # merge origin's origin/master
git push origin master        # job's done, turn it in.
cd ../main
rm -rf ../wip                 # wip was pushed here, wip's done

git checkout master           # payload

Problem ze wszystkimi innymi odpowiedziami tutaj polega na tym, że w rzeczywistości nie pociągają one za sobą. Jeśli potrzebujesz skonfigurowanego łączenia lub ponownego bazowania, potrzebujesz innego drzewa roboczego i powyższej procedury. W przeciwnym razie po prostu git fetch; git checkout -B master origin/masterzrobi.


2
Po uruchomieniu git checkout masterwyewidencjonujesz starą mastergałąź, ponieważ nie zrobiłeś git pullw mainfolderze synchronizacji z origin / master. To jest to, czego staram się uniknąć.
Malvineous

Wyewidencjonowanie dokonane przez klona pochodzi ze starego mastera, ale to wyewidencjonowanie jest do katalogu, którego serwer WWW nie ogląda. Master checkout na końcu to w pełni scalony master, który został wypchnięty z wip.
jthill

W wierszu 6 wypychasz scalone (zaktualizowane) z masterpowrotem do origin, ale nie sądzę, aby Twoje ostateczne pobranie było takie zaktualizowane master. Nie ma git pullpotrzeby aktualizowania mastergałęzi w mainkatalogu, więc jeśli czegoś mi brakuje, twoje polecenia nie różnią się od zwykłego uruchamiania git checkout masteri pobierania starego masterdrzewa. Jeśli przyjrzysz się uważnie, nie uruchamiasz żadnych poleceń w mainkatalogu, które komunikują się z nadrzędnym strumieniem (z wyjątkiem linii 1, która jest uruchamiana przed wprowadzeniem jakichkolwiek zmian w repozytorium).
Malvineous

cóż, możesz wypróbować to na repozytorium testowym lub sprawdzić dokumenty push.
jthill

1
@jwg w porównaniu z czym, proszę? Upewnij się, że spełniasz wszystkie określone potrzeby OP.
jthill

163

Prosta: Aktualizacja z odległego oddziału do chwili obecnej nie sprawdził-out oddziału kapitana :

git fetch origin master:master

gdzie origin jest twoim pilotem i aktualnie jesteś sprawdzany w jakiejś gałęzi, np . dev .

Jeśli chcesz zaktualizować swój obecny oddział oprócz określonego oddziału za jednym razem:

git pull origin master:master

4
Hm, wydaje się, że to nie zawsze działa; Właśnie zostałem poproszony o połączenie z moją gałęzią WIP.
underscore_d

@underscore_d to samo dla mnie.
Greg,

1
Pracował dla mnie ... jeśli podpowiada scalenie, to wyobrażam sobie, że w twoim oddziale są zmiany, które aktualizujesz, a które nie są związane z pochodzeniem
przejrzyj

2
Jak to ma działać? To nie działa dla mnie, po prostu próbuje scalić źródło / wzorzec w mojej aktualnie wyewidencjonowanej gałęzi.
mhogerheijde

3
To ciągnie mistrza do bieżącej gałęzi. To zdecydowanie NIE jest to, o co się prosi. Jeśli zmienisz pull na fetch, będzie to dokładnie to, o co jest proszone.
Jeff Wolski

90

Odpowiedź na to pytanie znajduje się tutaj: Scal, aktualizuj i ściągaj gałęzie Git bez korzystania z płatności

# Merge local branch foo into local branch master,
# without having to checkout master first.
# Here `.` means to use the local repository as the "remote":
git fetch . foo:master

# Merge remote branch origin/foo into local branch foo,
# without having to checkout foo first:
git fetch origin foo:foo

2
To jest najlepsze, ponieważ działa z niezatwierdzonymi zmianami lokalnymi.
Tomasz Gandor

2
Jeśli chcesz po prostu nadążyć za najnowszymi zmianami, to byś zrobił git fetch origin master:master. git fetchsamo w sobie zakładałoby, że zamierzasz zaktualizować bieżącą gałąź, a nie inną gałąź.
John Leidegren

2
To najprostsza i najbardziej bezpośrednia odpowiedź. To powinna być akceptowana odpowiedź IMO.
Keego,

@JohnLeidegren - z wyjątkiem tego, że nie zawsze działa zgodnie z przeznaczeniem. Zobacz komentarze do stackoverflow.com/a/42902058/274579 odpowiedzi.
ysap

22

Jak się okazuje, odpowiedź jest zwodniczo prosta:

$ git fetch                           # Update without changing any files
$ git branch -d master                # Remove out-of-date 'master' branch
$ git checkout --track origin/master  # Create and check out up-to-date 'master' branch

To pozwala na aktualizację masteroddział bez przełączania do niego, aż po to został zaktualizowany.


11
To nie robi tego, o co prosiłeś.
jthill

Jak mówi powyższy komentarz, pytanie, które zadałeś, nie jest w rzeczywistości pytaniem, na które ostatecznie odpowiedziałeś. Powinieneś zaktualizować swoje pytanie, aby mniej konkretnie dotyczyło scalania do gałęzi bez sprawdzania go, a bardziej przejścia bezpośrednio do najnowszej wersji gałęzi dostępnej na pilocie bez uprzedniego sprawdzania starej wersji.
meagar

1
To absolutna odpowiedź, której tu szukałem :)
Sophistifunk

1
Nie tego chciał OP, ale pomógł mi, szczerze mówiąc.
Marcel Bro

1
@anoniim, nie to, czego chciał OP? Masz na myśli OP, który właśnie odpowiedział na to pytanie?
smac89

12

Martwisz się czymś, czego nie można naprawić, ponieważ operacje Git nie są atomowe. Zawsze będziesz mieć dziurę, w której twój katalog roboczy jest w połowie drogi między gałęziami, nawet jeśli zaktualizujesz master bez wcześniejszego przełączenia się na niego. Dlatego Git nie jest narzędziem do wdrażania .

Ponieważ w rzeczywistości nie zatwierdzasz kodu w swoim środowisku produkcyjnym (mam nadzieję), nie musisz w rzeczywistości sprawdzać gałęzi. Możesz po prostu zrobić a, git fetchaby zaktualizować swoje zdalne referencje, a następnie git checkout origin/masterprzenieść katalog roboczy bezpośrednio do zatwierdzenia aktualnie wskazywanego przez origin/master. To wprowadzi cię w stan odłączonej głowy, ale znowu, ponieważ nie wprowadzasz kodu, to nie ma znaczenia.

To jest najmniejsza dziura, którą dostaniesz, ale jak powiedziałem, dziura nadal istnieje; checkoutnie jest atomowy.


Rozumiem ograniczenia używania gita do wdrożenia, problem polega na tym, że w tym przypadku dziura będzie trwała minuty, a nie mniej niż jedną sekundę. Niezły pomysł na sprawdzenie, origin/masterale to może po prostu załatwić sprawę.
Malvineous

Co sprawia, że ​​dziura ma „minuty”? Pobieranie danych przez sieć? Po prostu zrób to, git fetchzanim zrobisz cokolwiek innego i wyeliminuj rzeczywisty transfer danych.
meagar

Trwa kilka minut, ponieważ (teraz) nieśledzony plik zostałby nadpisany przez wcześniejsze zatwierdzenie. Więc muszę skopiować plik, zrobić rzeczy git, a następnie umieścić go z powrotem. „Długość minut” wynika z mojej szybkości pisania. (Tak, mogłem to
napisać,

3

Możesz użyć do tego update-ref:

git fetch
git update-ref refs/heads/master origin/master
git checkout master

Zauważ, że spowodowałoby to odrzucenie wszelkich lokalnych zatwierdzeń w gałęzi master. W twoim przypadku ich nie będzie, więc to jest w porządku. Dla innych osób, które próbują to zrobić, gdy są lokalne zatwierdzenia, nie sądzę, aby było to możliwe, ponieważ scalanie można uruchomić tylko w bieżącej gałęzi.


Czy byłoby to równoważne git branch --force master origin/master? To zmusza lokalną głowę masterdo wskazywania na głowę originsmaster
Keego

2

Rozwiązanie Malvineous działa dla mnie

$ git fetch                           # Update without changing any files
$ git branch -d master                # Remove out-of-date 'master' branch
$ git checkout --track origin/master  # Create and check out up-to-date 'master' branch

Po prostu podaj błąd


warning: not deleting branch 'master' that is not yet merged to
         'refs/remotes/origin/master', even though it is merged to HEAD.
error: The branch 'master' is not fully merged.
If you are sure you want to delete it, run 'git branch -D master'.

Więc uruchamiam z opcją -D

dzięki


0

git fetch origin master:master

  • „Pulls” (faktycznie pobiera) master.
  • Jeśli masz na swoim koncie zmiany master, które nie zostały jeszcze przesłane, origin/masterzostanie scalony z Twoim mistrzem.
  • Jeśli występują konflikty scalania, musisz je najpierw rozwiązać.
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.