Miki's Blog

フロントエンジニアに、俺はなる!

git pushしたらrejectedにハマった話【備忘録】

先日、Hugo + GitHub Pages でポートフォリオを作る-【GitHub PagesでWebページ公開】 - Miki's Blog での作業でのこと。
Webサイトは作ったし、あとはGitに上げるだけ。
意気揚々とターミナルからpushすると...

$ git push -u origin master
To github.com:gomagaru/test.git
 ! [rejected]        master -> master (fetch first)
error: failed to push some refs to 'git@github.com:gomagaru/test.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

ひぇえ... rejectedってなに...
ひとまず落ち着いてエラー文を読むと、
hint:に「もう一度pushする前に『git pull』してみてね」と書いてある。
やってみます。

git pull origin master
warning: no common commits
remote: Enumerating objects: 9, done.
remote: Counting objects: 100% (9/9), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 9 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (9/9), done.
From github.com:gomagaru/test
 * branch            master     -> FETCH_HEAD
 * [new branch]      master     -> origin/master
fatal: refusing to merge unrelated histories

おぉ...?何やら動いたぞ。
もう一回pushしてみよう。

...してみよう。(n回目)
やってもやってもrejected...
何このrejected地獄!!(プチパニック)



と、しばらくハマり、絶望していました。。

※自分の場合、結局pullでpush出来る状態に戻ったのは一回だけ...

reject発生原因と解決方法を、備忘録兼ねて書いておきます。

そもそも、pullとは?

git pullとは
他の人が開発した機能をリモートリポジトリにpushしたとします。
その変更を自分のローカルリポジトリに取り込まないと自分のレポジトリだけ開発から取り残されてしまうことになります。
そうならないためにgit ではgit pullというリモートリポジトリの変更点をローカルリポジトリに取り込む機能が用意されています。

https://techacademy.jp/magazine/10274

つまり、他人が編集したために自分が作業してるものは最新じゃないから
同期してからプッシュし直してね
、ということか。


と、ここでギモンが。
えっこれ他人に編集されてるの... ??ホラーじゃん...
Git初心者のわたし、ここで背筋が凍りかける。パスワードが漏れたのかとか気になり出す。でも、気付きました。。


ブラウザでReadMe.mdとか編集しながら、ターミナルでコマンドたたいてた。。
これがズレを生んでいたのですね。納得。

解決方法は?

今回は、3つの方法を試して直すことができました。
4つの解決方法を見つけました。

1. pull する

エラー文下部に書いてある通り、pullしてみる。

git pull origin master

2. fetchしてmergeする

fetch は、リモートからの変更をとってくる。
merge で、変更分をマージする。

git fetch
git merge origin/master

3. fetchしてrebaseする

fetchで、リモートからの変更をとってくる。
rebaseで、自分の変更分をリモートの後に持ってくる。

git fetch
git rebase origin/master

【追記 1/13】4. コマンドオプション -f を使う

コマンドオプションの-fを使うと、「リモートリポジトリの状態を強制的に現在のローカルリポジトリの状態に合わせる」ことができます。

git push -f origin master

コミットが消えてしまったり他開発者の履歴も消してしまう場合があるので
ローカルが古い状態であった場合や、チームで開発している場合などは使用を避けた方が無難とのこと。

おわりに

今回、pushがrejectされた件についてコマンドを使った対処方法を書きましたが、
ターミナルからGitコマンドをたたきながらブラウザでも編集作業をしてしまったことが厄介事を生んだ一番の原因だったと考えています。

Gitさわりたてですが、これからもGitさんとお友達になれるよう
勉強をすすめていきたいと思います!