git pushもgit pullもできない状況を解決した

はじめに

これは、リモートとローカルの変更履歴が並行して進んでいたことが原因で起こっている。

ローカルの状態

vue-js-02というコミットは、リモートには反映されていない。

リモートの状態

READMEの変更をリモートで手動で行った。これがローカルに反映されていない。

git push origin mainができない

ローカルの変更をリモートに反映しようとしたが、現在のブランチがビハインドとのこと。

hiroki@shibatahiroshitakanoiMac my-vue-js % git push origin main
To https://github.com/ki-hi-ro/my-vue-js.git
 ! [rejected]        main -> main (non-fast-forward)
error: failed to push some refs to 'https://github.com/ki-hi-ro/my-vue-js.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 origin mainを行った後のメッセージ

遅れを取り戻すため、git pull origin mainを行う。しかし、これもできない。

hiroki@shibatahiroshitakanoiMac my-vue-js % git pull origin main
From https://github.com/ki-hi-ro/my-vue-js
 * 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.
fatal: Need to specify how to reconcile divergent branches.

Need to specify how to reconcile divergent branchesの意味

分岐したブランチを解決する必要があるという意味。

fatal: Need to specify how to reconcile divergent branches.
ローカル
リモート

上記のように、mainブランチがローカルとリモートで分岐している。

vue-js-1から分岐している。

ローカルでは、vue-js-02に進んでいて、リモートでは、READMEに進んでいる。

3つの選択肢

マージか、リバースか、ファストフォワードのみか。

hint:   git config pull.rebase false  # merge
hint:   git config pull.rebase true   # rebase
hint:   git config pull.ff only       # fast-forward only

今回は、リモートとローカルの変更点を両方取り込みたいので、マージを選択する。

リバースは、ローカルで加えた変更を無視して、リモートの変更に戻すときに使われるんだろう。

正直よく分からない。

ファストフォワードオンリーはリモートのみだろう。

ということは、リバースは、ローカルのみにするということか?

マージを行う

設定をいじっただけなので何も起こらない。

hiroki@shibatahiroshitakanoiMac my-vue-js % git config pull.rebase false
hiroki@shibatahiroshitakanoiMac my-vue-js % 

git pull origin mainを行うと、以下の画面になった。

Merge branch 'main' of https://github.com/ki-hi-ro/my-vue-js
# Please enter a commit message to explain why this merge is necessary,
# especially if it merges an updated upstream into a topic branch.
#
# Lines starting with '#' will be ignored, and an empty message aborts
# the commit.
~                    

続行をクリックした。

グラフが以下のようになった。

リモートの変更をマージしたということだろう。

上記の画面は、:q → Enterで抜ける。

git pushに成功した

hiroki@shibatahiroshitakanoiMac my-vue-js % git push origin main        
Enumerating objects: 8, done.
Counting objects: 100% (8/8), done.
Delta compression using up to 12 threads
Compressing objects: 100% (5/5), done.
Writing objects: 100% (6/6), 1.72 KiB | 1.72 MiB/s, done.
Total 6 (delta 0), reused 0 (delta 0), pack-reused 0
To https://github.com/ki-hi-ro/my-vue-js.git
   ac176f6..08b6851  main -> main

リモートの状態

マージコミットが反映された。

まとめ

今回のエラーは、ローカルとリモートの main ブランチがそれぞれ独自に進んでいたことが原因でした。
つまり、ローカルには vue-js-02 というコミットがあり、リモートには README.md の手動編集が加わっていた。
このように分岐した状態では、Git は自動で統合方法を決めてくれません。

そこで今回は、リモートとローカルの両方の変更を活かしたいと考え、merge を選びました。
git config pull.rebase false で設定を行い、git pull origin main を実行すると、マージコミットの作成画面に移りました。
続行ボタンをクリックしてマージコミットを確定し、その後 git push origin main が無事に成功しました。

今回の一連の流れを通して、「リモートとローカルが分岐して push/pull できないときに、どう対応すればよいか」が実感できました。
merge / rebase / fast-forward という3つの統合方法の中から、状況に応じて適切なものを選べば、Git はちゃんと応えてくれます。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です