Ponieważ rozgałęzianie jest tanie w Git, dlaczego nie sprawdzić kopii, a następnie nie musisz wykonywać suchego rozruchu? Możesz po prostu wyrzucić kopię później.
To świetnie, ale nadal modyfikuje kopię roboczą. Jeśli Twoje repozytorium jest serwerem na żywo, możesz udostępniać pliki z konfliktami.
dave1010
21
Naprawdę nie można wykonać scalenia bez wpływu na kopię roboczą.
mipadi
55
To prawda, ale coś takiego git merge --only-if-there-wont-be-any-conflictslub git diff --show-conflicts <commit>byłoby naprawdę przydatne. Szkoda, że to jeszcze nie możliwe, czy coś mi umknęło?
dave1010
344
@ dave1010 Nigdy nie powinieneś zajmować się scalaniem na serwerze internetowym na żywo !!! Do tego właśnie służy twoje pudełko programistyczne! Napraw gałąź „prod”, a następnie prześlij ją na prawdziwy serwer WWW.
jpswain 12.01.11
52
Jeśli pracujesz na serwerze na żywo / produkcyjnym, nigdy nie chcesz nic robić, tylko git pull --ff-only!
ThiefMaster
237
Musiałem tylko zaimplementować metodę, która automatycznie wykryje konflikty między repozytorium a jego zdalnym. To rozwiązanie scala pamięć, aby nie dotknąć indeksu ani drzewa roboczego. Myślę, że jest to najbezpieczniejszy możliwy sposób rozwiązania tego problemu. Oto jak to działa:
Pobierz pilota do swojego repozytorium. Na przykład:
git fetch origin master
Uruchom git merge-tree: git merge-tree mergebase master FETCH_HEAD( mergebase to szesnastkowy identyfikator, który scalono -bazę wydrukowano w poprzednim kroku)
Załóżmy teraz, że chcesz połączyć zdalny master z lokalnym master, ale możesz użyć dowolnych gałęzi. git merge-treewykona scalenie w pamięci i wydrukuje wynik na standardowe wyjście. Grep dla wzoru <<lub >>. Lub możesz wydrukować dane wyjściowe do pliku i to sprawdzić. Jeśli znajdziesz linię zaczynającą się od „zmieniono w obu”, najprawdopodobniej wystąpi konflikt.
Ta odpowiedź jest niedoceniana, IMHO, ponieważ jest to czyste rozwiązanie bez dotykania kopii roboczej lub indeksu.
sschuberth
23
BTW, kroki 2 i 3 można połączyć w jeden krok, używając operatora backtick konsoli Linux, który ocenia na miejscu jego zawartość:git merge-tree `git merge-base FETCH_HEAD master` FETCH_HEAD master
jakub.g
15
Dodaj do [alias] w .gitconfig: dry = "! F () {git merge-tree` git merge-base 2 $ 1 $ 2 $ 1 $;}; f "# sprawdź, jak przebiegnie scalenie dev w master: git dry mistrz dev
Noel
8
Moja nowa ulubiona linia GIT: po git merge-tree `git merge-base clieop master` clieop master | grep -A3 "changed in both"prostu niesamowita! +100
Rudie
4
Podczas testowania tego stwierdziłem, że grepowanie dla scalonych flag „zmieniono w obu”, w których obie gałęzie modyfikują ten sam plik, nawet jeśli nie powodują konfliktu scalenia. Aby zidentyfikować tylko rzeczywiste konflikty, uznałem za konieczne grep dla znacznika konfliktu, który zaczyna się w ten sposób: +<<<<<<< .ourwięc używam wyrażenia grep, takiego jakgrep -q '^+<* \.our$'
Guy
55
Moje proste rozwiązanie tego problemu to:
Utwórz gałąź „pre-master” (oczywiście od master)
Połącz wszystkie rzeczy, które chcesz, w ten przed-mistrz.
Następnie możesz zobaczyć, jak doszło do scalenia bez dotykania wzorca.
Scal pre-master w master OR
Scal wszystkie niedbale wypuszczone gałęzie w master
W każdym razie postępowałbym zgodnie z radą @ orange80.
Lubię rozwiązanie @akostajti, ale jest to kolejna niedoceniana opcja. W rzeczywistości wolę być defensywny i utworzyć nową gałąź tymczasową (oczywiście tylko wtedy, gdy oczekuję konfliktów, w przeciwnym razie będzie to przesada), a jeśli coś pójdzie nie tak, po prostu ją usuń.
jakub.g
1
nie wiem, czy jest to „brudne” rozwiązanie, czy nie, ale naprawdę działa. Lubię to! (Y)
sara,
3
To powinno być przyjęte rozwiązanie, imo. Jest szybki, łatwy, bezpieczny, odwracalny, intuicyjny i dopóki nie rozpoczniesz żadnych nieprzewidzianych zmian, nie będzie miał żadnych skutków ubocznych.
Bob Ray
3
To rozwiązanie informuje, że nie rozumiesz, jak działa git. Rozgałęzienia są tylko wskaźnikami, a Ty tworzysz tylko zbędny wskaźnik. Masz złe przeczucie, że możesz w jakiś sposób zaszkodzić łączeniu się oddziałów, ale nie możesz. Zawsze możesz to zrobićgit merge --abort jeśli występują konflikty, git reset --hard HEAD~1jeśli nastąpiło scalenie lub git reset --hard origin/master. Utworzenie kolejnej gałęzi daje poczucie bezpieczeństwa, ale jeśli nauczysz się, jak działa git, zrozumiesz, że to stracony strach. Jeśli chodzi o to, aby nie zmieniać kopii roboczej, nie ma rozwiązania.
Thibault D.
@ thibault-d Pomyśl o tym, jak skomplikowane jest rozwiązanie, gdy nie zaczynasz od czystej gałęzi. git merge --no-commitnie przerwie scalania, jeśli można je szybko przesłać dalej. git merge --abortnie działa, jeśli został scalony. Jeśli chcesz napisać to jako skrypt, jest to niewygodne, ponieważ git mergenie odpowiada wystarczająco dobrymi kodami błędów, aby wyjaśnić różne typy konfliktów. Praca z nową gałęzią zapobiega pozostawieniu uszkodzonego skryptu w repozytorium w stanie wymagającym ręcznej interwencji. Pewnie, że nic nie możesz stracić. Ale łatwiej jest zbudować inaczej.
Erik Aronesty,
47
Cofanie scalenia za pomocą git jest tak łatwe, że nie powinieneś nawet martwić się suchym przebiegiem:
$ git pull $REMOTE $BRANCH
# uh oh, that wasn't right
$ git reset --hard ORIG_HEAD
# all is right with the world
EDYCJA: Jak zauważono w komentarzach poniżej, jeśli masz zmiany w katalogu roboczym lub obszarze przejściowym, prawdopodobnie zechcesz je ukryć przed wykonaniem powyższej czynności (w przeciwnym razie znikną po wykonaniu git resetpowyższych czynności)
Po prostu sprawdzenie, czy scalenie zostanie przewinięte do przodu (FF), polega na sprawdzeniu listy, git branch --contains HEADa nawet bardziej bezpośrednio, wystarczy użyćgit merge --ff-only
Brian Phillips
7
git reset --hard jest jedną z niewielu komend usuwania informacji bez wycofywania, które ma git, dlatego należy go używać z najwyższą ostrożnością. Jako taki -1
Kzqai
8
@Tchalvak nadal jest rejestrowany.
Kissaki,
3
--dry-runnie „po prostu sprawdzałby, czy scalenie będzie przewijać do przodu”. Zwróciłoby to dokładnie dane wyjściowe scalenia: pliki, konflikty itp. Czy ff nie jest tak naprawdę interesujące, prawda?
Rudie,
3
jak o git stash; git reset --hard? @BrianPhillips
Code Whisperer
41
Stworzyłem alias, aby to zrobić i działa jak urok, robię to:
Ciekawy pomysł. Jak spojrzę na ten wynik i ustalę, czy scalenie zadziała, czy nie?
MatrixFrog,
6
Nie powie ci to, czy wystąpią jakiekolwiek konflikty ... ale da ci ogólne wyobrażenie o tym, co się stanie, jeśli wykonasz pull / merge.
timh
10
To powie ci tylko różnicę między dwiema gałęziami, nie powie ci, jaki będzie wynik połączenia. Jest to ważne rozróżnienie, ponieważ łączenie w niektórych przypadkach automatycznie przyjmuje zmiany z różnych gałęzi, w zależności od tego, kiedy zostały zatwierdzone. Zasadniczo więc zrobienie różnicy może sprawić, że pomyślisz, że niektóre z twoich zmian zostaną cofnięte, gdy w rzeczywistości proces scalania automatycznie przyjmie nowsze zmiany niż starsze. Mam nadzieję, że to ma sens.
markquezada
3
Aby oprzeć się na komentarzu @ mirthlab, będzie istniała znacząca różnica między różnicowaniem i scalaniem, jeśli ktoś wcześniej przeprowadził scalanie ze strategią scalania „naszą” (lub innymi ręcznymi poprawkami scalania); diff pokaże również różnice, które są już liczone jako „scalone”.
Tao
21
Używam do tego polecenia git request-pull . Pozwala zobaczyć każdą zmianę, która miałaby miejsce podczas łączenia, ale bez robienia czegokolwiek na lokalnych lub zdalnych repozytoriach .
Na przykład wyobraź sobie, że chcesz scalić gałąź o nazwie „feature-x” z gałęzią master
git request-pull master origin feature-x
pokaże podsumowanie tego, co by się stało (bez robienia czegokolwiek):
The following changes since commit fc01dde318:
Layout updates (2015-06-25 11:00:47 +0200)
are available in the git repository at:
http://fakeurl.com/myrepo.git/ feature-x
for you to fetch changes up to 841d3b41ad:
----------------------------------------------------------------
john (2):
Adding some layout
Refactoring
ioserver.js | 8 +++---
package.json | 7 +++++-
server.js | 4 +--
layout/ldkdsd.js | 277 +++++++++++++++++++++++++++++++++++++
4 files changed, 289 insertions(+), 7 deletions(-)
create mode 100644 layout/ldkdsd.js
Jeśli dodasz -pparametr, otrzymasz również pełny tekst poprawki, dokładnie tak, jakbyś robił różnicę git dla każdego zmienionego pliku.
Możesz to uczynić nieco jaśniejszym, dodając co masteri originrobię w opcjach wiersza poleceń, a co jeśli na przykład jestem na komputerze lokalnym branch1i chcę zrobić request-pullna lokalnej gałęzi funkcji branch2? Czy nadal potrzebuję origin? Oczywiście zawsze można przeczytać dokumentację.
Ela782
Niestety to polecenie działa tylko wtedy, gdy Rev # 2 jest nazwą gałęzi, nie działa dla skrótów: /
Jared Grubb
20
Dziwię się, że nikt jeszcze nie sugerował używania łatek.
Że chcesz przetestować scalania od your_branchdo master(Ja zakładając masz masterwyrejestrowany):
error: patch failed: test.txt:1
error: test.txt: patch does not apply
oznacza to, że łatka nie powiodła się, a scalenie spowodowałoby konflikty. Brak danych wyjściowych oznacza, że łatka jest czysta i można łatwo połączyć gałąź
Zauważ, że tak naprawdę nie zmieni to twojego działającego drzewa (oprócz tworzenia pliku łatki oczywiście, ale później możesz go bezpiecznie usunąć). Z dokumentacji git-Apply:
--check
Instead of applying the patch, see if the patch is applicable to the
current working tree and/or the index file and detects errors. Turns
off "apply".
Uwaga dla każdego, kto jest mądrzejszy / bardziej doświadczony w git ode mnie: daj mi znać, jeśli się mylę, a ta metoda wykazuje inne zachowanie niż zwykłe scalanie. Dziwne wydaje się, że w ciągu ponad 8 lat istnienia tego pytania nikt nie sugerowałby tego pozornie oczywistego rozwiązania.
Ta metoda jest przyjętą odpowiedzią na to pytanie, aw komentarzach są pewne zastrzeżenia, takie jak: „git nie był w stanie użyć„ rekurencyjnej ”strategii scalania” i „plik łatek podaje błąd dla nowych plików”. W przeciwnym razie wydaje się świetnie.
neno
1
Krótsza droga bez tworzenia pliku tymczasowego patch: git diff master your_branch | git apply --check.
ks1322
9
To może być interesujące: Z dokumentacji:
Jeśli próbowałeś scalenia, które zakończyły się złożonymi konfliktami i chcesz zacząć od nowa, możesz odzyskać za pomocą git merge --abort .
Ale możesz to zrobić naiwnie (ale powoli):
rm -Rf /tmp/repository
cp -r repository /tmp/
cd /tmp/repository
git merge ...
...if successful, do the real merge. :)
(Uwaga: nie będzie działało po prostu klonowanie do / tmp, potrzebujesz kopii, aby mieć pewność, że niezatwierdzone zmiany nie spowodują konfliktu).
Odmów scalenia i wyjdź ze stanu niezerowego, chyba że bieżący HEAD jest już aktualny lub scalenie można rozwiązać jako przewijanie do przodu.
Wykonanie tego spowoduje połączenie i szybkie przewijanie do przodu, a jeśli nie będzie możliwe, przerywa działanie i wyświetla monit o niemożność wykonania szybkiego przewijania do przodu, ale pozostawia działającą gałąź bez zmian. Jeśli może szybko przewinąć do przodu, wówczas wykona scalenie w działającym oddziale. Ta opcja jest również dostępna w dniu git pull. W ten sposób możesz wykonać następujące czynności:
git pull --ff-only origin branchA #See if you can pull down and merge branchA
git merge --ff-only branchA branchB #See if you can merge branchA into branchB
To zrobi scalenie, jeśli można to zrobić za pomocą szybkiego przewijania do przodu, czego nie chciałem w pierwotnym pytaniu. Myślę, że zaakceptowana odpowiedź ma drugą połowę, która ją naprawia.
Otto
Naprawdę jednak fantazyjne podpowiedzi gitów eliminują potrzebę, jaką mam do tego rodzaju rzeczy.
Otto
2
To nie jest tak samo. Wyjście ze statusem niezerowym, ponieważ scalenie nie może zostać rozwiązane, ponieważ przewijanie do przodu nie oznacza, że występują konflikty . Oznacza to po prostu, że historia się rozdzieliła i konieczne jest zatwierdzenie przez scalenie.
ADTC
7
Używam git log, aby zobaczyć, co zmieniło się w gałęzi funkcji od gałęzi master
Jeśli chcesz przewinąć do przodu z B do A, musisz upewnić się, że git log B..A niczego nie pokazuje, tzn. A nie ma niczego, czego B nie ma. Ale nawet jeśli B..A ma coś, nadal możesz być w stanie łączyć się bez konfliktów, więc powyższe pokazuje dwie rzeczy: że nastąpi szybkie przewijanie do przodu, a zatem nie dostaniesz konfliktu.
Zobaczysz, czy są jakieś konflikty i możesz zaplanować, jak je rozwiązać.
Następnie możesz albo przerwać scalanie za pomocą git merge --abort, albo (jeśli nie było żadnych konfliktów i scalenie się zdarzyło) wycofać do poprzedniego zatwierdzenia przezgit reset --hard HEAD~1
Odpowiedzi:
Jak wspomniano wcześniej, przekaż
--no-commit
flagę, ale aby uniknąć zatwierdzenia przewijania do przodu, przekaż także--no-ff
:Aby zbadać zmiany etapowe:
Możesz cofnąć scalanie, nawet jeśli jest to scalanie do przodu:
źródło
git merge --only-if-there-wont-be-any-conflicts
lubgit diff --show-conflicts <commit>
byłoby naprawdę przydatne. Szkoda, że to jeszcze nie możliwe, czy coś mi umknęło?git pull --ff-only
!Musiałem tylko zaimplementować metodę, która automatycznie wykryje konflikty między repozytorium a jego zdalnym. To rozwiązanie scala pamięć, aby nie dotknąć indeksu ani drzewa roboczego. Myślę, że jest to najbezpieczniejszy możliwy sposób rozwiązania tego problemu. Oto jak to działa:
git fetch origin master
git merge-base FETCH_HEAD master
git merge-tree mergebase master FETCH_HEAD
( mergebase to szesnastkowy identyfikator, który scalono -bazę wydrukowano w poprzednim kroku)Załóżmy teraz, że chcesz połączyć zdalny master z lokalnym master, ale możesz użyć dowolnych gałęzi.
git merge-tree
wykona scalenie w pamięci i wydrukuje wynik na standardowe wyjście. Grep dla wzoru<<
lub>>
. Lub możesz wydrukować dane wyjściowe do pliku i to sprawdzić. Jeśli znajdziesz linię zaczynającą się od „zmieniono w obu”, najprawdopodobniej wystąpi konflikt.źródło
git merge-tree `git merge-base FETCH_HEAD master` FETCH_HEAD master
git merge-tree `git merge-base clieop master` clieop master | grep -A3 "changed in both"
prostu niesamowita! +100+<<<<<<< .our
więc używam wyrażenia grep, takiego jakgrep -q '^+<* \.our$'
Moje proste rozwiązanie tego problemu to:
Utwórz gałąź „pre-master” (oczywiście od master)
Połącz wszystkie rzeczy, które chcesz, w ten przed-mistrz.
Następnie możesz zobaczyć, jak doszło do scalenia bez dotykania wzorca.
W każdym razie postępowałbym zgodnie z radą @ orange80.
źródło
git merge --abort
jeśli występują konflikty,git reset --hard HEAD~1
jeśli nastąpiło scalenie lubgit reset --hard origin/master
. Utworzenie kolejnej gałęzi daje poczucie bezpieczeństwa, ale jeśli nauczysz się, jak działa git, zrozumiesz, że to stracony strach. Jeśli chodzi o to, aby nie zmieniać kopii roboczej, nie ma rozwiązania.git merge --no-commit
nie przerwie scalania, jeśli można je szybko przesłać dalej.git merge --abort
nie działa, jeśli został scalony. Jeśli chcesz napisać to jako skrypt, jest to niewygodne, ponieważgit merge
nie odpowiada wystarczająco dobrymi kodami błędów, aby wyjaśnić różne typy konfliktów. Praca z nową gałęzią zapobiega pozostawieniu uszkodzonego skryptu w repozytorium w stanie wymagającym ręcznej interwencji. Pewnie, że nic nie możesz stracić. Ale łatwiej jest zbudować inaczej.Cofanie scalenia za pomocą git jest tak łatwe, że nie powinieneś nawet martwić się suchym przebiegiem:
EDYCJA: Jak zauważono w komentarzach poniżej, jeśli masz zmiany w katalogu roboczym lub obszarze przejściowym, prawdopodobnie zechcesz je ukryć przed wykonaniem powyższej czynności (w przeciwnym razie znikną po wykonaniu
git reset
powyższych czynności)źródło
git branch --contains HEAD
a nawet bardziej bezpośrednio, wystarczy użyćgit merge --ff-only
--dry-run
nie „po prostu sprawdzałby, czy scalenie będzie przewijać do przodu”. Zwróciłoby to dokładnie dane wyjściowe scalenia: pliki, konflikty itp. Czy ff nie jest tak naprawdę interesujące, prawda?git stash; git reset --hard
? @BrianPhillipsStworzyłem alias, aby to zrobić i działa jak urok, robię to:
Teraz dzwonię
Aby dowiedzieć się, czy są jakieś konflikty.
źródło
Po prostu różnicuj swoją obecną gałąź z gałęzią zdalną, to powie ci, co się zmieni, kiedy wykonasz ściąganie / scalanie.
źródło
Używam do tego polecenia git request-pull . Pozwala zobaczyć każdą zmianę, która miałaby miejsce podczas łączenia, ale bez robienia czegokolwiek na lokalnych lub zdalnych repozytoriach .
Na przykład wyobraź sobie, że chcesz scalić gałąź o nazwie „feature-x” z gałęzią master
pokaże podsumowanie tego, co by się stało (bez robienia czegokolwiek):
Jeśli dodasz
-p
parametr, otrzymasz również pełny tekst poprawki, dokładnie tak, jakbyś robił różnicę git dla każdego zmienionego pliku.źródło
master
iorigin
robię w opcjach wiersza poleceń, a co jeśli na przykład jestem na komputerze lokalnymbranch1
i chcę zrobićrequest-pull
na lokalnej gałęzi funkcjibranch2
? Czy nadal potrzebujęorigin
? Oczywiście zawsze można przeczytać dokumentację.Dziwię się, że nikt jeszcze nie sugerował używania łatek.
Że chcesz przetestować scalania od
your_branch
domaster
(Ja zakładając maszmaster
wyrejestrowany):To powinno wystarczyć.
Jeśli wystąpią błędy, takie jak
oznacza to, że łatka nie powiodła się, a scalenie spowodowałoby konflikty. Brak danych wyjściowych oznacza, że łatka jest czysta i można łatwo połączyć gałąź
Zauważ, że tak naprawdę nie zmieni to twojego działającego drzewa (oprócz tworzenia pliku łatki oczywiście, ale później możesz go bezpiecznie usunąć). Z dokumentacji git-Apply:
Uwaga dla każdego, kto jest mądrzejszy / bardziej doświadczony w git ode mnie: daj mi znać, jeśli się mylę, a ta metoda wykazuje inne zachowanie niż zwykłe scalanie. Dziwne wydaje się, że w ciągu ponad 8 lat istnienia tego pytania nikt nie sugerowałby tego pozornie oczywistego rozwiązania.
źródło
git diff master your_branch | git apply --check
.To może być interesujące: Z dokumentacji:
Ale możesz to zrobić naiwnie (ale powoli):
(Uwaga: nie będzie działało po prostu klonowanie do / tmp, potrzebujesz kopii, aby mieć pewność, że niezatwierdzone zmiany nie spowodują konfliktu).
źródło
cp -r repository/.git /tmp/repository/.git
,cd /tmp/repository
,git reset --hard
,git add --all
,git reset --hard
(na wszelki wypadek),git status
(aby sprawdzić, że jest czysty).Wiem, że to stare pytanie, ale pierwsze pojawia się w wyszukiwarce Google.
Podczas łączenia Git wprowadził opcję --ff-only.
Wykonanie tego spowoduje połączenie i szybkie przewijanie do przodu, a jeśli nie będzie możliwe, przerywa działanie i wyświetla monit o niemożność wykonania szybkiego przewijania do przodu, ale pozostawia działającą gałąź bez zmian. Jeśli może szybko przewinąć do przodu, wówczas wykona scalenie w działającym oddziale. Ta opcja jest również dostępna w dniu
git pull
. W ten sposób możesz wykonać następujące czynności:źródło
Używam git log, aby zobaczyć, co zmieniło się w gałęzi funkcji od gałęzi master
np. - aby zobaczyć, jakie zatwierdzenia znajdują się w gałęzi funkcji, która została / nie została scalona z master:
źródło
Jeśli chcesz przewinąć do przodu z B do A, musisz upewnić się, że git log B..A niczego nie pokazuje, tzn. A nie ma niczego, czego B nie ma. Ale nawet jeśli B..A ma coś, nadal możesz być w stanie łączyć się bez konfliktów, więc powyższe pokazuje dwie rzeczy: że nastąpi szybkie przewijanie do przodu, a zatem nie dostaniesz konfliktu.
źródło
Moim rozwiązaniem jest scalenie wstecz.
Zamiast scalać gałąź w zdalną gałąź „docelową”, scal ją z własną.
Zobaczysz, czy są jakieś konflikty i możesz zaplanować, jak je rozwiązać.
Następnie możesz albo przerwać scalanie za pomocą git
merge --abort
, albo (jeśli nie było żadnych konfliktów i scalenie się zdarzyło) wycofać do poprzedniego zatwierdzenia przezgit reset --hard HEAD~1
źródło
Utwórz tymczasową kopię swojej kopii roboczej, a następnie połącz ją i rozróżnij obie.
źródło