Wyciągnij wszystkie zatwierdzenia z gałęzi, prześlij określone zatwierdzenia do innej

102

Mam następujące oddziały:

  • master
  • production

oraz następujące zdalne oddziały:

  • origin/master
  • origin/production

Mam skrypt, który pobiera origin/mastergałąź i pobiera różnicę tego, co zmieniło się od mojego ostatniego fetch ( log -p master..origin/master). Potem łączę się origin/master.

Znalezione zatwierdzenia są przekazywane do narzędzia do przeglądania kodu.

Chcę skierować udane commity - i tylko je - do gałęzi produkcyjnej, a potem oczywiście do origin/production.

Jak mogę to zrobić?

Mam również uruchomione 2 skrypty: ten, który pobiera z origin/master, przekazuje szczegóły zatwierdzeń do bazy danych i łączy, oraz drugi, który właśnie piszę, i który będzie musiał wypychać udane zatwierdzenia.

Chciałbym, aby te 2 skrypty działały, unikając konfliktu warunków wyścigu / scalania. Ponieważ chcę pracować tylko z określonymi zatwierdzeniami, może jest sposób na pozbycie się zatwierdzeń, których nie chcę?

Sylvain
źródło
Co masz na myśli mówiąc o „udanych zatwierdzeniach”?
bdonlan
ten, który został sprawdzony i oznaczony jako pomyślny. to naprawdę nie ma znaczenia, ważne jest to, że są zatwierdzenia, które chcę zachować i wypchnąć do innej gałęzi, a także inne, których chcę się pozbyć / zignorować.
Sylvain

Odpowiedzi:

313

Wydaje mi się, że termin, którego szukasz, to „wiśniowy wybór”. Oznacza to, że weź pojedynczy commit ze środka jednej gałęzi i dodaj go do innego:

A-----B------C
 \
  \
   D

staje się

A-----B------C
 \
  \
   D-----C'

Można to oczywiście zrobić za pomocą polecenia git cherry-pick.

Problem z tym zatwierdzeniem polega na tym, że git uważa, że ​​zatwierdzenia zawierają całą historię przed nimi - więc jeśli masz trzy takie zatwierdzenia:

A-----B-----C

I spróbuj pozbyć się B, musisz stworzyć zupełnie nowy commit, taki jak:

A-----------C'

Gdzie C 'ma inny identyfikator SHA-1. Podobnie, wiśniowe wybieranie zmiany z jednej gałęzi do drugiej polega w zasadzie na wygenerowaniu łatki, a następnie zastosowaniu jej, a tym samym utracie historii w ten sposób.

Ta zmiana identyfikatorów zatwierdzeń łamie między innymi funkcjonalność scalania git (chociaż jeśli jest używana oszczędnie, istnieją heurystyki, które to opisują). Co ważniejsze, ignoruje zależności funkcjonalne - jeśli C faktycznie używał funkcji zdefiniowanej w B, nigdy się nie dowiesz.

Być może lepszym sposobem radzenia sobie z tym byłoby posiadanie bardziej drobnoziarnistych gałęzi. Oznacza to, że zamiast po prostu mieć „master”, miej „featureA”, „bugfixB” itd. Przeprowadź przegląd kodu na całej gałęzi na raz - gdzie każda gałąź jest bardzo skoncentrowana na robieniu tylko jednej rzeczy - a następnie połącz ją jedna gałąź, kiedy skończysz. To jest przepływ pracy, do którego jest przeznaczony git iw czym jest dobry :)

Jeśli nalegasz na zajmowanie się rzeczami na poziomie łatek, możesz spojrzeć na darcs - traktuje repozytorium jako zestaw łatek, a zatem wybieranie wiśni staje się podstawową operacją. Ma to jednak swój własny zestaw problemów, takich jak bycie bardzo wolnym :)

Edycja: Poza tym nie jestem pewien, czy rozumiem twoje drugie pytanie, dotyczące dwóch skryptów. Może mógłbyś opisać to bardziej szczegółowo, być może jako osobne pytanie, aby uniknąć zamieszania?

bdonlan
źródło
Jeśli chodzi o moje drugie pytanie, chcę się tylko upewnić, że procesy pobierania zmian (pierwszy skrypt) i wypychanie danych zatwierdzeń do innej lokalizacji (drugi skrypt) mogą działać bez sytuacji wyścigu / konfliktu scalania, podczas pracy z różnymi gałęziami. Ale ostatecznie myślę, że to nie ma znaczenia, ponieważ mogłem połączyć 2 skrypty w jeden, więc 2 skrypty nie działają jednocześnie :)
Sylvain
9
„Ta zmiana identyfikatorów zatwierdzeń łamie między innymi funkcjonalność scalania gita
Narek
5
@Narek Prawdopodobnie oznacza to, że zmiany w zatwierdzeniu C 'będą kolidować z tymi samymi zmianami w zatwierdzeniu C, gdy scalisz drugą gałąź. To konsekwencja utraty historii za popełnieniem C.
bytefu,
1
„I spróbuj się pozbyć B” - dlaczego próbujesz się pozbyć B?
d512
3
@ user1334007, ma na myśli, że wcześniej było to ABC. Teraz, ze względu na Twój ulubiony C, twoja gałąź to AD-C ”, która nie zawiera już„ B ”.
AnneTheAgile
1

Zdaję sobie sprawę, że to stare pytanie, ale odwołuje się do niego tutaj: Jak scalić określone zatwierdzenie w Git

Stąd nowsza odpowiedź: użyj gałęzi funkcji i żądań ściągnięcia.

Jak to wygląda, gdzie fA jest zatwierdzeniem z funkcją A, a fB jest zatwierdzeniem z funkcją B:

            fA   fC (bad commit, don't merge)
           /  \ /
master ----A----B----C
                \  /
                 fB

Żądania pull są powiązane z funkcjonalnością GitHub, ale tak naprawdę mam na myśli tylko to, że ktoś jest odpowiedzialny za scalenie gałęzi funkcji w master.

MattJenko
źródło