1
1

gitエラー:Updates were rejected because the remote contains work that you do not have locally.

Posted at

はじめに

qiita-cli を使って qiita の記事投稿を Github 管理しているのですが、新しい記事を書いて「よし、投稿しよー」と思い、コミット&プッシュを実施したところ、git のほうで reject(拒否)されました。

エラー内容はこんな感じ

$ git push
To github.com:{username}/{repository-name}.git
 ! [rejected]        main -> main (fetch first)
error: failed to push some refs to 'github.com:{username}/{repository-name}.git'
hint: Updates were rejected because the remote contains work that you do not
hint: have locally. This is usually caused by another repository pushing to
hint: the same ref. If you want to integrate the remote changes, use
hint: 'git pull' before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

...なんてこったい。こんなとこでつまづいたらモチベーション下がっちゃうよ。

ということでとりあえず先人たちのエラー解消ノウハウを調査。

エラー解決方法

エラー内容で検索してヒットした記事を素直に見てみる。

どうやら、リモートリポジトリ(Github)の main ブランチにあって、ローカルの main ブランチにない変更があるみたい。

解決するには、リモートリポジトリからgit pullでコミットを取得して、差分を解消すればいいらしい。

ということでまずは pull してみる

git pull origin main

するとこんなメッセージが出た

$ git pull origin main
From github.com:{username}/{repository-name}
 * 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.

ふむ、とりあえず Google 翻訳してみる

You have divergent branches and need to specify how to reconcile them.
>分岐したブランチがあり、それらを調整する方法を指定する必要があります。

You can do so by running one of the following commands sometime before your next pull:
>これを行うには、次のプルの前に次のコマンドのいずれかを実行します。

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

You can replace "git config" with "git config --global" to set a default preference for all repositories.
>「git config」を「git config --global」に置き換えて、すべてのリポジトリのデフォルト設定を設定できます。

You can also pass --rebase, --no-rebase, or --ff-only on the command line to override the configured default per invocation.
>コマンドラインで --rebase、--no-rebase、または --ff-only を渡して、呼び出しごとに構成されたデフォルトをオーバーライドすることもできます。

Need to specify how to reconcile divergent branches.
>分岐したブランチを調整する方法を指定する必要があります。

git pullコマンドがうまく実行できない状態(リモートとローカルでのコミット差分)だから、対処が必要とのこと。

git config ~git pullの挙動設定(3 パターン)をおこなうことで回避できる。(--globalをつけると、このリポジトリだけじゃなく全体の git のデフォルト設定にも反映できる)

設定変更できなくてもコマンドラインでオプション指定すると、デフォルト設定をオーバーライドして意図した挙動にできる。

こんなことが書いてありますね。

書いてある内容はだいたいわかったけど、git の挙動をあまりカスタマイズしたくないので、今回は「ローカルの変更を一時退避して、リモートと同期し直してから反映する」という方法にしようと思います。

修正作業

まずはローカルのログを確認

git log --oneline

結果

$ git log --oneline
cc30f73 (HEAD -> main) add article cm03j33di000087n91kurcbfd
1c44383 qiita-cliバージョン更新
9922530 fix tag

このfix tagの後にリモート側で変更差分がはさまる感じみたい。

ローカルの変更を soft リセット(コミットを取り消すけどファイルの変更はステージングに残る)

git reset --soft

コミットが消えてステージングに変更差分が出てきた

VSCodeステージング

もっかい git のログ確認

$ git log --oneline
6287207 (HEAD -> main, origin/main) Updated by qiita-cli
9922530 fix tag

リモートの変更が取得できた!

改めてローカルでの変更をコミットしてログ確認してみる

$ git log --oneline
45edfcd (HEAD -> main) add article cm03j33di000087n91kurcbfd
660ee2a qiita-cliバージョン更新
6287207 (origin/main) Updated by qiita-cli
9922530 fix tag

ふむ、よさそうなので push してみる

git push

結果

$ git push
Enumerating objects: 12, done.
Counting objects: 100% (12/12), done.
Delta compression using up to 10 threads
Compressing objects: 100% (8/8), done.
Writing objects: 100% (8/8), 4.28 KiB | 4.28 MiB/s, done.
Total 8 (delta 4), reused 0 (delta 0), pack-reused 0 (from 0)
remote: Resolving deltas: 100% (4/4), completed with 3 local objects.
To github.com:{username}/{repository-name}.git
   6287207..45edfcd  main -> main

よし!できた!

おわりに

なんとか解消できたけど、そもそも面倒くさがって main ブランチで作業しないで、作業用ブランチ切っておけば簡単に rebase で解決できたなーと反省。

ひとりしか触らないリポジトリだとあるあるな気がするけど、今後はちゃんとやります。

まあポジティブに考えると、git の仕組みに対する理解を深めるいい機会になった。

参考

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1