【Git】refusing to merge unrelated histories
エラーの原因と解決法を徹底解説
はじめに
Gitを使い始めた頃、ローカルでgit init
して、GitHub上でもリポジトリを作り、「さあ、連携しよう!」とgit pull
やgit push
を実行したら、このエラーに出会ったことはありませんか?
fatal: refusing to merge unrelated histories
これは、Gitが「共通の歴史を持たない、全く無関係な2つのリポジトリを統合しようとしていますよ!」と、危険を察知して処理を止めてくれている親切なエラーです。
この記事では、このエラーがなぜ起きるのか、どうすれば未然に防げるのか、そして起きてしまった場合にどう対処すればよいのかを、日記の例え話を交えながら分かりやすく解説します。
なぜこのエラーが起きるのか? unrelated historiesの正体
このエラーの根本原因は、**「それぞれ別の場所で生まれた、全く繋がりのないコミット履歴(歴史)をマージしようとしている」**ことにあります。
Gitの歴史を日記に例えてみましょう。
-
あなたのPC上(ローカル)
git init
を実行すると、あなたのPCに新しい日記帳(リポジトリ)が作られます。
git commit
をすると、その日記帳に最初の1ページ目が書き込まれます。 -
GitHub上(リモート)
GitHubで新しいリポジトリを作成する際に、「Add a README file」にチェックを入れると、GitHub上にも全く別の新しい日記帳が作られ、READMEファイル作成のコミット、つまり別の歴史を持つ1ページ目が自動で書き込まれます。
この状態でgit pull
を実行すると、Gitは「ローカルの日記」と「リモートの日記」を統合しようとします。しかし、両者の出発点となる最初のページが全くの別物であるため、「この2冊の日記は話が繋がらないから、安全のためにマージを中止します」と判断し、refusing to merge unrelated histories
エラーを出力するのです。
エラーを未然に防ぐ!最も綺麗な連携手順 ✅
このエラーを回避する最もクリーンで推奨される方法は、**「空のリモートリポジトリに、ローカルの歴史を最初に反映させる」**ことです。
ステップ1: GitHubで「空っぽの」リポジトリを作成する
これが最も重要なポイントです。GitHubでリポジトリを新規作成する際、**Add a README file
、.gitignore
、license
のチェックを一切入れないでください。**コミット履歴が何もない、完全に空のリポジトリを作成します。
ステップ2: ローカルで最初のコミットまで済ませる
あなたのPCで、通常通りプロジェクトの準備を進めます。
# 1. Gitリポジトリを初期化
git init
# 2. 全てのファイルをステージング
git add .
# 3. 最初のコミットを作成
git commit -m "Initial commit"
ステップ3: リモートリポジトリを登録する
ステップ1で作成した空のリポジトリのURLを、origin
という名前で登録します。
git remote add origin <GitHubリポジトリのURL>
ステップ4: ローカルの歴史をプッシュする
最後に、ローカルのコミット履歴をリモートにプッシュ(送信)します。
# -u オプションは、今後のpush/pullをorigin/mainに紐づける設定
git push -u origin main
リモートリポジトリは空っぽだったので、ローカルの歴史をすんなりと受け入れてくれます。これでローカルとリモートの歴史が完全につながり、エラーは発生しません。
すでにエラーが出てしまった場合の対処法 ⚠️
もし、すでにローカルとリモートの両方でコミットが存在し、エラーに直面してしまった場合は、以下のコマンドで2つの歴史を強制的に繋げることができます。
git pull origin main --allow-unrelated-histories
このコマンドは、「歴史が違うのは分かっているけど、それでもマージして」という特別な許可を与えるオプションです。実行すると、2つの異なる歴史を統合するための新しいマージコミットが作成されます。
ただし、これは本当に無関係だった2つのプロジェクトを1つに統合したい場合などに使うべき、いわば最終手段です。基本的には、上記で説明した**「空のリモートリポジトリにプッシュする」手順**を踏むのが最も安全で確実です。
補足:こまめなコミットとプッシュの重要性 💡
Gitの操作に慣れてきたら、「こまめにcommit
し、キリの良いところでpush
する」習慣をつけたましょう。(現に私自身がcommit/pushをこまめにできていませんでした、、)
なぜ、こまめにコミットするのか?
commit
は、作業の区切りごとに行うセーブポイントのようなものです。
- 変更内容が明確になる:「ログイン機能を追加」「ボタンのスタイルを修正」のように、1つのコミットに1つの役割を持たせることで、後から履歴を見返したときに何をしたか一目瞭然になります。
- 問題の切り分けが簡単になる:バグが発生した際に、どのコミットが原因か特定しやすくなります。
- 安心して変更できる:何か問題が起きても、直前の正常なコミットにすぐ戻ることができます。
なぜ、こまめにプッシュするのか?
push
は、ローカルのセーブポイント(コミット)を、GitHubなどのリモートサーバーにバックアップする行為です。
- コードのバックアップ:PCが故障しても、コードはリモートリポジトリで安全に保護されます。
- チームでの情報共有:複数人で開発している場合、あなたの進捗をチームメンバーに共有できます。
理想的な作業フローの例
- 小さな機能(例:お問い合わせフォームの項目を1つ追加)を実装する。
git add .
git commit -m "feat: お問い合わせフォームに電話番号欄を追加"
- 別の小さな機能(例:送信ボタンのデザイン変更)を実装する。
git add .
git commit -m "style: 送信ボタンの色を青に変更"
- 今日の作業のキリが良いところで、まとめて
push
する。
git push
まとめ
-
refusing to merge unrelated histories
は、共通の歴史を持たないリポジトリ同士をマージしようとすると発生する。 -
最も良い解決策は、GitHubで空のリポジトリを作成し、ローカルの初コミットを
push
すること。 - どうしても必要な場合は
--allow-unrelated-histories
オプションで強制マージできるが、利用は慎重に。 - 良いGitの習慣として、こまめなコミ-ットとプッシュを心がけましょう。
このエラーの仕組みを理解して、スマートなGit運用を目指しましょう!