Git新手教程-標籤、分支和合並(六)

前言

在以前的文章中,咱們已經對倉庫和提交已經有必定的瞭解了,在該篇文章中,咱們將學習git taggit branchgit checkoutgit 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(標籤)通常表示比較重要的節點信息。編輯器

Tag展現.jpg

即便更多的提交被添加到倉庫中(在下圖中,咱們假設在D提交以後又陸續的提交了E、F、G三個提交),Tag(標籤)仍然鎖定着某個提交,以下所示:ide

Tag展現2.jpg

既然標籤有着如此重要的做用,那如今咱們來看看在Git中如何建立標籤吧。在Git中標籤有兩種類型:輕量標籤附註標籤工具

  • 輕量標籤在Git中,是不存儲任何的信息,只是一個特定提交的引用。
  • 附註標籤存儲在Git數據中,且附註標籤中包含了打標籤者的名稱、電子郵件,日期等信息,通常狀況咱們都會使用附註標籤。

建立輕量標籤

建立輕量標籤的方式很是簡單使用git tag+標籤名稱。以下所示:學習

git tag v1.0.0
複製代碼

建立附註標籤

建立附註標籤很是簡單,須要在建立輕量標籤的方式上,添加選項-a。以下所示:ui

git tag -a v1.0.0
複製代碼

經過上述方式,Git會運行你配置的文本編輯器輸入標籤信息。以下所示:idea

git_tag_3.png

上圖中,我配置的是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_1.png

經過使用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
複製代碼

而建立的輕量標籤中,是不包含該信息的,以下所示:

git_show_2.png

須要注意的是,建立的標籤老是與commit進行綁定的。好比在上圖中,標籤是指向 441796... 這個提交的。

標籤的刪除

要刪除掉本地的標籤,咱們可使用命令 git tag -d <tagname> 。例如使用下面的命令刪除標籤:

git tag -d v1.0.0
Deleted tag 'v1.0.0' (was 3132ff5)
複製代碼

其中 -d 選項表示delete(刪除)

向之前的提交的 commit 添加標籤

經過運行 git tag -a v1.0.0 ,咱們能夠給最近的commit添加標籤,可是若是你想向倉庫中好久以前的commit添加標籤呢?很簡單!咱們能夠在原來的命令基礎上,直接添加對應的commit的 SHA 便可。

使用 git log 命令查看歷史提交記錄。這裏咱們能夠提供完整的SHA,或SHA前七個 字符,

git tag -a v1.0.0 abd12d0
複製代碼

在上述命令中,咱們爲 abd12d0 這個提交打上了標籤。

分支

在Git中,分支就像是科幻電影中的平行世界。每一個平行世界都運行在獨立的環境中,在正常狀況下,每一個平行世界中所做的事,對於現實世界或另外一個平行世界是無感知的且不影響的。在某些特殊的狀況下,平行世界與現實世界可能重合,那麼就會產生混亂與衝突。那這個時候就須要咱們來解決這些衝突與問題。

平行世界.jpg

扯太遠了,分支在Git中,主要用於項目的開發或者對項目進行修正。由於全部的修改都是在分支中進行,因此並不會影響到項目(項目通常在主分支上,通常是 master 分支)。當咱們在分支中進行更改後,咱們能夠將分支中的內容合併到分支上,這種分支組合過程,稱爲合併(merge)。後續咱們會一一講解這些內容。

那麼接下來,咱們來看看Git中分支的使用方式和重要的概念。

master 分支與 HEAD 指針

在下圖倉庫中,咱們建立了一些提交,並在提交D中建立了名爲 v1.0 的標籤,除了標籤之外還包含一個隱藏的 master 分支。在咱們沒有建立分支的狀況下,Git會爲咱們建立一個名爲 master 的分支。其實 master 的本質實際上是一個 指針

分支1.png

master 並無什麼特殊的意義,它只是第一個默認分支名。

隨着咱們不斷向倉庫進行提交,這些提交都會添加到該分支上。同時 master指針 也會指向對應提交。以下所示:

分支2.png

在上圖中,masetr 指針隨着提交而不斷移動。圖中紅線所鏈接的提交都屬於 master 分支。

相對於 Tag(標籤) ,分支指針不會永久的指向某次提交,而是會隨着提交不斷的移動。

HEAD指針

在某些狀況下,咱們可能會建立另外一個分支。在下圖中,咱們又建立了另外一分支 branch1

分支3.png

這個時候若是咱們再進行一個提交,哪一個分支會移動呢?是 master 仍是 branch1 分支呢?這裏就涉及到另外一個知識點----> HEAD 指針。

在Git中,HEAD 老是指向當前活躍的分支。在你沒有切換分支的狀況下,默認指向 master 分支。以下圖所示。

分支4.jpg

由於當前 HEAD指針 指向 master 分支,因此當咱們再向倉庫提交一個I提交對象時,該提交仍然會在 master 分支上。以下所示:

分支5.jpg

固然咱們能夠改變 HEAD 指針所指向的內容, 使用 git checkout 命令,咱們能夠切換 HEAD 指針所指向的分支。好比咱們能夠經過命令git checkout branch1,將 HEAD 指針指向 branch1

當咱們切換分支到 branch1 後,咱們後續的提交,都會添加到 branch1 分支上。好比下圖,咱們又建立了一個 A提交 ,那麼這時 branch1 分支指針會指向該提交。

分支6.jpg

分支中的提交的可見性

須要注意的是,分支中的提交對於其餘分支來講是不可見的。

分支7.jpg

在上圖中,若是咱們當前切換到了 master 分支,那麼在咱們的工做目錄與文件系統中, branch1 分支的 Abranch2 分支中的 J ,這兩個提交對文件形成的更改,將不會出如今 master 分支上的任何文件中。若是須要查看這個兩個對應的文件修改,只須要切換到咱們想要查找的提交所在的分支就好了。

咱們基本已經熟悉了分支的相關概念與總體流程後,下面咱們來學習一下 相關命令的使用。

建立分支

建立分支其實很簡單,只需使用 git branch + 分支名稱 。若是你想建立一個叫作 "branch1" 的分支,只需運行如下命令:

git branch branch1
複製代碼

須要注意的是,若是你在某個提交上建立了一個分支,那麼該提交以前的全部提交也是屬於當前分支,在下圖中,在 H 提交中使用了建立分支命令建立了 branch1 分支,那麼在 H 提交以前的 D、E、F、G 也都屬於 branch1 分支。

分支3.png

上圖中 branch1 分支如藍線所示。

之前的提交的 commit 添加分支

固然,與建立標籤同樣,咱們也能夠向之前的提交的 commit 添加分支。在下述命令中,咱們在 SHAdfs14fo 的提交中建立了test分支。

git branch test dfs14fo
複製代碼

切換分支

要切換到另外一個分支,咱們須要使用命令 git checkout 命令,好比咱們須要切換到分支dev上,那麼咱們可使用以下命令:

git checkout dev
複製代碼

經過上述操做,HEAD 指針會指向 dev ,須要注意的是,當你切換分支時,在你的工做目錄中,會刪除其餘分支中 commit 引用的全部文件,同時會引用 dev 分支中的 commit 引用的文件。固然你不用擔憂真的刪除了你另外一分支上的文件。Git會將它們都存儲在倉庫中。當你切換回來後,又會將對應分支引用的文件顯示在你的工做目錄中。

分支的查看

若是你須要查看當前項目的分支,可使用 git branch 命令,經過該命令咱們不只能夠知道倉庫中所建立的分支,還能查看當前活躍的分支,也就是 HEAD 指針指向的分支。

在下圖中,星號(*) 標記的爲當前活躍的分支。

git_branch.png

查看全部分支

經過使用 git branch命令,咱們只能查看當前活躍的分支,若是說咱們的項目有不一樣的分支,咱們又想查看全部分支提交內容,那麼咱們又該怎麼辦了呢?還記得咱們以前提到過的 git log指令嗎,這裏咱們將添加 --graph--all選項。

  • --graph 選項:將條目和行添加到輸出的最左側。
  • --all 選項:將顯示倉庫中的全部的分支信息。

那麼咱們可使用以下命令:

git log --oneline --graph --all
複製代碼

--oneline 能夠省略掉 commit 中的日期、做者等信息。以最簡單的形式顯示commit信息。

經過此命令,咱們能查看倉庫中的全部的分支和 commit 信息:

顯示全部分支信息.png

分支刪除

在上文中,咱們提到,分支通常用於進行開發或對項目進行修正。當咱們將分支的更改 合併(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) 的方式有兩種類型。一種是普通合併,另外一種是快進合併。下面咱們就來分別瞭解這兩種合併方式。

普通合併

假設咱們的項目存在這兩條分支 masterbranch1 兩條分支。

普通合併1.jpg

這個時候咱們想將 branch1 合併到 master 分支上,因爲當前HEAD指向 master 分支,因此當兩個分支合併時,將會生成一個合併提交 B 將放置在 master 分支上,而且 master指針 將會向前移動。以下所示:

普通合併2.jpg

須要注意的是, B提交 會連接branch1中的 4A 提交。同時當分支進行合併時,並不會影響到以前的分支,好比咱們仍然能夠切換到branch1分支上,並建立一個新的提交 J ,以下圖所示:

普通合併3.jpg

快進合併

假設咱們的項目存在這兩條分支masterbranch1支。且branch1分支在master分支前面。以下所示:

快速合併1.jpg

由於master中是不包含 branch1 中的提交(I,K,2)。若是這個時候咱們想將這些提交歸入master分支中,也就是須要將 branch1 分支 合併(merge)master 分支中。當咱們在master分支中使用命令 git merge branch1 時,由於 branch1分支master分支 前,Git會作一個所謂的快進合併。以下圖所示:

快速合併2.jpg

在上圖中,master分支移動到了branch1分支指向的commit。須要注意的是,快進合併並不像普通合併那樣再建立一個提交。

合併衝突

大部分狀況下,咱們都能成功的合併分支,可是某些狀況下,Git沒法自動的進行合併,當合並失敗時,就稱爲合併衝突。當出現衝突時,咱們須要手動的去修復文件中的衝突。看下面的例子:

在例子中,咱們已經建立了一個名爲GitTestProject的倉庫,在倉庫中咱們已經添加了一個名爲Jvm系列之總目.md文件到倉庫中,以下所示:

合併演示1.gif

其中 Jvm系列之總目.md 文件中的內容以下

合併演示2.png

這個時候咱們經過 git branch dev 命令建立了 dev 分支,並切換到該分支中,這個時候咱們原文中添加了下圖中紅框中的內容。

注意的是,你須要常用git branch來查看活躍分支

合併演示3.png

在修改該文件並保存後,咱們能夠經過git status查看當前倉庫的狀態,而後咱們將在dev分支修改的內容進行commit。內容以下所示:

合併演示4.png

咱們在原來的文件中,添加了一句Java class文件格式。接下來,咱們經過git checkout master切換到 master 分支,而後繼續修改該文件,一樣的修改的內容如紅框所示:

合併演示5.png

一樣的,在咱們完成修改後,咱們將在master分支修改的內容進行commit。內容以下所示:

合併演示6.png

當提交完畢後,若是咱們想將dev分支合併到 master分支中,使用 git merge dev命令,咱們能夠看到以下報錯:

當使用 git merge 命令時,你必定要注意當前所在的分支,你能夠經過 git branch 或者 git status 來查看。

合併演示7.png

在上圖中,Git告訴咱們文件 Jvm系列之總目錄.md 出現了衝突。這個時候咱們再打開該文件,咱們可能看到以下內容:

衝突文件顯示.png

在該文件中顯示了一些特殊的一些符號,其實這些符號是Git定義的合併衝突指示符,下面對這些指示符進行介紹:

  • <<<<<<< HEAD 此行下方的全部內容(直到下個指示符)顯示了當前分支上的行
  • ======= 表示原始行內容的結束位置,以後的全部行(直到下個指示符)是被合併的當前分支上的行的內容
  • >>>>>>> dev 是要被合併的分支(此例中是 dev 分支)上的行結束指示符

注意一個文件可能在多個部分存在合併衝突,所以檢查整個文件中的合併衝突指示符,搜索 <<< 可以幫助你找到全部這些指示符。

當出現衝突時,咱們須要手動的刪除掉這些指示符,在該例子中,咱們想保留兩個分支提交的內容,那麼咱們能夠進行以下操做:

衝突合併.gif

注意:由於 dev 分支與 master 分支修改的是同一文件,那麼結合上文咱們所講解的合併的類型,那麼上例中的提交爲普通合併,故須要一個新的提交。

固然,當咱們解決衝突後,咱們仍然須要將修改的內容 add 到暫存區中,而後提交。以下所示:

合併演示9.png

當提交完畢後,咱們再使用git log命令,咱們就能看到咱們的提交記錄啦。

合併演示10.png

在上述提交記錄中,咱們能夠看到 master 分支上不只包含了 dev 分支上的提交,還包括了一個合併的提交(merge branch 'dev')。

IntelliJ IDEA or Android Sutdio 圖形化界面的使用

最後仍是回到咱們熟悉的圖形化界面的使用流程中。咱們來看看IDEA爲咱們提供了哪些便利吧。

Tag的建立

經過依次點擊編譯器底部的 Version Control -> Log ,選擇咱們想建立 Tag 的 commit ,而後點擊鼠標右鍵,依次選擇 New -> Tag ,並輸入你想輸入的 Tag 名稱就行啦,具體以下所示:

建立Tag.gif

在建立Tag成功後,在該commit記錄中會有一個灰色的標籤。

Tag的刪除

標籤的刪除也特別簡單,在Git提交記錄中點擊包含咱們所建立的標籤的commit,而後點擊隨便右鍵,依次選擇標籤名稱->delete。就能夠完成標籤的刪除啦。具體以下所示;

刪除標籤.gif

分支的建立

IntelliJ IDEA or Android Sutdio中,建立分支的地方大概有三個。我先說一下他們的具體位置,與他們之間的區別。

第一種方式

在編譯器中,咱們只要選擇工具欄中的VCS->Git->Branches,就能夠從建立分支啦。

建立分支方式1.png

根據上述操做後,會彈出以下選擇框,這個時候咱們只要選擇 New Branch 選項就能夠建立分支了。

建立分支方式1.2.png

下面對該選擇框中的內容進行簡單的介紹:

  • New Branch: 建立新的分支。
  • Checkout Tag or Revision...:切換到相應Tag或分支。
  • Local Branches:本地全部的分支。
  • Remote Branches:遠程分支。(關於遠程分支,會在後文介紹)。

須要注意的是:經過該種方式建立的分支。分支指針所指向的commit,是你所在分支下最新的commit!!!!

第二種方式

第二種方式建立分支,是經過點擊編譯器最右下角Git:master(該左下角的內容可能變化,好比你切換到了dev分支上,那麼這個時候顯示的是 Git:dev 。這裏以 master 分支爲例,來建立分支。

建立分支方式2.png

經過該種方式建立的分支。分支指針所指向的commiit,是你所在分支下最新的commit!!!!

第三種方式

經過依次點擊編譯器底部的Version Control->Log,而後選中咱們須要建立分支的commmit,而後點擊鼠標右鍵,選擇 New ->Branch

建立分支方式3.png

經過上述這種方式所建立的分支,分支指針所指向的commit爲你選中的commit。

分支的刪除

分支的刪除也比較簡單,經過依次點擊編譯器底部的Version Control->Log,而後找到有分支的commit,點擊鼠標鍵,找到你要刪除的分支名稱,而後選擇 delete 就能夠刪除分支了。這裏以刪除分支 fix-23 爲例:

分支的刪除.png

分支的合併

分支的合併也一樣的簡單。

  • 要麼咱們只要選擇工具欄中的VCS->Git->Branches 彈出下列選擇框,
  • 要麼是經過點擊編譯器最右下角Git:master(該左下角的內容可能變化,好比你切換到了 dev 分支上,那麼這個時候顯示的是 Git:dev

而後咱們就能夠選擇相應的分支合併到對應分支下了,好比這裏咱們以 master 分支須要合併 dev 分支爲例:

分支的合併展現.png

在上述圖中,咱們只用選擇 Merge into Current 就能夠了,須要注意的是,當咱們選擇合併分支時,咱們須要切換到正確的的分支上。

分支的切換

怎樣切換分支?參考上圖,當咱們選擇了 dev 分支後,右方有一個 Checkout 選項,只要點擊該選項,咱們就能切換到對應分支啦~~~

解決衝突

當合並分支出現衝突的時候,編譯器會提示咱們合併衝突,會彈出以下代碼框:

衝突展現框.png

整個代碼塊分爲三個部分:

  • 左邊(Left) Your version : 表明你當前分支上的更改。
  • 右邊(Right) Change from branch :表明你合併的分支。
  • 中間的 Result 表明通過處理後的內容。

內容區域的代碼顏色分爲四個部分:

  • 紅色區域:表明當前分支和合並分支都編輯過的內容,屬於衝突
  • 藍色區域:表明被單方面編輯過的內容,屬於更改。
  • 灰色區域:表明被刪除的內容,屬於更改。
  • 綠色區域:表明新增的內容,屬於更改。

對於衝突與更改,咱們均可以使用左側或右側的 >> 按鈕來應用你想應用的更改,若是你並不想應用這些更改你可使用 X 按鈕。最終你的全部的操做都會應用到中間的Result代碼中。

當全部的衝突都被解決,全部更改都被應用後。咱們能夠點擊 Apply 按鈕來完成咱們最終的合併操做。

固然你也能夠點擊 Accept Left 仍是 Accept Right 按鈕來選擇應用當前分支的內容仍是其餘分支的內容。這個根據你直接的實際需求而定。

深度學習:查看 IntelliJ IDEA 中的官方介紹:Resolve Conflicts

小提示

若是說當你合併衝突的時候,不當心點擊了 Abort 按鈕,不用擔憂,你仍然能夠點擊鼠標右鍵,依次選擇 Git -> Resolve Conflicts選項來解決衝突。 以下所示:

遺忘解決的衝突.png

最後

站在巨人的肩膀上,才能看的更遠~

相關文章
相關標籤/搜索