質問: *解決したいこと git push時にerror: failed to push some refs toと出てくるのでそれを解決したいです。 *前提 RailsでWebアプリケーションを作成中です。 作業ブランチ:implement_bookmark_for_post エラーが出るまでの流れ 変更したファイルをコミットする→上記のブランチにpush→やり残しがあったのでgit reset --soft HEAD^をコマンドラインで叩く→再びコミット→作業ブランチにpurh(ここでエラー) *エラー内容 ``` ! [rejected] implement_bookmark_for_post -> implement_bookmark_for_post (non-fast-forward) error: failed to push some refs to 'https://github.com/keisuke713/cities.git' 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. ``` *試したこと 以下のコマンドを試しましたがエラーは治りませんでした。 git pull git fetch -> git merge origin/master git fetch -> git rebase origin/master 以上、もし分かる方いましたら、よろしくお願いします。
回答: エラー自体は、リモートとローカルでコミットが分かれてしまい単純にはマージできない状況になってしまったため起こっています。 ``` o---o---o---o (リモートにはミスしたコミットが push されてしまっている) \---o (ローカルではミスしたコミットの 1 つ前から別のコミットが生えている) ``` このズレを解消した上で push する必要があります。 解決法1: pull して手動マージ `git pull` した時点で merge conflict が発生しており、`git status` を見ると `Your branch and 'origin/なんとかかんとか' have diverged, ...` と言われているのではないかと思います。 `git status` の表示にしたがって手動で merge conflict を解消し、マージコミットを入れることで push できるようになります。最終的なコミットグラフは下のように分岐したコミットが合流するという形になります。全ての作業完了後 `git log --graph` で確認できるので見てみてください。 ``` o---o---(ミスしたコミット)---\ \---(正しいコミット)---(マージコミット) ``` たとえば次のようなコマンドを打つことになります。 ``` $ git pull $ git status $ (コンフリクトしたファイルをエディタで開き、手動でコンフリクトを解消する) $ git add 〈コンフリクトを解消したファイル〉 $ git commit $ git push ``` 解決法2: git pull --rebase `git merge` の代わりに `git rebase` をすることでコンフリクトを解消する方法です。ローカル側で行った変更をひとまとめにした新しいコミットを作ります。最終的なコミットグラフは下のようになります。`(正しいコミット)` は消え、`(rebaseコミット)` に吸収されています。 ``` o---o---(ミスしたコミット)---(rebaseコミット) ``` まず、もし `git pull` などをしていればマージが始まってしまっているので、これを中止します。マージが始まっているか分からなければ `git status` で確認してください。 ``` $ git merge --abort ``` その後、`git rebase origin/〈ブランチ名〉` でこの作業を行えます。 ``` $ git rebase origin/〈ブランチ名〉 $ (git status を見ながらエディタでコンフリクトを解消する。 たとえば、エディタでコンフリクトを解消した後、git rebase --continue するなど) $ git push ``` ちなみにこの作業は、まだ `git pull` を行っていなければ `git pull --rebase` というコマンドで一発でできます。 ``` $ git push (コンフリクトエラーが出た) $ git pull --rebase $ (コンフリクトを直す) $ git push ``` 解決法3: git push -f 他のふたつと比べるとやや危険な方法です。何をしているのか分かった上で使ってください。 もしまだ誰もそのブランチを pull していないのであれば、force push してリモートのコミットログを無理矢理変えることができます。典型的には、自分しか使っていない個人用リポジトリで使える手段です。**この方法はリモートのコミットログを書き換える**ため、注意して使ってください。 最終的なコミットグラフは下のようになります。 ``` o---o---(正しいコミット) ``` まず、もし `git pull` などをしていればマージが始まってしまっているので、これを中止します。マージが始まっているか分からなければ `git status` で確認してください。 ``` $ git merge --abort ``` `git reset` 後新しいコミットを `git commit` したのが現在の状況ですので、そのまま `-f` オプション付きで push すれば force push になります。 ``` git push -f 〈リモート名〉 〈ローカルのブランチ名〉 ```