天天看點

git 分支合并_圖解git,用手繪圖帶你了解git中分支的原理和應用Git的結構分支與HEAD指針分支合并

大家好,今天我們來聊git當中一個非常非常重要的特性,就是branch。

git branch可以說是git當中最重要的概念了,甚至沒有之一。因為git最重要的使用場景就是協同開發,大家一起在一個項目當中開發不同的功能。正是由于有了分支的概念,可以讓大家在開發的時候互不影響。如果沒有這個功能,git的其他功能做的再好,可能都沒有用。

是以某種程度上可以了解為,學git最重要的就是學習分支的相關内容。當然分支的相關内容和指令非常多,我們想要瞬間全部都學會顯然不太現實。但對這個概念有一些了解,懂得一些基本指令的用法應該還是做得到的。

在了解分支這個概念之前,我們需要先來介紹一下Git的結構。

Git的結構

branch的英文就是樹枝,後來衍生出了分叉、支路等意思。這個單詞非常形象,因為git倉庫的所有送出節點之間的關系,其實就是一棵樹,是以一個分支也可以看成是樹上的一條鍊路。但是這樣有一個小問題是,如果說分支是一條鍊路的話,那麼這個鍊路上的每一個節點代表的是一個commit送出,意味着一份代碼快照,有些像是遊戲存檔。

一個branch上有多個commit,一個遊戲也可以有多個存檔,但是當下顯然隻能加載一個。是以git當中用一個指針指向目前加載的commit,也就是說縱向來看一個分支代表的是一連串的送出,但在git當中我們使用的分支其實是一個指針,一個在commit當中切換的指針。

我們來看個例子,比如一開始的時候我們隻有預設分支master,它指向目前的一個送出。

git 分支合并_圖解git,用手繪圖帶你了解git中分支的原理和應用Git的結構分支與HEAD指針分支合并

現在我們使用git branch test指令建立一個測試分支,執行之後,其實隻不過是多了一個指針也指向目前的commit。git當中的結構變成這樣:

git 分支合并_圖解git,用手繪圖帶你了解git中分支的原理和應用Git的結構分支與HEAD指針分支合并

當我們在test分支上做了改動送出之後,git會産生一個新的送出,并且移動test指針,而master指針會留在原地。

git 分支合并_圖解git,用手繪圖帶你了解git中分支的原理和應用Git的結構分支與HEAD指針分支合并

如果我們再回到master也進行了改動和送出之後,又會産生新的節點,并且這個節點會和test的節點區分開,形成新的鍊路,于是就形成了一棵樹的樣子。

git 分支合并_圖解git,用手繪圖帶你了解git中分支的原理和應用Git的結構分支與HEAD指針分支合并

分支與HEAD指針

怎麼分支建立,我們剛才已經講過了,可以通過git branch加上我們想要的分支名來完成。使用了這個指令之後,git内部會建立一個新的指針指向目前的commit。

有一個問題是git怎麼知道我們目前的代碼在哪裡呢?即使知道了代碼在哪個分支上,又怎麼确定在哪一個節點呢?其實git内部還有一個特殊的指針叫做HEAD,它指向的是目前代碼倉庫的位置。當我們送出代碼的時候,不止隻有分支的這些指針會往前移動,HEAD指針也會随着移動。

其實HEAD指針不僅可以往前移動,還可以移動到任意節點上,哪怕不再目前的分支上也可以。移動HEAD指針需要用到git checkout指令,它可以指定HEAD指針移動到其他位置。既可以是某一個分支,也可以是根據commit id來确定的節點。

比如我們目前在master分支,我們要切換到test分支上,我們隻需要運作:

git checkout master
           

另外,使用git checkout指令加上參數-b,我們還可以建立分支。比如假如目前test分支不存在,我們可以通過git checkout -b test來建立,并且還會自動切換到建立出的test分支上。

git 分支合并_圖解git,用手繪圖帶你了解git中分支的原理和應用Git的結構分支與HEAD指針分支合并

我們在新的分支上做了送出之後,可以通過git log --oneline --decorate指令來檢視每一個分支所指向的位置。這裡的oneline是将log壓縮到一行展示,decorate用來檢視分支所指向的位置。

git 分支合并_圖解git,用手繪圖帶你了解git中分支的原理和應用Git的結構分支與HEAD指針分支合并

我們可以發現test和master分支指向的送出不同,并且目前我們的HEAD在test上,說明我們目前在test分支。我們前面說了git checkout指令可以改變HEAD指針指向的位置,假如我們在目前目錄下執行git checkout 18a417,這個18a417對應的是add article 6這個送出。這個送出是在master分支的,是test分支的上遊,我們使用指令會自動将HEAD跳轉到master分支。

git 分支合并_圖解git,用手繪圖帶你了解git中分支的原理和應用Git的結構分支與HEAD指針分支合并

使用之後我們發現的确到了master分支,這裡由于我配置了zsh工具,它會提示我目前所處的位置是比master分支指向的最新位置落後3個送出。

這也驗證了我們說的,HEAD指針可以随意跳轉。現在想必你們應該能了解上一篇文章當中介紹的,撤銷目前分支的指令git reset HEAD^的含義了,HEAD指的就是HEAD指針,^表示的上一個送出。如果是前多個送出,我們可以用~加數字的形式來表示。比如上圖當中劃了紅線标注的master~3,就表示master節點上3個送出。

分支合并

最後來簡單說說分支合并,我們在使用git進行協同開發的過程當中,雖然大家都在各自的分支。但是最後代碼還是要合并到一起的,這樣才可以投入使用。git當中代碼的合并是通過分支合并來展現的。

比如目前的這一篇文章被我加在了test分支當中,這顯然是不行的,因為使用方不可能一一去了解每一個分支做了什麼,當中的代碼邏輯。是以大多數的分支隻是暫時的,用來暫時完成一項功能的,等功能完成之後,一般都會再合并回master分支,将所有的改動合并進去。

合并的方式非常簡單,我們隻需要先checkout我們想要合并的目标分支。比如我們要合并到master,就checkout到master。然後使用git merge test指令,表示和test這個分支合并。

git 分支合并_圖解git,用手繪圖帶你了解git中分支的原理和應用Git的結構分支與HEAD指針分支合并

合并之後,如果沒有報錯就算是合并成功了。它會展示出來合并進來的代碼改動,我們注意到日志裡有一個fast-forward這個單詞,它表示快速合并。快速合并的意思也很簡單,因為我們test分支是從master分支當中切出去的。後來master分支就再也沒有進行過改動,那麼當我們合并的時候,其實隻需要移動一下master指針,将它移動到test分支上即可。

我們用圖來展示,合并前:

git 分支合并_圖解git,用手繪圖帶你了解git中分支的原理和應用Git的結構分支與HEAD指針分支合并

合并後:

git 分支合并_圖解git,用手繪圖帶你了解git中分支的原理和應用Git的結構分支與HEAD指針分支合并

那如果我們在master分支上也有改動,不再是待合并分支的直接上遊,會發生什麼呢?

git 分支合并_圖解git,用手繪圖帶你了解git中分支的原理和應用Git的結構分支與HEAD指針分支合并

上圖當中我們做了一系列操作,首先我們建立了一個叫做test_merge的分支,在其中建立了一個檔案叫做a.txt,接着我們切回master分支建立了b.txt。最後我們把兩個分支合并。

合并當然也沒有問題,但是我們來用git log來檢視一下日志:

git 分支合并_圖解git,用手繪圖帶你了解git中分支的原理和應用Git的結構分支與HEAD指針分支合并

會發現日志裡多了一個commit,這個commit并不是我送出的,而是它自動産生的。我們一樣用圖來展示一下,這是合并前:

git 分支合并_圖解git,用手繪圖帶你了解git中分支的原理和應用Git的結構分支與HEAD指針分支合并

合并之後:

git 分支合并_圖解git,用手繪圖帶你了解git中分支的原理和應用Git的結構分支與HEAD指針分支合并

由于不再擁有直接上下遊關系了,是以git建立了一個新的commit用來合并兩個分支的代碼。當我們合并完成之後,我們就可以把沒用的分支都删除了。删除的指令是git branch -d test。

當然git merge的時候并不是永遠都一帆風順的,難免會遇到沖突。所謂的沖突也就是兩個人修改了同一份代碼,git會不知道應該保留哪一個,于是提示沖突,讓程式員自己搞定。關于git merge時遇到沖突怎麼辦的問題,我們放到下一篇文章當中和大家分享。

今天的文章就到這裡,衷心祝願大家每天都有所收獲。如果還喜歡今天的内容的話,請來一個三連支援吧~(點贊、關注、轉發)

- END -

本文始發于公衆号:TechFlow,求個關注

繼續閱讀