Отслеживание слияния для Git сбора вишни?
Например, у меня есть ветвь dev
и ветвь stable
.
В случае, если я выбрал вишню, выделите из dev
в stable
.
Есть ли способ сообщить Git о выбранных вишнях коммитах и избежать двойного слияния, если я позже слияю, переустанавливаю или вишня выбираю перекрытый диапазон, от dev
до stable
? (для которого базовая функция отслеживания слияния в SVN)
Ответы
Ответ 1
На самом деле существует команда с именем git cherry, которая печатает каждое сообщение, которое не объединено между двумя ветвями.
Для каждой напечатанной фиксации знак "+" означает, что вы можете объединить ее, знак "-" означает, что вы уже выбрали червь, который зафиксировал.
Выход не очень хорош.
Для тех, кто пришел из SVN и используется для svnmerge.py, я сделал эквивалент svnmerge avail -l bash script для git, который я назвал gitavail:
#!/bin/bash
# get current branch
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
# get tracked branch (1st argument), if no arg or arguments are only options, assume master
if test -z $1 || grep -q '^-' <<< $1;
then TRACKED_BRANCH=master
else TRACKED_BRANCH=$1; shift
fi
# Log commits available for merge from tracked branch
LOG_OPTIONS=$*
for i in $(git cherry $CURRENT_BRANCH $TRACKED_BRANCH | egrep '^\+' | awk '{print $2}'); do git --no-pager log -n1 $i ${LOG_OPTIONS}; echo; done
Предполагая, что вы находитесь на ветке, и вы хотите перечислить, что подходит для слияния с главной ветвью, просто запустите:
gitavail --name-status
И вы получите результат, очень похожий на "svnmerge avail -l".
Я думаю, что коммиты с вишневым записями не должны быть изменены вручную (как насчет конфликтов?), если изменяется патч-идентификатор, git вишня не поймет, что фиксация уже выбрана вишней.
Ответ 2
Также примечательно, что флаг -x
для cherry-pick
добавляет SHA исходной фиксации в конец сообщения фиксации.
Мне нравится добавлять сокращенную SHA в конец сводки фиксации тоже, чтобы было проще связать собранную вишней фиксацию с оригиналом при просмотре журнала. Указание того, кто сделал вишневый выбор, также может быть полезным, с флагом -s
signoff.
Пример:
> git cherry-pick -sex 27d4985
#333: fixes all the things (27d4985)
- how it fixes all the things
(cherry picked from commit 27d49855238364d0184ad344884a366b5b16e)
Signed-off-by: Chuck Norris <[email protected]>
Ответ 3
git cherry-pick
является забавным случаем git rebase
, а не git merge
, поэтому он действительно перезаписывает фиксацию, которую вы выбрали черри, чтобы она применила те же самые изменения к вершине ветки, которую вы выбрали в вишне. Поскольку идентификаторы git commit основаны на содержимом коммита, новый commit имеет другой идентификатор и поэтому считается совершенно другим фиксацией с помощью git.
git merge
, с другой стороны, создает фиксацию слияния; это средство, с помощью которого git реализует отслеживание слиянием. Комбинация слияния отмечает точку, в которой сходятся две (или более) расходящиеся истории. Допустимо вызывать git merge [commit-id]
вместо git cherry-pick [commit-id]
для явного создания фиксации слияния, но это приводит не только к последствиям одиночной фиксации вишни, но и ко всему набору изменений в этой ветки, расходящейся в истории.
При всем том, что "двойное слияние" обычно не является проблемой в git. Если вы попытаетесь объединиться с историей, содержащей набор изменений, который уже присутствует, он просто станет no-op, когда истории склеиваются; git действительно заботится только о состоянии дерева в каждом коммите, а не об изменениях, которые попали в это состояние.