Kako selektivno združiti ali izbrati spremembe iz druge veje v sistemu Git?

Uporabljam sistem git pri novem projektu, ki ima dve vzporedni - vendar trenutno eksperimentalni - razvojni veji:

  • master: uvoz obstoječe baze kode in nekaj modifikacij, o katerih sem na splošno prepričan
  • exp1: eksperimentalna veja #1
  • exp2: eksperimentalna veja #2

exp1 in exp2 predstavljata dva zelo različna arhitekturna pristopa. Dokler ne pridem še dlje, ne morem vedeti, kateri (če sploh kateri) bo deloval. Ko napredujem v eni veji, včasih imam popravke, ki bi bili uporabni v drugi veji, in bi rad združil le te.

**Kateri je najboljši način za združitev izbranih sprememb iz ene razvojne veje v drugo, pri čemer ostane vse drugo?

Pristopi, o katerih sem razmišljal:

  1. git merge --no-commit, ki mu sledi ročno odstranjevanje velikega števila sprememb, za katere ne želim, da bi bile skupne med vejami.

  2. Ročno kopiranje skupnih datotek v začasni imenik, ki mu sledi git checkout za premik v drugo vejo, nato pa še eno ročno kopiranje iz začasnega imenika v delovno drevo.

  3. Različica zgornjega načina. Za zdaj opustite veje exp in uporabite dve dodatni lokalni shrambi za eksperimentiranje. Tako je ročno kopiranje datotek veliko bolj preprosto.

Vsi trije pristopi se zdijo zamudni in nagnjeni k napakam. Upam, da obstaja boljši pristop; nekaj podobnega parametru poti za filtriranje, ki bi naredil git-merge bolj selektiven.

Rešitev

Z ukazom cherry-pick pridobite posamezne revizije iz ene veje.

Če želene spremembe niso v posameznih revizijah, uporabite tukaj prikazano metodo razdelitev revizije na posamezne revizije. V grobem uporabite git rebase -i, da dobite prvotno oddajo za urejanje, nato git reset HEAD^ za selektivno vračanje sprememb, nato git commit za oddajo tega dela kot nove oddaje v zgodovino.

Tu je še ena lepa metoda v Red Hat Magazine, kjer uporabljajo git add --patch ali morda git add --interactive, ki omogoča dodajanje samo delov hunka, če želite razdeliti različne spremembe na posamezno datoteko (na tej strani poiščite "split").

Ko ste razdelili spremembe, lahko zdaj izberete le tiste, ki jih želite.

Komentarji (12)

Zgornji pristopi mi niso všeč. Uporaba cherry-pick je odlična za izbiro ene spremembe, vendar je boleča, če želite vnesti vse spremembe, razen nekaterih slabih. Tukaj je moj pristop.

Ni argumenta `--interaktivno´, ki bi ga lahko posredovali programu git merge.

Tukaj je alternativa:

imate nekaj sprememb v veji 'feature' in želite nekatere, vendar ne vse, prenesti v vejo 'master' na način, ki ne bi bil površen (tj. ne želite izbrati in oddati vsake od njih).

git checkout feature
git checkout -b temp
git rebase -i master

# Above will drop you in an editor and pick the changes you want ala:
pick 7266df7 First change
pick 1b3f7df Another change
pick 5bbf56f Last change

# Rebase b44c147..5bbf56f onto b44c147
#
# Commands:
# pick = use commit
# edit = use commit, but stop for amending
# squash = use commit, but meld into previous commit
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#

git checkout master
git pull . temp
git branch -d temp

Zato to preprosto zapakirajte v lupinsko skripto, spremenite master v $to in spremenite feature v $from in lahko začnete:

#!/bin/bash
# git-interactive-merge
from=$1
to=$2
git checkout $from
git checkout -b ${from}_tmp
git rebase -i $to
# Above will drop you in an editor and pick the changes you want
git checkout $to
git pull . ${from}_tmp
git branch -d ${from}_tmp
Komentarji (7)

1800 INFORMACIJA'odgovor je popolnoma pravilen. Kot git noob pa "use git cherry-pick" ni bilo dovolj, da bi to ugotovil brez malo več brskanja po internetu, zato sem mislil, da bom objavil podrobnejši vodnik, če je še kdo v podobni situaciji.

Moj primer uporabe je bil, da sem želel selektivno prenesti spremembe iz neke druge veje githuba v svojo vejo. Če že imate lokalno vejo s spremembami, morate opraviti le korake 2 in 5-7.

  1. Ustvarite (če še niste ustvarili) lokalno vejo s spremembami, ki jih želite vnesti.

    $ git branch mybranch

  2. Preklopite vanjo.

    $ git checkout mybranch

  3. Z računa druge osebe prenesite želene spremembe. Če jih še niste dodali, jih dodajte kot oddaljene.

    $ git remote add repos-w-changes

  4. Iz njihove veje prenesite vse, kar potrebujete.

    $ git pull repos-w-changes branch-i-want

  5. Oglejte si dnevnike sprememb in ugotovite, katere spremembe želite:

    $ git log

  6. Preklopite nazaj na vejo, v katero želite prenesti spremembe.

    $ git checkout originalbranch

  7. Svoje spremembe po vrsti izberite s pomočjo hashev.

    $ git cherry-pick -x hash-of-commit

Nasvet: http://www.sourcemage.org/Git_Guide

Komentarji (3)