間違ってmainから派生させたブランチを、git cherry-pickを使ってdevelopからの派生に修正してみた
間違ってmainからブランチを切ってしまった
おのやんです。
みなさん、本来はdevelopブランチから機能追加ブランチを作成するべきものを、間違ってmainブランチから機能追加ブランチを作成してコミットを重ねてしまった経験はありませんか?私はあります(懺悔)。
こういった場合、git rebase onto
コマンドを使って派生元ブランチを修正できます。しかし、git rebase onto
はコミットの改変に当たるため、すでにremoteにpushしている場合や複数人で作業している場合はNGとのことです。実際、私が遭遇したケースでも複数コミットを重ねた上で、それらをGitHubにpushしていました。
ただしこの方法は「コミットの改変にあたる」点に注意が必要です。
すでにpush済だったブランチの場合、リモートとローカルの履歴が不整合になるため普通にpushしようとしてもエラーになりす。-f
オプションをつけて強制的にpushさせなければなりません。
自分ひとりで作業しているブランチであればこれで全く問題ないのですが、他の人と共同で作業しているブランチで勝手に過去のコミットを改変するのはNG。
方法1を使う際は、この点が確実にクリアできる状況であるときだけにしておきましょう。
ということで、今回はgit rebase ontoではないもうひとつの方法である、git cherry-pickを使って、remoteにpush済みのブランチを修正してみたいと思います。
状況
今回のケースでは、機能追加用ブランチ(feature/xxxx)は原則developブランチから派生させるという規則がありました、そのため、通常であればこちらのようなブランチの管理になるはずでした。
しかし、本来developブランチから派生させるはずの機能追加用ブランチを、誤ってmainブランチから派生させてしまいました。この間違ったブランチにはコミットが重なっていて、GitHubにもpushしていました。
ということで、これらの間違ったブランチ・コミットを、develop派生の新しいブランチに修正したいと思います。
解決策
まず、developブランチから修正用の新しい機能追加ブランチを作成します。
git switch -c feature/yyyy
そして、 新しく作成した機能追加用ブランチにいる状態で、git cherry-pick コマンドを実行します。今回は、一度に複数のコミットを新ブランチにコピーしたいため、..
でコミットIDをつなげています。このとき、aaaa..dddd
のように複数コミットを範囲指定しますが、git cherry-pick
の仕様として、コピー対象のコミットのうちaaaa
は含めません。またdddd
は含めます。このため、画像のようなイメージでcherry-pickの範囲を確認するのを強くオススメします。
git cherry-pick aaaa..dddd
こうすることで、先ほど新規作成したブランチに誤ブランチのコミットがコピーされた状態になります。この状態で、git push origin feature/yyyy
で新しいブランチをpushしたり、git branch -d feature/xxxx
で誤ブランチを削除したりすれば、実質的に派生元ブランチをmainからdevelopに修正できるという寸法です。
git cherry-pickは慎重に
git cherry-pickは、カレントブランチに変更を加える作業ですので、gitコマンドの仕様などを確認して、確実に期待した通りの挙動を示すことを確認してから実行するようにしてください。私自身、20分くらいコマンドの挙動の確認に時間をかけました。
Gitブランチの派生元を間違えた場合は、参考にしていただけると幸いです。では!