Pracuję nad projektem, który ma 2 gałęzie, A i B. Zazwyczaj pracuję na gałęzi A i łączę rzeczy z gałęzi B. Zazwyczaj robiłbym:
git merge origin/branchB
Chciałbym jednak zachować lokalną kopię oddziału B, ponieważ od czasu do czasu mogę sprawdzić oddział bez uprzedniego połączenia z moim oddziałem A. W tym celu zrobiłbym:
git checkout branchB
git pull
git checkout branchA
Czy istnieje sposób na wykonanie powyższej czynności za pomocą jednego polecenia i bez konieczności przełączania gałęzi tam iz powrotem? Czy powinienem tego używać git update-ref
? W jaki sposób?
git
git-merge
git-pull
git-checkout
Charles
źródło
źródło
--no-ff
opcji, co powoduje, że i tak rejestrowanie zatwierdzenia scalania jest rejestrowane. Jeśli jesteś zainteresowany, moja odpowiedź tam pokazuje, jak możesz to zrobić - nie tak solidna, jak moja zamieszczona tutaj odpowiedź, ale mocne strony tych dwóch można z pewnością połączyć.Odpowiedzi:
Krótka odpowiedź
Tak długo, jak wykonujesz szybkie przewijanie do przodu , możesz po prostu użyć
Przykłady:
Podczas gdy odpowiedź Amber będzie działać również w przypadkach szybkiego przewijania do przodu, użycie
git fetch
w ten sposób jest nieco bezpieczniejsze niż zwykłe przesunięcie odniesienia gałęzi, ponieważgit fetch
automatycznie zapobiegnie przypadkowemu nie przewinięciu do przodu, o ile nie użyjesz go+
w refspec.Długa odpowiedź
Nie można scalić gałęzi B z gałęzią A bez uprzedniego sprawdzenia A, jeśli spowodowałoby to scalenie nie do przodu. Wynika to z faktu, że kopia robocza jest potrzebna do rozwiązania wszelkich potencjalnych konfliktów.
Jest to jednak możliwe w przypadku połączeń szybkiego przewijania , ponieważ połączenia takie z definicji nigdy nie mogą prowadzić do konfliktów. Aby to zrobić bez uprzedniego sprawdzenia gałęzi, możesz użyć
git fetch
z refspec.Oto przykład aktualizacji
master
(nie zezwalającej na zmiany inne niż szybkie przewijanie do przodu), jeśli maszfeature
wyewidencjonowany inny oddział :Ten przypadek użycia jest tak powszechny, że prawdopodobnie będziesz chciał utworzyć dla niego alias w pliku konfiguracyjnym git, taki jak ten:
Ten alias robi to:
git checkout HEAD
: powoduje to oderwanie kopii roboczej. Jest to przydatne, jeśli chcesz dokonać aktualizacji,master
gdy zdarzyło się, że została wyewidencjonowana. Myślę, że było to konieczne, ponieważ w przeciwnym razie odwołanie do gałęzimaster
nie ruszy się, ale nie pamiętam, czy to naprawdę od razu z mojej głowy.git fetch upstream master:master
: szybko przesyła lokalną wiadomośćmaster
w to samo miejsce, coupstream/master
.git checkout -
sprawdza twoją poprzednio wyrejestrowaną gałąź (tak dzieje się-
w tym przypadku).Składnia
git fetch
for (nie) szybkiego przewijania do przoduJeśli chcesz, aby
fetch
polecenie zakończyło się niepowodzeniem, jeśli aktualizacja nie obsługuje szybkiego przewijania, wystarczy użyć refspec formularzaJeśli chcesz zezwolić na aktualizacje nie do szybkiego przewijania, dodajesz znak
+
z przodu refspec:Pamiętaj, że możesz przekazać swoje lokalne repozytorium jako parametr „zdalny”, używając
.
:Dokumentacja
Z
git fetch
dokumentacji wyjaśniającej tę składnię (wyróżnienie moje):Zobacz też
Przejdź do kasy i połącz bez dotykania działającego drzewa
Scalanie bez zmiany katalogu roboczego
źródło
git checkout --quiet HEAD
jestgit checkout --quiet --detach
od Git 1.7.5.git fetch . origin/foo:foo
zaktualizować mojego lokalnego foo do mojego lokalnego pochodzenia / foogit checkout -
podstęp! Tak proste jakcd -
.Nie, nie ma. Wyewidencjonowanie gałęzi docelowej jest konieczne, aby między innymi rozwiązać konflikty (jeśli Git nie jest w stanie automatycznie ich scalić).
Jeśli jednak scalanie byłoby szybkie, nie trzeba sprawdzać gałęzi docelowej, ponieważ tak naprawdę nie trzeba niczego scalać - wystarczy zaktualizować gałąź, aby wskazywała nowa głowa ref. Możesz to zrobić za pomocą
git branch -f
:Zaktualizuje się,
branch-b
aby wskazywać na głowębranch-a
.-f
Opcja oznacza--force
, co oznacza, że trzeba być ostrożnym podczas korzystania z niego.źródło
git reset
działa tylko w aktualnie wyrejestrowanym oddziale.git fetch upstream branch-b:branch-b
(wzięty z tej odpowiedzi ).git fetch <remote> B:A
, gdzie B i A to zupełnie inne gałęzie, ale B można szybko połączyć do przodu w A. Możesz także przekazać swoje lokalne repozytorium jako „zdalne”, używając.
jako zdalnego aliasu:git fetch . B:A
.branch -f
może być niebezpieczne, jak zauważyłeś. Więc nie używaj tego! Użyjfetch origin branchB:branchB
, która zakończy się niepowodzeniem, jeśli scalenie nie jest przewijane do przodu.Jak powiedział Amber, szybkie połączenia do przodu to jedyny przypadek, w którym można to zrobić. Każde inne scalenie prawdopodobnie musi przejść przez całą trójstronną fuzję, stosowanie poprawek, rozwiązywanie konfliktów - a to oznacza, że muszą istnieć pliki.
Tak się składa, że mam skrypt, którego używam właśnie do tego: wykonuję scalanie do przodu bez dotykania drzewa roboczego (chyba że łączysz się w HEAD). Jest trochę długi, ponieważ jest co najmniej trochę solidny - sprawdza, czy scalenie będzie szybkie do przodu, a następnie wykonuje go bez sprawdzania gałęzi, ale daje takie same wyniki, jak gdybyś miał - widzisz
diff --stat
podsumowanie zmian, a wpis w reflogu jest dokładnie jak szybkie scalanie do przodu, zamiast „resetowania”, które otrzymujesz, jeśli używaszbranch -f
. Jeśli to nazwęgit-merge-ff
i upuść go w katalogu bin, można nazwać to jako polecenie git:git merge-ff
.PS Jeśli ktoś zauważy jakiekolwiek problemy z tym skryptem, proszę o komentarz! To była praca polegająca na pisaniu i zapominaniu, ale chętnie ją poprawię.
źródło
# or git branch -f localbranch remote/remotebranch
przypomina mi o źródle i opcjach. Daj komentarz do drugiego linku +1."$branch@{u}"
Możesz to zrobić tylko wtedy, gdy scalenie jest przewijaniem do przodu. Jeśli nie, to git musi pobrać pliki, aby je scalić!
Aby to zrobić tylko w przypadku szybkiego przewijania do przodu :
gdzie
<commit>
jest pobrany commit, ten, do którego chcesz szybko przewinąć do przodu. Zasadniczo jest to jak użyciegit branch -f
do przeniesienia gałęzi, z tym wyjątkiem, że rejestruje go również w dzienniku reflogu, tak jakby to było scalenie.Proszę, proszę, proszę , nie rób tego za coś, co nie jest do przodu, czy to po prostu być zresetowanie oddziału na drugi popełnić. (Aby sprawdzić, sprawdź, czy
git merge-base <branch> <commit>
daje SHA1 oddziału).źródło
git merge-base --is-ancestor <A> <B>
. „B” to rzecz, którą należy połączyć w „A”. Przykładem może być A = master i B = develop, upewniając się, że develop jest szybko przewijalny do master. Uwaga: Istnieje z 0, jeśli nie jest w stanie FF, istnieje z 1, jeśli jest.W twoim przypadku możesz użyć
co robi, co chcesz (zakładając, że scalanie jest szybkie przewijanie do przodu). Jeśli gałąź nie może zostać zaktualizowana, ponieważ wymaga scalenia nie do szybkiego przewijania, oznacza to, że komunikat nie powiedzie się bezpiecznie.
Ta forma pobierania ma również kilka bardziej przydatnych opcji:
Pamiętaj, że
<remote>
może to być lokalne repozytorium i<sourceBranch>
może być gałąź śledzenia. Możesz więc zaktualizować lokalny oddział, nawet jeśli nie jest wyewidencjonowany, bez dostępu do sieci .Obecnie mój dostęp do serwera nadrzędnego odbywa się za pośrednictwem wolnej sieci VPN, więc okresowo łączę się,
git fetch
aby zaktualizować wszystkie piloty, a następnie rozłączam się. Jeśli, powiedzmy, zdalny mistrz zmienił się, mogę to zrobićaby bezpiecznie zaktualizować mojego lokalnego mistrza, nawet jeśli obecnie mam jakiś inny oddział. Nie wymaga dostępu do sieci.
źródło
Innym, co prawda dość brutalnym sposobem jest po prostu odtworzenie oddziału:
Wyrzuca to lokalną nieaktualną gałąź i odtwarza ją o tej samej nazwie, więc używaj jej ostrożnie ...
źródło
Możesz sklonować repozytorium i wykonać scalenie w nowym repozytorium. W tym samym systemie plików będzie to dowiązanie twarde zamiast kopiowania większości danych. Zakończ, przeciągając wyniki do oryginalnego repozytorium.
źródło
Wprowadź polecenie git-forward-merge :
https://github.com/schuyler1d/git-forward-merge
Działa tylko w przypadku automatycznych połączeń, jeśli występują konflikty, należy użyć zwykłego scalania.
źródło
W wielu przypadkach (takich jak scalanie) możesz po prostu użyć zdalnego oddziału bez konieczności aktualizacji lokalnego oddziału śledzenia. Dodanie wiadomości do reflogu brzmi jak przesada i przestanie być szybsze. Aby ułatwić odzyskiwanie, dodaj następujące elementy do konfiguracji git
Następnie wpisz
aby zobaczyć najnowszą historię swojego oddziału
źródło
[core]
nie[user]
? (i jest domyślnie włączony, w przypadku repozytoriów z obszarem roboczym (tj. non-go).Napisałem funkcję powłoki dla podobnego przypadku użycia, z którym spotykam się codziennie w projektach. Jest to w zasadzie skrót do aktualizowania lokalnych oddziałów za pomocą wspólnego oddziału, takiego jak rozwijanie przed otwarciem PR itp.
glmh
(„git pull and merge here”) automatyczniecheckout branchB
,pull
najnowsze, ponowniecheckout branchA
imerge branchB
.Nie rozwiązuje potrzeby przechowywania lokalnej kopii oddziału A, ale można ją łatwo zmodyfikować, dodając krok przed sprawdzeniem oddziału B. Coś jak...
W przypadku prostych operacji szybkiego przewijania następuje przejście do monitu komunikatu zatwierdzenia.
W przypadku połączeń bez szybkiego przewijania powoduje to, że oddział znajduje się w stanie rozwiązywania konfliktu (prawdopodobnie konieczna jest interwencja).
Aby skonfigurować, dodać do
.bashrc
lub.zshrc
itp .:Stosowanie:
źródło
Innym sposobem na skuteczne wykonanie tego jest:
Ponieważ jest to mała litera
-d
, usunie ją tylko, jeśli dane gdzieś nadal będą istnieć. Jest podobny do odpowiedzi @ kkoehne, tyle że nie wymusza. Z tego powodu-t
ponownie skonfiguruje pilota.Miałem nieco inną potrzebę niż OP, która polegała na utworzeniu nowej gałęzi funkcji poza
develop
(lubmaster
) po scaleniu żądania ściągnięcia. Można tego dokonać w jednej linijce bez użycia siły, ale nie aktualizuje ona lokalnegodevelop
oddziału. To tylko kwestia sprawdzenia nowego oddziału i oparcia go naorigin/develop
:źródło
po prostu wyciągnąć mistrza bez sprawdzania mistrza, którego używam
git fetch origin master:master
źródło
Absolutnie możliwe jest wykonanie dowolnego scalenia, a nawet nie szybkich połączeń do przodu
git checkout
.worktree
Odpowiedź przez @grego to dobra wskazówka. Aby rozwinąć tę kwestię:Teraz połączyłeś lokalny oddział pracy z lokalnym
master
oddziałem bez zmiany kasy.źródło
Jeśli chcesz zachować to samo drzewo co gałąź, którą chcesz scalić (tzn. Nie jest to prawdziwe „scalenie”), możesz to zrobić w ten sposób.
źródło
Możesz spróbować
git worktree
otworzyć dwie gałęzie obok siebie, to może brzmieć tak, jakbyś tego chciał, ale bardzo różni się od niektórych innych odpowiedzi, które tu widziałem.W ten sposób możesz mieć dwie osobne gałęzie śledzące w tym samym repozytorium git, więc musisz pobrać tylko raz, aby uzyskać aktualizacje w obu drzewach roboczych (zamiast klonować dwa razy i ciągnąć każde z nich)
Worktree utworzy nowy katalog roboczy dla twojego kodu, w którym możesz jednocześnie wyewidencjonować inną gałąź zamiast zamiany gałęzi na miejsce.
Kiedy chcesz go usunąć, możesz to wyczyścić
źródło