Как выбрать несколько коммитов

У меня есть две ветви. совершить a является главой одного, в то время как другой имеет b, c, d, e а также f на вершине a, Я хочу переехать c, d, e а также f на первую ветку без коммита b, С помощью вишневого кирки это легко: оформить первую ветку вишневого кирка по одному c в f и перебазировать вторую ветку на первую. Но есть ли способ черри все c-f в одной команде?

Вот визуальное описание сценария (спасибо JJD):

17 ответов

Решение

В Git 1.7.2 появилась возможность черпать ряд коммитов. Из примечаний к выпуску:

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


Включая важные комментарии (благодарности соответствующим авторам)

Примечание 1: В форме "cherry-pick A..B" A должно быть старше, чем B. Если они в неправильном порядке, команда молча завершится ошибкой. - Дамиан

Примечание 2: Кроме того, это будет не вишня А, а скорее все после А до B. Включая Б. - Д.Б. Рейнсбергер

Примечание 3: Для включения просто наберите git cherry-pick A^..B - sschaef

Если у вас есть выборочные ревизии для объединения, скажем, A, C, F, J из коммитов A,B,C,D,E,F,G,H,I,J, просто используйте команду ниже:

мерзкая вишня A C F J

Самый простой способ сделать это с 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 cherry-pick commit

Примеры:

      git cherry-pick my_branch                                 # by branch name
git cherry-pick 1e038f108a130831f108329b1083a8139813fabc  # by full hash
git cherry-pick 1e038f10                                  # by partial hash

2. выбрать несколько коммитов

Обратите внимание, что вы можете выбрать любое количество хэшей фиксации одновременно и в любом порядке. Они будут просто применяться по очереди и в указанном вами порядке. Если возникнут какие-либо конфликты, вам придется разрешать их по очереди, а затем использовать git add my_file тогда git cherry-pick --continue когда закончите, чтобы продолжить процесс выбора вишни.

      git cherry-pick commit1 commit2 commit3 commit4 commit5

3. выбрать диапазон коммитов

Изначально я изучил основы этого стиля из ответа @Eric Darchis, получившего наибольшее количество голосов.

Обратите внимание, что для выбора диапазона коммитов вы должны указать начальный и конечный хеш фиксации с помощью ..между ними. Однако в ряд коммитов начальная фиксация НЕ включается. Следовательно, чтобы включить его, вы должны указать фиксацию перед началом фиксации. Синтаксис для указания предыдущей фиксации: ~, ~1, или ^сразу после вашего коммита, как в: beginning_commit~, что означает: "фиксация прямо перед beginning_commit".

      # A. INCLUDING the beginning_commit
git cherry-pick beginning_commit~..ending_commit
# OR (same as above)
git cherry-pick beginning_commit~1..ending_commit
# OR (same as above)
git cherry-pick beginning_commit^..ending_commit 

# B. NOT including the beginning_commit
git cherry-pick beginning_commit..ending_commit

Примечание: commit~, commit~1, а также commit^все означают «одна фиксация до » или иначе сказано: «фиксация до».

Чтобы указать два коммита до, вы можете использовать такой синтаксис:

      commit~~
commit~2  # my preferred syntax
commit^^

Чтобы указать три коммита до commit, ты можешь сделать это:

      commit~~~  
commit~3   # my preferred syntax
commit^^^

Это не работает:

      commit^3   # INVALID syntax

Чтобы самостоятельно проверить приведенные выше концепции "синтаксиса предыдущей фиксации", проще всего использовать git logкоманда. Бывший:

      git log commit
git log commit~
git log commit~1
git log commit^
git log commit~~
git log commit~5
# etc.

Или запрашиваемый однострочный

git rebase --onto a b f

Вы можете использовать последовательную комбинацию git rebase а также git branch применить группу коммитов к другой ветке. Как уже сообщал wolfc, первая команда фактически копирует коммиты. Однако это изменение не будет отображаться до тех пор, пока вы не добавите имя ветви в самый верхний коммит группы.

Пожалуйста, откройте картинку в новой вкладке...

Workflow

Чтобы суммировать команды в текстовом виде:

  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 ветка.

В дополнение к этому ответу я написал сообщение в блоге, в котором описываются команды в другом сценарии, которые должны помочь в общем его использовании.

Чтобы применить комментарии JB Rainsberger и sschaef, чтобы конкретно ответить на вопрос... Чтобы использовать диапазон выбора вишни в этом примере:

git checkout a
git cherry-pick b..f

или же

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

Чтобы выбрать вишневый код от идентификатора фиксации до конца ветки, вы можете использовать:

git cherry-pick commit_id^..branch_name

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

Другой вариант, о котором стоит упомянуть, - если вы хотите, чтобы последний n совершает из ветки, ~ синтаксис может быть полезен:

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

В этом случае приведенная выше команда выберет последние 4 коммита из ветки с именем some-branch (хотя вы также можете использовать хеш фиксации вместо имени ветки)

Выберите несколько коммитов:

Перейдите в свою ветку, где вы хотите выбрать вишневые коммиты.

Используйте эту команду: (частичным хешем)

git вишневый выбор 1e038f10 1e038f11 1e038f12 ...

git format-patch --full-index --binary --stdout range... | git am -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 (и любые другие, которые вы хотите)


Мне нужно выбрать фиксацию из одной ветки в другую по приоритету, но коммиты здесь было трудно понять, надеюсь, ниже поможет с простым:


Порядок действий ниже:

  1. Получите 1 коммит с именем ("Удалить поле Фамилия") из ветки "dev"
  2. Закоммитить в ветке "hotfix1"

1 . Получить информацию о коммите из ветки "dev"

      // Go to "dev" branch
git checkout dev

// Get the commit id (1e2e3e4e1 here)
git log --oneline

    > ...
    > ...
    > 1e2e3e4e1     Remove Last Name field
    > ...
    > ...

2 . Вставьте фиксацию в ветку "hotfix1"

      // Go to "hotfix1" branch
git checkout hotfix1

// Get the commit (1e2e3e4e1) from "dev" branch to "hotfix1" branch
git cherry-pick 1e2e3e4e1

// verify changes are correct
gitk

// push to "hotfix1" branch
git push

Чтобы сделать несколько сразу, только 1 изменение в приведенном выше, укажите все идентификаторы коммитов последовательно:

      git cherry-pick 1e2e3e4e1 1e2e3e4e2 1e2e3e4e3

В дополнение к commit-ish вы можете передать список SHA из stdin.

      git rev-list --reverse ..main -- path/ | git cherry-pick --stdin 

rev-listпо сути, это команда сантехников («уродливая», но скорая родственница) git-log Обратите внимание , что --reverseнужно.

Таким образом вы можете делать более продвинутые вещи, а не просто диапазон коммитов.

Вот скрипт, который позволит вам выбрать несколько коммитов подряд, просто сообщив скрипту, какие исходные и целевые ветви для выбора вишни и количество коммитов:

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

Чтобы выбрать вишню из вашей ветки к мастеру (в качестве источника используется текущая ветка):

./gcpl.sh -m

Чтобы выбрать последние 5 коммитов из вашей ветки 6.19.x, выполните следующие действия:

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

В качестве альтернативы можно использовать настольное приложение GitHub ,

Вы можете выбрать несколько коммитов на вкладке истории исходной ветки, а затем щелкнуть правой кнопкой мыши, чтобы получить опцию «Cherry-Pick Selected Commits».

Другие вопросы по тегам