前提
feature/hoge
feature/fuga
を並行して開発中。
feature/fugaはfeature/hogeの実装を前提としており、開発着手前に
git rebase feature/hoge
を行っている。
(feature/hogeのコミットは hogehoge1, hogehoge2)
(feature/fugaのコミットは hogehoge1, hogehoge2, fugafuga1, fugafuga2)
問題1: feature/hogeを取り込んだブランチ"feature/fuga"の実装
ブランチ"feature/hoge" で実装を進めている。
git commit -am "hogeの実装その3"
こうしてコミットhogehoge3が作成された。
ここで問題。
ブランチ"feature/fuga" にも、コミットhogehoge3を反映したい。
このとき、どういう操作をすればいい?
feature/fugaにて
git rebase feature/hoge
を再度行えばいい?
(つまり、
hogehoge1, hogehoge2, fugafuga1, fugafuga2
から
hogehoge1, hogehoge2, hogehoge3, ffuuggaa1, ffuuggaa2
にする)
ただ、feature/fugaがローカルにのみ存在している場合はそれでもいいが、
既にリモートにpushされていた場合、コミットのSHA-1が変化してしまい、
同内容のコミットが複数現れることになってしまうのでは…?
fugafuga1とffuuggaa1の内容は同じだが、SHA-1が違うので別のコミットとみなされてしまうはず。
…えーと、これについて「そりゃそうだ、やっちゃダメだよ」って一刀両断したい方、もうちょっと待って。最後まで読んでいただきたい。
--
問題2: developを取り込んだブランチ"feature/fuga"の実装
feature/hogeの実装は、hogehoge3で完了とする。
これをリモートのdevelopへとmergeしたい。
developのコミットも進んでいるので、グラフを綺麗にするために、
git rebase develop
git push
(GitHubにてプルリクをmergeして、)
git hf finish
という手順を踏み、無事にdevelopに機能が取り込まれた。
この手順は特に妙なことはしていない…ですよね?
ただ、ここでふたたび問題。
これ以降、feature/fugaにてdevelopの変更を取り込みたいとき、どうすれば良い?
feature/hogeのコミットは、feature/hogeをpushしたときのrebaseにより、
hogehoge1, hogehoge2,hogehoge3
から
hhooggee1, hhooggee2, hhooggee3
に変化している。
この状態で、feature/fugaにて
git rebase develop
しようとすると、feature/fugaのコミットは、
hhooggee1, hhooggee2, hhooggee3, hogehoge1, hogehoge2, hogehoge3, ffuuggaa1, ffuuggaa2
となってしまうのでは?
rebase絡みでの作業で、同内容のコミットが複数現れることが多くあり、
何がその原因になっているのかうまく頭の中で整理しきれておらず、認識が間違ってるかもしれません。
正しい操作はどうすべきで、何をするときには気をつければいいのか…という点について、
ご教授願えたら幸いです。
Q.そもそもpush済みのブランチでrebaseするなって話じゃない?
A.そうなんですけど。
以下の記事がよくまとまってますね。読みましたよ。
git rebase に関するメモ - Life like a clown
rebase に関しては、まだ使いどころが今一つ掴めないでいるのですが、明快な指針が一つ示されていました。
あぁ、このすばらしいリベース機能。しかし、残念ながら欠点もあります。その欠点はほんの一行でまとめることができます。
公開リポジトリにプッシュしたコミットをリベースしてはいけない
この指針に従っている限り、すべてはうまく進みます。もしこれを守らなければ、あなたは嫌われ者となり、友人や家族からも軽蔑されることになるでしょう。
Git - リベース
なぜ、公開リポジトリに push した commit に対して、後から rebase を行ってはいけないのかと言うと、「(rebase で作られた commit は元の commit と同内容でも別の commit となるため)rebase してしまうと push できなくなる」と言う理由のようです。何故、push できなくなってしまうのかについては こわくない Git と言うスライドで分かりやすく解説されていますので、このスライドの 104 ~ 146 枚目を何度か追うと理解できると思います。
んー、全部ローカルで作業して最後にpushってフローが守れるならいいんだけれど。
- pushされたブランチではrebaseしてはいけない
- push前にはログを綺麗にするためにrebaseを行う必要がある
このふたつの問題が、それぞれ矛盾していて、どう運用すればいいのかわからないっていうのが現状です。
WIPとして途中のコードをメンバーに見てもらいつつ実装進める場合、最後までpushしないってわけにはいかない。
また、随時developの内容を反映しつつ実装を行うためには、最後のpushの時までrebaseを行わないってわけにもいかない。
ここいら、皆さんどうやって対処してるんだろうなーというのが疑問。