概要
・ 初心者がgitコマンドで遊んでいたら、いつの間にかpushできなくなっていた。
・ pushできない原因をfatal: refusing to merge unrelated historiesに特定。
・ 最終的に自分が何をやらかしたのか推測(なんのコマンドを実行したか覚えていないため)。
※fatal: refusing to merge unrelated historiesに対する結論は、「解決法」に記載がございます。
環境
% git --version
git version 2.36.1
※リモート名「origin」、ブランチ名「main」で作業しています。
エラー状況
①. 「main」ブランチをpushしようとしたところ、エラーが発生
②. エラー文に基づいて、「main」ブランチをpullを実行するも再度エラーが発生
③. 再度出たエラー文に基づいて、config pull.rebase falseを実行し、再度pullするも再再度エラーが発生
それぞれ状況を確認していきます。
エラー状況①
「main」ブランチをpushしようとしたところ、下記のエラーが発生した。
% git push origin main
To https://github.com/xxxxxxxxxxxxxxxxxxx
! [rejected] main -> main (non-fast-forward)
error: failed to push some refs to 'https://github.com/xxxxxxxxxxxxxxxxxxx'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
- エラー文の内容は以下の通り。
- xxxxxxxxxxxxxxxxxxxに
pushできなかったよ - リモートブランチより現在のブランチが古いから、拒否されたよ
- 再
pushする前に、リモートの変更を統合してね(例えばgit pullでね)
- xxxxxxxxxxxxxxxxxxxに
エラー文中の(non-fast-forward)について、GitHub Docsによると、
別の人が同じブランチにすでにプッシュしてしまった場合、Git はあなたの変更をプッシュできません。
別の人はいない(自分一人でしか作業をしていない)ので、自分が既にリモートリポジトリへpush済みであることが原因のよう。
とりあえずエラー文の指示通り、pullを実行してみることに...
エラー状況②
pullを実行したところ、またエラーが発生。下記の通り。
% git pull origin main
From https://github.com/xxxxxxxxxxxxxxxxxxx
* branch main -> FETCH_HEAD
hint: You have divergent branches and need to specify how to reconcile them.
hint: You can do so by running one of the following commands sometime before
hint: your next pull:
hint:
hint: git config pull.rebase false # merge
hint: git config pull.rebase true # rebase
hint: git config pull.ff only # fast-forward only
hint:
hint: You can replace "git config" with "git config --global" to set a default
hint: preference for all repositories. You can also pass --rebase, --no-rebase,
hint: or --ff-only on the command line to override the configured default per
hint: invocation.
- エラー文の内容は以下の通り。
- 分岐したブランチがあって、それらを一致させる方法を指定する必要があるよ
- 次の
pullの前に、次のコマンドのうちのどれかを実行すればそれができるよ
(git config以下略)
エラー文の指示通り、1つめのコマンドgit config pull.rebase falseを実行し、
その後に再度pullをしてみることに...
エラー状況③
pullを実行したところ、下記のエラーが発生。またpull出来ず...
% git pull origin main
From https://github.com/xxxxxxxxxxxxxxxxxxx
* branch main -> FETCH_HEAD
fatal: refusing to merge unrelated histories
- エラー文の内容は以下の通り。
- 関係ない履歴同士は
mergeできないよ
- 関係ない履歴同士は
どうやら問題の根本はunrelated historiesをmergeできないことにありそうです。
解決法
下記のコードを実行することで、強制的にリモートリポジトリの内容をローカルに引っ張ってくることができ、最終的にpushすることができました。
% git merge --allow-unrelated-histories origin/main
公式Docによる--allow-unrelated-historiesオプションの詳細は以下の通りです。
--allow-unrelated-histories
By default, git merge command refuses to merge histories that do not share a common ancestor.
This option can be used to override this safety when merging histories of two projects that started their lives independently.
As that is a very rare occasion, no configuration variable to enable this by default exists and will not be added.
- --allow-unrelated-histories
- "merge"コマンドは、共通の祖先を持っていない履歴同士を"merge"できないよ
- 独立して生成された2つのプロジェクトの履歴を"merge"したい時は、このオプションを使えばOK!
(As that以下略)
なるほど、共通の祖先を持っていないもの同士をmergeしようとしていたことが、本問題の原因であると特定できました。
自分がやらかしたことを推測
自分が行った行為は下記の通りと推測されます。
①. git.initで「ローカルリポジトリA」を作成
②. Aで管理されたデータをリモートリポジトリにpush
③. git.initで別の「ローカルリポジトリB」を作成
④. Bで新規作成したデータを、②でpushしたのと同じリモートリポジトリ・ブランチにpush←ここで最初のエラー発生
⑤. 共通の祖先を持っていないためpullできない←次のエラー発生
たぶんこんな感じなのかな??
最後に公式Docに出てきた「共通の祖先を持っている」とは、共通の親コミットを持っているということなのでしょうか。
上記の③でローカルBを作成後、開幕一発目のコミットデータには当然親コミットは存在しないので、共通の親を持っているどころではありませんね。
大変勉強になりました。
参考にした記事