> For the complete documentation index, see [llms.txt](https://bwtit.gitbook.io/phpdev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://bwtit.gitbook.io/phpdev/ban-ben-guan-kong/fen-zhi-he.md).

# 分支與合併

branch、merge

分支與合併可說是版本管控與協同開發時最需要了解的地方。

## 儲存庫的目錄樹

### 觀察主要分支

儲存庫在首次提交之後，預設就會產生一個主要分支，名稱為 master，它是一個指標，指向最新的提交點，另外還會有一個指標稱之為 HEAD，它會指向目前作用的分支，在進行第二次提交時，master 指標會移動到第二個提交點，當然因為目前只有主要分支，所以 HEAD 仍然指向 master，也會跟著移動到第二個提交點。

![](https://1996372433-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LAOb18hLWbZPa07Vdcl%2F-LB5JbCGgwxNf3TrKuMW%2F-LB5KbOqvazhj9zuxfss%2FbranchRealFile.jpg?alt=media\&token=f4f5403b-3d9f-4aa8-8709-0612055e4683)

請注意 master 檔案的內容就是最後一次 commit 的雜湊值(40bit SHA-1)、HEAD檔案的內容就是master 檔案的路徑。 總之每一個分支，都會指向某個 commit 物件，而 HEAD 則會指著某一個分支。

> Git 的標籤(tag)功能跟分支很像，差別在於 commit 時，分支指標會自動隨著往後移動，但標籤要手動設定，所以標籤定下來之後就不會再移動，因此分支指標會指向該分支最後一次提交，而標籤指標會指向有特定意義(例如 v1.3版)的提交。

### 建立分支

透過以下指令就可建立分支 testing，可想像最後一次的提交點上擁有 master 與 testing 二個分支 (指標)

```
# dir /b ".git\refs\heads"    #觀察建立分支前有哪些分支檔
git branch testing
# dir /b ".git\refs\heads"    #觀察建立分支後的分支檔案變化
```

![](https://1996372433-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LAOb18hLWbZPa07Vdcl%2F-LB4yo6bKeh1q-rjTF6I%2F-LB557lGEg9AVkglZET_%2Fhead-to-master.png?alt=media\&token=b106c880-c927-4eb4-afb0-5bd99da2b4a7)

### 查詢分支

透過以下指令可查詢目前有多少分支存在

```
git branch     # 查詢目前有多少分支
* master       # 目前分支 (HEAD指向)
  testing    
```

### 切換分支

透過以下 git checkout 指令就可切換到分支 testing，此時 HEAD 指標改為指向 testing 這個分支

```
# type ".git\HEAD"       # 觀察 HEAD 目前指向的分支
git checkout testing
# type ".git\HEAD"       # 觀察切換分支後 HEAD 指向是否有跟著改變
```

切換分支的同時，會將該分支的工作區一起切換到該分支當時的狀況。

> 請留意 checkout在此為切換分支的意思，並非取回檔案

![](https://1996372433-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LAOb18hLWbZPa07Vdcl%2F-LB4yo6bKeh1q-rjTF6I%2F-LB55BdbcYiETzEOLeUm%2Fhead-to-testing.png?alt=media\&token=d660a13a-9a6d-4918-8fd0-a846e6b6cc1b)

### 建立後同時切換分支

建立與切換分支二行指令，可合併為以下一行

```
git checkout -b testing
# git branch testing     # 建立分支
# git checkout testing   # 切換分支
```

> 若目前分支與想切換的分支指向不同的提交點，在工作區有檔案異動尚未暫存或暫存區有檔案尚未提交時，是無法切換分支的。

### 在分支中隱藏封存目前進度(\*進階)

若在分支中的工作尚未完成，所以無法 commit ，但又需要暫時切換到其他分支，此時可使用隱藏功能，將受 git 控管的檔案狀態暫時 stash 隱藏封存起來，

```
git checkout testing             # 切到分支 testing
echo changed1>master.txt         # 在分支建立檔案
git stage .
git commit -m "testing change1"  # 在分支提交一次，
echo changed2>>master.txt        # 在分支修改檔案
git checkout -                   # 切換到前一個分支(master)，但會失敗
```

![](https://1996372433-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LAOb18hLWbZPa07Vdcl%2F-LDGIvJDskLcnkb76udu%2F-LDGgl6FQDJPcPSUdvSU%2FgitCheckoutFail.jpg?alt=media\&token=b2dc8c6c-557b-483e-aa62-535352503c6b)

```
git stash              # 將分支的工作區與暫存區檔案隱藏封存下來
git stash list
git checkout -         # 切換到前一個分支(master)，會將工作區與暫存區的檔案也一起還原
dir                    # 所以在前一個分支中找不到 master.txt
git stash pop          # 叫回隱藏的進度
```

### 在分支提交

因為已經切換到 testing 分支，接下來透過以下指令提交

```
echo changed>testing.txt
git stage .
git commit -m "first commit on testing branch"
```

![](https://1996372433-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LAOb18hLWbZPa07Vdcl%2F-LB4yo6bKeh1q-rjTF6I%2F-LB56mVelpbtu6HYRKDt%2Fadvance-testing.png?alt=media\&token=d83ecdd5-2f5e-4897-9edb-c4ad97da5f8c)

### 切換回主要分支

透過以下指令可切換回 master 分支，但此時請注意 HEAD 指標移動時會造成工作目錄的檔案內容改變，因此在 testing 分支增加的檔案，在切換到 master 分支後會看不見，因此若在 testing 分支中有檔案增修過但沒有提交(commit) 或隱藏(stash) 時，就不能夠切換分支(移動 HEAD)。

```
git checkout master
dir                  # 會發現工作目錄看不到 testing.txt
```

![](https://1996372433-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LAOb18hLWbZPa07Vdcl%2F-LB4yo6bKeh1q-rjTF6I%2F-LB57rW4ziXbt24zV5l4%2Fcheckout-master.png?alt=media\&token=8d8074ef-02e8-4ecc-bbc9-f8da729aea52)

### 在主要分支提交

透過下列指令在主要分支提交時，此時產生的 commit 節點就是獨立的一條路徑了，未來可以在不同的分支切換，之後等 testing 的工作完成後，再合併回 master

```
echo changed>master.txt
git stage .
git commit -m "new change"
```

![](https://1996372433-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LAOb18hLWbZPa07Vdcl%2F-LB58u3QKnEXAezuJBdY%2F-LB5AtTn1mBtjxqAbtIn%2Fadvance-master.png?alt=media\&token=003b942e-39b1-461b-ab88-9b9e97709254)

## 參考網頁 <a href="#kao" id="kao"></a>

* [ ] [圖解Git](https://marklodato.github.io/visual-git-guide/index-zh-tw.html)
* [ ] [連猴子都能懂的Git入門指南-進階篇](https://backlog.com/git-tutorial/tw/stepup/stepup1_1.html)
* [ ] [學習Git分支](https://learngitbranching.js.org/)
* [ ] [使用 Git 分支 - 簡述分支](https://git-scm.com/book/zh-tw/v2/%E4%BD%BF%E7%94%A8-Git-%E5%88%86%E6%94%AF-%E7%B0%A1%E8%BF%B0%E5%88%86%E6%94%AF)
