はじめに
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
コミットが消えてステージングに変更差分が出てきた
もっかい 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 の仕組みに対する理解を深めるいい機会になった。