7. Conflict 衝突

在前面幾章,我們學會了開闢平行宇宙(分支)以及合併(Merge)。Git 通常很聰明,只要兩個人改的是不同的檔案、或是同個檔案的不同行,Git 都會默默地幫你自動合體(Fast-forward 或自動合併)。

但是,天有不測風雲。

當主線宇宙(main有人改了 index.html 的第 3 行,而你的平行宇宙(feature)也改了 index.html 的第 3 行。當你快樂地輸入 git merge 時……

此時 Git 會不知道到底「誰改的才是對的」,於是它會雙手一攤,把檔案丟回給你,叫你自己處理好:

CONFLICT (content): Merge conflict in index.html

Automatic merge failed; fix conflicts and then commit the result.

這就是傳說中的衝突。Git 選擇不擅自作主,而是把決定權交還給你。

gitGraph
    commit id: "建立專案 (Line 3: 原始文字)"
    
    branch feature/conflict-test
    
    checkout main
    commit id: "main 修改 Line 3 (主線文字)"
    
    checkout feature/conflict-test
    commit id: "feature 修改 Line 3 (平行宇宙文字)"
    
    checkout main
    merge feature/conflict-test id: "💥 Conflict! 兩邊都改了 Line 3"

1. 模擬衝突

為了學會解衝突,最好的方式就是自己搞出一場衝突。我們來實作一次:

步驟 1

main 分支改動第 3 行。確保你在 main 分支,把 index.html 的第 3 行改成:

<p>這是主線宇宙改寫的文字</p>
Code language: HTML, XML (xml)

然後打包提交:

git add .
git commit -m "style: update line 3 in main"
Code language: JavaScript (javascript)

步驟 2

去新分支改動「同一行」。我們從這個時間點開一個新分支,故意也去改第 3 行:

git checkout -b feature/conflict-test

打開 index.html,把第 3 行改成完全不同的東西:

<p>這是平行宇宙完全不一樣的文字!!!</p>
Code language: HTML, XML (xml)

一樣打包提交:

git add .
git commit -m "style: update line 3 in branch"
Code language: JavaScript (javascript)

步驟 3:

衝突!現在,切換回 main 分支,準備強行把新分支合進來:

git checkout main
git merge feature/conflict-test

此時終端機會跳出錯誤訊息,而且你的專案資料夾會進入 (main|MERGING) 的特殊狀態。

2. 所以怎辦 ?

這時候如果你用 VS Code打開 index.html,你會發現程式碼被 Git 塞了一些奇怪的符號:

<<<<<<< HEAD
<p>這是主線宇宙改寫的文字</p>
=======
<p>這是平行宇宙完全不一樣的文字!!!</p>
>>>>>>> feature/conflict-test
  • <<<<<<< HEAD:代表「你目前站的分支(也就是 main)」裡面的內容。
  • =======:楚河漢界。用來隔開雙方的修改。
  • >>>>>>> feature/conflict-test:代表「你想合進來的那個分支」裡面的內容。

VS Code 會自動把這段衝突染成醒目的顏色(綠色與藍色),並在最上方提供四個點擊按鈕:

  1. Accept Current Change(採用目前變更): 留下 main(你目前的版本),丟掉分支的版本。
  2. Accept Incoming Change(採用來源變更): 留下分支(合進來的版本),丟掉你目前的版本。
  3. Accept Both Changes(同時保留雙方): 小孩子才做選擇,兩行我都留!
  4. Compare Changes(比較變更): 幫你左右對齊,細細比對。

實際解法工作流:

  1. 跟當事人討論(最重要): 去問問改那行程式碼的同事,確認到底要把誰的扣留下來。
  2. 點擊按鈕: 在 VS Code 上點擊你決定好的按鈕(例如點選 Accept Both Changes)。那些奇怪的 <<<=== 符號就會瞬間消失。
  3. 存檔離開。

3. 重新提交

當你把檔案裡的所有衝突符號都清理乾淨、程式碼存檔後,Git 還在等你的最後一步:重新提交

# 1. 告訴 Git 我把衝突檔案修好了
git add index.html

# 2. 重新 Commit(通常 Git 會自動幫你寫好 "Merge branch..." 的預設訊息)
git commit -m "fix: resolve merge conflict in index.html"
Code language: PHP (php)

輸入完後,你會發現終端機後方的 |MERGING 消失了,專案重回和平的狀態。恭喜你,完美拆彈!

小結

遇到 Conflict 真的不用怕,它代表 Git 正在盡忠職守地保護你的專案,防止你盲目覆蓋掉夥伴的成果。

  • 衝突的原因:兩個人在不同的分支改了同個檔案的同一行
  • 解決的密碼:認清 HEAD(自己)與 Incoming(他人),並用 VS Code 點選決定。
  • 拆彈完畢後:務必重新 git addgit commit 才能順利結束合併。

到這裡,你已經掌握了 Git 最核心、最精華、連許多實習生都會卡關的所有技術。你已經可以說自己「會用 Git 進行團隊協作」了!