-
1. 開始
-
2. Git 基礎
-
3. Git 分支
-
4. 伺服器上的 Git
- 4.1 通訊協定
- 4.2 在伺服器上取得 Git
- 4.3 產生您的 SSH 公開金鑰
- 4.4 設定伺服器
- 4.5 Git Daemon
- 4.6 智慧 HTTP
- 4.7 GitWeb
- 4.8 GitLab
- 4.9 第三方託管選項
- 4.10 總結
-
5. 分散式 Git
-
A1. 附錄 A:其他環境中的 Git
- A1.1 圖形介面
- A1.2 Visual Studio 中的 Git
- A1.3 Visual Studio Code 中的 Git
- A1.4 IntelliJ / PyCharm / WebStorm / PhpStorm / RubyMine 中的 Git
- A1.5 Sublime Text 中的 Git
- A1.6 Bash 中的 Git
- A1.7 Zsh 中的 Git
- A1.8 PowerShell 中的 Git
- A1.9 總結
-
A2. 附錄 B:在應用程式中嵌入 Git
-
A3. 附錄 C:Git 命令
3.1 Git 分支 - 分支簡介
幾乎每個 VCS 都有某種形式的分支支援。分支是指您從主要開發線路分歧出去,並繼續工作而不會干擾該主要線路。在許多 VCS 工具中,這是一個有點昂貴的過程,通常需要您建立原始程式碼目錄的新副本,這對於大型專案來說可能需要很長時間。
有些人將 Git 的分支模型稱為其「殺手級功能」,它也確實使 Git 在 VCS 社群中脫穎而出。為什麼它如此特別?Git 分支的方式非常輕巧,使得分支操作幾乎是瞬間完成的,並且在分支之間來回切換通常也一樣快。與許多其他 VCS 不同,Git 鼓勵經常進行分支和合併的工作流程,甚至一天多次。理解和掌握此功能可以為您提供強大而獨特的工具,並且可以完全改變您的開發方式。
分支簡介
為了真正了解 Git 如何進行分支,我們需要退一步,檢視 Git 如何儲存其資料。
您可能還記得什麼是 Git?中的內容,Git 不會將資料儲存為一系列變更集或差異,而是儲存為一系列快照。
當您進行提交時,Git 會儲存一個提交物件,其中包含指向您暫存的內容快照的指標。此物件還包含作者的姓名和電子郵件地址、您輸入的訊息以及指向該提交之前直接提交的提交 (其父代或父代) 的指標:初始提交的零父代、正常提交的一個父代以及由兩個或多個分支合併產生的提交的多個父代。
為了視覺化此內容,我們假設您有一個包含三個檔案的目錄,您將它們全部暫存並提交。暫存這些檔案會計算每個檔案的檢查總和 (我們在什麼是 Git?中提到的 SHA-1 雜湊),將該檔案版本儲存在 Git 儲存庫中 (Git 將它們稱為Blob),並將該檢查總和新增至暫存區
$ git add README test.rb LICENSE
$ git commit -m 'Initial commit'
當您透過執行 git commit
建立提交時,Git 會檢查每個子目錄 (在此案例中,僅限根專案目錄) 的總和,並將它們作為樹狀物件儲存在 Git 儲存庫中。然後,Git 會建立一個提交物件,其中包含中繼資料和指向根專案樹狀的指標,以便在需要時重新建立該快照。
您的 Git 儲存庫現在包含五個物件:三個 Blob (每個代表三個檔案之一的內容)、一個 樹狀 (列出目錄內容並指定哪些檔案名稱儲存為哪些 Blob) 和一個 提交 (具有指向該根樹狀的指標和所有提交中繼資料)。

如果您進行一些變更並再次提交,下一個提交將會儲存一個指向其之前提交的指標。

在 Git 中,分支只是一個輕量的、可移動的指標,指向這些提交中的其中一個。Git 中的預設分支名稱是 master
。當您開始進行提交時,會給您一個 master
分支,它指向您所做的最後一次提交。每次您提交時,master
分支指標會自動向前移動。
注意
|
Git 中的 "master" 分支並不是一個特殊的分支。它與任何其他分支完全相同。幾乎每個儲存庫都有它的唯一原因是 |

建立新分支
當您建立一個新分支時會發生什麼?嗯,這樣做會為您建立一個新的指標,以便您四處移動。假設您想要建立一個名為 testing
的新分支。您可以使用 git branch
命令來完成此操作
$ git branch testing
這會建立一個新的指標,指向您目前所在的相同提交。

Git 如何知道您目前在哪個分支上?它保留一個名為 HEAD
的特殊指標。請注意,這與您可能習慣的其他 VCS(例如 Subversion 或 CVS)中的 HEAD
概念大不相同。在 Git 中,這是一個指向您目前所在本地分支的指標。在這種情況下,您仍然在 master
上。git branch
命令只會建立一個新的分支 — 它沒有切換到該分支。

您可以透過執行一個簡單的 git log
命令來輕鬆看到這一點,該命令會顯示分支指標指向的位置。此選項稱為 --decorate
。
$ git log --oneline --decorate
f30ab (HEAD -> master, testing) Add feature #32 - ability to add new formats to the central interface
34ac2 Fix bug #1328 - stack overflow under certain conditions
98ca9 Initial commit
您可以看到 master
和 testing
分支就在 f30ab
提交旁邊。
切換分支
若要切換到現有的分支,您可以執行 git checkout
命令。讓我們切換到新的 testing
分支
$ git checkout testing
這會移動 HEAD
指向 testing
分支。

這有什麼意義?嗯,讓我們再做一次提交
$ vim test.rb
$ git commit -a -m 'Make a change'

這很有趣,因為現在您的 testing
分支已經向前移動,但是您的 master
分支仍然指向您在執行 git checkout
以切換分支時所在的提交。讓我們切換回 master
分支
$ git checkout master
注意
|
git log 並不會一直顯示所有分支如果您現在執行 該分支沒有消失;Git 只是不知道您對該分支感興趣,而且它正嘗試向您顯示它認為您感興趣的內容。換句話說,預設情況下, 若要顯示所需分支的提交歷史,您必須明確指定它: |

該命令做了兩件事。它將 HEAD 指標移回指向 master
分支,並將您工作目錄中的檔案還原為 master
指向的快照。這也表示您從此點開始所做的變更將與專案的舊版本分歧。它本質上是將您在 testing
分支中所做的工作倒回,以便您可以朝不同的方向前進。
注意
|
切換分支會變更您工作目錄中的檔案
重要的是要注意,當您在 Git 中切換分支時,您工作目錄中的檔案將會變更。如果您切換到較舊的分支,您的工作目錄將會還原為您上次在該分支上提交時的樣子。如果 Git 無法乾淨地執行此操作,它根本不會讓您切換。 |
讓我們進行一些變更並再次提交
$ vim test.rb
$ git commit -a -m 'Make other changes'
現在您的專案歷史已經分歧(請參閱分歧的歷史)。您建立並切換到一個分支,在該分支上進行了一些工作,然後切換回主分支並進行其他工作。所有這些變更都隔離在不同的分支中:您可以在分支之間來回切換,並在準備就緒時將它們合併在一起。而您只用簡單的 branch
、checkout
和 commit
命令就完成了這一切。

您也可以使用 git log
命令輕鬆看到這一點。如果您執行 git log --oneline --decorate --graph --all
,它將會列印出您提交的歷史記錄,顯示您的分支指標所在的位置以及您的歷史記錄如何分歧。
$ git log --oneline --decorate --graph --all
* c2b9e (HEAD, master) Make other changes
| * 87ab2 (testing) Make a change
|/
* f30ab Add feature #32 - ability to add new formats to the central interface
* 34ac2 Fix bug #1328 - stack overflow under certain conditions
* 98ca9 Initial commit of my project
因為 Git 中的分支實際上是一個簡單的檔案,其中包含它所指向的提交的 40 個字元的 SHA-1 總和檢查碼,所以建立和銷毀分支的成本很低。建立新分支就像將 41 個位元組寫入檔案一樣快速簡單(40 個字元和一個換行符)。
這與大多數較舊的 VCS 工具分支的方式形成鮮明對比,後者涉及將專案的所有檔案複製到第二個目錄中。這可能需要幾秒鐘甚至幾分鐘的時間,具體取決於專案的大小,而在 Git 中,該過程始終是瞬時的。此外,由於我們在提交時會記錄父提交,因此尋找用於合併的適當合併基礎會自動為我們完成,而且通常很容易做到。這些功能有助於鼓勵開發人員經常建立和使用分支。
讓我們看看為什麼您應該這樣做。
注意
|
同時建立新分支並切換到它
通常會建立一個新分支,並希望同時切換到該新分支 — 這可以使用 |
注意
|
從 Git 2.23 版本開始,您可以使用
|