できない.dev

Git で「fatal: refusing to merge unrelated histories」が解決できない

共通の祖先を持たない 2 つの履歴を merge / pull すると Git 2.9 以降が安全のため拒否する。
意図的な統合なら --allow-unrelated-histories を付け、そうでなければ clone し直すか subtree を検討する。

#git#merge#pull#history#allow-unrelated-histories

要約

fatal: refusing to merge unrelated histories は、共通の祖先コミットを持たない 2 つの履歴git merge または git pull で統合しようとしたときに、Git 2.9 以降が安全装置として拒否する状態。
統合が妥当なら --allow-unrelated-histories を明示的に付けて許可する。
そうでなければ履歴を繋がず別の取り込み方を選ぶ。

よくある原因

  1. 空リポジトリ + 別履歴: GitHub 側で README 付きリポジトリを作り、手元の git init 済みプロジェクトを後から git pull した
  2. リモートを後付け: ローカルで何度かコミットした後に git remote add し、初期コミットがリモートと噛み合わない
  3. 2 リポジトリの統合: 別々に育てたリポジトリを 1 つにまとめようとしている
  4. 履歴の作り直し: .git を削除して再 git init し、過去の履歴と分岐した

解決策

1. 意図的な統合なら明示フラグを付ける

git pull origin main --allow-unrelated-histories
# merge を直接呼ぶ場合
git merge other-branch --allow-unrelated-histories

Git 2.9 で既定が「拒否」に変わったため、統合が正しいと判断できるときだけ このフラグで上書きする。
詳細は git-merge 公式ドキュメントgit-pull 公式ドキュメント--allow-unrelated-histories の項を参照。

2. リモートの初期コミットを取り込む

git remote add origin <url>
git fetch origin
git merge origin/main --allow-unrelated-histories

両方の履歴が残る。
同じファイル(README など)が衝突したら、通常のコンフリクト解消(編集 → git addgit commit)で片付ける。

3. ローカルがほぼ空なら clone し直す

git clone <url> project
# 手元の必要ファイルを project/ にコピーして
git add .
git commit -m "import local work"

履歴を無理に接続せず、リモートを正として作業を載せ替える方が後で履歴が読みやすい。

4. 別履歴として取り込む

2 つのプロジェクト履歴をどちらも保持したい場合は、merge ではなく subtree を使う。

git subtree add --prefix=vendor/lib <url> main

vendor/lib/ 配下に相手リポジトリを取り込み、自分の履歴とは分けて管理できる。
統合すべきでないものを --allow-unrelated-histories で繋ぐと、後からログ追跡が困難になる点に注意する。

この記事は役立ちましたか?