私の同僚と私はマージ戦略について活発な議論をしており、それを解決するのに役立つ情報を手に入れることができることを望んでいます。
tl:drは次のとおりです。変更をリモートブランチからプルするときにマージまたはリベースを使用して、競合解決を常にやり直さないようにします。
- svn:マスターゴールデンリポジトリ
- trunk:gitリモートブランチトラッキングsvn。 Subversionにコミットする前にgitの変更をステージングするために使用されます。
- 機能ブランチ:1つの機能に関する2人以上の同僚の作業を組み合わせたgitリモートブランチ
- colleague1:最初の同僚のローカル支店
- colleague2:2番目の同僚のローカル支店。
Sebastien Varetteの優れたワークフローを使用しています gitにマージした後のgit-svn dcommitは危険ですか?.
私たちが得ている問題は、毎回colleague1は、svnからリベースし(トランクにリベースし、その後、機能ブランチにプッシュする前にcolleague1にリベースすることにより)、次に、互いに競合する機能ブランチにコミットします。 svn rebaseワークフローが完了するたびに、同じ競合解決を何度も繰り返し行う必要があります。
私たちが使用していることに注意してください git rebase mirror un-3451
このリベース用。
私の主張は git merge mirror un-3451
。私の理解では、これにより、2つの以前のコミットのマージとしてマークされたコミットが生成されます。したがって、gitは以前のコミットを使用せず、代わりにマージコミットを使用することを知っています。
一方、私の同僚は、mergeを使用すると、svnとの最終的なマージがはるかに難しくなり、rebaseの使用がより優先されます。彼はそれを簡単に見つけました-悲しいことに、彼はすべての対立を解決する人ではありません。彼は、スカッシュコミットを使用しても同じ効果が得られると主張します。
私の主張は、マージはスカッシュと同じ効果がありますが、含まれていたコミットのマーク付けを含むということです。
状態1
svn-trunk: A
git-trunk: A"
remote-feature: A"-----C
/
c1-feature: A"--C
c2-feature: A"--D
状態2
Cはファイル1(F1)のDと競合します。 F1で競合が解決されるため、DはD "になります。
git pull --rebase remote feature
git add F1
git rebase --continue
git push
コミットグラフ:
svn-trunk: A-----B
(svn rebase)
git-trunk: A"----B"
remote-feature: A"-----C---------D"
/ /
c1-feature: A"--C / (git push)
/
c2-feature: A"-------C--D"
状態3
さて、colleague1はsvn-trunkから変更を取り込みたいと思っています:
git checkout trunk
git svn rebase
そして、それらをc2-featureにリベースします
git checkout feature-branch
git rebase trunk
リベースは、B1をc2フィーチャーに入れ、次にCに入れてからD "を取得し、同じ競合解決を強制的にD" "にします
コミットグラフ:
svn-trunk: A--------B
(svn rebase)
git-trunk: A"--------B"
remote-feature: A"-----C-------D"
/ ----
c1-feature: A"--C
c2-feature: A"----------B"-C--D""
毎回 git checkout trunk; git svn rebase; git checkout feature-branch; git rebase trunk; git push remote
サイクルが発生し、すべての競合解決が何度も繰り返される必要があります。
質問
- SVNからリベースする場合は、リモートにプッシュしますブランチ、colleague2がリモートブランチにいくつかのコミットをプッシュしてから、後でcolleague1がリモートブランチからプルマージを行い、結果のマージコミットがsvnコミットに言及するようにします(したがって、後続のリベースで問題が発生します)。
- 上記のシナリオのどちらが良いですか:リベースまたはマージ?
- rerere機能はもっと役立つでしょうか?
どうもありがとう!
回答:
回答№1は0最初に、同一のノードを省略し、ツリーをより適切に表現するために、各ブランチのヘッドが右端のノードになるようにノードを再編成します。 (ツリーが間違っている場合は修正してください)。 私のコメントは太字です。
状態1
svn-trunk: A
git-trunk: A"
c1/remote-feature: ----C
c2-feature: --D
その後、DはD "としてCにリベースされました。これは(理解しやすい)簡単な部分です。競合がなければ、チェリーピック(または"プレーン "D)であった可能性があります。
状態2
Cはファイル1(F1)のDと競合します。 F1で競合が解決されるため、DはD "になります。
svn-trunk: A-----B
(svn rebase)
git-trunk: A"----B"
c1-feature: C
c2/remote feature: D"
今、私たちは難しい部分に着きます。
状態3
さて、colleague1はsvn-trunkから変更を取り込みたいと思っています:
git checkout trunk
git svn rebase
そして、それらをc2-featureにリベースします
git checkout feature-branch
git rebase trunk
リベースは、B1をc2フィーチャーに入れ、次にCに入れてからD "を取得し、同じ競合解決を強制的にD" "にします
コミットグラフ:
svn-trunk: A
git-trunk: A"----B"
c1-feature: C
remote feature: D"
c2-feature: C----D""
理解するのが少し難しいコメントがグラフの状態と一致しないように見えるため、状態2から状態3に移行します(これは、c2機能をトランクに(cのリモート機能をリベースするための試みのようです)。結果。あなたが本当に欲しかったのはこれだと思います:
望ましい状態3
svn-trunk: A-----B
(svn rebase)
git-trunk: A"----B"
c1-feature: C
c2/remote feature: D"
つまり、A "-C-D"をリベースできませんでしたこれは起こるべきではないので奇妙です(私はgit-svnリポジトリでこれを再現しようとしましたが、意図したとおりに動作します)。あるgitブランチを別のブランチに対してリベースするだけなので、git-svnの問題でさえもです。あなたが適切にリベースしようとしているように見えるので、私はいくつかの情報が欠落していると推測できます。つまり、私が説明したことは実際に起こったことではありません。
回答№2の場合は0
私は同僚2です。
私の立場は、頻繁にリベースすることです痛みを引き起こしている機能ブランチへのSVN。変更セットをリベースするたびに、SVNの変更の上で再生されます。実際の競合は、リプレイされた変更セットにあります。
理想的には、変更セットで発生した競合を解決し、別のリベース後に再度解決する必要がないように、変更セットを単一のコミットに押しつぶします。
または、機能ブランチが完了してコミットの準備ができるまで、SVNからリベースするのを待つこともできます。
私はリベースから切り替えることを確信していないマージを実行すると、プロセスが改善されます。問題は、SVNから頻繁にリベースされることです。機能ブランチとローカルブランチをマージするとSVNリベースが改善されるとは思いません。