Contents

git同步分支衝突解決方法

有一次我把本地已經開發一段時間的專案推到新建的 GitLab 遠端儲存庫,結果第一個 push 就撞到 fatal: refusing to merge unrelated histories。這個錯誤不難解,但如果當下不理解原因,很容易會誤以為是遠端權限、分支名稱或 pull/push 順序出了問題。

這篇整理一下這個錯誤真正代表什麼、什麼情況會出現,以及比較安全的處理流程。

這個錯誤是什麼意思

refusing to merge unrelated histories 的意思是,目前你的本地分支歷史和遠端分支歷史,Git 判定它們不是從同一條提交鏈分支出來的,所以不願意直接幫你合併。

常見情境有這幾種:

  1. 你本地專案早就自己 git init 過,後來才接上一個已經有初始 commit 的遠端儲存庫。
  2. 遠端平台自動幫你建立了 README.md.gitignore 或 License,導致遠端已經有一個獨立歷史。
  3. 你是從別的來源複製過來,再硬接到另一個不相關的 repo。

最直接的處理方法

如果你確定本地和遠端就是要合併成同一個專案,可以先 pull 並允許合併不相關歷史:

1
git pull origin master --allow-unrelated-histories

如果你的遠端預設分支是 main,就把 master 改成 main

1
git pull origin main --allow-unrelated-histories

接著 Git 可能會要求你解衝突,處理完之後再 commit,最後再 push。

比較完整的安全流程

我自己會比較建議用下面這種順序:

  1. 先確認遠端預設分支名稱是 master 還是 main
  2. 先做一次 git status,確保本地工作目錄是乾淨的。
  3. 執行 git pull origin <branch> --allow-unrelated-histories
  4. 如果發生衝突,逐一修正檔案內容。
  5. git add . 後建立合併 commit。
  6. 最後再 git push origin <branch>

如果想看目前遠端設定,也可以先查:

1
2
git remote -v
git branch -vv

另一種做法:重新 clone 再搬檔案

我後來也想到另一種比較直觀的方法,就是先把遠端 repo 重新 clone 下來,再把舊專案檔案複製進去後重新 commit。

這種方式的優點是流程單純、比較不容易被 Git 歷史搞混;缺點也很明顯,就是本地原本的 commit 歷史通常不會一起保留下來。

所以如果你很在意歷史完整性,還是應該走 --allow-unrelated-histories 的正規合併方式。

什麼時候不該這樣做

如果你其實是接錯 repo,或把不相干的兩個專案硬湊在一起,那就不應該用這個參數。因為它只是強迫 Git 接受合併,不代表兩邊內容真的應該混在一起。

實務上先確認下面兩件事會比較保險:

  1. 遠端 repo 是不是你真正要推送的專案。
  2. 遠端初始 commit 裡面有沒有使用者已經正式提交的重要內容。

小結

refusing to merge unrelated histories 本身不是大問題,重點是先判斷兩邊歷史為什麼會分開。如果只是本地專案要接上一個剛建立的遠端 repo,那用 git pull origin <branch> --allow-unrelated-histories 就能解;如果是接錯專案,硬合併反而會把歷史弄亂。

參考來源