なぜgit pullはデフォルトでリベースの代わりにマージを実行するのですか?


71

次の状況を考慮してください。

  • Gitリポジトリのクローンがあります
  • ローカルコミット(まだどこにもプッシュされていないコミット)がある
  • リモートリポジトリには、まだ調整されていない新しいコミットがあります

このようなもの:

マージされていないコミット

git pullデフォルト設定で実行すると、次のようなものが得られます。

マージコミット

これは、gitがマージを実行したためです。

ただし、代替手段があります。代わりにリベースを行うようにpullに指示できます:

git pull --rebase

これが得られます:

リベース

私の意見では、リベース版には多くの利点があり、それらは主にコードと履歴の両方をきれいに保つことに集中しているため、gitがデフォルトでマージを行うという事実に少し驚いています。はい、ローカルコミットのハッシュは変更されますが、これは、より単純な履歴の見返りとして支払う小さな代償のようです。

しかし、これが何らかの形で悪いまたは間違ったデフォルトであることを決して示唆しているわけではありません。デフォルトではマージが優先される理由を考えるのに苦労しています。なぜ選ばれたのかについての洞察はありますか?デフォルトとしてより適切にする利点はありますか?

この質問の主な動機は、私の会社がリポジトリを整理および管理する方法についてのいくつかのベースライン標準(できればガイドラインに似ている)を確立しようとしていることです。私は通常、このタイプの状況でリベースする必要があるというケースを作成することに興味があります(そしておそらく開発者がデフォルトでリベースするようにグローバル構成を設定することを推奨するため)とても素晴らしい場合はデフォルトです。だから私は私が不足している何かがあるのだろうかと思っています。

この質問は、なぜ多くのウェブサイトが「git merge」よりも「git rebase」を好むのかを複製したものであることが示唆されています。; ただし、この質問はこの質問のです。この質問では、リベースよりもマージの利点について質問されていますが、マージよりもリベースのメリットについて説明します。そこでの答えはこれを反映しており、マージの問題とリベースの利点に焦点を当てています。



もう1つの問題は、誤ってマスターにコミットしてからマージしたプルを実行すると、マージが正常に見えても2つのマスターが同期しなくなる可能性があることです。これが、プルエイリアスに--ff-onlyが含まれている理由です。
Ixrec

sourcetreeがグラフビューを変更してリベース/マージを異なる方法で表示する場合、マージに切り替えますか?
ユアン

1
@Ewan SourceTreeは、これのグラフビューを変更しないでください。グラフを正確に表します。
jpmc26

4
だまされた有権者の場合、私が受け入れた回答の内容は、あなたが重複していると主張している質問には絶対に存在しないことに注意してください。
jpmc26

回答:


56

その決定をした人からの連絡なしでは、なぜマージがデフォルトであるのかを確実に知ることは困難です。

ここに理論があります...

Gitは、プルごとに--rebaseしても問題ないと推測できません。それがどのように聞こえるかを聞いてください。「すべてのプルをリベースします。」プルリクエストなどを使用していると、間違っているように聞こえます。プルリクエストに基づいてリベースしますか?

一元化されたソース管理にGitを使用しているだけではないチームでは...

  • アップストリームおよびダウンストリームからプルできます。一部の人々は、ダウンストリーム、貢献者などから多くのプルを行います。

  • 他の開発者と緊密に連携して機能を開発したり、開発者や共有トピックブランチから引き出したり、アップストリームから時々更新したりすることがあります。常にリベースすると、楽しい競合サイクルは言うまでもなく、共有履歴が変更されてしまいます。

Gitは、誰もが単一の中央リポジトリにプルアンドプッシュしない大規模な高度に分散したチーム向けに設計されました。したがって、デフォルトは理にかなっています。

  • いつリベースしてもよいかわからない開発者は、デフォルトでマージされます。
  • 開発者は、必要なときにリベースできます。
  • 多くのプルを行い、多くのプルを行うコミッターは、自分に最も適したデフォルトを取得します。

意図の証拠として、リナス・トーバルズからよく知られている電子メールへのリンクがあります。 Dri-devel git pullメール

スレッド全体をフォローすると、ある開発者が別の開発者からプルし、Linusが両方の開発者からプルしていることがわかります。彼は自分の意見をかなり明確にしている。彼はおそらくGitのデフォルトを決定したので、これが理由を説明するかもしれません。

現在、多くの人々がGitを集中的に使用しています。小さなチームの全員が、上流の中央リポジトリからのみプルし、同じリモートにプッシュします。このシナリオは、リベースが適切でない状況の一部を回避しますが、通常はそれらを排除しません。

提案:デフォルトを変更するポリシーを作成しないでください。大きなグループの開発者とGitを組み合わせると、一部の開発者はGitをあまり深く理解しません(自分も含めて)。彼らはグーグルに行き、クックブックのアドバイスを受けて、なぜいくつかのことがうまくいかないのか不思議に思うgit checkout --ours <path>でしょう。好みに合わせて、ローカル環境をいつでも修正したり、エイリアスを作成したりできます。


5
デフォルトを変更しないための+1-独自のgitワークフローをローリングするよりも、存在するワークフロー(たとえば、Atlassianatlassian.com/git/tutorials/comparing-workflows/ …で文書化されたワークフローのいずれかを取得する方がよいでしょう)
Rob Church

1
答えてくれてありがとう。ダウンストリームからのプルに関する情報は、私が欠けていたものでした。また、興味深いことに、あなたが与えたリンクは、私が達成したいまさに奨励:「人々は(そしておそらく必要があります)そのリベースできるプライベート。木(自分の仕事を)」
jpmc26

2
@jpmcすばらしい。確かに。プライベートツリーのリベースは、共有された履歴から気を散らす多くの邪魔を排除できます。私がやる。重要なのは、いつそれをしないのかを明確にすることです。
joshp

「一部の開発者はGitをそれほど深く理解していません」。RebaseはGitの素晴らしい機能(「ディープ」など)の機能ではありません。このことを本当に理解しにくいと思いますか?これは、devを無能に呼び出すトリガーになるはずだと思います。
ビクターYarema

15

リベース用のgitマンページを読むと、次のように表示されます

他の人が作業のベースにしているブランチをリベース(または他の形式の書き換え)するのは悪い考えです。その下流の人は手動で履歴を修正する必要があります。このセクションでは、ダウンストリームの観点から修正方法を説明します。ただし、実際の修正は、最初にアップストリームのリベースを回避することです。

それはリベースをまったく使用しない理由として十分に言っていると思います。もちろん、すべてのプルに対して自動的にそれを行います。一部の人々は、リベースが有害であると考えています。おそらく、それは決してgitに入れられるべきではなかったのです。なぜなら、それがするように見えるのは、歴史をきれいにすることだけであるからです。

「歴史をきれいに保つ」と言うとき、あなたは間違っていると思います。見栄えはよくなりますが、リビジョンの履歴を保持するように設計されたツールの場合、すべてのコミットを保持して何が起こったかを確認できるようにする方がはるかにクリーンです。その後の履歴のサニタイズは、古さを磨き、光沢のある再現のような豊かなアンティークの外観にするようなものです:-)


3
@Ewan IMHO「うまくいかないがきれいに見える」というのは、ITではなくファッション業界にのみ残すべきものです。私見gitは、スタイルよりも実質が重要であると考える人が多すぎることを明らかに奨励しているため、削除する必要があります。
gbjbaanb

12
歴史をきれいに保つことは役に立たないというあなたの提案に異議を唱えます。そうではありません。リポジトリの履歴は人間が使用することを目的としているため、読みやすくすることには多くの価値あります。私の特定のユースケースでは、開発以外のプロジェクトマネージャーが履歴を読み取れるようにすることさえ意図しています。クリーンな履歴はそれでしか役に立ちません。また、コードベースを見たことのない新しい開発者がコードの特定の領域で何が起こったのかを理解し、バグを修正するのに役立ちます。
jpmc26

3
コードは最初に存在し、何よりもまずマシンによって実行されます(おそらくコンパイル後に)。上記の哲学を適用すると、コードの読みやすさは問題ではないと結論付けられます。なぜなら、読みやすさの量はコードを理解する難しさを解決しないからです。私は何かをつぶすべきだと提案したことはありません。多くの交差パスに分岐する複雑なグラフを辿るのは難しいと言っているだけなので、履歴をかなりきれいに保つために少し投資する価値があります。また、線形履歴は、非難や二分法などのgitツールを活用するのに役立ちます。
jpmc26

6
ドキュメントには「リベースしない」と書かれていません。「他の人の上流にある変更をリベースしないでください」と書かれています。これら2つの間に世界の違いがあります。Linus自身は、受け入れられた回答のリンクに見られるように、歴史を整理するためのいくつかのリベースを助言しています。そして、どのコミットが無関係であるかをツールがどのように知るのか(特に、ツールが非線形の履歴を分析するのが難しい場合)、そしてどのコミットを比較したいのかをどのように知るのでしょうか(特に履歴を掘り下げることができません!)?特定の状況について、独断的な極端な注意を払っています。
jpmc26

4
開発者がこれまでに行ったすべてのコミットが含まれる場合、「リビジョンの履歴を保持する」ことは絶対に望まないでしょう。このロジックに従って、バックスペースキーがヒットするたびに元のバージョンのコードも記録する必要があります。すべてのコミットは、プロジェクト全体を安定した状態に維持する最小限の完全な変更である必要があります。元のコミットが後でバグがあることが判明した場合、別のコミットを作成するよりも、コミットをリベース/編集/修正する方がはるかに優れています。ただし、mail-archive.com / dri
Mikko Rantalainen

12

正しいのは、ローカル/変更されたリポジトリが1つしかないことを前提としています。ただし、たとえば、2番目のローカルPCがあることを検討してください。

ローカル/変更されたコピーが他の場所にプッシュされると、リベースはそれらのコピーを台無しにします。もちろん、プッシュを強制することもできますが、それはすぐに複雑になります。これらの1つ以上に別の完全に新しいコミットがある場合はどうなりますか?

ご覧のとおり、非常に状況に応じたものですが、基本戦略は(私にとっては)特別ではない/コラボレーションの場合にはるかに実用的です。


2番目の違い:マージ戦略は、明確で時間的に一貫した構造を維持します。リベース後、古いコミットが新しい変更に追随する可能性が非常に高く、履歴全体とそのフローを理解しにくくします。


1
「リベースした後、古いコミットが新しい変更に従う可能性が非常に高い」-しかし、それはマージでも発生するため、それを理解するためにきれいなグラフが必要な場合があります。コミットが行われた時間は、このブランチにコミットをマージする前に長い場合があります。
スティーブジェソップ

6

大きな理由はおそらく、デフォルトの動作が公開リポジトリで「正常に動作する」はずだからです。他の人がすでにマージした履歴をリベースすると、問題が発生します。私はあなたがあなたのプライベートレポについて話していることを知っていますが、一般的に言えば、gitはプライベートまたはパブリックのことを知らないか気にしませんので、選択されたデフォルトは両方のデフォルトになります。

git pull --rebaseはプライベートリポジトリでかなり多くを使用しますが、それでも潜在的な欠点があります。つまり、HEAD実際に作業を行ったときに、私の履歴がツリーを反映しなくなるということです。

そのため、大きな例として、コミットを実行する前に常にテストを実行し、それらが合格することを確認するとします。私がaを行った後、これはあまり関係git pull --rebaseがありません。なぜなら、各コミットのツリーがテストに合格したということはもはや真実ではないからです。変更が何らかの方法で干渉せず、私がプルするコードがテストされている限り、おそらくテストに合格するでしょうが、試したことがないのでわかりません。継続的インテグレーションがワークフローの重要な部分である場合、CIにされているレポ内のあらゆる種類のリベースが問題になります。

私はこれを本当に気にしませんが、それは一部の人々を悩ませます:彼らはgitの彼らの歴史が実際に働いたコードを反映することを好むでしょう(またはおそらく彼らがそれをプッシュするまでに、いくつかの使用後の真実の簡略版「fixup」の)。

特にこの問題が、Linusがデフォルトでリベースではなくマージを選択した理由であるかどうかはわかりません。私が遭遇していない他の欠点があるかもしれません。しかし、彼は自分の意見をコードで表現することに恥ずかしくないので、彼がそれについてあまり考えたくない人(特に公共の場で働いている人)に適したワークフローであると思うことになると確信していますプライベートリポジトリよりも)。きれいなグラフで平行線を避け、それが起こったときの平行開発を表していないきれいな直線を支持することは、それがあなたのものであってもおそらく彼の最優先事項ではありません:-)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.