93

これは、私が仕事でよく扱うワークフローです。

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

この時点で、フィーチャー ブランチは同僚によるレビュー待ちですが、 に依存する他のフィーチャーの開発を続けたいと思っています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

ここで問題が発生します。マスターにはスカッシュ ポリシーがあります。つまり、マスターにマージされた機能ブランチは、単一のコミットにスカッシュする必要があります。

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競合としてマークします。のすべての変更を実行し、基本的にやり直すか、競合を解消するのは PITAdependent_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.

何か案は?スカッシュ中に履歴が書き換えられたためにこれが発生することはわかっていますが、これは変更できない要件です。最善の解決策/回避策は何ですか? 私にできる魔法はありますか?または、差分を手動で作成することに関連するすべての手順を実行するより高速な方法はありますか?

4

4 に答える 4

121

これが起こる理由について少し:

機能ブランチがマージされた後、私はO「元のマスター」になり、「新しいマスター」になります。FB

次のように言いfeature_branchます。

O - A - B - C 

dependent_featureその上にいくつかの追加のコミットがあります:

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

元の機能ブランチを master にマージしてつぶすと、次のようになります。

O - FB

ここで、依存ブランチをリベースしようとすると、git はそれらのブランチ間の共通の祖先を見つけようとします。元々でしたがC、コミットを押しつぶさなければ、git は代わりOに共通の祖先を見つけます。その結果、git は、既に に含まれているAB、およびを再生しようとしているため、C多くの競合が発生します。FB

このため、典型的な rebase コマンドに実際に依存することはできず、--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
于 2014-03-23T16:03:33.897 に答える
2

この特定のケースでは、最初に作業したブランチの押しつぶされた作業のみがマスターに配置されていることを「知っている」ようです。

したがって、競合が発生するたびに変更を保持することで、喜んでマージできます。そのためのオプションがあります:

git merge -Xours master

詳細については、 https://git-scm.com/docs/git-rebaseを参照してください。

于 2016-10-21T15:47:10.487 に答える
0

「すべての機能開発を 1 つのコミットにまとめる」というポリシーには心から反対しますが、それが彼らの呼びかけです...

ブランチをそのままにして、特別なブランチで公開用にマッシュアップしたコミットを作成します。経営陣がそれを信じていなくても、開発を段階的に追跡できることは価値があります。「実際の」ブランチのタグでスカッシュの場所をマークします。実際のコミットを指すメッセージを使用して、スカッシュ間タグを追加することもできます。

于 2014-03-23T16:48:56.780 に答える