Korzystając z GIT, jak mogę selektywnie scalać zmiany z jednego zatwierdzenia w innym „rozwidleniu”?

81

Weź ten scenariusz:

  1. Decyduję się na „rozwidlenie” bazy kodu na github.com i zaczynam wykonywać swoją procedurę: Edycja - Zatwierdź - Wypchnij; aka hack hack hack.
  2. Po wprowadzeniu kilku zmian widzę zmiany, które inna osoba wprowadziła w tym samym projekcie i lubię je!
  3. Postanawiam, że chcę je połączyć w moje. Problem w tym, że chcę tylko „część” jednego konkretnego zatwierdzenia spośród kilku wykonanych przez niego zatwierdzeń.

Jaka byłaby najskuteczniejsza metoda połączenia tych wybranych ilości zmian w moim „forku”?

Tim
źródło

Odpowiedzi:

119

Po trollowaniu na falach świata IRC, ktoś podał świetne rozwiązanie:

git cherry-pick SHA1 --no-commit
git add --patch

Miejmy nadzieję, że to pomoże komukolwiek z tym samym pytaniem!

EDYCJA: OK, może to nie jest takie proste. Oto pełne kroki:

  1. Najpierw musisz być w swoim repozytorium, wykonać niezbędne czynności, cdaby dostać się do katalogu roboczego.

  2. Musisz teraz dodać zdalną gałąź, a następnie ją pobrać. Zrób to przez:

    git remote add someUser git://github.com/someUser/someRepo.git

    git fetch someUser

  3. Możesz teraz uruchamiać polecenia, takie jak git log someUser/masterznalezienie SHA1 zatwierdzenia, które chcesz scalić „częściowo”.

  4. Gdy masz już SHA, możesz teraz uruchomić:

    git cherry-pick -n SHA1

    gdzie SHA1jest zatwierdzenie SHA, duh!

  5. Prawdopodobnie wystąpią konflikty, w zależności od tego, ile lat ma zatwierdzenie i jak często zmienia się ten konkretny obszar projektu. Przepraszamy, ale musisz ręcznie rozwiązać te problemy za pomocą zaufanego edytora. Wyciągnij więc VIM lub cokolwiek innego, z którego korzystasz, i zrywaj konflikty, aż dojdziesz do etapu, na którym lubisz zmiany.

  6. Musisz teraz zresetować indeks do wersji HEAD, a następnie możesz użyć sprawdzonego add --patchpolecenia GIT, aby wybrać i wybrać żądane zmiany:

    git reset HEAD

    git add --patch lub git add -p

  7. Yay! Czas realizacji:

    git commit -m "I merged a select amount of changes"

  8. Aby posprzątać bałagan (rzeczy, którym odmówiłeś git add --patch) i zachować tylko wybrane zmiany w repozytorium roboczym, uruchom:

    git reset --hard HEAD

    Najwyraźniej git checkout -fjest to również inna opcja.

Tim
źródło
Cieszę się, że znalazłeś git add -p; jest niezwykle potężny. Jeśli masz już dane zatwierdzenie (np. Nie zostało użyte --no-commitna pick-upie lub jest to jedno z twoich zatwierdzeń), możesz użyć git reset HEAD^do przewinięcia indeksu do zatwierdzenia z powrotem, a następnie dodać zmiany z powrotem za pomocą git add -p, zatwierdzając krokami . Jeśli zatwierdzenia nie ma w końcówce gałęzi, możesz użyć git rebase -ii wybrać edycję danego zatwierdzenia.
Cascabel,
3
ładne przejście. pamiętaj, jeśli chcesz tylko całego zatwierdzenia, po prostu -ngit cherry-pick SHA1
emitujesz
Kluczowe jest tutaj git remote add <user> <fork-url>- wtedy możesz git cherry-picknormalnie.
Tom
2

Nie wiem, czego chcesz. Jeśli chcesz sprowadzić tylko niektóre zatwierdzenia z innych forków, możesz użyć git cherry-pick SHA. Pełne wyjaśnienie na temat gitready .

hgmnz
źródło
Jestem dopiero za „częścią” / „sekcją” / „kilkoma wierszami” jednego konkretnego zatwierdzenia, scalonymi z moim repozytorium. Niezbyt specyficzne dla pliku.
Tim
W takim przypadku, git format-patch SHA, git apply <patch> jest opcją
hgmnz
2

Naprawdę podoba mi się rozwiązanie Tima, jednak czasami lubię majsterkować w vimdiff. Moje rozwiązanie tego problemu jest prymitywne, ale działa dla mnie, ponieważ lubię vim.

Mam ustawionego vimdiffa jako moje difftool, a następnie, aby selektywnie scalić, odróżniam gałąź:

git difftool <branch> <file>

Następnie przechodzę do okienka z wersją bieżącej gałęzi i edytuję oryginał w vimie (czasami nie jest to konieczne, ale czasami vimdiff otwiera wersję w / tmp) i wyłączam tryb tylko do odczytu:

:e <file>
:set readonly!

Teraz mogę używać narzędzi łatek Vima, takich jak doi, dpaby zastosować to, co chcę, i wprowadzać inne drobne zmiany w trakcie. Kiedy skończę, zapisuję plik, wychodzę z vima, a następnie umieszczam i zatwierdzam plik w git jak zwykła edycja.

Jak powiedziałem, nie jest to szczególnie wyrafinowane, ale jest bardzo potężne i nadal działa wyłącznie w wierszu poleceń. Po prostu upewnij się, że dodałeś wyraźną wiadomość o zatwierdzeniu, ponieważ git nie dołączy automatycznie wiadomości o scaleniu.

przykład vimdiff http://j.mp/1dZVllt

Mike Dacre
źródło
Nie sądzę, aby ta odpowiedź w pełni kwalifikowała się jako godna niezależnej, pełnoprawnej odpowiedzi. Przydatne informacje, ale niezbyt istotne. (dlaczego to jest na górze odpowiedzi?)
Mike Kormendy
1

Jeśli chcesz tylko portu zatwierdzenia, prawdopodobnie najlepiej będzie, wybierając odpowiedni commit i resetując pliki, których nie chcesz zmieniać.

git cherry-pick SHA1
git checkout HEAD file1 file2 ... fileN

Oczywiście, jeśli masz kilka zmodyfikowanych części w pliku i chcesz zachować tylko niektóre z nich, nie masz innego wyjścia, jak edytować plik ręcznie, wycinając ich zmiany.

Bombe
źródło
2
Czy w tym miejscu konieczna jest płatność? Czy polecenie cherry pick nie umieszcza zmian w katalogu roboczym?
Casey Watson,