上篇我們操作了一下分支,對於分支的基本運作大概有個認識,讓我們再花點時間了解他的運作。
分支間的關係
其實開分支並不是把原本的所有檔案複製一份過去,如果是這樣的話,一個專案開了幾十個分支,
這樣幾個大專案下來硬碟就吃不消了。
他的概念還是在 commit 上,開分支的時候就是從上個 commit 開始各分東西,
從此以後兩個分支各有各的人生,當然人生有時也會相會。
還記得我們提過的工作目錄、暫存區與儲存庫吧?其實分支的運作就是靠 commit 利用儲存庫配製好你分支的工作目錄而已。
其實儲存庫與暫存區都是同一個,大家共用。
共用暫存區
因為暫存區是共用的,所以在 A 分支的暫存區,切換到 B 分支去還是看得到,
我們做個實驗,就是在 master 分支做某事後切到 test 分支把結果提交到 test 分支去。
現在這兩個分支的暫存區都是空的,都有 abc.txt 檔案且內容為空。
# 確定自己在 master 分支
$ git branch
* master
test
# 在 abc.txt 加一行字到 abc.txt 當中
$ echo '想你想你' >> abc.txt
# 檢查暫存區狀態
$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: abc.txt
no changes added to commit (use "git add" and/or "git commit -a")
# 記錄到暫存區
$ git add .
# 檢查暫存區狀態
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: abc.txt
# 切到 test 分支
$ git checkout test
Switched to branch 'test'
M abc.txt
# 他會提醒你,有個 abc.txt 被變更了還在暫存區
$ git branch
master
* test
$ git status
On branch test
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: abc.txt
# 看到了吧,明明是在 master 做的,但因為都是同一個暫存區,所以切到 test 也是一樣
$ git commit -m '修改 abc.txt'
[test a6a0896] 修改 abc.txt
1 file changed, 1 insertion(+)
# 看一下 test 的 abc.txt
$ cat abc.txt
想你想你
# 再去 master 看看 abc.txt
$ git checkout master
Switched to branch 'master'
# 因為暫存區沒東西,所以也沒有什麼提示
$ cat abc.txt
# 空空沒東西,因為我們是在 test commit 的
不能切分支
那時麼時候不能切分支了,就是當相同的檔案但兩個分支的內容不同時。
其中一個分支又改了這個檔案放在暫存區,此時想切到其他分支就會發生錯誤,要你先處理一下暫存區再說。
就像我們現在的 master 跟 test 的 abc.txt 檔案內容已經不同了,
讓我們試看看:
# 這一次一樣在 master 的 abc.txt 加一行字,但內容跟之前不同
$ echo '你好你好' >> abc.txt
# 紀錄到暫存區
$ git add .
# 確認一下狀態
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: abc.txt
# 切到 test 分支
$ git checkout test
error: Your local changes to the following files would be overwritten by checkou
t:
abc.txt
Please commit your changes or stash them before you switch branches.
Aborting
這次就沒辦法切到 test 了,為什麼?因為暫存區紀錄的來源是工作目錄,
兩個分支的工作目錄的 abc.txt 內容是不同的,當然就沒辦法這樣囉。
但如果是不衝突的修改就可以切換分支共享暫存區了。
那如果是提交上去的怎麼辦?那就要來合併分支囉。
補充
我們想把 abc.txt 恢復原狀,但我們剛剛已經 git add .
到暫存區了怎麼辦?
# 先把 abc.txt 從暫存區拔掉
$ git restore --stage abc.txt
# 看一下狀態有沒有回到修改檔案但尚位 git add . 的狀況
$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: abc.txt
no changes added to commit (use "git add" and/or "git commit -a")
# 把 abc.txt 還原到還沒修改的狀態
$ git restore abc.txt
# 看一下狀態應該像沒動過檔案那樣就可以收工囉
$ git status
On branch master
nothing to commit, working tree clean
其實 git status
都有把這些指令寫在畫面上,大家可以自己玩玩看。