git push origin HEADの”HEAD”とgit pull origin HEADの”HEAD”は別物だという話

2022.10.01

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、CX事業本部 IoT事業部の若槻です。

今回は、git push origin HEADのHEADとgit pull origin HEADのHEADは別物だということを認識できておらず、やらかしてしまった話です。

やらかした概要

GitHub上のRepositoryで管理しているソースコードに対して私を含めた複数人で作業をしていたところ、次のようなやらかしをしてしまいました。

  1. コミットAからCheckoutしたtopic1ブランチで作業をする。(コミットB、Cの追加)
  2. 別のユーザーが同じくコミットAからCheckoutしたtipic2ブランチで作業をし、mainブランチにマージする。(コミットD、E、Fの追加)
  3. git pull origin HEADを実行してローカルの変更をPullする。
    • これにより、OriginのHEADがローカルブランチでRebaseされてしまう。

この結果、ローカルブランチをPushできなくなりました。(ここでForce PushをするとOrigin側で不具合が生じる場合がある)

詳細

1.,2.,3.の詳細です。

1.では、私がコミットAからCheckoutしたtopic1ブランチで作業をしました。(コミットB、C)

一方2.では、別のユーザーが同じくコミットAからCheckoutしたtipic2ブランチで作業をし、mainブランチにマージしました。(コミットD、E、F)

この時点でのCommit Graphは次のようになります。

3.で、私がgit pull origin HEADを実行しました。これにより、オリジンのHEADがローカルブランチにマージされました。

これによりローカルブランチをリモートにプッシュができなくなってしまいました。(やらかした!)

$ git push origin HEAD
To https://github.com/cm-rwakatsuki/test.git
 ! [rejected]        HEAD -> topic1 (non-fast-forward)
error: failed to push some refs to 'https://github.com/cm-rwakatsuki/test.git'
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.

原因

git pull origin HEADによりPullされるのは、Origin側のデフォルトブランチの先頭になるためです。普段ローカルでの作業の変更をPushする際にgit push origin HEADと実行していたため、その手癖でPull時にもHEADを指定してしまっていました。

対策

git pull origin HEADをしないように気をつける

リモートブランチ側での変更(Pull RequestでChange Suggestionを取り込んだ時など)をローカルに反映させたい時は、git pull origin <topic branch>を使うようにしましょう。

RebaseではなくMergeするようにする

Pullする際にOriginから取得した変更をローカルに対してRebaseするかどうかを設定で指定できます。現状の設定を確認する場合はgit config --get pull.rebaseを実行します。trueならRebase、falseならMergeされるようになっています。

# trueの場合はRebaseされるようになっている
$ git config --get pull.rebase
true

Mergeされるようにしたい場合は、git config pull.rebase falseを実行します。

下記はpull.rebase falseの場合の挙動です。pull.rebase trueの場合と挙動が異なることが分かります。

Pushも問題なくできます。(Pull RequestにMerge Commitが反映された様子)

参考

以上