Як вишнево підбирати кілька комірок


873

У мене є два відділення. Commit aє главою одного, а інші мають b, c, d, eі fна вершині a. Я хочу рухатися c, d, eі fдо першої гілки без фіксації b. Використання вишні забрати його легко: фотографії першої гілки вишневого вибрати один за іншим cдо fі перебазуватися другу гілку на першій. Але чи є спосіб вибрати всіх c- fоднією командою?

Ось наочний опис сценарію (дякую JJD ):

введіть тут опис зображення


3
ребайна база, яку ви згадуєте, не дуже важлива для питання, чи не так? (Я розумію, що ви, можливо, хочете bбазуватися на fпізніше, але це не має нічого спільного з збиранням вишні.)
Superole

Відповіді:


1280

Git 1.7.2 представив можливість вишні вибирати діапазон вигод. З приміток до випуску :

git cherry-pickнавчився вибирати ряд комісій (наприклад, cherry-pick A..Bта cherry-pick --stdin), так і робив git revert; вони не підтримують приємніший контроль послідовності rebase [-i], хоча.

Щоб вишнево вибрати всі зобов’язання від зобов’язання Aдо здійснення B(там, де Aстарше B), запустіть:

git cherry-pick A^..B

Якщо ви хочете ігнорувати A, запустіть:

git cherry-pick A..B

(Кредит стосується Даміана, Дж. Б. Райнсбергера та сшаф у коментарях)


249
У формі "вишневий A..B" форма A повинна бути старшою за B. Якщо вони неправильні, команда мовчки не виконає.
даміан

294
Крім того, це не буде вибирати вишню A, а скоріше все після A до B, включаючи B.
JB Rainsberger

454
Щоб включити A just typegit cherry-pick A^..B
kiritsuku

17
Якщо у вас є git 1.7.1 або новішої версії, і ви не можете оновити, ви можете досить швидко вибрати їх у порядку, запустивши git cherry-pick f~3потім git cherry-pick f~2і т.д. до git cherry-pick f(натискання стрілки вгору отримує попередню команду, щоб я міг швидко змінити номер і запустити воно, має бути подібним у більшості консолей).
Девід Мейсон

19
Можливо, добре знати, що цей синтаксис працює і з іменами гілок. git cherry-pick master..somebranchвибере всі коміти на якомусь відгалуженні, оскільки master (якщо припустити, що вже перезавантажено на master), і застосує їх до вашої поточної гілки.
Tor Klingberg

102

Найпростіший спосіб зробити це з ontoможливістю rebase. Припустимо , що галузь , яка в даний час закінчується в aназивається mybranch і це підрозділ , яке ви хочете перемістити c- fна.

# checkout mybranch
git checkout mybranch

# reset it to f (currently includes a)
git reset --hard f

# rebase every commit after b and transplant it onto a
git rebase --onto a b

1
Дякую! Чи можете ви також додати git checkout secondbranch && git rebase mybranchповну відповідь
тигр

1
Ця відповідь мені дуже допомогла розібратися в тому, яка фіксація є в цьому сценарії. І: ви також можете використовувати rebaseінтерактивний режим. Дякую, @Charles!
Олівер

1
Краса такого підходу полягає в тому, що ви можете використовувати --interactiveдля вилучення деяких послідовностей з послідовності або впорядкувати їх перед "вишневим вибором". +1
Michael Merickel

це геніальна команда, трохи хитра, щоб обернути голову, але це творить чудеса.
Валеріо

Не дивно, що ви повинні взяти на себе зобов’язання, яке ви не хочете переглядати як один із аргументантів ( bу цьому прикладі), але так, це спрацювало для мене.
asontu

85

Або запитуваний однолінійний:

git rebase --onto a b f

5
Якби тільки для його стислості, це найкраща відповідь.
Нейт Чендлер

9
Оновлено, але залишить вас у відокремленому стані HEAD, якщо f - фіксація (на відміну від гілки) - вам слід відредагувати, щоб додати, що слід оформити перевірку гілки, як відповідь нижче
Mr_and_Mrs_D

68

Ви можете використовувати послідовну комбінацію git rebaseта git branchзастосувати групу комітетів до іншої гілки. Як вже було опубліковано wolfc, перша команда фактично копіює коміти. Однак зміни не видно, доки ви не додасте ім'я гілки до верхньої частини комісії групи.

Будь ласка, відкрийте зображення в новій вкладці ...

Робочий процес

Для узагальнення команд у текстовій формі:

  1. Відкритий gitk як самостійний процес , з допомогою команди: gitk --all &.
  2. Біжи git rebase --onto a b f.
  3. Преса F5в gitk . Нічого не змінюється. Але ні HEADвідмічено.
  4. Біжи git branch selection
  5. Преса F5в gitk . З'являється нова філія з її комісіями.

Це має з’ясувати:

  • Команда a- це нове кореневе призначення групи.
  • Коміт b- це вчинення перед першим вчиненням групи (виключно).
  • Коміт f- це остання комісія групи (включно).

Після цього ви можете використовувати , git checkout feature && git reset --hard bщоб видалити коммітов cдо fвід featureфілії.

На додаток до цієї відповіді я написав допис у блозі, де описуються команди за іншим сценарієм, який повинен допомогти загалом її використовувати.


2
Якщо mybranch (a..f фіксує) більше не потрібен, це можна спростити до: git rebase --onto a b mybranchі btw - за якою програмою роблять ці чудові зображення git?
Mr_and_Mrs_D

2
@Mr_and_Mrs_D Дякуємо за ваш коментар Я думаю, що я використав cacoo.com для малювання фотографій.
JJD

48

Щоб застосувати коментарі JB Rainsberger та sschaef, щоб спеціально відповісти на питання ... Використовувати на цьому прикладі діапазон вишень:

git checkout a
git cherry-pick b..f

або

git checkout a
git cherry-pick c^..f

3
Я використовував git 2.7.0.windows.1і зауважував, що коли я намагаюся вибирати вишневий діапазон фільмів, все нормально, але git ніде вам не скаже, що вам потрібно зробити, git cherry-pick --continue | --abort | --quitперш ніж спробувати здійснити / вишневий вибір. Отже, якщо ви вибираєте вишневий діапазон зобов’язань, вам потрібно буде виконувати git cherry-pick --continueкожен раз, коли ви будете готові (вирішувати конфлікти чи подібне) з дозволом із заданого діапазону.
кускмен

Я зробив саме так, але фатально: Не можу знайти "a..b"
Аміт Карник

Я не знаю, де я помиляюся, але коли я роблю 'git cherry-pick c ^ .. f' на моєму боці, це включає в себе команду f, але не фіксацію c. Але, як я читаю всюди, це повинно визначати c і f як включно. Або я помиляюся?
Самуїл

@Samuel так, це правильно. ^Після того , як з на самому ділі означає «фіксація , перш ніж з" , який є б у даному випадку. Ось чому c^..fце синонім до b..f. Спробуйте зробити, git log c^..fі ви повинні побачити, що виконує c через f, точно так само, як і виgit log b..f
Енді

40

Якщо у вас є вибіркові редакції для злиття, скажімо, A, C, F, J від A, B, C, D, E, F, G, H, I, J чини, просто використовуйте команду нижче:

git cherry-pick ACFJ


1
приємно і просто
спіну

21
git rev-list --reverse b..f | xargs -n 1 git cherry-pick

2
Працює ідеально, якщо немає конфліктів, інакше "перестановка на" може бути простішою, оскільки вам не доведеться з'ясовувати, де вона зупинилася, і повторно застосовувати решту патчів.
Руслан Кабалін

6
Будь ласка, додайте коментарі, що пояснюють, що це робить
Mr_and_Mrs_D

7
оскільки ніхто не пояснював ... git rev-list друкує всі зміни від гілки b до f (зворотній), так що коли кожен рядок (хеш фіксації) буде переданий в порядку, він буде вишнево вибирати кожен на поточну Git HEAD. тобтоgit cherry-pick {hash of c}; git cherry-pick {hash of d}; ...
кодератчет

8

Щоб вибрати вишневий ідентифікатор коміксу до кінця гілки, ви можете використовувати:

git cherry-pick commit_id^..branch_name


Це вже частина відповіді stackoverflow.com/a/31640427/96823
салити

1
Ця відповідь насправді інша і була мені корисною. Він вказує назву філії, а не остаточну комісію SHA.
Subtletree

7

Ще один варіант, який варто згадати, полягає в тому, що якщо ви хочете останнього nкомітету з гілки, ~синтаксис може бути корисним:

git cherry-pick some-branch~4..some-branch

У цьому випадку вищевказана команда вибирає останні 4 коміти з названої гілки some-branch(хоча ви також можете використовувати хеш фіксації замість назви гілки)


1
ДУЖЕ корисна відповідь, дякую! :)
Яцек Джурджиковскі

3

Насправді найпростішим способом це було:

  1. записати базу злиття між двома гілками: MERGE_BASE=$(git merge-base branch-a branch-b)
  2. перемотати вперед або переставити стару гілку на нову гілку
  3. перезавантажте отриману гілку на себе, починаючи з основи злиття з кроку 1, і видаліть вручну елементи, які не бажані:

    git rebase ${SAVED_MERGE_BASE} -i
    

    Крім того, якщо є лише кілька нових комітетів, пропустіть крок 1 і просто скористайтеся

    git rebase HEAD^^^^^^^ -i
    

    на першому кроці, використовуючи достатньо, ^щоб пройти повз базу злиття.

Щось подібне ви побачите в інтерактивній базі даних:

pick 3139276 commit a
pick c1b421d commit b
pick 7204ee5 commit c
pick 6ae9419 commit d
pick 0152077 commit e
pick 2656623 commit f

Потім видаліть рядки b (і будь-які інші, які ви хочете)



0

Ось сценарій, який дозволить вам вибирати кілька команд підряд, просто повідомляючи сценарій, яке джерело та цільові гілки для вишень вибору та кількість комісій:

https://gist.github.com/nickboldt/99ac1dc4eb4c9ff003a1effef2eb2d81

Щоб вибрати вишню з вашого відділення для майстра (використовує поточну гілку як джерело):

./gcpl.sh -m

Щоб вибрати останні 5 комітетів з вашої гілки 6.19.x для освоєння:

./gcpl.sh -c 5 -s 6.19.x -t master

Навіщо потрібен цей сценарій, коли ви можете це робити безпосередньо з Git? ...
code_dredd

Менше набирайте текст, і мій сценарій автоматично підбирає вам зобов’язання, тому вам не доведеться вибирати кожного за його SHA. У всякому разі, YMMV.
nickboldt
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.