git cherry-pick говорить: "... 38c74d - це злиття, але жодна опція -m не була надана"


518

Я вніс кілька змін у свою головну галузь і хочу перенести їх вище. коли я вишу наступні зобов’язання, однак я застряг на fd9f578, де git говорить:

$ git cherry-pick fd9f578
fatal: Commit fd9f57850f6b94b7906e5bbe51a0d75bf638c74d is a merge but no -m option was given.

Що git намагається сказати мені, і чи є вишневий вибір потрібної речі тут? Основна гілка включає зміни у файлах, які були змінені у верхній частині гілки, тому я впевнений, що виникнуть деякі конфлікти злиття, але вони не надто погані для виправлення. Я знаю, які зміни потрібні, де.

Це зобов'язання, які я хочу внести вище за течією.

e7d4cff added some comments...
23e6d2a moved static strings...
44cc65a incorporated test ...
40b83d5 whoops delete whitspace...
24f8a50 implemented global.c...
43651c3 cleaned up ...
068b2fe cleaned up version.c ...
fd9f578 Merge branch 'master' of ssh://extgit/git/sessions_common
4172caa cleaned up comments in sessions.c ...

Відповіді:


606

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

Отже, якщо в комісії є два або більше батьків, воно також представляє два чи більше відмінностей - який із них слід застосовувати?

Ви намагаєтеся вибирати вишню fd9f578, яка була злиттям з двома батьками. Тож вам потрібно вказати команду cherry-pick, яку саме команду слід розраховувати, використовуючи -mпараметр. Наприклад, git cherry-pick -m 1 fd9f578використовувати батьківський 1 в якості основи.

Я не можу сказати точно для вашої конкретної ситуації, але використовувати git mergeзамість цього, git cherry-pickяк правило, доцільно. Коли ви вибираєте вибір злиття, він згортає всі зміни, внесені в батьківській програмі, яку ви не вказали, -mв цю одну комітку . Ви втрачаєте всю їхню історію, і збираєте разом усі їхні відмінності. Твій дзвінок.


3
@wufoo Ви, мабуть, також повинні дізнатися про git rebaseце - це як злиття, але замість того, щоб інтегрувати дві гілки, він пересаджує одну, щоб сидіти поверх іншої.
Borealid

91
як ти знаєш батьківський номер?
Анентропний

66
@Anentropic 1 - це "перший батько", 2 - "другий батько" тощо. Порядок - це той, у якому вони вказані у коміті (як переглянуто git showтощо).
Borealid

2
@lkraav Ви також могли б лише щойно зробити, git reset --hard HEAD@{1}щоб повернути пропущене зобов’язання. git resetне обмежується переміщенням "назад" в історії. git checkout -b mybranch HEAD@{1}також працював би.
Borealid

4
ПОПЕРЕДЖЕННЯ: git mergeможе мати непередбачувані наслідки. Ця команда додасть усі інші (старіші) комісії, які існують у батьківській гілці. Зазвичай люди обирають вишню, бо не хочуть інших зобов'язань. Переконайтесь, що ви двічі переконайтеся, що впроваджуєте лише потрібні зміни!
Kay V

52

-m означає батьківський номер.

З git doc:

Зазвичай ви не можете вибирати злиття, оскільки ви не знаєте, яку сторону злиття слід вважати основною лінією. Цей параметр вказує батьківський номер (починаючи з 1) основної лінії та дозволяє вишневому вибору відтворити зміну відносно вказаного батьківського.

Наприклад, якщо дерево ваших комірок наведено нижче:

- A - D - E - F -   master
   \     /
    B - C           branch one

то git cherry-pick Eвидасть проблему, з якою ви стикалися.

git cherry-pick E -m 1означає використовувати D-E, тоді як git cherry-pick E -m 2означає використовувати B-C-E.


32

@ Відповідь Borealid правильна, але припустимо, що вам не байдуже зберігати точну історію з’єднання гілки, а просто хочете вишнево вибрати лінеаризовану її версію. Ось простий і безпечний спосіб зробити це:

Початковий стан: ви перебуваєте на гілці X, і ви хочете, щоб вишні взяли коміти Y..Z.

  1. git checkout -b tempZ Z
  2. git rebase Y
  3. git checkout -b newX X
  4. git cherry-pick Y..tempZ
  5. (необов’язково) git branch -D tempZ

Для цього потрібно створити гілку tempZна основі Z, але з історією від Yподальшого лінеаризації, а потім виберіть вишню на копії, що Xназивається newX. (Безпечніше робити це на новій гілці, а не мутувати X.) Звичайно, на кроці 4 можуть виникнути конфлікти, які вам доведеться вирішувати звичайним способом ( cherry-pickпрацює дуже як rebaseу цьому відношенні). Нарешті він видаляє тимчасову tempZгілку.

Якщо на кроці 2 подано повідомлення "Поточна tempZ гілки оновлена", вона Y..Zвже була лінійною, тому просто ігноруйте це повідомлення та продовжуйте виконувати кроки 3 вперед.

Потім перегляньте newXі подивіться, чи зробили це те, що хотіли.

(Зауважте: це не те саме, що просто, git rebase Xколи ви на гілці Z, оскільки це жодним чином не залежить від взаємозв'язку між Xі Y; між спільним предком можуть бути коміти, Yякі ви не хотіли.)


1
git rebase YкажеCurrent branch tempZ is up to date
Василевс

Я думаю, це означає, що Y..Zце вже було лінійним. Тож ви можете проігнорувати це повідомлення та перейти до кроків 3 та 4.
Дайра Хопвуд

1
Цікава ідея, мені довелося намалювати її на папері, щоб повністю оцінити, що відбувається = D
Кріс

2
Блискуча. git cherry-pick для цілого ряду скаржився або на те, що опція -m відсутня, або що вона надана. Ваше рішення було золотим. (Одна пропозиція: видалити гілку tempZ після)
Отей

1
це дивно! я боровся з вишневим вибором, і тільки це мало сенс. У мене були проблеми з
вибраними

19

Спростіть. Вишні виберіть коміти. Не вишне вибирайте злиття.

Ось перезапис прийнятої відповіді, який ідеально пояснює переваги / ризики можливих підходів:

Ви намагаєтеся вибрати вишню fd9f578, що було об'єднанням з двома батьками.

Замість того, щоб вишні вибирати злиття, найпростіше - це вишня вибрати комбінент (и), які ви насправді хочете з кожної гілки в об'єднанні.

Оскільки ви вже об'єдналися, швидше за все, всі бажані вами зобов'язання є у вашому списку. Виберіть їх безпосередньо, і вам не потрібно возитися з об'єднанням.

пояснення

Спосіб вибору вишні полягає в тому, щоб взяти diff, який являє собою набір змін (різниця між робочим деревом у цій точці та робочим деревом його батьків) і застосував набір змін до вашої поточної гілки.

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

альтернативи

Якщо ви визначите, що вам потрібно включити злиття проти вишні, пов'язані з ними, у вас є два варіанти:

  1. (Більш складний і незрозумілий; також викидає історію) ви можете вказати, до кого з батьків слід звернутися.

    • Використовуйте -mваріант, щоб зробити це. Наприклад, git cherry-pick -m 1 fd9f578буде використаний перший батьківський згаданий в об'єднанні в якості основи.

    • Також врахуйте, що коли ви вибираєте комісію злиття, вона згортає всі зміни, внесені в батьківському, який ви не вказали, -mу цей один коміт . Ви втрачаєте всю їхню історію, і збираєте разом усі їхні відмінності. Твій дзвінок.

  2. (Простіший і звичніший; зберігає історію), який ви можете використовувати git mergeзамість git cherry-pick.

    • Як і зазвичай git merge, вона намагатиметься застосувати всі комітети, які існують у гілці, яку ви об’єднуєте, та перелічити їх окремо у вашому журналі git.

2

Спрощення методу @Daira Hopwood добре для вибору одного окремого комітету. Не потрібні тимчасові відділення.

У випадку з автором:

  • Z потрібний фіксатор (fd9f578)
  • Y здійснює перед цим
  • X поточна робоча галузь

тоді зробіть:

git checkout Z   # move HEAD to wanted commit
git reset Y      # have Z as changes in working tree
git stash        # save Z in stash
git checkout X   # return to working branch
git stash pop    # apply Z to current branch
git commit -a    # do commit

2
Це, звичайно, втрачає метадані, пов'язані з початковим комітом. Я думаю, це питання думки, чи простіше це. Я використовую його іноді, коли хочу втратити метадані і зберегти лише зміни загального коду. Зауважте, що він працює, навіть якщо Y не є безпосереднім батьком Z (в цьому випадку зміни будуть стиснуті).
Дайра Хопвуд
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.