2019年1月25日金曜日

git コミットの範囲を指定したPushのやり方。

gitでpushしようとしたときにプッシュしたくないコミットが出てきたので、うまいことそのコミットだけ除いてプッシュしたかったので、調べてみた。

参照仕様


Gitの公式ドキュメントの例にgit push origin HEADとあったので、じゃあHEAD~でひとつ前のコミットを省いてプッシュできるのかなと思ったら以下のようなエラーが起きた。

 remote part of refspec is not a valid name in HEAD~

HEAD~はrefspecのリモート部分では有効な名前ではないという英文で、悲しいかなHEAD~は使えないようだ。

git push origin HEADのHEADの部分はrefspec(参照仕様)を指定する部分だそうで、HEADはローカル環境の最新のコミットではないみたいだ。

参照仕様は+<src>:<dst>で表記される。

push時に参照仕様を使う場合は以下のようになる。

git push origin master:refs/heads/master
# こんな感じの意味になる。

git push リモート名 リモート先のブランチ名:ローカルブランチの参照の名前
ちなみにプルのときはプッシュとは反対でローカルの参照名を指定してからリモートの方を指定する形になる。

git fetch origin master:refs/remotes/origin/master
#こんな感じの意味になる
git fetch ローカル名 ローカルのブランチ名:リモートブランチの参照名

うん、git pushではコミットを指定してプッシュすることができないようだ。

ちなみに全ての参照の名前を確認したいときはgit show-refを使うといいようだ。

ローカルのHEADをずらしてからプッシュ

git pushではできないことが分かったので、ローカルのHEADをずらしてやってからプッシュすればできるのではないかと考えたので、HEADのずらし方を調べてみる。

参考サイト

HEADがローカルの最新コミットを指していない状態をGitではDetached HEADと呼んでいるそうだ。

今回の場合はわざとDetached HEAD状態にして、プッシュを行う。

Detached HEADにする方法はいくつかあるみたいだ。


  • git checkoutを使う方法
  • git reflogを使う方法
  • git reset --hardを使う方法
  • git revert を使う方法


今回はgit reflogを使う方法を試してみた。

git reflogを使うとコミットしたものがメッセージと共に表示される。

表示されるコミットにはそれぞれHEAD@{X}とXに番号が割り当てられている。(最新のコミットが0であとは昇順に並んでいる)

それで、HEADにしたいコミットの番号を使って

git checkout HEAD@{X}

とコマンドを打つと無事Detached HEADな状態にできる。(git checkoutは最終的には使っている)

あとはプッシュしてやると、初めの目的であるコミットの範囲を指定したプッシュができる。

と思ったらできなかった。

fatal: You are not currently on a branch.
To push the history leading to the current (detached HEAD)
state now, use

    git push origin HEAD:<name-of-remote-branch>


どうやら、Detached HEADな状態ではプッシュする際は参照仕様を指定してあげる必要があるみたいだ。

エラーメッセージにコマンドの使い方を教えてくれているので、その通りに実行してみよう。

git push origin HEAD:master

これで無事プッシュできた。

最後に


あとは、HEADを最新コミットに戻してあげるのを忘れずにすればOKだ。

一度この操作を行うと、ローカルでの最新コミットにHEADを移しても、Detached HEADな状態とGitは見るみたいなので、同じ操作が必要になる。

だから、なるべく区切り良いところでコミットすることを心がけることが大事だとは思うが、うっかりミスをするのが常なので、リカバーできるようになると安心でしょう。


0 件のコメント:

コメントを投稿