67
52

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

git push `--force-with-lease`はいつも安全?

Last updated at Posted at 2016-04-06

git push --force-with-leasegit push --forceと違って、他の人がpushしていたら良い感じにコケてくれるので安全、という話を聞き、さっそく使っています。

ただ、ちょっとだけ注意しないとな、と思ったところがあるので書き残しておきます。

前提

git 2.6.4で確認

最後にfetchしたタイミングでの一致を保証する

man git-pushを見るとこんな記述があります。

--force-with-lease alone, without specifying the details, will protect all remote refs that are going to be updated by requiring their current value to be the same as the remote-tracking branch we have for them.

つまり--force-with-leaseはremote refsとローカルのremote-tracking branchのrefsの間に違いがないかどうかで、正否を判定しているわけですね。

ちなみにrefsというのはコミットへのポインタみたいなもので、ブランチやタグなどの単位で.git/refs配下に保存されているものです。
remoteのrefsはgit ls-remoteで見られて、多分これと一致判定をしている様子です。

なので、remote-tracking branchのrefsが、push --force-with-lease時のremote refsと一致しているときは通る、ということです。

普通に上書きされちゃうパターン

ということは、push --force-with-lease前にfetchをしていると、refsが一致して問題ないって勘違いしちゃう。

git checkout dev

# いくつかの変更をコミット & 同時にremoteに他の人がpush

git fetch origin dev
git push --force-with-lease origin dev

これが通っちゃうということですね。
こんなことをわざわざすることはあまりないとは思いますが、例えば次のようにorigin/masterに対してrebaseするような場合はあり得るかなあと思います。

git checkout dev

# ↓ここ
git fetch origin
git rebase origin/master
git push --force-with-lease origin dev

git fetch originとすると全部のブランチがfetchされるのですが、現在いるトピックブランチもfetchされてしまうので、結果的にさっきの例と同じ状況になってしまう、というわけですね。

僕はよくこういうことやるので、しっかりとgit fetch origin masterとしたうえでrebaseしないとな、と思った次第です。

※もしくは、remote-tracking branchのorigin/masterに対するrebaseではなく、ローカルへmasterをpullしてからrebaseすればこの問題は起こりません

67
52
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
67
52

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?