在以前的文章中,咱們已經對倉庫和提交已經有必定的瞭解了,在該篇文章中,咱們將學習git tag
、git branch
、 git checkout
和 git merge
。下面簡單的介紹一下幾個命令的功能:html
git tag
你能夠爲特定提交添加標籤。標籤是提交的額外標記,能夠指示有用的信息。git branch
你能夠建立分支。用於並行開發項目的不一樣功能。而不會對哪些提交屬於那個功能而感到困惑。git checkout
你能夠在不一樣的分支和標籤之間進行切換。git merge
能夠將不一樣分支上的更改自動合併在一塊兒咱們先從最簡單的標籤開始。git
假設咱們已經向倉庫提交了 A、B、C、D 四個commit,其中最後的一個提交也就是D
,標誌着咱們項目的1.0版本。如何在Git中指出這一點呢?你們可能會以爲,咱們能夠在D的提交中說明這是咱們的版本1.0。可是這並非最理想的。Git像其餘版本控制系統同樣,提供了給提交打Tag(標籤)
的功能。也就是說咱們能夠給D
提交打上標籤。以下所示:bash
Tag(標籤)
通常表示比較重要的節點信息。編輯器
即便更多的提交被添加到倉庫中(在下圖中,咱們假設在D提交以後又陸續的提交了E、F、G三個提交),Tag(標籤)
仍然鎖定着某個提交,以下所示:ide
既然標籤有着如此重要的做用,那如今咱們來看看在Git中如何建立標籤吧。在Git中標籤有兩種類型:輕量標籤
與附註標籤
。工具
建立輕量標籤的方式很是簡單使用git tag
+標籤名稱
。以下所示:學習
git tag v1.0.0
複製代碼
建立附註標籤很是簡單,須要在建立輕量標籤的方式上,添加選項-a
。以下所示:ui
git tag -a v1.0.0
複製代碼
經過上述方式,Git會運行你配置的文本編輯器輸入標籤信息。以下所示:idea
上圖中,我配置的是Sublime Text,固然你也可使用
git config --global core.editor
命令配置你喜歡的編輯器。spa
除了使用上述方式建立附註標籤之外,咱們還可使用 -m
選項來指定存儲在標籤中的信息,若是你添加了 -m
選項,那麼Git就會繞過你配置的編輯器。以下所示:
git tag -a v1.0.0 -m "發佈新版本v1.0.0"
複製代碼
在講解了輕量標籤與附註標籤的使用以後,咱們來看一下這兩個標籤的實際區別,咱們能夠經過git show
命令查看實際的區別,咱們先查看附註標籤,以下所示:
經過使用git show v1.0.0
,你能夠看到命令行的輸出中是包含Tag信息的:
tag v1.0.0
Tagger: AndyJennifer <1225868370@qq.com>
Date: Sun Sep 15 18:20:28 2019 +0800
發佈新版本v1.0.0
複製代碼
而建立的輕量標籤中,是不包含該信息的,以下所示:
須要注意的是,建立的標籤老是與commit進行綁定的。好比在上圖中,標籤是指向 441796...
這個提交的。
要刪除掉本地的標籤,咱們可使用命令 git tag -d <tagname>
。例如使用下面的命令刪除標籤:
git tag -d v1.0.0
Deleted tag 'v1.0.0' (was 3132ff5)
複製代碼
其中 -d
選項表示delete(刪除)
。
經過運行 git tag -a v1.0.0
,咱們能夠給最近的commit添加標籤,可是若是你想向倉庫中好久以前的commit添加標籤呢?很簡單!咱們能夠在原來的命令基礎上,直接添加對應的commit的 SHA
便可。
使用
git log
命令查看歷史提交記錄。這裏咱們能夠提供完整的SHA
,或SHA
的前七個
字符,
git tag -a v1.0.0 abd12d0
複製代碼
在上述命令中,咱們爲 abd12d0
這個提交打上了標籤。
在Git中,分支就像是科幻電影中的平行世界
。每一個平行世界都運行在獨立的環境中,在正常狀況下,每一個平行世界中所做的事,對於現實世界或另外一個平行世界是無感知的且不影響的。在某些特殊的狀況下,平行世界與現實世界可能重合,那麼就會產生混亂與衝突。那這個時候就須要咱們來解決這些衝突與問題。
扯太遠了,分支在Git中,主要用於項目的開發或者對項目進行修正。由於全部的修改都是在分支中進行,因此並不會影響到項目(項目通常在主分支上,通常是 master
分支)。當咱們在分支中進行更改後,咱們能夠將分支中的內容合併到分支上,這種分支組合過程,稱爲合併(merge)
。後續咱們會一一講解這些內容。
那麼接下來,咱們來看看Git中分支的使用方式和重要的概念。
在下圖倉庫中,咱們建立了一些提交,並在提交D
中建立了名爲 v1.0
的標籤,除了標籤之外還包含一個隱藏的 master
分支。在咱們沒有建立分支的狀況下,Git會爲咱們建立一個名爲 master
的分支。其實 master
的本質實際上是一個 指針
。
master 並無什麼特殊的意義,它只是第一個默認分支名。
隨着咱們不斷向倉庫進行提交,這些提交都會添加到該分支上。同時 master指針
也會指向對應提交。以下所示:
在上圖中,masetr
指針隨着提交而不斷移動。圖中紅線
所鏈接的提交都屬於 master
分支。
相對於
Tag(標籤)
,分支指針不會永久的指向某次提交,而是會隨着提交不斷的移動。
在某些狀況下,咱們可能會建立另外一個分支。在下圖中,咱們又建立了另外一分支 branch1
。
這個時候若是咱們再進行一個提交,哪一個分支會移動呢?是 master
仍是 branch1
分支呢?這裏就涉及到另外一個知識點----> HEAD
指針。
在Git中,HEAD
老是指向當前活躍的分支。在你沒有切換分支的狀況下,默認指向 master
分支。以下圖所示。
由於當前 HEAD指針
指向 master
分支,因此當咱們再向倉庫提交一個I
提交對象時,該提交仍然會在 master
分支上。以下所示:
固然咱們能夠改變 HEAD
指針所指向的內容, 使用 git checkout
命令,咱們能夠切換 HEAD
指針所指向的分支。好比咱們能夠經過命令git checkout branch1
,將 HEAD
指針指向 branch1
。
當咱們切換分支到 branch1
後,咱們後續的提交,都會添加到 branch1
分支上。好比下圖,咱們又建立了一個 A提交
,那麼這時 branch1
分支指針會指向該提交。
須要注意的是,分支中的提交對於其餘分支來講是不可見的。
在上圖中,若是咱們當前切換到了 master
分支,那麼在咱們的工做目錄與文件系統中, branch1
分支的 A
與 branch2
分支中的 J
,這兩個提交對文件形成的更改,將不會出如今 master
分支上的任何文件中。若是須要查看這個兩個對應的文件修改,只須要切換到咱們想要查找的提交所在的分支就好了。
咱們基本已經熟悉了分支的相關概念與總體流程後,下面咱們來學習一下 相關命令的使用。
建立分支其實很簡單,只需使用 git branch + 分支名稱
。若是你想建立一個叫作 "branch1"
的分支,只需運行如下命令:
git branch branch1
複製代碼
須要注意的是,若是你在某個提交上建立了一個分支,那麼該提交以前的全部提交也是屬於當前分支,在下圖中,在 H
提交中使用了建立分支命令建立了 branch1
分支,那麼在 H
提交以前的 D、E、F、G
也都屬於 branch1
分支。
上圖中 branch1
分支如藍線所示。
固然,與建立標籤同樣,咱們也能夠向之前的提交的 commit 添加分支。在下述命令中,咱們在 SHA
爲 dfs14fo
的提交中建立了test分支。
git branch test dfs14fo
複製代碼
要切換到另外一個分支,咱們須要使用命令 git checkout
命令,好比咱們須要切換到分支dev
上,那麼咱們可使用以下命令:
git checkout dev
複製代碼
經過上述操做,HEAD
指針會指向 dev
,須要注意的是,當你切換分支時,在你的工做目錄中,會刪除其餘分支中 commit
引用的全部文件,同時會引用 dev
分支中的 commit
引用的文件。固然你不用擔憂真的刪除了你另外一分支上的文件。Git會將它們都存儲在倉庫中。當你切換回來後,又會將對應分支引用的文件顯示在你的工做目錄中。
若是你須要查看當前項目的分支,可使用 git branch
命令,經過該命令咱們不只能夠知道倉庫中所建立的分支,還能查看當前活躍的分支,也就是 HEAD
指針指向的分支。
在下圖中,星號(*)
標記的爲當前活躍的分支。
經過使用 git branch
命令,咱們只能查看當前活躍的分支,若是說咱們的項目有不一樣的分支,咱們又想查看全部分支提交內容,那麼咱們又該怎麼辦了呢?還記得咱們以前提到過的 git log
指令嗎,這裏咱們將添加 --graph
與 --all
選項。
--graph
選項:將條目和行添加到輸出的最左側。--all
選項:將顯示倉庫中的全部的分支信息。那麼咱們可使用以下命令:
git log --oneline --graph --all
複製代碼
--oneline
能夠省略掉 commit 中的日期、做者等信息。以最簡單的形式顯示commit信息。
經過此命令,咱們能查看倉庫中的全部的分支和 commit 信息:
在上文中,咱們提到,分支通常用於進行開發或對項目進行修正。當咱們將分支的更改 合併(merge)
到 master
分支後,咱們可能就再也不須要該分支了。那麼這個時候若是咱們想刪除分支,那麼咱們使用命令 git branch -d + 分支名稱
來刪除咱們想要刪除的分支。這裏咱們以刪除dev
分支爲例:
git branch -d dev
複製代碼
在刪除分支的時候,咱們須要注意如下兩點:
git checkout dev
命令切換到dev
分支上的話,那麼咱們是不能刪除 dev
分支的。咱們須要切換到其餘分支上,才能刪除該分支。dev
分支上有任何的commit,那麼經過 -d
選項是不能刪除該分支的,你須要使用大寫的 D
選項,也就是使用 git branch -D dev
。分支的主要做用就是讓咱們作出不影響 master
分支的更改,當咱們在非 master
分支上作出更改後,若是以爲不須要該分支上的更改,則能夠刪掉該分支,或者你能夠將給分支上的內容與其餘分支進行合併。
將分支組合到一塊兒的這種行爲,咱們稱之爲
合併(merge)
。
在Git中使用 git merge
命令來合併分支:
git merge <other-branch>
複製代碼
在Git中 合併(merge)
的方式有兩種類型。一種是普通合併,另外一種是快進合併。下面咱們就來分別瞭解這兩種合併方式。
假設咱們的項目存在這兩條分支 master
與 branch1
兩條分支。
這個時候咱們想將 branch1
合併到 master
分支上,因爲當前HEAD
指向 master
分支,因此當兩個分支合併時,將會生成一個合併提交 B
將放置在 master
分支上,而且 master指針
將會向前移動。以下所示:
須要注意的是, B提交
會連接branch1
中的 4
與 A
提交。同時當分支進行合併時,並不會影響到以前的分支,好比咱們仍然能夠切換到branch1
分支上,並建立一個新的提交 J
,以下圖所示:
假設咱們的項目存在這兩條分支master
與branch1
支。且branch1
分支在master
分支前面。以下所示:
由於master
中是不包含 branch1
中的提交(I,K,2)
。若是這個時候咱們想將這些提交歸入master
分支中,也就是須要將 branch1
分支 合併(merge)
到 master
分支中。當咱們在master
分支中使用命令 git merge branch1
時,由於 branch1分支
在 master分支
前,Git會作一個所謂的快進合併
。以下圖所示:
在上圖中,master
分支移動到了branch1
分支指向的commit。須要注意的是,快進合併並不像普通合併那樣再建立一個提交。
大部分狀況下,咱們都能成功的合併分支,可是某些狀況下,Git沒法自動的進行合併,當合並失敗時,就稱爲合併衝突
。當出現衝突時,咱們須要手動的去修復文件中的衝突。看下面的例子:
在例子中,咱們已經建立了一個名爲GitTestProject
的倉庫,在倉庫中咱們已經添加了一個名爲Jvm系列之總目.md
文件到倉庫中,以下所示:
其中 Jvm系列之總目.md
文件中的內容以下
這個時候咱們經過 git branch dev
命令建立了 dev
分支,並切換到該分支中,這個時候咱們原文中添加了下圖中紅框
中的內容。
注意的是,你須要常用
git branch
來查看活躍分支
在修改該文件並保存後,咱們能夠經過git status
查看當前倉庫的狀態,而後咱們將在dev
分支修改的內容進行commit。內容以下所示:
咱們在原來的文件中,添加了一句Java class文件格式
。接下來,咱們經過git checkout master
切換到 master
分支,而後繼續修改該文件,一樣的修改的內容如紅框所示:
一樣的,在咱們完成修改後,咱們將在master
分支修改的內容進行commit。內容以下所示:
當提交完畢後,若是咱們想將dev
分支合併到 master
分支中,使用 git merge dev
命令,咱們能夠看到以下報錯:
當使用
git merge
命令時,你必定要注意當前所在的分支,你能夠經過git branch
或者git status
來查看。
在上圖中,Git告訴咱們文件 Jvm系列之總目錄.md
出現了衝突。這個時候咱們再打開該文件,咱們可能看到以下內容:
在該文件中顯示了一些特殊的一些符號,其實這些符號是Git定義的合併衝突指示符
,下面對這些指示符進行介紹:
<<<<<<< HEAD
此行下方的全部內容(直到下個指示符)顯示了當前分支上的行=======
表示原始行內容的結束位置,以後的全部行(直到下個指示符)是被合併的當前分支上的行的內容>>>>>>> dev
是要被合併的分支(此例中是 dev 分支)上的行結束指示符注意一個文件可能在多個部分存在合併衝突,所以檢查整個文件中的合併衝突指示符,搜索 <<< 可以幫助你找到全部這些指示符。
當出現衝突時,咱們須要手動的刪除掉這些指示符,在該例子中,咱們想保留兩個分支提交的內容,那麼咱們能夠進行以下操做:
注意:由於
dev
分支與master
分支修改的是同一文件,那麼結合上文咱們所講解的合併的類型,那麼上例中的提交爲普通合併
,故須要一個新的提交。
固然,當咱們解決衝突後,咱們仍然須要將修改的內容 add
到暫存區中,而後提交。以下所示:
當提交完畢後,咱們再使用git log
命令,咱們就能看到咱們的提交記錄啦。
在上述提交記錄中,咱們能夠看到 master
分支上不只包含了 dev
分支上的提交,還包括了一個合併的提交(merge branch 'dev')。
最後仍是回到咱們熟悉的圖形化界面的使用流程中。咱們來看看IDEA爲咱們提供了哪些便利吧。
經過依次點擊編譯器底部的 Version Control
-> Log
,選擇咱們想建立 Tag
的 commit ,而後點擊鼠標右鍵,依次選擇 New
-> Tag
,並輸入你想輸入的 Tag 名稱就行啦,具體以下所示:
在建立Tag
成功後,在該commit記錄中會有一個灰色的標籤。
標籤的刪除也特別簡單,在Git提交記錄中點擊包含咱們所建立的標籤的commit,而後點擊隨便右鍵,依次選擇標籤名稱
->delete
。就能夠完成標籤的刪除啦。具體以下所示;
在 IntelliJ IDEA
or Android Sutdio
中,建立分支的地方大概有三個。我先說一下他們的具體位置,與他們之間的區別。
在編譯器中,咱們只要選擇工具欄中的VCS
->Git
->Branches
,就能夠從建立分支啦。
根據上述操做後,會彈出以下選擇框,這個時候咱們只要選擇 New Branch
選項就能夠建立分支了。
下面對該選擇框中的內容進行簡單的介紹:
須要注意的是:經過該種方式建立的分支。分支指針所指向的commit,是你所在分支下最新的commit!!!!
。
第二種方式建立分支,是經過點擊編譯器最右下角
的 Git:master
(該左下角的內容可能變化,好比你切換到了dev分支上,那麼這個時候顯示的是 Git:dev
。這裏以 master
分支爲例,來建立分支。
經過該種方式建立的分支。分支指針所指向的commiit,是你所在分支下最新的commit!!!!
。
經過依次點擊編譯器底部的Version Control
->Log
,而後選中咱們須要建立分支的commmit,而後點擊鼠標右鍵,選擇 New
->Branch
經過上述這種方式所建立的分支,分支指針所指向的commit爲你選中的commit。
分支的刪除也比較簡單,經過依次點擊編譯器底部的Version Control
->Log
,而後找到有分支的commit,點擊鼠標右
鍵,找到你要刪除的分支名稱,而後選擇 delete
就能夠刪除分支了。這裏以刪除分支 fix-23
爲例:
分支的合併也一樣的簡單。
VCS
->Git
->Branches
彈出下列選擇框,最右下角
的 Git:master
(該左下角的內容可能變化,好比你切換到了 dev
分支上,那麼這個時候顯示的是 Git:dev
)而後咱們就能夠選擇相應的分支合併到對應分支下了,好比這裏咱們以 master
分支須要合併 dev
分支爲例:
在上述圖中,咱們只用選擇 Merge into Current
就能夠了,須要注意的是,當咱們選擇合併分支時,咱們須要切換到正確的的分支上。
怎樣切換分支?參考上圖,當咱們選擇了 dev
分支後,右方有一個 Checkout
選項,只要點擊該選項,咱們就能切換到對應分支啦~~~
當合並分支出現衝突的時候,編譯器會提示咱們合併衝突,會彈出以下代碼框:
整個代碼塊分爲三個部分:
Left
) Your version
: 表明你當前分支上的更改。Right
) Change from branch
:表明你合併的分支。Result
表明通過處理後的內容。內容區域的代碼顏色分爲四個部分:
對於衝突與更改,咱們均可以使用左側或右側的 >>
按鈕來應用你想應用的更改,若是你並不想應用這些更改你可使用 X
按鈕。最終你的全部的操做都會應用到中間的Result
代碼中。
當全部的衝突都被解決,全部更改都被應用後。咱們能夠點擊 Apply
按鈕來完成咱們最終的合併操做。
固然你也能夠點擊 Accept Left
仍是 Accept Right
按鈕來選擇應用當前分支的內容仍是其餘分支的內容。這個根據你直接的實際需求而定。
深度學習:查看 IntelliJ IDEA 中的官方介紹:Resolve Conflicts
若是說當你合併衝突的時候,不當心點擊了 Abort
按鈕,不用擔憂,你仍然能夠點擊鼠標右鍵
,依次選擇 Git
-> Resolve Conflicts
選項來解決衝突。 以下所示:
站在巨人的肩膀上,才能看的更遠~