好的,这是我的情况。我有以下分支
我的老板希望我的开发变革kirby合并到开发中,但他不希望整个事情在一个巨大的合并中。勺子如何在几个较小的块中提交提交(一次50个,按顺序)?我只是在开发 - kirby分支中检查几个点并以这种方式合并它们还是有更好的东西?
我确信这个问题已经以更好的方式提出并得到了解答,但搜索结果并没有太多。
答案 0 :(得分:2)
要直接回答,您可以分支选定的提交(语法:git branch< branchname>< start-point>),将主干合并到此新分支中,将合并结果拉(推)到主干中,删除临时分支并转到下一个提交部分。
OTOH我想你的老板是错的:除非将提交重新组织成逻辑组,可以单独应用而不破坏整个应用程序逻辑,否则没有任何好处。但在这种情况下,不应简单地计算承诺。您可以使用交互式rebase重新组织它们(重新排序,重新排序)。 [更新:情况并非如此,见下文]答案 1 :(得分:1)
是的,你可以完全按照你的要求做(但是,不要;见下文)。例如(这是一个非常脆弱,因为我假设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
时你在做什么正在添加 - 您当前的分支 - 一个新的提交,其父母是:
development
),git merge
命令中命名的提交ID(可以在任何地方任何提交ID)。(新提交的内容当然是将“HEAD commit”的内容与“named commit”的内容合并的结果,这意味着找到这两个提交之间发生了什么变化等,有时获得帮助解决合并冲突。)在新的提交进入后,当前的分支提示被重新指向新的合并提交。在这种情况下,development
会向前移动到新添加的合并。
因此,您需要做的就是重复运行git merge --no-ff
(强制实际的合并提交,而不是快进),每次在development-kirby
分支中指定一个适当的提交ID “拓扑顺序”,即mp1&lt; mp2&lt; mp3&lt; mp4(否则你最终会遇到合并图的灾难;并看到脚注)。有很多方法可以指定commit-ID,例如使用上面的~
表示法,但“最佳”(对于某些“最佳”值)的方法是找到单独的“好的”({ {1}}),然后标记它们(git checkout
),这样您就不必记住长数字字符串。
git tag
查看某些提交ID列表的顺序是否正确,但这有点痛苦。我不知道一个更好的方法,快速的谷歌搜索没有改变任何东西,所以我写了一个简短的脚本:
git rev-list --no-walk --topo-order
在制作一组合并点标签之后,你可以运行,例如:
#! /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
它会告诉你mp1&lt; mp2&lt; mp3&lt; MP4。
<小时/> 而且,虽然你没有问过这个问题,但在270次提交中崩溃(“压缩”)可能是合理的。很大程度上取决于您的公司喜欢做事的方式,但最常见的是,将您的270个提交链组合成一个新的“添加功能F,添加功能G,添加功能H”链总共可能需要5到10次提交。
例如,您可能会结束3次提交“添加功能F” - 可能“清理以准备F”,然后“为F添加基础设施”,然后是“启用功能F” - 然后只需1 ,以及2或3次提交以添加功能H.这将为您提供一个6-commit-long分支(例如,可能称之为check-topo-order mp1 mp2 mp3 mp4
)。此时,您有一个非常干净的开发链,可以直接拼接到名为devel-kirby-squashed
的分支中或其上。
当然,有时是保留所有中间工作的理由,在这种情况下,一系列development
合并是合理的。