2012-03-24 64 views
1

好的,这是我的情况。我有以下分支机构如何从分支分支中按顺序部分合并提交?

  • 发展
  • 发展 - 柯比(270款超前发展)

我的老板想从开发 - 柯比我修改合并到发展,但他不希望整个事情在一个巨大的合并中。勺子如何以几个较小的块为单位提交提交(按顺序说50个)?我是否仅仅在开发-kirby分支中检查几个点并合并它们,或者有更好的方法?

我敢肯定这个问题已经有了更好的回答,但是回答这个问题还没有找到。

回答

2

直接回答,您可以在选定的提交分公司(语法:git的分支<BRANCHNAME> <起点>),合并主干到这个新的分支,拉(推)合并结果到主干,删除临时分支并转到下一个提交部分。

OTOH我想你的老板是错误的:没有这种缓慢喂养的好处,除非提交重组为逻辑组,可以单独应用而不会破坏整个应用程序逻辑;但在这种情况下,提交不应简单计数。您可以使用交互式重新整理它们(重新排序,重新构建)。 [更新:情况并非如此,请参阅下文]

+0

好的,这就是我的想法。是的,我必须仔细选择我的检查点提交。这主要是内存清理,所以每个提交都非常原子化,应该干净利用。 – 2012-03-24 10:11:44

+0

好吧,如果它不是新功能而是修复,那么将主干与小部分进行测试套件之间的连续运行确实更加正确。如果有事情中断,你必须处理一小组更改而不是完整列表,并且你可以检测到不正确的更改。 – Netch 2012-03-24 13:57:03

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被添加到你在做什么你当前分支 - 一个新的提交,其父母分别是:

  • 你的分支现任掌门(在这种情况下最好是development),并且
  • 您在中提交的提交ID命令(其可以是任何提交ID在任何地方)。

(该内容新的承诺是,当然,合并“HEAD的内容提交的”同“命名提交的内容”,这意味着找到了什么这两个提交间变化等结果并且有时可以帮助解决合并冲突。)新提交进入后,当前分支提示将重新指向新的合并提交。在这种情况下,development前进到新添加的合并。因此,您所需要做的就是重复运行git merge --no-ff(强制实际合并提交,而不是快进),每次在您的development-kirby分支中指定一个合适的提交ID“拓扑顺序”,即, mp1 < mp2 < mp3 < mp4(否则,你将面临一个合并图的灾难;并参见脚注)。有很多方法可以指定提交ID,例如使用上面的~表示法,但“最佳”(对于某些“最佳”值)方法是去查找单个“好的”(git checkout),然后标记他们(git tag),以便您不必记住长数字字符串。


脚注:您可以使用 git rev-list --no-walk --topo-order来查看某些提交ID列表是否按正确的顺序排列,但这有点痛苦。我不知道一个更好的方式和快速谷歌搜索不转任何东西,所以我写了一个简短的脚本:

#! /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 [email protected] > $TF1 || exit 1 
# and topo-sort the arguments into another 
git rev-list --topo-order --no-walk --reverse [email protected] > $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 [email protected]" 
     # finding them is a pain, we don't bother trying 
     exit 1 
    } 
    echo "ERROR: [email protected] NOT in topo order" 
    echo "use instead:" 
    # read the topo-ordered raw IDs 
    while read sha1; do 
     # and find the (single) arg in [email protected] 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 "[email protected] in topo order" 
exit 0 

制作了一组你运行合并点标记,如后:

check-topo-order mp1 mp2 mp3 mp4 

,它会告诉你是否MP1 MP2 < MP3 < MP4 <。


此外,虽然您没有问这个问题,但可能合理的做法是将这270个提交中的某些提交(“挤压”)。一大堆事情取决于你的公司喜欢做什么的方式,但它更像平常一样,结合你的270承诺链到一个新的“添加功能F,添加功能G,添加功能H”链中。这可能总共需要5到10次提交。例如,你可能会提交3个提交“添加功能F” - 也许“清理准备F”,然后是“添加F的基础设施”,然后是“启用功能F” - 然后只需要1 G和2或3提交添加特性H.这会给你一个6-commit-long分支(可能称之为 devel-kirby-squashed)。在那个时候,你有一个非常干净的开发链,可以直接拼接到名为 development的分支上。

当然,有时原因保留所有的中间工作,在这种情况下,一系列--no-ff合并是合理的。