Използвам git в нов проект, който има два паралелни, но в момента експериментални клона за разработка:
master
: внос на съществуващата база данни плюс няколко модификации, за които като цяло съм сигуренexp1
: експериментален клон #1exp2
: експериментален клон #2exp1
и exp2
представляват два много различни архитектурни подхода. Докато не стигна по-далеч, няма как да знам кой от тях (ако изобщо има такъв) ще работи. Докато напредвам в единия клон, понякога имам редакции, които биха били полезни в другия клон, и бих искал да обединя само тях.
Какъв е най-добрият начин за сливане на селективни промени от един клон за разработка в друг, като се остави всичко останало?
Подходи, които съм обмислял:
git merge --no-commit
, последвано от ръчно разформироване на голям брой редакции, които не искам да бъдат общи за клоновете.
Ръчно копиране на общите файлове във временна директория, последвано от git checkout
за преместване в другия клон и след това още ръчно копиране от временната директория в работното дърво.
Вариация на горното. Отказ от клоновете exp
засега и използване на две допълнителни локални хранилища за експериментиране. Това прави ръчното копиране на файловете много по-просто.
И трите подхода изглеждат досадни и склонни към грешки. Надявам се, че има по-добър подход; нещо подобно на параметър за филтриране на пътя, който би направил git-merge
по-селективен.
Използвате командата cherry-pick, за да получите отделни коммити от един клон.
Ако желаните промени не са в отделни коммити, използвайте метода, показан тук, за да разделите коммита на отделни коммити. Грубо казано, използвате git rebase -i
, за да получите оригиналния коммит, който да редактирате, след това git reset HEAD^
, за да върнете селективно промените, и след това git commit
, за да запишете тази част като нов коммит в историята.
Има и друг хубав метод тук в Red Hat Magazine, където се използва git add --patch
или евентуално git add --interactive
, който ви позволява да добавяте само части от хънка, ако искате да разделите различни промени на отделен файл (търсете в тази страница за "split").
След като сте разделили промените, сега можете да изберете само тези, които искате.
Не харесвам горните подходи. Използването на cherry-pick е чудесно за избор на една промяна, но е мъчително, ако искате да въведете всички промени, с изключение на някои лоши. Ето моя подход.
Няма аргумент --интерактивен
, който да подадете на git merge.
Ето и алтернативата:
Имате някои промени в клона 'feature' и искате да прехвърлите някои от тях, но не всички, в клона 'master' по небрежен начин (т.е. не искате да избирате и да предавате всяка от тях)
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
Така че просто обвийте това в шел скрипт, променете master в $to и променете feature в $from и сте готови:
#!/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
1800 ИНФОРМАЦИЯ'отговорът е напълно верен. Като git noob обаче, "use git cherry-pick" не ми беше достатъчен, за да разбера това без малко повече ровене в интернет, затова реших да публикувам по-подробно ръководство, в случай че някой друг е в подобна лодка.
Моят случай на употреба беше, че исках избирателно да изтегля промени от някой друг клон на github в моя собствен. Ако вече имате локален клон с промените, трябва да направите само стъпки 2 и 5-7.
Създайте (ако не сте създали) локален клон с промените, които искате да внесете.
$ git branch mybranch <base branch>
Превключете се в него.
$ git checkout mybranch
Изтеглете желаните промени от акаунта на другия човек. Ако все още не сте ги добавили, ще трябва да ги добавите като отдалечени.
$ git remote add repos-w-changes <git url>
Изтеглете всичко от техния клон.
$ git pull repos-w-changes branch-i-want
Прегледайте дневниците за извършени промени, за да видите кои промени искате:
$ git log
Превключете обратно към клона, в който искате да изтеглите промените.
$ git checkout originalbranch
Изберете поотделно своите ангажименти с помощта на хешовете.
$ git cherry-pick -x hash-of-commit
Съвет от шапката: http://www.sourcemage.org/Git_Guide