web-dev-qa-db-ja.com

Gitリベースは履歴を失いますが、なぜリベースするのですか?

私は過去数日間、Gitでリベースすることを検討してきました。リベースの議論のほとんどは、それが歴史をきれいにし、それをより直線的にすることを言っています。たとえば、単純なマージを行うと、履歴がいつ分岐し、いつ元に戻されたかを示す履歴が得られます。私の知る限り、リベースはその履歴をすべて削除します。質問はこれです:なぜ、どこでどのように分岐したかを含め、コードが開発されたすべての方法をリポジトリの履歴に反映させたくないのですか?

49
ngephart

私の知る限り、リベースはその履歴をすべて削除します。

それは正しくありません。名前が示すように、リベースすると、コミットのbaseが変更されます。通常、そのプロセスでコミットが失われることはありません(マージコミットを取得しない場合を除く)。開発プロセスのすべてを実際に行われた方法で履歴内に保持することについてのあなたの議論は正しいですが、これはしばしば混乱する履歴につながります。

特に、それぞれが独自のブランチで作業している他のユーザーと作業する場合、必須他のユーザーからの特定の変更を続行する必要があります(たとえば、AがBに何かを実装して、Aが自分の開発でその機能を使用できるようにする)、これ多くのマージにつながります。たとえば、次のようになります。

     #--#--#--#--*-----*-----------------*---#---\         Branch B
    /           /     /                 /         \
---#-----#-----#-----#-----#-----#-----#-----#-----*       Branch A

この例では、一時的に個別に機能するブランチがありますが、常に元のブランチから変更を取得します(#は元のコミット、*はマージ)。

ここで、マージして戻す前にブランチBでリベースを実行すると、次のようになります。

                             #--#--#--#--#---\         Branch B
                            /                 \
---#---#---#---#---#---#---#---#---------------*       Branch A

これは実際の変更と同じですが、BはAの古いコミットにリベースされたため、以前に行われたBのすべてのマージは不要になりました(これらの変更はその古いコミットにすでに存在するため)。そして、現在欠落しているすべてのコミットはマージであり、通常、開発プロセスに関する情報は含まれていません。 (この例では、最後のコミットを後でAにリベースして直線を取得し、2番目のブランチへのヒントを効果的に削除することもできます)

27
poke

あなたが世界征服の秘密プロジェクトに取り組んでいると想像してみてください。この陰謀には3つの首謀者がいます。

  • 天才
  • 一般的な
  • コンピュータハッカー

そして、彼らは皆、1週間でそれぞれ1つの詳細な計画を持って秘密基地に来ることに同意します。

実用的なプログラマーであるコンピューターハッカーは、Gitを使用して計画のすべてのファイルを保存することを提案しました。それぞれが最初のプロジェクトリポジトリをフォークし、1週間ですべてをマージします。

彼らは皆同意し、次の日には物語は次のようになります:

天才

彼は毎日10回、合計70回のコミットを行いました。

一般

彼は彼らの仲間のレポをスパイし、彼らを倒すための戦略を立てました。彼は最後の日、3回のコミットを行いました。

コンピュータハッカー

この実用的なプログラマーはブランチを使用しました。彼は4つの異なる計画を立て、それぞれが支店にありました。各ブランチは、1つのコミットになるようにリベースされました。

7日が経過し、グループは再び集まり、すべての計画を1つの傑作に統合しました。彼ら全員が始めたがっていたので、彼ら全員が自分ですべてのものをマージしようとしました。

ここに物語があります:

天才

彼は、将軍のリポジトリからのすべての変更をマージしてから、コンピューターハッカーのリポジトリをマージしました。そして、論理愛好家である彼は、ログを調べました。彼は、物事が以前のアイデア-コミットに基づいて構築された、アイデアの論理的な進化を見ることを期待していました。

しかし、ログに示されているのは、さまざまなアイデアの無数のコミットがすべてタイムラインに混在していることでした。ある読者は、コミットのタイムラインを読んだだけでは、進化、コミットの理由を本当に理解できませんでした。

それで彼は、天才でさえ理解できない混乱で終わりました。

一般

一般的な考え:分割統治!

そして、彼は天才のレポを自分のレポにマージしました。彼はログを見て、最終日まで不安定な進行をたどった天才のアイデアからのコミットの束を見ました。最終日、将軍と天才の考えが混ざり合った。

彼はコンピューターハッカーをスパイしていて、リベースソリューションについて知っていました。そこで彼は自分の考えをリベースし、マージを再試行しました。

現在、ログは毎日論理的な進行を示しています。

コンピュータハッカー

この実用的なプログラマーは、Geniusアイデア用の統合ブランチ、Generalアイデア用の統合ブランチ、および彼自身のアイデア用の統合ブランチを作成しました。彼は各支店にリベースを行いました。そして、彼はすべてをマスターに統合しました。

そして、彼のチームメイト全員が彼のログが素晴らしいことを知りました。簡単でした。一目で不安定でした。

アイデアが問題を引き起こした場合、どのコミットが導入されたかは明らかでした。1つしかなかったからです。

彼らは全世界を征服することをやめ、Subversionの使用をやめました。

そして、すべてが幸せでした。

55
Nerian

競合をローカルで解決するために、主にリモートブランチ(フェッチするだけ)の上でローカルコミット(まだプッシュしていないもの)を作り直すためにリベースを行います(つまり、それらをアップストリームリポジトリにプッシュバックする前)。
gitワークフローとリベースとマージの質問 」および詳細:「 gitリベースとgitマージ "」を参照してください。

ただし、リベースはそのシナリオに限定されず、「-interactive」と組み合わせると、ローカルでの並べ替えと履歴のクリーニングが可能になります。 " GITチェックインのトリミング/ GIT履歴の潰し "も参照してください。

どこでどのように分岐したかなど、コードが開発されたすべての方法をリポジトリの履歴に反映させたくないのはなぜですか

  • 一元化されたVCSでは、履歴を決して失わないことが重要であり、実際に「コードが開発されたすべての方法」を反映する必要があります。
  • 分散VCSでは、一部のブランチをアップストリームに移行する前に公開、あらゆる種類のローカル実験を実行できます。 すべてを履歴内に保持する意味がありません。すべてのブランチ、テスト、代替などを複製して表示する必要があるわけではありません。
11
VonC

パブリックリポジトリでミスを犯し、まだ誰もそこからフォーク/マージ/プルしていない場合は、顔と混乱を避けることができます。

git reset --hard [SHAnumber]

git rebase -f master

git Push -f Origin HEAD:master

ごみ箱を空にするには:

git gc
0
mda