Non-Fast-Forward Push の解決

他の開発者とともに同じリモートリポジトリ (depot リポジトリ) を利用していれば、しばしば発生するのが Non-Fast-Forward Push 問題です。

Non-Fast-Forward とは何かということを説明するために、そもそも Fast-Forward とは何かということを説明します。

Fast Forward とは?

ある時点で master ブランチからブランチ A ができたとします。その後、ブランチ A にてコミットします。

Git - Fast Forward

その間、master ブランチでは全くコミットが行われていないとします。

この状態ではブランチ A はブランチ master に安全にマージ可能ですよね。ブランチ A に対して行ったコミットを master にも行えば良いだけですから。

ただ、実際に Fast Forward マージは同じ変更をせっせと再生するのではなく、単に master ブランチをブランチ A と同じコミットをポイントするように変更するだけです。

これが Fast Forward マージです。

Non Fast Forward とは?

Non Fast Forward というのは、Fast Forward と違う、ということなのですが・・・ (笑)

Git - Non-Fast Forward

ブランチ A を作ってそこでコミットを行う、そして同時に master ブランチでもコミットを行った場合です。このときは明らかに master のポインタを差し替えるだけではマージ作業は解決できません。

ブランチ A の内容と master の内容を活かしつつ、それらをマージして新たな合流地点を作る、そうした作業が Non Fast Forward のマージです。

もちろん、どちらかの変更を完全に破棄してしまうことも可能ですし、そこをどのように処理するかはあなた次第です。

Non Fast Forward Push を解決する典型的な手順

リモートリポジトリに push を試みたとき、 もしもより新しいコミットがあり Fast Forward で解決出来ない場合は次のようなエラーになります。

$ git push
To git://iskrdevq/project1.git
 ! [rejected]        master -> master (non-fast-forward)
error: failed to push some refs to 'git://iskrdevq/project1.git'
To prevent ... See the 'Note about
fast-forwards' section of 'git push --help' for details.

こうなったときの典型的な手順は次のとおりです。

まず、ローカルの origin/master に origin をフェッチします。

$ git fetch
remote: Counting objects: 5, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From git://iskrdevq/project1
   5af725a..0d567b6  master     -> origin/master

master に origin/master をマージします。

$ git merge origin/master
Auto-merging hello.py
CONFLICT (content): Merge conflict in hello.py
Automatic merge failed; fix conflicts and then commit the result.

もちろんこのままでは、コンフリクトですよね。マージツールを起動してマージします。

$ git mergetool
merge tool candidates: meld opendiff kdiff3 tkdiff xxdiff 
tortoisemerge gvimdiff diffuse ecmerge p4merge araxis emerge 
vimdiff
Merging the files: hello.py

Normal merge conflict for 'hello.py':
  {local}: modified
  {remote}: modified
Hit return to start merge resolution tool (meld): 

ここでは Meld が設定してあるので Meld が起動しました。

Meld によるマージ

マージを行い保存します。

Meld によるマージ

変更をコミットして、プッシュを行います。

$ git commit -m "Fixed conflict"
[master d6fb4e2] Fixed conflict
$ git push
Counting objects: 8, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (4/4), 413 bytes, done.
Total 4 (delta 1), reused 0 (delta 0)
To git://iskrdevq/project1.git
   79d7dc2..d6fb4e2  master -> master

以上でマージが完了でき、その結果を origin/master に push もできました。

ここまでお読みいただき、誠にありがとうございます。SNS 等でこの記事をシェアしていただけますと、大変励みになります。どうぞよろしくお願いします。

© 2024 Linux 入門