Git 版本管理工具:分支合并與沖突處理

Git branches merge and confict process
雖然人生不能重復(fù),但 Git 可以在我們?nèi)松膬?nèi)部實現(xiàn)部分倒流效果,比如可以讓開發(fā)者、創(chuàng)作者方便的保存代碼的版本,并且能夠快速的切換到指定的以前的版本,如果新代碼出現(xiàn)錯誤,可以再次回到過去,如同通關(guān)游戲,打到某個比較好的戰(zhàn)績可以保存一下,防止失敗后,又要重新開始。
一個典型的 git 工作流程大概如下:
+ 創(chuàng)建本地倉庫或克隆一個現(xiàn)有的倉庫;
+ 添加需要監(jiān)視的文件到倉庫里;
+ 修改文件,這些平常的編輯動作是在git的暫存區(qū)進行的;
+ 將修改過的文件提交到本地倉庫,這個過程可以看作是登記,這樣 git 數(shù)據(jù)庫才有記錄;
+ 通過 push 推送到服務(wù)器倉庫,如果只是本地工作可以省略;
+ 通過 pull 拉取服務(wù)器倉庫的文件到本地;
+ 創(chuàng)建版本分支;
+ ....
對應(yīng)使用到的命令如下:
- `git init` 建立本地倉庫,或 clone 服務(wù)器的倉庫;
- `git checkout` 簽出一個分支作為當(dāng)前的工作分支;
- `git add` 命令將工作區(qū)未跟蹤和修改文件提交到暫存區(qū);
- `git commit` 命令將暫存區(qū)內(nèi)容提交到當(dāng)前版本;
- `git remote` add 添加關(guān)聯(lián)的遠端倉庫地址,默認命名 origin;?
- `git push` 命令推送本地倉庫到服務(wù)器上;
Git 是一種分布式版本控制系統(tǒng) DVCS - Distributed Version Control System。在 Git 中絕大多數(shù)的操作都只需要訪問本地文件和資源,一般不需要來自網(wǎng)絡(luò)上其他計算機的信息。
它和集中式版本控制系統(tǒng) CVCS - Centralized Version Control Systems 相比,其不存在單點故障的問題。在 CVCS 中,如果中央服務(wù)器出現(xiàn)故障,則所有的人都無法繼續(xù)協(xié)同工作,而且數(shù)據(jù)如果沒有很好的備份,會出現(xiàn)數(shù)據(jù)丟失找不回的情況。但是在 DVCS 中就不存在這個問題,在網(wǎng)絡(luò)中的每一個節(jié)點都包含代碼倉庫的鏡像,當(dāng)協(xié)同工作用的服務(wù)器出現(xiàn)故障的時候,都可以使用任何一處鏡像出來的本地倉庫進行恢復(fù)。
理解 Git,首先得記住 Git 的三種基本狀態(tài)和對應(yīng)三種工作區(qū)域:

Git 基本操作都與三種狀態(tài)有關(guān)
上面的三種狀態(tài)對應(yīng)于 Git 的三個工作區(qū)域的概念:
1. 工作目錄:即操作系統(tǒng)中包含 .git 文件夾的目錄,.git 目錄是版本數(shù)據(jù)庫目錄;
2. 暫存區(qū)域:對應(yīng) .git 目錄中的數(shù)據(jù)據(jù)已經(jīng)在暫存區(qū)記錄了文件的狀態(tài)信息;
3. 已提交狀態(tài):對應(yīng):工作區(qū)的文件內(nèi)容已提交到 Git 倉庫中。
對于已經(jīng)提交的所有文件,都會在包含完整的歷史提交記錄,文件歷史修改數(shù)據(jù)都有記錄,即表示 .git 目錄下的數(shù)據(jù)已經(jīng)包含文件的所有數(shù)據(jù),即使將工作區(qū)的文件刪除,也可以通過 git checkout -- * 從數(shù)據(jù)庫中檢出所有文件。
所謂分布式,是指所有 .git 數(shù)據(jù)倉庫都是一個完整獨立的版本數(shù)據(jù)庫,通過 git clone 命令可以從一個數(shù)據(jù)倉庫克隆到另一個位置:可以是操作系統(tǒng)中的目錄,或者是遠程主機上的數(shù)據(jù)倉庫,例如 github.com。比如,當(dāng)前系統(tǒng)中的 test_branch_merge 文件有一個版本數(shù)據(jù)倉庫,那么通過 clone 就可以復(fù)制它的副本:
使用 Node.js watch 工具監(jiān)視文件改動,并自動重新運行指定的命令:
過濾器文件是一個返回過濾函數(shù)的 Node.js 模塊腳本,過濾函數(shù)名稱隨意,但需要在作為 exports 返回,然后通過 -f 或者 --filter 將文件名傳遞給 watch 工具:
通常,主分支 master 是其它分支的來源,首次創(chuàng)建分支一般都基于初始化的 master 分支。
以下是 git 分支合并與沖突處理的演示腳本,此操作演示使用了 port.o 和 able.o 兩個文件來演示分支的創(chuàng)建、合并與沖突內(nèi)容的處理,步驟說明如下:
1. Step 初始化目錄結(jié)構(gòu);
2. Step 初始化 git 數(shù)據(jù)庫,為默認的 master 分支添加初始文件 port.o;
3. Step 基于 master 創(chuàng)建新分支 test_branch,切換到此分支并為其添加新文件 able.o;
4. Step 在新分支 test_branch 上刪除原來的 port.o 以測試文件在合并時的處理策略;
5. Step 切換回 master 分支,創(chuàng)建并添加和新分支同名的文件 able.o 以測試內(nèi)容沖突處理;
6. Step 執(zhí)行 git merge test_branch 合并分支到當(dāng)前的 master 分支,此時有多種可能:
6.1. 一是可以自動處理的分支合并,不需要用戶手動處理;
6.2. 二是如果當(dāng)前分支未修改相應(yīng)文件,就保持與正在合并分支的文件狀態(tài)一致:刪除 port.o。
6.3. 三是內(nèi)容沖突,最常見操作,因為待合并分支與當(dāng)前分支的文件內(nèi)容有 diff 差異需要手動處理。
7. Step 合并后分支的狀態(tài),處理方式:繼續(xù)使用,或者刪除;
說明:如果新分支持將其源分支的文件刪除,在合并到源分支時,并且源分支上沒有再對文件進行改動,那么合并操作就會按新分支的狀刪除文件。一般,新分支會以 some-feature 的形式命名,以提示此分支的功能與目標(biāo)。執(zhí)行 git merge 命令時,是將指定的分支內(nèi)容合并到當(dāng)前活動分支內(nèi)。
沖突內(nèi)容中會出現(xiàn) git 檢測到的 diff 內(nèi)容,并且用 <<<<<<< HEAD 表示當(dāng)前讀寫指針是最頂端,>>>>>>> test_branch 表示待合并的分支,diff 內(nèi)容分別對應(yīng) ======= 分割符的前后內(nèi)容。手動解決沖突就是處理這些有沖突的內(nèi)容,選擇需要的留下,刪除不需要的內(nèi)容,甚至可以將所有內(nèi)容都保留。
輸出內(nèi)容參考:
最后,Linxu 和 Windows 系統(tǒng)使用了不同的文本換行規(guī)則,CR vs. CRLF。Unix 類系統(tǒng)心 CR end-of-line 作為換行標(biāo)志,Windows 則以 CRLF "\r\n" 作為換行符號,Mac OS 9 系統(tǒng)則會使用 LF。在機械式找字機上,CR 是指打印頭復(fù)位到行首,LF 是指進紙機構(gòu)移動紙張前進一行。部分程序未對換行符做特別處理,則可能會導(dǎo)致運行出錯,比如 Vim 配置文件,如果在 WSL 等系統(tǒng)出現(xiàn) CRLF 就會出現(xiàn) ^M 的錯誤提示。
1. LF for "line feed", encoded as 0x0A, \r;
2. CR for "carriage return", encoded as 0x0D, \n;
Git 提供了自動處理兩種系統(tǒng)的換行符號,打開 autocrlf 功能有兩種不同的處理策略:
https://markentier.tech/posts/2021/10/autocrlf-true-considered-harmful/
1. core.autocrlf true 方式提交件時轉(zhuǎn)換為 LF,檢出時轉(zhuǎn)換為 CRLF;
2. core.autocrlf input 方式提交件時轉(zhuǎn)換為 LF,但是檢出時不轉(zhuǎn)換;
3. core.autocrlf false 禁用自動轉(zhuǎn)換,提交檢出均不轉(zhuǎn)換;
自動轉(zhuǎn)換是指定 Git 根據(jù)當(dāng)前操作系統(tǒng),將? CR CRLF LF 等等換行形式轉(zhuǎn)換為 LF,如果使用 autocrlf true 方式,則會在檢出文件時替換回當(dāng)前系統(tǒng)風(fēng)格的換行符,autocrlf input 方式則只會在檢入文件時替換所有換行符為 LF。如果收到以下警告信息,就表示開啟了自動 autocrlf true:
warning: LF will be replaced by CRLF in file.
warning: CRLF will be replaced by LF in port.o.??
手動檢出所有文件:
全局配置或配置文件: