%%{init: { 'logLevel': 'debug', 'theme': 'base', 'gitGraph': {'rotateCommitLabel': true, 'mainBranchName': 'local'}}}%% gitGraph commit id: "local-mod-1" branch remote commit id: "remote-mod-1" checkout local merge remote id:"pull" commit id: "conflict-resolve"
問題
ローカルの開発ブランチeda/data-sanity-check
で作業をしているとします.ローカルでいくつかの変更をコミットした後,リモートブランチにpushしようとしたところ, pushできないことに気づきました.
git push
を実行すると,以下のようなエラーが表示されます:
% git push
...
To https://github.com/RyoNakagami/github_sandbox
! [rejected] eda/data-sanity-check -> eda/data-sanity-check (fetch first)
error: failed to push some refs to 'https://github.com/RyoNakagami/github_sandbox'
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.
何が起きているのか
一般的に,pushする前にリモートの変更をpullして最新の状態を保つ必要があります. しかし,現在のブランチで既にいくつかの変更をコミットしている状態で,リモートブランチにも コミットがある場合,履歴のコンフリクトによってリモートの変更をpullすることもできません.
%%{init: { 'logLevel': 'debug', 'theme': 'base', 'gitGraph': {'rotateCommitLabel': true, 'mainBranchName': 'local'}}}%% gitGraph commit id: "local-mod-1" branch remote commit id: "remote-mod-1" checkout local commit id: "local-mod-2" commit id: "local-mod-3" checkout remote merge local id:"❗️push失敗"
%%{init: { 'logLevel': 'debug', 'theme': 'base', 'gitGraph': {'rotateCommitLabel': true, 'mainBranchName': 'local'}}}%% gitGraph commit id: "local-mod-1" branch remote commit id: "remote-mod-1" checkout local commit id: "local-mod-2" commit id: "local-mod-3" merge remote id:"❗️pull失敗"
解決策: git pull --rebase
▶ 手順
- ローカルとリモートの差分を確認
- ローカル-リモート間のコンフリクトを解決
- コンフリクト解決後にリモートにpush
▶ コマンド
## リモートの情報を取得
% git fetch
## リモートとの差分があるファイルを確認
% git difftool eda/data-sanity-check origin
上記のコマンドはリモート-ローカル間の差分を確認するためのものです. 問題を素早く解決したい場合は,このプロセスをスキップしても構いません.
では,コンフリクトを解決しましょう.
## ステップ2
% git pull --rebase
...
Auto-merging eda/check_datasanity.py
CONFLICT (content): Merge conflict in eda/check_datasanity.py
error: could not apply <your-current HEAD commit-id>... eda: add histogram
hint: Resolve all conflicts manually, mark them as resolved with
hint: "git add/rm <conflicted_files>", then run "git rebase --continue".
hint: You can instead skip this commit: run "git rebase --skip".
hint: To abort and get back to the state before "git rebase", run "git rebase --abort".
Could not apply <your-current HEAD commit-id>... eda: add histogram
## コンフリクト解決後
% git rebase --continue
git pull --rebase
コマンドはgit pull
とgit rebase
を組み合わせたものです. git pull --rebase
を実行すると,コンフリクトがある場合はコンフリクト解決プロセスに入ります. 通常のマージコンフリクトと同様に,コンフリクトが発生したファイルを開いて手動で修正する必要があります.
コンフリクトを解決した後は,必ずgit rebase --continue
を実行してください. 実行しないと,コンフリクト解決モードのままになってしまいます.
あなたのGit履歴は以下のようになります:
上記のconflict-resolve
ノードで,リポジトリの履歴に残すローカルの変更を選択します.
これで,リモートにpushできるようになりました.
## ステップ3:リモートにpush
% git push origin HEAD
▶ REMARKS
git pull --rebase
を実行した際,すべての差分が自動的に解決されることもあります.- 例えば,あなたが変更したファイルとリモートの変更が関係ない場合など.
git pull --rebase
はコンフリクトを引き起こさない差分を自動的に解決します.
- 混乱してしまい,保存せずにコンフリクト解決モードを抜けたい場合は,
git rebase --abort
を実行してください.