1. ホーム
  2. git

[解決済み] masterへのマージ時に最初のブランチが潰された後のブランチのマージ

2023-03-04 23:41:48

質問

私が仕事でよく扱うワークフローを紹介します。

git checkout -b feature_branch
# Do some development
git add .
git commit
git push origin feature_branch

この時点で feature ブランチは同僚からのレビューに上がっていますが、私は feature_branch . そのため feature_branch はレビュー中です...

git checkout feature_branch
git checkout -b dependent_branch
# Do some more development
git add .
git commit

feature_branchのコードレビューに対応するため、いくつかの変更を加えます。

git checkout feature_branch
# Do review fixes
git add .
git commit
git checkout dependent_branch
git merge feature_branch

さて、ここで問題が発生します。 私たちは master で squash ポリシーを採用しており、master にマージされる機能ブランチは単一のコミットに squash されなければならないことを意味します。

git checkout feature_branch
git log # Look for hash at beginning of branch
git rebase -i  first_hash_of_branch # Squash feature_branch into a single commit
git merge master

すべてがクールです。 dependent_branch . 依存するブランチを master にリベースしたり master をマージしたりしようとすると、git は書き換えられたり潰されたりした履歴に惑わされ、基本的に depedendent_branch のすべての変更を競合としてマークします。 のすべての変更をやり直したり競合を解除したりするのは大変な作業です。 dependent_branch . これに対する解決策はあるのでしょうか? 時々、私は手動でパッチを作成し、master の新しいブランチからそれを適用しますが、もしそれに本当の競合があるならば、修正するのはさらに悪いことです。

git checkout dependent_branch
git diff > ~/Desktop/dependent_branch.diff
git checkout master
git checkout -b new_dependent_branch
patch -p1 < ~/Desktop/dependent_branch.diff
# Pray for a clean apply.

何か思い当たることはありますか? スクショの時に履歴を書き換えるからこうなるのは分かっているのですが、これは変えられない要件です。 最良の解決策/回避策は何でしょうか? 何か魔法のようなものがあるのでしょうか? または、手動で diff を作成することに関係するすべての手順を実行する、より高速な方法はありますか?

どのように解決するのですか?

なぜこのようなことが起こるのか、少し考えてみましょう。

をさせる O は "オリジナル・マスター" とし FB は機能ブランチがマージされた後の "新しい master" である必要があります。

というのは feature_branch のように見える。

O - A - B - C 

dependent_feature はその上にいくつかの余分なコミットがあります。

O - A - B - C - D - E - F

元の機能ブランチをmasterにマージして、それを潰した結果です。

O - FB

さて、依存するブランチをリベースしようとすると、git はそれらのブランチ間の共通の先祖を探そうとします。一方、それは はもともと であったでしょう。 C もしコミットを削除していなければ、git は代わりに O を共通の祖先として見つけます。その結果、git が再生しようとしているのは A , B そして C であり、これらは を既に含んでいる FB を含んでおり、競合が多発することになります。

このため、典型的なリベースコマンドはあまりあてにならず、より明示的に --onto パラメータを指定することで、より明確にする必要があります。

git rebase --onto master HEAD~3  # instruct git to replay only the last
                                 # 3 commits, D E and F, onto master.

を修正します。 HEAD~3 パラメータを修正すれば、冗長な競合の解決に対処する必要はありません。

範囲を指定するのが嫌で、元の機能ブランチをまだ削除していない場合は、別の構文もあります。

git rebase --onto master feature_branch dependent_feature

                                 # replay all commits, starting at feature_branch
                                 # exclusive, through dependent_feature inclusive 
                                 # onto master