2012-03-24 63 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合併是合理的。