問題描述#
問題的最開始是我在 Vercel 部署了 lobechat,但是我 fork 的倉庫從原倉庫經常同步失敗,然後在 Pull requests 頁面看到了有一個 request
圖片中可以看到有一個合併衝突,需要解決這個衝突才能正常合併
在 GitHub 上,Pull Request(簡稱 PR)是一個請求,通常是由開發者發起,向項目的維護者提出將自己分支上的更改合併到項目的主分支中。Pull Request 允許開發者在代碼合併之前進行討論、審查和測試,確保代碼質量和功能符合預期。(你可以通過點擊 Pull Request 的標題來查看詳細信息,包括提交的更改、討論和審查狀態。)
為什麼我 fork 的倉庫也可以收到開發人員合併到原倉庫的請求呢?
當你 fork 一個倉庫時,你創建了一個與原始倉庫完全獨立的複製副本。然而,如果你在 fork 的倉庫中啟用了 GitHub Actions 或者某些自動化工具,這些工具可能會自動創建 Pull Request 來同步原始倉庫的更新。這通常是為了保持你的 fork 與上游倉庫的代碼同步。
具體情況#
我在 Fork 一個倉庫後( lobehub/lobe-chat
),為了讓自己 Fork 的倉庫能夠保持和原始倉庫一致,我執行了與原始倉庫同步的操作(即將原始倉庫的最新更改拉取到我自己的分支)。在執行命令時,Git 報告了一些文件存在代碼衝突,具體錯誤如下:
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
Auto-merging README.zh-CN.md
CONFLICT (content): Merge conflict in README.zh-CN.md
Automatic merge failed; fix conflicts and then commit the result.
這是由於我的 Fork 倉庫 (origin
) 和原始倉庫 (upstream
) 在某些文件(如 README.md
和 README.zh-CN.md
)中都有修改,Git 無法自動合併這些衝突,所以需要手動解決。
解決問題的思路和方法#
基於以上問題,可以分為以下幾個步驟解決:
1. 配置 upstream
遠程倉庫#
Fork 後默認只關聯到自己的 GitHub 倉庫(origin
),而未設置與原始倉庫(upstream
)的關聯。為了同步原始倉庫,需要先添加一個名為 upstream
的遠程倉庫。
git remote add upstream https://github.com/lobehub/lobe-chat.git
解釋:
git remote add
:用於添加遠程倉庫。upstream
:這是遠程倉庫的名稱(習慣將原始倉庫命名為upstream
)。https://github.com/lobehub/lobe-chat.git
:原始倉庫的地址。
通過以下命令可以確認遠程倉庫是否配置正確:
git remote -v
輸出示例:
origin https://github.com/<your-username>/lobe-chat.git (fetch)
origin https://github.com/<your-username>/lobe-chat.git (push)
upstream https://github.com/lobehub/lobe-chat.git (fetch)
upstream https://github.com/lobehub/lobe-chat.git (push)
2. 從原始倉庫拉取最新代碼#
配置完 upstream
後,可以拉取原始倉庫的最新代碼到本地:
git fetch upstream
這將獲取 upstream
倉庫的所有更新,並在本地形成一個更新的引用,如 upstream/main
。
接著需要將 upstream/main
的最新更改合併到自己的分支(假設是 main
分支):
git checkout main # 確保切換到主分支
git merge upstream/main # 將原始倉庫的更新合併到當前分支
如果一切順利,Git 會完成自動合併,但由於我們之前遇到了衝突,Git 會提示以下錯誤並停止:
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
Auto-merging README.zh-CN.md
CONFLICT (content): Merge conflict in README.zh-CN.md
Automatic merge failed; fix conflicts and then commit the result.
3. 解決合併衝突#
此時需要手動解決衝突文件中的衝突問題。
3.1 定位衝突文件#
運行以下命令,查看哪些文件存在衝突:
git status
輸出會標記衝突的文件為 both modified
,例如:
both modified: README.md
both modified: README.zh-CN.md
3.2 編輯文件解決衝突#
通過編輯器(如 VS Code)打開這些衝突文件。Git 會在衝突部分添加特殊標記,格式如下:
<<<<<<< HEAD
(分支 HEAD 的代碼內容)
=======
(來自 upstream/main 的代碼內容)
>>>>>>> upstream/main
你需要根據需要進行編輯,選擇保留哪部分內容,或合併兩部分內容。例如:
當前文件內容(衝突前)
<<<<<<< HEAD
我修改過的 README 內容在這裡。
=======
一個新的更新來自於上游倉庫。
>>>>>>> upstream/main
衝突解決後(調整後)
假設你希望保留兩部分內容並進行合併後:
我修改過的 README 內容在這裡。
一個新的更新來自於上游倉庫。
編輯完成後,保存文件,並確保衝突標記(<<<<<<<
, =======
, >>>>>>>
)都已刪除。
3.3 標記衝突解決完成#
解決完衝突後,將已修改的文件添加到暫存區:
git add README.md README.zh-CN.md
或使用通配符一次性添加所有文件:
git add .
3.4 提交合併結果#
所有衝突解決並添加到暫存區後,提交此次合併的解決結果:
git commit -m "Resolve merge conflicts in README files"
4. 推送本地改動到遠程倉庫#
完成合併後,將本地的更改推送到自己的 Fork 倉庫:
git push origin main
此時,GitHub 上會顯示你的分支已經與原始倉庫同步。如果這是為了解決 GitHub 上的 Pull Request 衝突,你現在可以在 GitHub 網站上將 PR 合併完成。
總結#
這是一個完整的 Git 合併衝突的處理實踐,通過上面的操作,我成功解決了文件衝突問題,並完成了原始倉庫更新同步到自己的 Fork 倉庫。
- 問題:在同步原始倉庫更新時,因兩個分支對同一文件的修改不同,導致合併衝突。
- 解決方案:
- 配置並拉取原始倉庫的更新。
- 合併更新到當前分支時,識別衝突文件。
- 手動解決衝突文件中的標記內容,保留合適的代碼。
- 提交修改並推送更新到遠程倉庫。
相關關鍵命令總結:
- 添加
upstream
遠程倉庫:git remote add upstream <url>
- 拉取並與原始倉庫同步:
git fetch upstream git merge upstream/main
- 查看衝突文件:
git status
- 自動或手動解決衝突後,提交改動:
git add <file> git commit -m "Resolve conflicts" git push origin main
通過這次實踐,我對 Git 合併衝突的解決過程有了更深的理解。無論是同步原始倉庫,還是處理複雜的團隊協作場景,這些技能都非常重要。希望能幫助有類似問題的小夥伴!