Jak mogę odrzucić zdalne zmiany i oznaczyć plik jako „rozwiązany”?

197

Mam trochę plików lokalnych, ściągam ze zdalnej gałęzi i są konflikty. Wiem, że chciałbym zachować moje lokalne zmiany i zignorować zmiany zdalne powodujące konflikty. Czy istnieje polecenie, którego mogę użyć, aby powiedzieć „oznacz wszystkie konflikty jako rozwiązane, użyj lokalnego”?

Tom DeMille
źródło
1
Poniższa odpowiedź była dla mnie bardzo pouczająca. Jest kilka subtelnych uwag, które naprawdę wyjaśniają mi wszystko. Polecam każdemu niewykwalifikowanemu użytkownikowi GIT przeczytanie wszystkich komentarzy pod postem poniżej i dziękuję Brian!
Tom DeMille,

Odpowiedzi:

332

git checkoutma --oursopcję sprawdzenia wersji pliku, który miałeś lokalnie (w przeciwieństwie do --theirswersji, którą ściągnąłeś). Możesz przejść, .aby git checkoutpowiedzieć mu, aby sprawdził wszystko w drzewie. Następnie należy oznaczyć konflikty jako rozwiązane, co można zrobić git add, i po zakończeniu zlecić swoją pracę:

git checkout --ours .  # checkout our local version of all files
git add -u             # mark all conflicted files as merged
git commit             # commit the merge

Zwróć uwagę .na git checkoutpolecenie. To bardzo ważne i łatwe do pominięcia. git checkoutma dwa tryby; jeden, w którym przełącza gałęzie, i jeden, w którym sprawdza pliki z indeksu do kopii roboczej (czasami najpierw wyciągając je do indeksu z innej wersji). Wyróżnia go to, czy podałeś nazwę pliku; jeśli nie podałeś nazwy pliku, spróbuje zamienić gałęzie (chociaż jeśli nie podasz też gałęzi, po prostu spróbuje ponownie sprawdzić bieżącą gałąź), ale odmawia tego, jeśli istnieją zmodyfikowane pliki to by miało wpływ. Jeśli więc chcesz zachować zachowanie, które zastąpi istniejące pliki, musisz przekazać .lub nazwę pliku, aby uzyskać drugie zachowanie git checkout.

Dobrym nawykiem jest także przekazywanie nazwy pliku, aby to zrównoważyć --, np git checkout --ours -- <filename>. Jeśli tego nie zrobisz, a nazwa pliku pasuje do nazwy gałęzi lub znacznika, Git pomyśli, że chcesz sprawdzić tę wersję, zamiast sprawdzić nazwę pliku, i użyj pierwszej formy checkoutpolecenia .

Rozwińę trochę, jak konflikty i scalanie działają w Git. Kiedy scalasz się w czyimś kodzie (co dzieje się również podczas ściągania; ściąganie to w zasadzie pobranie, a następnie scalenie), istnieje kilka możliwych sytuacji.

Najprostsze jest to, że korzystasz z tej samej wersji. W tym przypadku „jesteś już na bieżąco” i nic się nie dzieje.

Inną możliwością jest to, że ich wersja jest po prostu twoją potomką, w takim przypadku domyślnie będziesz miał „szybkie przewijanie do przodu”, w którym twój HEADjest właśnie aktualizowany do zatwierdzenia, bez łączenia się (to można wyłączyć, jeśli naprawdę chcę nagrać scalenie, używając --no-ff).

Następnie przechodzisz do sytuacji, w których faktycznie potrzebujesz scalić dwie wersje. W takim przypadku istnieją dwa możliwe wyniki. Jednym z nich jest to, że scalanie odbywa się czysto; wszystkie zmiany są w różnych plikach lub w tych samych plikach, ale wystarczająco daleko od siebie, aby oba zestawy zmian można było zastosować bez problemów. Domyślnie, gdy nastąpi czyste scalenie, jest ono automatycznie zatwierdzane, ale możesz to wyłączyć, --no-commitjeśli musisz go wcześniej edytować (na przykład, jeśli zmienisz nazwę funkcji foona bar, a ktoś inny doda nowy wywołujący kod foo, scali się czysto , ale produkuj złamane drzewo, więc możesz to wyczyścić w ramach zatwierdzenia scalania, aby uniknąć przerwania zatwierdzeń).

Ostateczna możliwość polega na tym, że istnieje prawdziwe scalenie i konflikty. W tym przypadku, Git zrobi tyle scaleniu jak to możliwe, a pliki produkt z markerów konfliktowych ( <<<<<<<, =======, i >>>>>>>) w kopii roboczej. W indeksie (znanym również jako „obszar przejściowy”; miejsce przechowywania plików git addprzed ich zatwierdzeniem ) będziesz mieć 3 wersje każdego pliku z konfliktami; istnieje oryginalna wersja pliku pochodząca od przodka dwóch gałęzi, które scalasz, wersja z HEAD(twojej strony scalania) i wersja ze zdalnego oddziału.

Aby rozwiązać konflikt, możesz edytować plik znajdujący się w kopii roboczej, usuwając znaczniki konfliktu i naprawiając kod tak, aby działał. Lub możesz sprawdzić wersję z jednej lub drugiej strony scalenia, używając git checkout --ourslub git checkout --theirs. Po ustawieniu pliku w żądanym stanie, oznaczasz, że skończyłeś git addscalać plik i jest on gotowy do zatwierdzenia za pomocą , a następnie możesz zatwierdzić scalenie git commit.

Brian Campbell
źródło
7
Prawdopodobnie powinieneś zauważyć, że git add --alldodaje wszystkie pliki do repozytorium, więc może dodać więcej plików, niż zamierzono, chyba że .gitignorewzorce są w idealnym stanie. git add -ujest prawdopodobnie bardziej odpowiedni w tej sytuacji, rzadziej wprowadzane są zmiany w plikach śledzonych, których nie chcesz dodawać podczas rozwiązywania scalania.
CB Bailey,
UPS przepraszam. O to mi chodziło. Poprawiłem to teraz.
Brian Campbell,
1
dziękuję za szczegółową odpowiedź. W rzeczywistości próbowałem git checkout --ours i otrzymałem komunikat o błędzie (którego teraz nie pamiętam). Pliki, o których mowa, to dll (mamy kilka, które przechowujemy, głównie referencje stron trzecich) i chciałem po prostu powiedzieć „OK, moja kopia to te, których chcę, ale błąd był taki, jak„ nie można kasy podczas scalania ” ..... Zachowam ten artykuł jako odniesienie i następnym razem, gdy to się stanie, spróbuj ponownie i sprawdź, czy działa lub czy mogę opublikować tę wiadomość. Jeszcze raz dziękuję
Tom DeMille,
ale twoje wyjaśnienie wyjaśnia mi wiele na temat tego procesu, jeszcze raz dziękuję ... Dalsze pytanie: Jakikolwiek sposób, aby git usunął pliki .orig, gdy tylko wyczyszczę scalanie?
Tom DeMille,
2
Musisz to zrobić git checkout --ours .. To .jest ważne; przekazując nazwę pliku (w tym przypadku cały katalog) wybiera się dwa różne tryby działania checkout, jeden, który przełącza gałęzie i jeden, który przenosi pliki z indeksu do kopii roboczej. Zgadzam się, to bardzo mylące. Możesz także git checkout --ours -- <filename>sprawdzić pojedynczy plik na raz.
Brian Campbell,
23

Upewnij się, że od początku konfliktu: czy jest to wynik o tematyce git mergepatrz Brian Campbell „s odpowiedź .

Ale jeśli jest to wynikiem git rebase, aby odrzucić zdalne (ich) zmiany i użyć zmian lokalnych , musisz wykonać:

git checkout --theirs -- .

Zobacz „ Dlaczego znaczenie„ ours”i„ theirs”jest odwrócone” ”, aby zobaczyć, jak oursi theirssą zamieniane podczas zmiany bazy (ponieważ gałąź nadrzędna jest wyewidencjonowana).

VonC
źródło