はじめに
皆さんは、git push --force または git push -f を実行したことはありますか?
リモートの履歴を上書きしたいときに使われると思います。
初めて使うときは git のログが期待通りの結果になるだろうか、他の方のコミットに影響しないかなど、不安に思うことがあるかもしれません。私がそうでした。
このことを新卒1年目ぐらいのときに先輩へ相談したことがあり、「 --force-with-leaseを使うといいよ」とアドバイスをもらったことがあります。
--force-with-leaseを教えてもらった日から、リモートの履歴を上書きするときは、基本的に--force-with-leaseを使うようにしています。
--force について
git push --force は、ローカルの履歴でリモートの履歴を無条件に上書きします。
たとえば、自分がリベース作業をしている間に、チームメンバーが同じブランチにコミットをプッシュしていたとします。その状態で --force を実行すると、メンバーのコミットは上書きされ、復元が困難になります。
Git の公式ドキュメントにも「リモートリポジトリのコミットが失われる可能性があるため、注意して使用すること」と明記されています。
実際に誤って上書きしてしまった事例は、検索するといくつか見つけられます。
発生した理由は異なりますが、そういった事例を知っていると、慎重に実行したいですよね。
特に他の誰かがリモートにプッシュしたコミットを消してしまうようなことは避けたいところです。
--force-with-lease とは
--force-with-lease は、リモートの履歴が自分の期待通りであることを確認してから強制プッシュを行うオプションです。
公式ドキュメントでは次のように説明されています。
これは、明示的にロックせずに参照を「リース」するようなもので、リモート参照は「リース」が有効な場合にのみ更新されます。
これは、自分が最後に fetch または pull した時点から、他の誰かがリモートにプッシュしていた場合はエラーになり、上書きを防いでくれます。
$ git push --force-with-lease
fetch 後はローカルのリモート追跡ブランチが最新の状態に更新されます。その状態で --force-with-lease を実行すると、他の人のコミットが存在していても、すでに確認済みとみなされるため、上書きできてしまうため注意が必要です。GUI クライアント等で自動的に fetch を実行している場合は気を付けてください。
おわりに
--force-with-lease は、知っているかどうかで安心感がまるで異なるオプションです。教えていただいたときから、force push に対する怖さがずいぶんと和らぎました。
まず --force-with-lease を使うことを習慣にするだけで、チームメンバーの作業を誤って消してしまうリスクを下げることができます。
--force が必要な場面もあるかと思います。コマンドを実行する前に結果を想像し、期待通りの結果となったかを確認するとよいでしょう。