Jeśli chcę scalić się z gałęzią Git, zmiany dokonane tylko w niektórych plikach zmienionych w konkretnym zatwierdzeniu, które obejmują zmiany wielu plików, jak można to osiągnąć?
Załóżmy, że git commit nazywa stuff
ma zmian w plikach A
, B
, C
, a D
jednak chcę scalić tylko stuff
„s zmian w plikach A
i B
. Brzmi jak zadanie, git cherry-pick
ale cherry-pick
wie tylko, jak scalić całe zatwierdzenia, a nie podzbiór plików.
git
github
cherry-pick
Tobias Kienzler
źródło
źródło
git checkout .
tego polecam równieżgit clean -f
usunięcie wszelkich nowych, ale niechcianych plików wprowadzonych przez zatwierdzony wybór.git add -p
która pozwala interaktywnie decydować, które zmiany chcesz dodać do indeksu na plikgit reset -p HEAD
. Jest to odpowiednik,add -p
ale bardzo niewielu wie, że istnieje.Inne metody nie działały dla mnie, ponieważ zatwierdzenie zawierało wiele zmian i konfliktów z wieloma innymi plikami. To, co wymyśliłem, było po prostu
W rzeczywistości nie zawiera
add
plików ani nie wykonuje zatwierdzenia, więc być może będziesz musiał to zrobićLub jeśli chcesz pominąć dodawanie, możesz użyć
--cached
argumentu dogit apply
Możesz także zrobić to samo dla całych katalogów
źródło
show SHA -- file | apply
zasadniczo nie robi tego samego,checkout SHA -- file
co w odpowiedzi Marka Longaira ?checkout SHA -- file
przejdzie dokładnie do wersji SHA, podczas gdyshow SHA -- file | apply
zastosuje tylko zmiany w SHA (tak jak robi to cherry-pick). Ma znaczenie, czy (a) istnieje więcej niż jeden zatwierdzenie zmieniające dany plik w gałęzi źródłowej, lub (b) istnieje zatwierdzenie zmieniające plik w bieżącej gałęzi docelowej.git revert
cofa całe zatwierdzenie). W takim przypadku wystarczy użyćgit show -R SHA -- file1.txt file2.txt | git apply -
git diff SHA -- file1.txt file2.txt | git apply -
oznacza zastosowanie wszystkich różnic między bieżącą wersją pliku a wersją w SHA do bieżącej wersji. W istocie jest to to samo cogit checkout SHA -- file1.txt file2.txt
. Zobacz mój wcześniejszy komentarz, dlaczego różni się on odgit show
wersji.git apply -3 -
zamiast po prostugit apply -
, a jeśli wystąpi konflikt, możesz użyć standardowej techniki rozwiązywania konfliktów, w tym przy użyciugit mergetool
.Zwykle używam
-p
flagi z kasą git z innej gałęzi, co uważam za łatwiejsze i bardziej szczegółowe niż większość innych metod, z którymi się spotkałem.Zasadniczo:
przykład:
Następnie pojawia się okno dialogowe z pytaniem, jakie zmiany chcesz w „obiektach blob”, co właściwie działa na każdą część ciągłej zmiany kodu, którą możesz następnie zasygnalizować
y
(Tak)n
(Nie) itp. Dla każdej części kodu.The
-p
lubpatch
działa z wieloma poleceniami w git, w tymgit stash save -p
co pozwala ci wybrać, co chcesz ukryć w bieżącej pracyCzasami używam tej techniki, kiedy wykonałem dużo pracy i chciałbym ją rozdzielić i zatwierdzić więcej tematycznych zatwierdzeń, używając
git add -p
i wybierając to, co chcę dla każdego zatwierdzenia :)źródło
git-add -p
, ale nie wiedziałemgit-checkout
też, że ma-p
flagę - czy to rozwiązuje problemy z-p
łączeniem, których brak odpowiedzi ?-p
pozwoliłoby na ręczną edycję takiej sprzecznej sekcji, któracherry-pick
prawdopodobnie i tak by się przyniosła. Przetestuję to następnym razem, gdy będę tego potrzebować, zdecydowanie interesujące podejściegit reset -p HEAD
zezwala również na to,-p
co może być przydatne, gdy chcesz usunąć tylko niektóre poprawki z indeksu.Być może przewaga tej metody nad odpowiedzią Jefromiego to, że nie musisz pamiętać, które zachowanie git reset jest właściwe :)
źródło
cherry-pick
i bezpośrednio użyćgit checkout stuff -- A B
? A przygit commit -C stuff
przekazie zatwierdzenia również pozostanie to samostuff
nie zostały zmienione na bieżącym oddział lub w dowolnym miejscu pomiędzy wspólnego przodkaHEAD
istuff
a końcówkąstuff
. Jeśli tak, tocherry-pick
tworzy poprawny wynik (zasadniczo wynik scalenia), podczas gdy twoja metoda odrzuci zmiany w bieżącej gałęzi i zachowa wszystkie zmiany od wspólnego przodka dostuff
- nie tylko tych w tym pojedyncze zatwierdzenie.stuff
że wynik wybrania wiśni odszedłA
iB
miał inną treść niż ich zawartość w zatwierdzeniustuff
. Jeśli jednak byłoby tak samo, masz rację - możesz zrobić tak, jak mówisz.Cherry pick to wybieranie zmian z określonego „zatwierdzenia”. Najprostszym rozwiązaniem jest wybranie wszystkich zmian określonych plików
W przykładzie:
Źródła i pełne wyjaśnienie http://jasonrudolph.com/blog/2009/02/25/git-tip-how-to-merge-specific-files-from-another-branch/
AKTUALIZACJA:
Dzięki tej metodzie git nie połączy pliku, po prostu nadpisze wszelkie inne zmiany dokonane w gałęzi docelowej. Konieczne będzie ręczne scalenie zmian:
źródło
Sytuacja:
Powiedzmy, że jesteś w swoim oddziale
master
i masz swoje zatwierdzenie w dowolnym innym oddziale. Musisz wybrać tylko jeden plik z tego konkretnego zatwierdzenia.Podejście:
Krok 1: Kasa w wymaganym oddziale.
Krok 2: Upewnij się, że skopiowałeś wymagany hash zatwierdzenia.
Krok 3: Masz teraz zmiany wymaganego pliku w wybranym oddziale. Wystarczy je dodać i zatwierdzić.
źródło
Po prostu wybrałbym wszystko, a następnie zrobiłbym to:
Następnie cofnę zmiany, których nie chcę, a następnie dokonam nowego zatwierdzenia.
źródło
Użyj
git merge --squash branch_name
tego, aby uzyskać wszystkie zmiany z drugiego oddziału i przygotować dla ciebie zatwierdzenie. Teraz usuń wszystkie niepotrzebne zmiany i pozostaw tę, którą chcesz. I git nie będzie wiedział, że nastąpiła fuzja.źródło
Znalazłem inny sposób, który zapobiega wszelkim konfliktowym połączeniom podczas zbierania wiśni, które IMO jest w pewnym sensie łatwe do zapamiętania i zrozumienia. Ponieważ tak naprawdę nie wybierasz zatwierdzenia, ale jego część, musisz najpierw go podzielić, a następnie utworzyć zatwierdzenie, które będzie odpowiadać twoim potrzebom i wybierz go.
Najpierw utwórz gałąź z zatwierdzenia, które chcesz podzielić, i sprawdź:
Następnie cofnij poprzednie zatwierdzenie:
Następnie dodaj pliki / zmiany, które chcesz wybrać:
i popełnij to:
zwróć uwagę na skrót zatwierdzenia, nazwijmy go PICK-SHA i wróć do głównej gałęzi, na przykład master wymuszając kasę:
i wybieraj zatwierdzenie:
teraz możesz usunąć gałąź temp:
źródło
Połącz gałąź w nową (squash) i usuń niepotrzebne pliki:
źródło
Dla kompletności najlepsze dla mnie jest:
Robi dokładnie to, czego chce OP. W razie potrzeby rozwiązuje konflikty, podobnie jak
merge
to robi. To robi,add
ale niecommit
twoje nowe zmiany.źródło
Możesz użyć:
Notacja
<commit>^
określa (pierwszego) rodzica<commit>
. Dlatego to polecenie diff wybiera zmiany dokonane<path>
w zatwierdzeniu<commit>
.Zauważ, że to jeszcze niczego nie popełni (jak to
git cherry-pick
robi). Więc jeśli tego chcesz, musisz zrobić:źródło