Да, вы можете делать именно то, что просили (но не делайте; см. Ниже).Например (это довольно хрупко, поскольку я предполагаю, что число 270 является правильным, и что первое слияние будет работать; оно также полностью не проверено ...):
b=development-kirby
m=development
git checkout $m
# 270 = 50 + 50 + 50 + 50 + 50 + 20
# hence, to be done in groups of 50, the commit-points are:
# $b~219, $b~169, $b~119, $b~69, $b~19, and $b (aka $b~0)
for dist in 219 169 119 69 19 0; do
# want to merge $b~$dist into $m, and we're (still) on $m
git merge --no-ff $b~$dist -m "mechanical merge at $b~$dist"
done
Это должно дать вам кое-чтонапример:
---- K1 --...-- K50 ---- K51..K100 --- ... --- K201...K250 --- K251..K270 development-kirby
/ \ \ \ \ \
* --- D1 --- D2 --- D3 --- M1 --------- M2 --- ... --- M4 ----------- M5 --- M6 development
, где K1..K270 - это ваши 270 коммитов, а D1 - D3 - три примера коммитов, которые были установлены на development
с тех пор, как вы начали свою работу.
(--no-ff
гарантирует, что все шесть действительных коммитов слияния, от M1 до M6, окажутся в репо, в противном случае вы получите быстрые форварды и у вас просто будет M1 в вышеупомянутом, с K51 до K270 на вершине, иветвь development
теперь указывает на то же место, что и ветвь development-kirby
:
---- K1 --...-- K50 --- --- K51..K270 development-kirby, development
/ \ /
* --- D1 --- D2 --- D3 --- M1
[Может быть полезно отметить, что между ними во время каждого «промежуточного ускоренного перехода вперед» development
будетуказывает на некоторый коммит в промежутке K51..K269, в то время как development-kirby
будет продолжать указывать на коммит K270. Только после самого последнего ускоренного перехода два имени ветви будут указывать на один и тот же коммит.])
Проблема в том, что это странно инеумная вещь, чтобы сделать.Эти промежуточные коммиты слияния, если они выбраны чисто механически («каждые 50» или что-то еще), бесполезны.Они не дают вам абсолютно ничего, что вы не могли бы получить, просто выполнив одно большое слияние с 270 коммитами.Было бы намного разумнее выбирать точки в вашей частной ветке разработки, которые «имеют смысл» (например, «полностью реализованная функция X»).Допустим, вы пошли и выбрали несколько таких моментов, например, выполнив:
git checkout $b~215
... poke around to make sure it's a good merge point,
and maybe move to $b~213 instead ...
git tag mp1 # merge point 1
git checkout $b~170
... poke around more, move to $b~172 because that's better ...
git tag mp2 # merge point 2
git checkout ...
# add more temporary tag labels as needed
# let's say you wind up with 4 total merge points
# which I've simply numbered mp1, mp2, mp3, mp4
git checkout development # get on target merge branch
git merge --no-ff mp1
<put in a sensible commit message this time, and resolve any merge conflicts>
git merge --no-ff mp2
<put in a sensible commit message for merge point 2>
git merge --no-ff mp3
<etc>
git merge --no-ff mp4
<etc>
git tag -d mp1 mp2 mp3 mp4 # get rid of temporary tags
Вот главное, что нужно знать о «git merge», в данном конкретном случае, когда всегда есть фактический коммит слияниявход (т.е. не ускоренная перемотка вперед): то, что вы делаете, когда запускаете git merge
, добавляет - к вашей текущей ветке - один новый коммит, чьи родители:
- текущий HEADветки, в которой вы находитесь (в данном случае лучше
development
), и - идентификатора коммита, который вы называете в команде
git merge
(может быть любой commit-ID где угодно).
( содержимое вашего нового коммита, конечно, является результатом слияния "содержимого коммита HEAD" с "контентом именованного коммита", что подразумевает нахождение того, что изменилось между этими двумя коммитами и т. д., и иногда получение помощи в разрешении конфликтов слияния.) После того, как ваш новый коммит входит, текущая подсказка ветвления перенаправляется на новый коммит слияния.В этом случае development
перемещается вперед к вновь добавленному слиянию.
Следовательно, все, что вам нужно сделать, это запускать git merge --no-ff
(для принудительного выполнения реальных слияний, а не ускоренных перемоток вперед), каждый развремя указания одного подходящего идентификатора фиксации в вашей ветви development-kirby
- в «топологическом порядке», то есть mp1 ~ выше, но самый лучший (для некоторого значения «лучший») способ - найти отдельные «хорошие» (git checkout
)), затем пометьте их (git tag
), чтобы вам не приходилось запоминать длинные строки цифр.
Сноска: вы можете использовать
git rev-list --no-walk --topo-order
, чтобы увидеть, находится ли какой-то список идентификаторов коммитов в правильном порядке, но это немного болезненно.Я не знаю лучшего способа, и быстрый поиск в Google ничего не дал, поэтому я написал короткий скрипт:
#! /bin/sh
#
# check a list of IDs to see if they're in "topo order"
usage()
{
echo "usage: $0 id [...]"
}
case $# in
0) usage 1>&2; exit 1;;
esac
TF1=$(mktemp)
TF2=$(mktemp)
trap "rm -f $TF1 $TF2; exit" 0 1 2 3 15
# parse the arguments into one file
git rev-parse $@ > $TF1 || exit 1
# and topo-sort the arguments into another
git rev-list --topo-order --no-walk --reverse $@ > $TF2 || exit 1
# If the list is in the correct order the files will be the same
cmp -s $TF1 $TF2 || {
# If the files differ, it's possible that some argument(s) name
# the same rev...
[ $(wc -l < $TF1) -eq $(wc -l < $TF2) ] || {
echo "ERROR: there are repeats in $@"
# finding them is a pain, we don't bother trying
exit 1
}
echo "ERROR: $@ NOT in topo order"
echo "use instead:"
# read the topo-ordered raw IDs
while read sha1; do
# and find the (single) arg in $@ that names this one
for i; do
if [ $(git rev-parse $i) = $sha1 ]; then
printf ' %s' $i
break
fi
done
done < $TF2
echo
exit 1
}
echo "$@ in topo order"
exit 0
После создания набора тегов точек слияния, которые вы запустите,Например:
check-topo-order mp1 mp2 mp3 mp4
, и вам будет указано, mp1 Кроме того, хотя вы и не просили об этом, вполне может быть разумным свернуть («раздавить») некоторые из этих 270 коммитов.Все зависит от того, как вашей компании нравится делать вещи, но гораздо более привычным является объединение цепочки из 270 коммитов в новую цепочку «добавить функцию F, добавить функцию G, добавить функцию H»это может занять от 5 до 10 коммитов.
Например, вы можете получить 3 коммита, которые «добавляют функцию F» - возможно, «очистить, чтобы подготовиться к F», затем «добавить инфраструктуру для F», а затем «включить функцию F» - затем только 1 для G и 2или 3 коммита для добавления функции H. Это даст вам ветвь длиной в 6 коммитов (например, назовите ее devel-kirby-squashed
).На этом этапе у вас есть довольно чистая цепочка разработки, которая может быть встроена непосредственно в ветвь с именем development
.
. Конечно, иногда является причиной сохранения всехэта промежуточная работа, в этом случае серия --no-ff
слияния является разумной.