gitでrebaseは呼吸するようにするものらしいですが、remote絡むと若干息苦しくなる。
$ git log --oneline --graph --decorate * caec1ad (HEAD, origin/master, origin/HEAD, master) add e * cb99644 add d * 912a264 add c * 14bb339 add b * b33a46a add a * 5fd8be9 init
push済みのこれをうっかりrebaseする。
$ git log --oneline --graph --decorate --all * f853362 (HEAD, master) add d * 4163b31 add e | * caec1ad (origin/master, origin/HEAD) add e | * cb99644 add d |/ * 912a264 add c * 14bb339 add b * b33a46a add a * 5fd8be9 init
こうなるともう別歴史になってしまう……。
やらないのがいいんですが、やっちゃった場合はーどうするんが良いんでしょ?
- 素直に取り込む
- えいやっと上書きする
(1) 素直に取り込む
同じ歴史を持っていればpush出来ます。なのでmergeしてやりましょう。
$ git merge origin/master Merge made by the 'recursive' strategy. $ git log --oneline --graph --decorate --all * 50b7f86 (HEAD, master) Merge remote-tracking branch 'origin/master' |\ | * caec1ad (origin/master, origin/HEAD) add e | * cb99644 add d * | f853362 add d * | 4163b31 add e |/ * 912a264 add c * 14bb339 add b * b33a46a add a * 5fd8be9 init
わあ素直。git賢いから特にファイルを追加したりせずに繋げてくれます。後は素直にpushするだけですね。
……でもこれはやりたいことじゃない。なんかごちゃごちゃするし、こんな歴史は誰得なんよ。と言うことで。
(2) えいやっと上書きする
push -f ですね。多人数開発では御法度。個人だとよくやる。複数人でもたまにやる。大丈夫ばれてない。
$ git push -f (略) + caec1ad...f853362 master -> master (forced update) $ git log --oneline --graph --decorate --all * f853362 (HEAD, origin/master, origin/HEAD, master) add d * 4163b31 add e * 912a264 add c | * bde3740 (origin/b1, b1) add y | * 1403611 add x |/ * 14bb339 add b * b33a46a add a * 5fd8be9 init
ブランチでやってるとき
masterからbranch生やして追随するためにrebaseすることも多々あります。
$ git log --oneline --graph --all * f853362 add d * 4163b31 add e * 912a264 add c | * bde3740 add y | * 1403611 add x |/ * 14bb339 add b * b33a46a add a * 5fd8be9 init
このx,yですね。rebaseしてx,yをdの後ろに続けるわけです。
$ git log --oneline --graph * 918becd add y * c2d3585 add x * f853362 add d * 4163b31 add e * 912a264 add c * 14bb339 add b * b33a46a add a * 5fd8be9 init
でもx,yのbranch(b1)をpushしちゃってたら?
$ git log --oneline --graph --decorate --all * 918becd (HEAD, b1) add y * c2d3585 add x * f853362 (origin/master, origin/HEAD, master) add d * 4163b31 add e * 912a264 add c | * bde3740 (origin/b1) add y | * 1403611 add x |/ * 14bb339 add b * b33a46a add a * 5fd8be9 init
こうなっちゃう。もちろんpushしようとしたら蹴られる。
$ git push To (remote) ! [rejected] b1 -> b1 (non-fast-forward) error: failed to push some refs to '(remote)' To prevent you from losing history, non-fast-forward updates were rejected Merge the remote changes (e.g. 'git pull') before pushing again. See the 'Note about fast-forwards' section of 'git push --help' for details.
もうこれは push -f でいいと思う……。
rebaseする予定があるならpushしない。それかpush -fでやる?
push -fしても取り込む側は普通にpullできたりする。でもマージコミット出来るアレになる。実害はないからいいんだけど、気になるなら一旦手元のブランチ破棄して、リモートのをcheckoutし直したらいいと思う。
pullった側はこんななってるから……
$ git log --oneline --graph --all --decorate * bb69e06 (HEAD, b1) Merge branch 'b1' of (remote) into b1 |\ | * 4b25a53 (origin/b1) add y | * ca28378 add x | * e9eab92 (origin/master, master) add g * | a8b376c add y * | e519e1b add x |/ * 6d01ded add f * f853362 add d
b1 を branch -D で消して、再度 b1 を checkout -b とかで作る。
$ git checkout master Switched to branch 'master' $ git branch -D b1 Deleted branch b1 (was bb69e06). $ git checkout b1 Branch b1 set up to track remote branch b1 from origin. Switched to a new branch 'b1' $ git log --oneline --graph --all --decorate * 4b25a53 (HEAD, origin/b1, b1) add y * ca28378 add x * e9eab92 (origin/master, master) add g * 6d01ded add f * f853362 add d
これで世界は平和になった。
まとめ
コミットグラフのいい見せ方がわかりません。絵描くのも面倒ですし。