Ответ 1
По умолчанию информация об исходном, "вишневом" фиксации не записывается как часть нового коммита.
Записать фиксацию источника в объявлении
Если вы можете принудительно использовать определенные рабочие процессы/параметры,
git cherry-pick имеет параметр -x
:
При записи фиксации добавьте к исходному сообщению фиксации примечание, указывающее, какое из этих изменений было выбрано из вишни.
Это, очевидно, бесполезно, если вы не можете полагаться на вишневых сборщиков, используя эту опцию.
Кроме того, поскольку записанная информация представляет собой простой текст, а не фактическую ссылку на Git, даже если вы используете -x
, вам все равно нужно предпринять шаги, чтобы убедиться, что исходная фиксация сохранена (например, является частью DAG тега или ветки без перематывания).
git вишня и Git patch-id
Если вы можете ограничить поиск двумя отдельными ветвями DAG истории, то git cherry может найти как "unpicked", так и "выбрал" вишни".
Примечание. Эта команда (и связанный с ней git патч-идентификатор) могут идентифицировать только конфликтные вишни, которые были индивидуально выбраны без дополнительных изменений. Если возник конфликт, когда вы выбираете вишню (например, вам нужно было слегка изменить его, чтобы заставить его применить), или вы использовали -n
/--no-commit
, чтобы выполнить дополнительные изменения (например, несколько вишней в одном коммите) или содержимое коммита было переписано после выбора, тогда вам придется полагаться на сравнение сообщений совершения (или информацию -x
, если она была записана).
git Вишня не предназначена для определения происхождения собранных вишен, но мы можем немного ее использовать, чтобы идентифицировать отдельные вишневые пары.
Учитывая следующую историю DAG (как в примере с оригинальными плакатами):
1---2---3---B---D master
\
A---C dev
# D is a cherry-picked version of C
вы увидите что-то вроде этого:
% git cherry master dev
+ A
- C
% git cherry dev master
+ B
- D
(A, B, C и D - полные SHA-1 хэши в реальном выходе)
Поскольку в каждом списке мы видим одну вишню (строки -
), они должны образовать вишневую пару. D была вишня, выбранная из C (или наоборот, вы не можете сказать только с помощью DAG, хотя даты фиксации могут помочь).
Если вы имеете дело с более чем одной потенциальной вишней, вам нужно будет "сворачивать свою" программу, чтобы сделать сопоставление. Код должен быть простым на любом языке с ассоциативными массивами, хешами, словарями или эквивалентными. В awk это может выглядеть так:
match_cherries() {
a="$(git rev-parse --verify "$1")" &&
b="$(git rev-parse --verify "$2")" &&
git rev-list "$a...$b" | xargs git show | git patch-id |
awk '
{ p[$1] = p[$1] " " $2 }
END {
for (i in p) {
l=length(p[i])
if (l>41) print substr(p[i],2,l-1)
}
}'
}
match_cherries master dev
В расширенном примере, в котором есть две собранные вишни:
1---2---3---B---D---E master
\
A---C dev
# D is a cherry-picked version of C
# E is a cherry-picked version of A
Результат может выглядеть так:
match_cherries master dev
D C
E A
(A, C, D и E - полные SHA-1 хэши в реальном выходе)
Это говорит нам, что C и D представляют одно и то же изменение и что E и A представляют одно и то же изменение. Как и раньше, нет способа определить, какая из каждой пары была "первой", если вы не учитываете (например) даты фиксации каждой фиксации.
Сравнение контрольных сообщений
Если ваши вишни не были выбраны с помощью -x
, или они "грязные" (имели конфликты или другие изменения, добавленные к ним (т.е. с помощью --no-commit
плюс дополнительные изменения или с помощью git commit --amend
или другой "истории переписывания" )), тогда вам, возможно, придется отказаться от менее надежной методики сравнения сообщений фиксации.
Этот метод работает лучше всего, если вы можете найти бит сообщения о фиксации, который, вероятно, будет уникальным для фиксации, и вряд ли изменится в фиксации, возникшей в результате выбора вишни. Бит, который будет работать лучше всего, будет зависеть от стиля сообщений фиксации, используемых в вашем проекте.
Как только вы выбрали "идентификационную часть" сообщения, вы можете использовать git log, чтобы найти коммиты (также продемонстрированные в Ответ Джефриса).
git log --grep='unique part of the commit message' dev...master
Аргумент --grep
на самом деле является регулярным выражением, поэтому вам может потребоваться избежать любых метасимволов регулярного выражения ([]*?.\
).
Если вы не уверены, какие ветки могут содержать исходную фиксацию и новую фиксацию, вы можете использовать --all
, как показал Jefromi.