ここ数日、Git を使ったリベースを検討してきました。リベースの議論のほとんどは、リベースによって履歴がクリーンアップされ、より直線的になると言われています。単純なマージを行うと (たとえば)、履歴がいつ分岐し、いつ元に戻されたかを示す履歴が得られます。私の知る限り、リベースするとその履歴がすべて削除されます。質問は次のとおりです。コードがどこでどのように分岐したかなど、コードが開発されたすべての方法をレポ履歴に反映させたくないのはなぜですか?
5 に答える
あなたが世界征服の秘密プロジェクトに取り組んでいると想像してみてください。この陰謀には 3 つの首謀者がいます。
- 天才
- 一般的な
- コンピューターハッカー
そして、彼らは全員、1週間ごとに1つの詳細な計画を持って秘密基地に来ることに同意します.
実用的なプログラマーであるコンピューターハッカーは、計画のすべてのファイルを保存するために Git を使用することを提案しました。それぞれが最初のプロジェクト リポジトリをフォークし、1 週間ですべてマージします。
彼らは皆同意し、次の日に話は次のようになります。
天才
彼は毎日 10 回、合計 70 回のコミットを行いました。
一般的な
彼は仲間のレポをスパイし、彼らを打ち負かすための戦略を立てました。彼は最終日、3 つのコミットを行いました。
コンピューターハッカー
この実用的なプログラマーはブランチを使用しました。彼は 4 つの異なる計画を立て、それぞれを枝にしました。各ブランチは、1 つのコミットだけになるようにリベースされました。
7 日が経過し、グループは再び集まり、すべての計画を 1 つの傑作にまとめました。全員が熱心に始めたので、全員が自分ですべてのものをマージしようとしました。
ここに話があります:
天才
彼は、General のレポと Computer Hacker のレポのすべての変更をマージしました。そして、ロジック愛好家である彼は、ログに目を通しました。彼は、物事が以前のアイデアコミットに基づいて構築された、アイデアの論理的進化を見ることを期待していました.
しかし、ログが示していたのは、さまざまなアイデアの無数のコミットがタイムラインに混在していたことです。ある読者は、コミットのタイムラインを読んだだけでは、コミットの進化や理由を本当に理解できませんでした。
それで彼は、天才でさえ理解できないような混乱で終わった.
一般的な
一般的な考え方: 分割して征服せよ!
そして、彼はGeniusのレポを自分のレポにマージしました。彼はログを見て、最後の日まで、不安定な進行をたどった Genius のアイデアからのコミットの束を見ました。最終日、将軍と天才の考えが混ざり合った.
彼は The computer Hacker をスパイしており、Rebase ソリューションについて知っていました。そこで、彼は自分のアイデアをリベースし、マージを再試行しました。
これで、ログは毎日論理的な進行を示しました。
コンピューターハッカー
この実用的なプログラマーは、Genius アイデア用の統合ブランチ、General アイデア用の統合ブランチ、および彼自身のアイデア用の統合ブランチを作成しました。彼は各ブランチにリベースを行いました。そして、彼はマスターですべてをマージしました。
そして、彼のチームメイト全員が、彼の丸太が素晴らしいことを知りました。シンプルでした。一目でわかりました。
アイデアが問題を引き起こした場合、コミットが導入されたのは 1 つだけだったので、明らかでした。
彼らは全世界を征服するのをやめ、Subversion の使用をやめました。
そしてみんな幸せでした。
私の知る限り、リベースするとその履歴がすべて削除されます。
それは正しくありません。名前が示すように、リベースはコミットのベースを変更します。通常、そのプロセスでコミットが失われることはありません (マージ コミットを取得しない場合を除く)。開発プロセスのすべてを実際に行われた方法で履歴内に保持するというあなたの議論は正しいですが、非常に多くの場合、これは履歴を混乱させることにつながります.
特に、他の人からの特定の変更を継続する必要がある一方で、それぞれが独自のブランチで作業している他の人と作業する場合(たとえば、A が自分の開発でその機能を使用できるように、A が B に何かを実装するように依頼する場合)、これは多くのマージにつながります。たとえば、次のようにします。
#--#--#--#--*-----*-----------------*---#---\ Branch B
/ / / / \
---#-----#-----#-----#-----#-----#-----#-----#-----* Branch A
この例では、しばらくの間は別々に機能するブランチがありますが、常に元のブランチから変更を取り込みます (# は元のコミット、* はマージです)。
ここで、再度マージする前にブランチ B でリベースを行うと、次のようになります。
#--#--#--#--#---\ Branch B
/ \
---#---#---#---#---#---#---#---#---------------* Branch A
これは同じ実際の変更を表していますが、B は A の古いコミットにリベースされているため、以前に行われた B のすべてのマージは不要になりました (これらの変更は古いコミットに既に存在するため)。現在失われているすべてのコミットはマージであり、通常、開発プロセスに関する情報は含まれていません。(この例では、最後のコミットを後で A にリベースして直線を取得し、2 番目のブランチへのヒントを効果的に削除することもできることに注意してください)
ローカルで(つまり、アップストリームリポジトリにプッシュバックする前に)競合を解決するために、主にリモートブランチ(フェッチするだけ)の上でローカルコミット(まだプッシュしていないもの)をリワークするためにリベースを実行します)。
「gitワークフローとリベースとマージの質問」を参照してください。詳細については、「gitリベースとgitマージ」を参照してください。
ただし、リベースはそのシナリオに限定されず、「-interactive」と組み合わせると、ローカルでの並べ替えと履歴のクリーニングが可能になります。「 GITチェックインのトリミング/GIT履歴の潰し」も参照してください。
どこでどのように分岐したかなど、コードが開発されたすべての方法をリポジトリの履歴に反映させたくないのはなぜですか
- 一元化されたVCSでは、履歴を決して失わないことが重要であり、実際に「コードが開発されたすべての方法」を反映する必要があります。
- 一部のブランチをアップストリームに公開する前にあらゆる種類のローカル実験を実行できる分散VCSでは、すべてを履歴内に保持することはあまり意味がありません。すべてのブランチ、テスト、代替案を複製して確認する必要はありません。等々。
公開リポジトリで間違いを犯し、まだ誰もそこからフォーク/マージ/プルしていない場合は、顔と混乱を避けることができます:
git reset --hard [SHAnumber]
git rebase -f master
git push -f origin HEAD:master
ゴミ箱を空にするには:
git gc