今回はフィヨルドブートキャンプの課題レビューで指摘され、久しぶりにGitであれこれやってみたことを書きます。
やりたいこと
プルリクエストに不必要な変更が紛れ込んでしまったため、修正してdiffを綺麗にしたい。
前提条件
- mainからdevelopブランチを切って作業していた
- developブランチでFile_AとFile_Bの修正を行いコミットした
- そのコミットをリモートブランチにプッシュし、プルリクエストを作成した
- File_Bに対する変更は今回のプルリクには不必要なため、diffに含まないようにとの指摘を受けた
手順
調べてみたところ、こういった場合はリモートブランチそのものを正しい状態にすればプルリクにも反映されるとのことだったので、今回はローカルで修正してリモートブランチを上書きするイメージで進めました。(主にこちらの記事を参考にさせていただきました。)
ケースバイケースで適切なやり方は異なるとは思いますが、今回はgit reset --soft
を使って過去に戻り、File_Bがコミットに含まれないように修正しました。
何はともあれgit reset
で過去に戻ります。
オプションは--soft
にしましたが、--mixed
でも良かったかもしれません。
これらに--hard
を加えた3つがgit reset
の際に使用する主なオプションです。(本当はもっとたくさんあるっぽいです。)
$ git reset --soft HEAD^
つまり、コミットをする前、ファイルに変更を加えてgit add
までは終わっている状態ということになります。
git status
で状態を確認すると、
$ git status On branch hogehoge Changes to be committed: (use "git restore --staged <file>..." to unstage) modified: File_A modified: File_B
こんな感じでFile_AとFile_Bがインデックスに追加されているのがわかります。 今回はコミットからFile_Bを除外したいので、インデックスから取り除きます。
$ git restore --staged File_B
もう一度git status
で確認するとインデックスにはFile_Aのみが登録されている状態になるはずです。
あとは普通にコミットすればローカルでの修正は完了です。
コミット後、リモートブランチにプッシュします。
今回の場合は自分しか触らないリポジトリなので、git push --force
で強制的にプッシュしてしまってもいいのですが、いざ複数人で作業をすることになった際に--force
に対して心理的抵抗が全くないのは問題な気がするので、今回はgit push --force-with-lease
を実行しました。
$ git push --force-with-lease
これでコミットの中の余計な変更をプルリクから排除できました。
--forceは取扱注意
今回、ローカルでの修正をリモートに反映させるためにgit push --force-with-lease
を使用しました。
これは自分のローカルリポジトリの履歴と比較して、リモートリポジトリに既に変更が加わっている(他の誰かが先にコミットしている)状況ではプッシュを強制できないようにするオプションで、無条件に--force
でプッシュするよりは他人の努力を水泡に帰する危険性が減ります。
とはいえ、直前にリポジトリ自体をfetchしてきている場合はプッシュできてしまったりするらしいので、絶対安全なものではありません。
いずれにしても、チームで開発するときはそのチームのルールを遵守して適切に対処すべきと思います。
安易に--force
でプッシュとかは絶対アカンやつ。(まだチームで開発したことないけど…)
まとめ
今回は歴史改変のお話でした。
実は最初にgit reset --soft
を実行する前に--hard
で実行してしまい、不必要に巻き戻しすぎたので、git reflog
を使ってそのreset
を更に無かったことにしたりしてますが、その辺は今回の本筋からはそれてしまうので別記事にまとめたいと思います。