git: Zastosuj zmiany wprowadzone przez zatwierdzenie w jednym repozytorium do innego repozytorium

115

Mam repo1i repo2na komputerze lokalnym. Są bardzo podobne, ale ta ostatnia jest jakąś inną gałęzią ( repo1nie jest już utrzymywana).

/path/to/repo1 $ git log HEAD~5..HEAD~4
<some_sha> Add: Introduce feature X

Jak zastosować zmiany dokonane przez zobowiązać <some_sha>się repo1do repo2?

Czy muszę przygotować jakąś łatkę, czy można zrobić kilka cherry-pickmiędzy repozytoriami?

Co powiesz na to samo, ale dla zakresu zatwierdzeń?

takeshin
źródło
2
Nie możesz po prostu przejść z repo1 do repo2?
zwol
w przypadku nieco bardziej szczegółowego przypadku, w którym chcesz zastosować zmiany w pliku lub plikach, które zostały przeniesione w jednym z repozytoriów, spójrz tutaj: stackoverflow.com/questions/3491270/ ...
Braham Snyder

Odpowiedzi:

31

Jako hack możesz spróbować zmodyfikować przepis na porównywanie zatwierdzeń w dwóch różnych repozytoriach na stronie GitTips , tj .:

GIT_ALTERNATE_OBJECT_DIRECTORIES=../repo/.git/objects \
git cherry-pick $(git --git-dir=../repo/.git rev-parse --verify <commit>)

gdzie ../repojest ścieżka do innego repozytorium.

Dzięki nowoczesnemu Gitowi możesz używać wielu wersji i zakresów wersji za pomocą najlepszego wyboru .

$(git --git-dir=../repo/.git rev-parse --verify <commit>) Jest tutaj, aby przetłumaczyć <commit>(na przykład HEAD, albo v0.2, lub master~2, które są wartościami w drugim repozytorium) do skopiowania z SHA-1 Identyfikator popełnić. Jeśli znasz SHA-1 zmiany, którą chcesz wybrać, nie jest to konieczne.

UWAGA jednak, że Git może pominąć kopiowanie obiektów z repozytorium źródłowego, ponieważ nie wie, że alternatywne repozytorium obiektów jest tylko tymczasowe, dla jednej operacji. Może być konieczne skopiowanie obiektów z drugiego repozytorium za pomocą:

GIT_ALTERNATE_OBJECT_DIRECTORIES=../repo/.git/objects git repack -a -d -f

Spowoduje to umieszczenie tych obiektów pożyczonych z drugiego repozytorium w oryginalnym repozytorium

Nie testowany.


Nie tak zręcznym rozwiązaniem jest podążanie za odpowiedzią Knittla :

  • Przejdź do drugiego repozytorium, z którego chcesz skopiować zatwierdzenia, i wygeneruj poprawki z zatwierdzeń, które chcesz git format-patch
  • Opcjonalnie skopiuj łaty (0001- * itp.) Do swojego repozytorium
  • Służy git am --3waydo nakładania łat
Jakub Narębski
źródło
1
Działa dobrze. Jeśli masz problemy z zatwierdzeniem, wykonaj 'git reset HEAD; git add. '.
gumik
5
to jest niesamowite - jak zrobiłbyś szereg zatwierdzeń? tylko sha1 ... sha2?
hvgotcodes
Ja też dostaję fatal: unable to read tree ...ale po git reset HEAD^wszystkim działa dobrze
jmarceli
@hvgotcodes zadziałało dla mnie po prostu przekazując zakres jako, <commit>ale rev-parse --verifypolecenie nie lubi tego, ponieważ akceptuje tylko pojedyncze wartości zatwierdzeń. Ale ponieważ cherry-pickakceptuje zarówno wartości zatwierdzenia pojedynczego, jak i zakresu, pytam: dlaczego jest rev-parsepotrzebny?
Chuim
1
@Chuim: git rev-parsejest potrzebna, jeśli chcesz zapoznać się zatwierdzeniem przez jego nazwę ref oparte na innej repozytorium, na przykład master, HEAD^^czy coś takiego; rev-parse zamienia go w uniwersalny identyfikator SHA-1.
Jakub Narębski
207

Prawdopodobnie będziesz chciał użyć, git format-patcha następnie git amzastosować tę poprawkę do swojego repozytorium.

/path/to/1 $ git format-patch sha1^..sha1
/path/to/1 $ cd /path/to/2
/path/to/2 $ git am -3 /path/to/1/0001-…-….patch

Lub w jednej linii:

/path/to/2 $ git --git-dir=/path/to/1/.git format-patch --stdout sha1^..sha1 | git am -3
knittl
źródło
9
To rozwiązanie okazało się prostsze i bezpieczniejsze niż przyjęta odpowiedź polegająca na bezpośrednim wybieraniu najlepszych GIT_ALTERNATE_OBJECT_DIRECTORIES(to mogłoby uszkodzić moje repozytorium).
Chuim
2
Kiedy występują konflikty, nie zadziała, ponieważ nie znajduje zatwierdzeń w drugiej gałęzi.
Roger Far
2
Dodanie --ignore-whitespacedo git ampolecenia może rozwiązać wszelkie konflikty i uniknąć konieczności wykonywania trójstronnego scalenia
Hugheth
98

Możesz to zrobić, cherry-pickjeśli dodasz drugie repozytorium jako pilot do pierwszego (a potem fetch).

wRAR
źródło
11
Właściwie to właściwy sposób, aby to zrobić.
Wilbert
5
Dla mnie to też jest właściwa droga. Po prostu go użyłem i działało dobrze.
Ricky Nelson,
11
Raczej powiedziałbym: zrób git fetch [remote-name]w drugim repozytorium, a potem git cherry-pick [sha1].
5
To podejście zadziałało świetnie, dzięki. Ponieważ drugie repozytorium również było lokalne, wystarczyło użyć identyfikatora URI pliku podczas dodawania go jako zdalnego.
palimpsestor
2
W moim przypadku mam dwa klony gigantycznego zdalnego repozytorium git (aby umożliwić równoległą pracę), co oznacza, że ​​cała jego historia jest już pobrana i dwukrotnie zapisana w moim HD. Gdybym musiał również dodać każdą z nich jako zdalne od drugiej, stworzyłoby to jeszcze dwie dodatkowe kopie tej samej historii i potencjalnie wymagałoby synchronizacji między nimi, zanim będę mógł cherry-pick. Więc nawet jeśli wydaje się to „właściwą” drogą, nie zawsze jest to najbardziej praktyczne.
Chuim