子樹合并

2018-07-10 17:25 更新

子樹合并

現(xiàn)在你已經(jīng)看到了子模塊系統(tǒng)的麻煩之處,讓我們來看一下解決相同問題的另一途徑。當(dāng) Git 歸并時(shí),它會(huì)檢查需要?dú)w并的內(nèi)容然后選擇一個(gè)合適的歸并策略。如果你歸并的分支是兩個(gè),Git使用一個(gè)遞歸策略。如果你歸并的分支超過兩個(gè),Git采用章魚策略。這些策略是自動(dòng)選擇的,因?yàn)檫f歸策略可以處理復(fù)雜的三路歸并情況——比如多于一個(gè)共同祖先的——但是它只能處理兩個(gè)分支的歸并。章魚歸并可以處理多個(gè)分支但是但必須更加小心以避免沖突帶來的麻煩,因此它被選中作為歸并兩個(gè)以上分支的默認(rèn)策略。

實(shí)際上,你也可以選擇其他策略。其中的一個(gè)就是子樹歸并,你可以用它來處理子項(xiàng)目問題。這里你會(huì)看到如何換用子樹歸并的方法來實(shí)現(xiàn)前一節(jié)里所做的 rack 的嵌入。

子樹歸并的思想是你擁有兩個(gè)工程,其中一個(gè)項(xiàng)目映射到另外一個(gè)項(xiàng)目的子目錄中,反過來也一樣。當(dāng)你指定一個(gè)子樹歸并,Git可以聰明地探知其中一個(gè)是另外一個(gè)的子樹從而實(shí)現(xiàn)正確的歸并——這相當(dāng)神奇。

首先你將 Rack 應(yīng)用加入到項(xiàng)目中。你將 Rack 項(xiàng)目當(dāng)作你項(xiàng)目中的一個(gè)遠(yuǎn)程引用,然后將它檢出到它自身的分支:

$ git remote add rack_remote git@github.com:schacon/rack.git
$ git fetch rack_remote
warning: no common commits
remote: Counting objects: 3184, done.
remote: Compressing objects: 100% (1465/1465), done.
remote: Total 3184 (delta 1952), reused 2770 (delta 1675)
Receiving objects: 100% (3184/3184), 677.42 KiB | 4 KiB/s, done.
Resolving deltas: 100% (1952/1952), done.
From git@github.com:schacon/rack
 * [new branch]      build      -> rack_remote/build
 * [new branch]      master     -> rack_remote/master
 * [new branch]      rack-0.4   -> rack_remote/rack-0.4
 * [new branch]      rack-0.9   -> rack_remote/rack-0.9
$ git checkout -b rack_branch rack_remote/master
Branch rack_branch set up to track remote branch refs/remotes/rack_remote/master.
Switched to a new branch "rack_branch"

現(xiàn)在在你的rack_branch分支中就有了Rack項(xiàng)目的根目錄,而你自己的項(xiàng)目在master分支中。如果你先檢出其中一個(gè)然后另外一個(gè),你會(huì)看到它們有不同的項(xiàng)目根目錄:

$ ls
AUTHORS           KNOWN-ISSUES   Rakefile      contrib           lib
COPYING           README         bin           example           test
$ git checkout master
Switched to branch "master"
$ ls
README

要將 Rack 項(xiàng)目當(dāng)作子目錄拉取到你的master項(xiàng)目中。你可以在 Git 中用git read-tree來實(shí)現(xiàn)。你會(huì)在第9章學(xué)到更多與read-tree和它的朋友相關(guān)的東西,當(dāng)前你會(huì)知道它讀取一個(gè)分支的根目錄樹到當(dāng)前的暫存區(qū)和工作目錄。你只要切換回你的master分支,然后拉取rack_branch到你主項(xiàng)目的master分支的rack子目錄:

$ git read-tree --prefix=rack/ -u rack_branch

當(dāng)你提交的時(shí)候,看起來就像你在那個(gè)子目錄下?lián)碛蠷ack的文件——就像你從一個(gè)tarball里拷貝的一樣。有意思的是你可以比較容易地歸并其中一個(gè)分支的變更到另外一個(gè)。因此,如果 Rack 項(xiàng)目更新了,你可以通過切換到那個(gè)分支并執(zhí)行拉取來獲得上游的變更:

$ git checkout rack_branch
$ git pull

然后,你可以將那些變更歸并回你的 master 分支。你可以使用git merge -s subtree,它會(huì)工作的很好;但是 Git 同時(shí)會(huì)把歷史歸并到一起,這可能不是你想要的。為了拉取變更并預(yù)置提交說明,需要在-s subtree策略選項(xiàng)的同時(shí)使用--squash--no-commit選項(xiàng)。

$ git checkout master
$ git merge --squash -s subtree --no-commit rack_branch
Squash commit -- not updating HEAD
Automatic merge went well; stopped before committing as requested

所有 Rack 項(xiàng)目的變更都被歸并可以進(jìn)行本地提交。你也可以做相反的事情——在你主分支的rack目錄里進(jìn)行變更然后歸并回rack_branch分支,然后將它們提交給維護(hù)者或者推送到上游。

為了得到rack子目錄和你rack_branch分支的區(qū)別——以決定你是否需要?dú)w并它們——你不能使用一般的diff命令。而是對你想比較的分支運(yùn)行git diff-tree

$ git diff-tree -p rack_branch

或者,為了比較你的rack子目錄和服務(wù)器上你拉取時(shí)的master分支,你可以運(yùn)行

$ git diff-tree -p rack_remote/master


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號