カテゴリー
コンピューター

【Git】ローカルからリモートリポジトリに push できない問題を解決するまでの記録!

ローカルで一区切りついたリポジトリをリモートに push し、その後も開発を続けておりました。

再び一区切りつきましたので、再度 push しようとしたところ、エラーです><。

今回はそんな状態から無事にリモートリポジトリへ push できるようになったところまでの記録をノートいたしました!

ポイント

  1. 作業用フォルダをクリーンな状態、git status で何も変更が表示されない状態、にしてから操作する。そうすれば、失敗してもこの状態に戻ることができる。
  2. ローカルリポジトリとリモートリポジトリを繋いだ状態にするには、ローカルブランチにリモートブランチから fetch → merge する。このとき、作業用フォルダの状態は、fetch する前のローカルの状態になるように作業する。 merge は一筋縄では行かないことが予想されるので、pull ではなく、fetch → merge と少しずつ進める。
  3. その後、push できるまで開発などを進め、リモートリポジトリへ push する。

問題の発生した状況

$ git push origin master
To http://111.11.1.1/gitremote/origin
 ! [rejected]        master -> master (non-fast-forward)
error: failed to push some refs to 'http://111.11.1.1/gitremote/origin'
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.

問題解決の方針

  1. リモートリポジトリをなんとかしてローカルリポジトリの先頭に pull する。
  2. あとは通常通りリモートへ push する。

問題解決手順の概要

  1. ローカルに temp_work ブランチを作る。
  2. ローカル master へリモート origin を fetch
  3. ローカル master へ origin/master をマージ
  4. コンフリクトを解消する。
    • マージ後の作業フォルダの状態は、リモートの origin/master ではなく HEAD (ローカル master) の状態となるようにする。
  5. ローカル master へ temp_work をマージ
  6. リモート origin/master へ push

解決してから振り返ると、temp_work ブランチは不要でした。。。

概要から省いてもよいのですけれども、作業ログの全体像ということで、残しておきますわ。

使用したコマンド説明

# リモートリポジトリの一覧を表示する。
git remote

# <remoterepository> の詳細を表示する。
git remote show <remoterepository>

# <branchname> ブランチを作成する。
git branch <branchname>

# <branchname> ブランチを作成し、<branchname> へチェックアウト
git checkout -b <branchname>

# <branchname> へチェックアウト
git checkout <branchname>

# <remoterepository> の変更内容をダウンロードする。
git fetch <remoterepository>

# <branchname> を現在のブランチへマージする。
git merge <branchname>

# 作業用フォルダとステージングの状態を表示する。
git status

# コンフリクトを解消するためにマージツールを使用して差分を表示する。
git mergetool

# ブランチを削除する。
git branch -d <branchname>

# 現在のブランチへマージ済みのブランチを表示する。
git branch --merged

# ブランチポインタのサスコミット、歴史の分岐も含めてコミットログを表示する。
git log --all --decorate --graph --oneline

作業ログ 1. 準備

リモートリポジトリ情報を確認

$ git remote
origin
$ git remote show origin
* remote origin
  Fetch URL: http://111.11.1.1/gitremote/origin
  Push  URL: http://111.11.1.1/gitremote/origin
  HEAD branch: master
  Remote branch:
    master tracked
  Local ref configured for 'git push':
    master pushes to master (local out of date)

作業ログ 2. 作業状態のバックアップとしてのブランチ作成

作業状態のバックアップとしてブランチを作成し、master へと戻ります。
ここには、反省点が 2 つございます。

  • そもそも、バックアップとしてのブランチは不要だった。
  • ブランチを作成してチェックアウトしないのであれば、git checkout -b コマンドではなく、git branch <branchname> コマンドを使用してブランチの作成のみを行えばよかった。
$ git checkout -b temp_work
Switched to a new branch 'temp_work'
$ git checkout master
Switched to branch 'master'

作業ログ 3. リモートリポジトリのダウンロードとマージを試す

fetch は当然成功しましたけれども、merge は失敗しました><。
残念ですけれども、やっぱりね!とも感じますの。

$ git fetch origin
$ git merge  origin/master
warning: Cannot merge binary files: bin/SampleExcel.xlsm (HEAD vs. origin/master)
Auto-merging src/SampleExcel.xlsm/ThisWorkbook.dcm
CONFLICT (content): Merge conflict in src/SampleExcel.xlsm/ThisWorkbook.dcm
Auto-merging src/SampleExcel.xlsm/AbcModel.cls
CONFLICT (content): Merge conflict in src/SampleExcel.xlsm/AbcModel.cls
Auto-merging src/SampleExcel.xlsm
CONFLICT (content): Merge conflict in src/SampleExcel.xlsm
Automatic merge failed; fix conflicts ans the commit the result.

作業ログ 4. コンフリクトの解消作業をし、ソースを push したい状態にする

マージ時のコンフリクトを解消いたします。
どのような状態へしたいかと申しますと、リモートリポジトリの状態にするのではなく、開発が完了してあとはもう push するだけ!の状態へいたします。
まずは現状を確認ですの。

$ git status
On branch master
You have unmerged paths.
  (fix conflicts ans run "git commit")

Unmerged paths:
  (use "git add <file>..." to mark resolution)

        both modified:    bin/SampleExcel.xlsm
        both added:       src/SampleExcel.xlsm/AbcModel.cls
        both modified:    src/SampleExcel.xlsm/ThisWorkbook.dcm

no changes added to commit (use "git add" and/or "git commit -a")

マージツールを使用して、コンフリクトを解消していきました。
すでに Visual Studio で Git を使用していたため、自動的にマージツールとして Visual Studio が登録されておりました。
Winmerge が使えるかしら?と winmerge と打ち込んでみましたけれども、起動しませんでした><。
なお、バイナリファイルであるエクセルはマージツールでコンフリクトを解消することができません。
残したいファイルを作業用フォルダに置きます。

$ git mergetool
Merging:
bin/SampleExcel.xlsm
src/SampleExcel.xlsm/AbcModel.cls
src/SampleExcel.xlsm/ThisWorkbook.dcm

Normal merge conflict for 'bin/SampleExcel.xlsm':
  {local}: modified file
  {remote}: modified file
Hit return to start merge resolution tool (vsdiffmerge):
merge of bin/SampleExcel.xlsm failed
Continue merging other unresolved paths (y/n) ? y

Normal merge conflict for 'src/SampleExcel.xlsm/AbcModel.cls':
{local}: created file
{remote}: created file
Hit return to start merge resolution tool (vsdiffmerge): winmerge

Normal merge conflict for 'src/SampleExcel.xlsm/ThisWorkbook.dcm':
{local}: modified file
{remote}: modified file
Hit return to start merge resolution tool (vsdiffmerge): winmerge

作業ログ 5. ズレに対処し、ローカルリポジトリへコミット

ステージングへの追加

コミットしたいエクセルファイルを作業用フォルダに置き、ステージングへ追加します。
そしてマージツールで修正sたコンフリクトもステージングへ追加、、、したつもりでした。。。
しかし、誤ってコンフリクト解消時に自動生成されたと思われるバックアップファイルをステージングに追加してしまいました><。
この時点ではこの失敗に気がついておりません。

後になって振り返ってみますと、そもそも、そのようなミスをしたのは、

  1. マージツールでコンフリクトを解消
  2. git add . でバックアップファイルをステージングに追加

されてしまいましたので、そこから考えると

  • マージツールでコンフリクト解消すると、自動的にステージングに追加される

ということが言えそうです。

fetch し merge した内容をローカル master へ一旦コミット

コンフリクトを解消しましたので、区切りとしてローカル master へコミットしました。
直後に前後のコミットを比較したところ、マージツールでコンフリクト解消した内容が一部変でした><。
インデントがズレており、コミット後のコードの行末の _ が一部消えておりました。

$ git add bin/SampleExcel.xlms
$ git add .
$ gti status
On branch master
All conflicts fixed but you are still merging.
  (use "git commit" to conclude merge)

Changes to be committed:

            modified:    src/SampleExcel.xlms/AbcModel.cls
            new file:    src/SampleExcel.xlms/AbcModel.cls.orig
            new file:    src/SampleExcel.xlms/ThisWorkbook.dcm.orig

$ git commit -m "push準備。リモートからローカルmasterへ、コンフリクト解消してマージした。"
[master 4955dd4] push準備。リモートからローカルmasterへ、コンフリクト解消してマージした。

発見した謎のズレを修正してコミット

ここで temp_work ブランチの存在を思い出しました。コンフリクトを解消して開発完了後の姿、つまり temp_work ブランチの状態にしたいのです。
ですので、ローカル master へ temp_work をマージすることで、謎のズレを解消できないかと考え、やってみました!
。。。特になにも起こりませんでした。。。
バックアップ用にと思って temp_work ブランチを作りましたけれども、そもそも不要でしたわね><。
また、何も起こらなかったとはいえ、マージ済みであることも確認いたしました。

$ git merge temp_work
Already up-to-date.
$ git branch --merged
  temp_work
* master

それから謎のズレを手動で修正し、ようやく push したい状態が作業用フォルダに整いました。
まずはコミットいたしました。
ちなみに、この時点で自動生成されたマージツール使用時のバックアップファイルの存在に気が付きましたの。
そこで、作業用フォルダとステージングから削除してからコミットいたしましたわ。

$ git add .
$ gti status
On branch master
Changes to be committed
  (use "git reset HEAD <file>..." to unstage)

            modified:    src/SampleExcel.xlms/AbcModel.cls
            deleted:     src/SampleExcel.xlms/AbcModel.cls.orig
            deleted:     src/SampleExcel.xlms/ThisWorkbook.dcm.orig
$ git commit -m "追加機能AAA完成。リモートリポジトリからの延長線上に機能追加を配置。"
[master 9b5841e] 追加機能AAA完成。リモートリポジトリからの延長線上に機能追加を配置。
 3 files changed, 26 insertions(+), 530 deletions(-)
 delete mode 100644 src/SampleExcel.xlsm/AbcModel.cls.orig
 delete mode 100644 src/SampleExcel.xlsm/ThisWorkbook.dcm.orig

作業ログ 6. リモートリポジトリへ push

ローカルリポジトリのコミット状況を見て、リモートリポジトリへ push できる状態であることを確認いたしました。

$ git log --all --decorate --graph --oneline
* 9b5841e (HEAD -> master) 追加機能AAA完成。リモートリポジトリからの延長線上に機能追加を配置。
*    4955dd4 push準備。リモートからローカルmasterへ、コンフリクト解消してマージした。
|\
| * 54a1700 (origin/master) 追加機能AAAの開発開始。
* | cdaf99a (temp_work) 追加機能AAA完成。試験を追加、実施した。
* | 8778970 追加機能AAA製造開始。
| | * b864e83 (add_XXX) XXX完成。
| | * f812ddf XXX開発中。
| |/
|/|
* | 171306e コードを整理した。
* | 1fb0a74 追加機能AAAの開発開始。
|/
* d49be4d 最初のコミット。

ただ、temp_work ブランチを削除し忘れていたことに気が付きました。
削除いたしましたの。

$ git branch -d temp_work
Deleted branch temp_work (was cdaf99a).

そうしてようやく、リモートリポジトリへと push いたしました。

$ git push origin master
Counting objects: 148, done.
Delta compression useing up to 4 threads.
Compressing objects: 100% (148/148), done.
Writing objects: 100% (148/148), 10.27 MiB | 1.95 MiB/s, done.
Total 148 (delta 77), reused 0 (delta 0)
To http://111.11.1.1/gitremote/origin
   54a1700..9b5841e master -> master

あっさりと成功です♪これで作業終了ですわ♪

反省点

今回の問題に関して

  • そもそも、リモートリポジトリから pull した状態から開発を始められる程度に Git を使いこなせるようにする必要がありそう。

問題解消の作業に関して

  • 作業開始前状態のバックアップとして temp_work ブランチを作ったが不要だった。手順を複雑にしただけで有害だった。

今後について

  • リモートリポジトリに今までのコミットもすべて反映されるのは、重要なコミットがそうでないコミットに埋もれてしまい、良くない。
  • そこで、ブランチの使い方にもっと習熟する必要があるのだろう。例えば次のような流れになろう。
    1. ローカル作業で、作業開始時に作業用ブランチを作って作業する。
    2. ローカルの master ブランチへは完成した状態など重要なコミットのみ行う。
    3. ローカル master ブランチをリモートリポジトリへ push する。

おわりに

次のページが参考になりました♪ありがとう存じます!

方針決めるのになんとなく役立った

作業時に役に立った

今後について考えるのに役に立った

Git を使ってバージョン管理を始めて 10 日ほど経ちました。まだまだわからないことが多いのですけれども、ローカルで多彩な管理ができ、魅力を感じております。

ローカルでの失敗は自分自身にのみ返ってきますのでよいのですけれども、リモートリポジトリが関わってくると間違えた時に解きほぐすのが難しそうです。

今回の投稿は、そんな習熟状況の中で発生した問題でした。

なんとか対象で来てホッとしておりますの♪

以上です。

「【Git】ローカルからリモートリポジトリに push できない問題を解決するまでの記録!」への2件の返信

コメントを残す