19

Git を初めて使用するほとんどの人のように、私も git merge と git rebase に適用可能なユース ケースを解読しようとして混乱に陥りました。結果として得られる作業コピーの状態に関しては、同じことが得られると最終的に判断したと思います。また、どちらも同じ競合を引き起こします。これが間違っている場合は、私を啓発するための例を提供してください。

私の見解では、(変更がプッシュまたはプルされていない場合) マージの代わりにリベースを使用する主な利点は、履歴を線形に保つことです。私が本当に理解していないのは、git-rerere を開発する理由です。

マンページから、 git-rerere は、以前に解決した競合を解決しようとしている場合に役立つはずです。これから参照する例は、http://www.kernel.org/pub/software/scm/git/docs/git-rerere.htmlにあります。

プロジェクトのポリシーが、メインラインからトピック ブランチ (Linux カーネルなど) に変更を常にマージしないことである場合、上記の例では、「使い捨て」マージ コミットを作成するように指示されています。基本的に、マスターをトピックにマージし、テストを実行してすべてが機能することを確認してから、「git reset --hard HEAD^」を実行して、本質的にマージ コミットを破棄します。後で、別の「使い捨て」マージ コミットを作成すると、最初の使い捨てマージで既に解決した競合を解決するのに git-rerere が役立ちます。

一時的なマージ コミットを作成するという面倒な作業をすべて行う代わりに、開発者が自分のトピックを master にリベースしない理由を説明してもらえますか? それが git-rebase のポイントではありませんか?変更を取得しますが、マージは避けますか? これは同じことを達成しませんか? また、誰もあなたのトピック ブランチの変更をプルしていないと仮定すると、これははるかに簡単なアプローチではないでしょうか? throw-away-merge+git-rerere ワークフローは本当に、変更がプッシュ/プルされた場合のためのものですか?

最後に 1 つの質問 - Linus は次のように述べていると引用されています。そこにいる...」 定期的なリベースでも、Linus は問題を抱えているでしょうか?

4

3 に答える 3

24

リベースとマージで同じ最終ツリーを作成できるのは正しいです。ただし、それらが生成する履歴は大きく異なり、バージョン管理はもちろんすべて履歴に関するものです。あなたは線形の歴史を好むと表明しました。これはローカルスケールでは確かに望ましいことですが、マージは機能やバグ修正などの大規模な相互作用を記録するのに役立ちます。

中心的な質問(リベースだけではない理由)に対する簡単な答えは、ブランチを開始するのに適切な場所がある場合があるということです。その場合は、リベースではなくマージする必要があります。

たとえば、現在のリリースだけでなく、メンテナンスリリースにも適用されるバグ修正がある可能性があります。両方のリリースの祖先である最新のコミットから分岐する必要があります。マスターブランチまたはメンテナンスブランチのいずれかに沿ってそのブランチを前方にリベースすることはできません。そうしないと、他のブランチにマージできなくなります。

同様に、すべてのトピックブランチはどこかで始まります。ある時点で、その履歴を保存したいとします。あなたは明確なケースの1つに言及します(他の人があなたの仕事を引っ張っています)が、それははるかに明白ではないかもしれません。他の機能との相互作用があるかもしれませんし、この機能にはサブ機能があり、階層全体を保持しようとしているのかもしれません。

したがって、確かに、ブランチがローカルであり、そのベースを固定しておく理由がない場合は、あなたが言うように、単にそれをリベースして実行する方がはるかに簡単です。しかし、それが正しくない場合もあります。

最後の質問は、実際には非常に異なるものについてであり、マージの競合とは関係ありません。Linusは、マージのコンテキストでは、実行する必要がなかったと述べました。これは、ブランチとマージの哲学の問題です。濱野純雄は、まさにその問題について素晴らしいブログ記事を書きました。手元のトピックを要約した簡単な引用:

トピックブランチ「add-frotz」を「master」ブランチにマージすると、明らかに新しい「frotz」機能が組み込まれますが、さらに重要なことに、「frotz」機能を「」に含めることが望ましいと述べています。マスターブランチ

Linusは、「linus」と呼ばれるこの奇妙なブランチを常にマージすることを望んでいません。これは、ブランチに含めることが望ましい特定のトピックをマージしていないことは明らかだからです。上流のブランチをトピックブランチに繰り返しマージしていますが、これはまったく間違った方向です。トピックを開発するために、マスター(またはライナス)からのすべてのものは必要ありません。トピックを完成させてから、逆に、上流のマスターにマージする必要があります。トピックブランチにmasterのすべてのコンテンツを含めることは望ましくありません。(そして、インテグレーターに関する限り、単一の開発者のマスターは実際にはトピックブランチです。)

したがって、Linusは頻繁なマージに問題はありません。彼は、目的のない非生産的なマージに問題があります。(そして、一般的に、マージが正当な理由で行われることを確認した場合、それらは頻繁に行われることはなく、ダウンストリームのマージになることはほとんどありません。)リベースが正当な理由で行われ、それらが履歴を作成する場合より良い、それならそれらは良いことですが、頻繁です。

于 2010-06-18T18:36:17.973 に答える
7

これは同じことを達成しませんか、そして誰もあなたのトピックブランチの変更を引っ張っていないと仮定すると、これははるかに簡単なアプローチではないでしょうか?throw-away-merge + git-rerereワークフローは、変更がプッシュ/プルされた場合にのみ当てはまりますか?

あなたは頭に釘を打ちました。リベースは、まだ公開していないブランチに適しています。rerere公開したブランチ(つまり、リベースが不適切である/ダウンストリームの開発者にとって煩わしいブランチ)に役立ちます。

Linusは、一定のリベースにも問題がありますか?

いいえ、リベースしてもマージコミットは発生せず、表面的にはブランチがリベースされていることを確認できませんが、ブランチが別のブランチに複数回マージされているかどうかは簡単に確認できます。

于 2010-06-18T18:35:48.287 に答える