[教學] git-19 分支的概念 - 討論區

[教學] git-19 分支的概念

文章瀏覽次數 1078 文章回覆數 0

特種兵

特種兵圖像(預設)

2020-03-24 20:12:35

From:211.23.21.202

上篇我們操作了一下分支,對於分支的基本運作大概有個認識,讓我們再花點時間了解他的運作。

分支間的關係

其實開分支並不是把原本的所有檔案複製一份過去,如果是這樣的話,一個專案開了幾十個分支,

這樣幾個大專案下來硬碟就吃不消了。

他的概念還是在 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 都有把這些指令寫在畫面上,大家可以自己玩玩看。