Git 子樹合并

2020-08-27 14:34 更新

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

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

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

首先你將 Rack 應用加入到項目中。你將 Rack 項目當作你項目中的一個遠程引用,然后將它檢出到它自身的分支:

$ 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項目的根目錄,而你自己的項目在master分支中。如果你先檢出其中一個然后另外一個,你會看到它們有不同的項目根目錄:

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

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

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

$ git checkout rack_branch
$ git pull

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

$ 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 項目的變更都被歸并并且可以進行本地提交。你也可以做相反的事情——在你主分支的rack目錄里進行變更然后歸并回rack_branch分支,然后將它們提交給維護者或者推送到上游。

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

$ git diff-tree -p rack_branch

或者,為了比較你的rack子目錄和服務器上你拉取時的master分支,你可以運行

$ git diff-tree -p rack_remote/master

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

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號