LoginSignup
135
85

なぜrebase後に強制プッシュをする必要があるのか

Last updated at Posted at 2018-09-30

rebase後の強制プッシュ

以下のようにfeatureブランチをmainブランチにrebaseして最新のmainを取り込むことはよくあると思います。

$ git pull --rebase origin main

で、それをリモートにpushしようとすると、**fast-forwardできないからpushできないよ!**と怒られます。

$ git push origin feature1
To github.com:hitochan777/test.git
 ! [rejected]        feature1 -> feature1 (non-fast-forward)
error: failed to push some refs to 'git@github.com:hitochan777/test.git'
(以下略)

これを解決するためには強制プッシュをするとうまくいきます。

git push origin feature1 -f

なぜ強制プッシュする必要があるのか

ポイントはpushはリモートブランチがfast-forwardできることを想定しているということです。
どういうことか、具体的に例を考えてみましょう。

origin/feature1がC3を、feature1がC5を指している状態を考えます。

C1--C2--C3          <- origin/feature1 (C5までfast-forwardできる)
         \        
          C4--C5    <- feature1

この場合、origin/feature1はC5までポインターを進められる(fast-forward)ので、
強制プッシュをしなくてもプッシュは成功します。

ではfeature1ブランチをorigin/mainブランチにrebaseしている場合はどうでしょうか。

C1--C2--C3--C6--C7  <- origin/main
         \        
          C4--C5    <- feature1, origin/feature1

rebase後は次のようになります。origin/mainにrebaseをするとfeature1origin/mainの共通の祖先からorigin/maiが指すコミットまでのコミットのコピーが作られます。下図ではC4', C5'としています。

C1--C2--C3-------C6--C7--C4'--C5'   <- feature1
         \  
          C4--C5                    <- origin/feature1

この場合origin/feature1のポインターを前に進めて(fast-forwardして)feature1と
同じコミットを指すようにすることはできないので、エラーが出てしまいます。

おまけ

feature1を複数人で共有している場合を考えます。
他のメンバーによってorigin/feature1がアップデートされたとしましょう。(C8の追加)
ここで、このことに気づかずfeature1を強制プッシュしてしまうと、リモートブランチは上書きされ、C8は消えてしまいます。

C1--C2--C3-------C6--C7--C4'--C5'   <- feature1
         \  
          C4--C5--C8                <- origin/feature1

こういったことが起きないように --force-with-leaseというオプションがあります。

135
85
0

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
135
85