web-dev-qa-db-ja.com

`git fetch`、` git rebase`、 `git pull --rebase`の違いは何ですか?

git pullページを読み取ると、git pull --rebaseに関する次の厳しい警告が表示されます。

これは潜在的に危険な操作モードです。それは歴史を書き直しますが、あなたがすでにその歴史を発表したとき、それは良い前兆ではありません。 git-rebase(1)を注意深く読んでいない限り、このオプションを使用しないでください。

git rebaseページでは、多くの説明が表示されますが、この種の警告はありません。

さらに、私は一部の人々がそう言うのを見ました

git fetch
git rebase

と同じです

git pull --rebase

他の人たちは、それらがわずかに異なると言います。

真実は何ですか?

41
Ryan Lundy

Gitのルールは、履歴が共有、公開、またはプッシュされた後で、履歴を変更しようとしないことです。もちろん、本当に十分な権限を持ちたい場合は、これを行うことができますが、他のユーザーを混乱させる可能性があるため、十分に注意して行う必要があります。

幸い、単一の上流リポジトリ(Origin)を備えた典型的なGitデプロイメントがあり、これが宇宙で善と真のすべてのソースである場合、_git pull --rebase_を心のコンテンツに使用でき、完全に安全になりますそして、私の意見では、はるかに健全な(線形を意味する)履歴を提供します。私と私のチームはそれを継続的に使用しています。

ただし、複数のリモートを持ち始めて_git pull --rebase <arguments>_を開始し、毎回同じターゲットをリベースしないようにする場合、またはブランチを別のリポジトリにプッシュし始める場合before running _git pull --rebase_をプライマリアップストリームで使用すると、問題が発生し始めます。

変更を別のリモート/リポジトリと共有し、それらの変更を変更するときはいつでも(コミットのメッセージ/コンテンツが変更されていなくても、変更の値はSHAや親の変更と同じです)、人を台無しにすることができます古い変更があった人。

リベースの健全性の枠を超えない限り、_git pull --rebase_は非常に役立ちます。

えーと、_git pull --rebase_と_git fetch && git rebase @{u}_の違いについての質問には答えません。私は先に進んで、違いに気づいていないと言います。違いがある場合は、Gitを使用してきた年に気づかなかったほど微妙です。複数のリポジトリがあり、「Origin」がこのブランチの上流でない場合、システムはブランチがフェッチする正しいリポジトリを計算する可能性があります。

そして、git-rebaseで非常にうまくいかなくても、もちろん_git log -g_や_git reset --hard ORIG_HEAD_を使用して、元のリベース前の環境に簡単に戻すことができます。強制プッシュを行わないでください(ほとんどすべてのGitサーバーではデフォルトで許可されていません)。

編集済み

時間とともに私の理解は広がりました。 _git pull --rebase_は_git rebase_を呼び出してリベース作業を行うため、その意味では両者に違いはありません。ただし、git-pullは実際にはgit rebase --onto @{u} $(git merge-base HEAD @{u}@{1})を呼び出します

わかりました。その構文( "@ {u} @ {1}")はおそらく少し不透明で、起動するのを簡単にするものですが、要は、マージベースが上流に何であったかがわかるということです[〜# 〜] before [〜#〜] fetchコマンドを実行しました。これはどのような違いがありますか?

まあ、通常の場合はありません。ただし、アップストリームが指している場所を変更する場合、またはアップストリーム自体がリベースされた場合は、かなりの数になります。アップストリームが書き直され、次に_git rebase @{u}_を実行した場合、非常に不幸になり、古いコミットがどれだけ書き換えられたかに応じて、二重のコミットまたは競合が発生する可能性があります。

ただし、_git pull --rebase_の背後にある魔法により、@ {u}の上には、自分のコミットと自分のコミットだけが適用されます。

わかりました、これtooは単純化です。アップストリームが100コミット前にリベースを行った場合(ただし、実際には履歴に101以上のコミットがあります)and _git fetch_ before _git pull --rebase_の場合、Gitは、ローカルコミットが何であるかを理解するために適切な履歴マージベースが何であったかを正確に判断できません。

その結果、_git fetch_は有害と見なされます(ローカルコミットがあり、アップストリームが書き換えられている場合)。ただし、本当の経験則は、「履歴が共有、公開、またはプッシュされた後で履歴を変更しようとしないこと」です。

TL; DR:

_git fetch_は有害と見なされます(したがって_git pull --rebase_を使用してください);また、履歴が共有、公開、またはプッシュされた後は、絶対に履歴を変更しようとしないでください(特に、_git fetch_が有害になるためです)。

30
Seth Robertson

真実は、それら[〜#〜] [〜#〜]が異なることです。ここにそれを美しく説明する本当に役立つウェブページがあります:

http://gitolite.com/git-pull--rebase.html

したがって、git pull --rebasegit fetch; git rebaseよりも重要な魔法を持っていますが、ほとんどの場合は気づきませんが、アップストリームのメンテナーは、これらの厳しい警告をいたずらに無視し、パブリックブランチの履歴を書き直すことにしました。ローカルのreflogを調べて、よりインテリジェントな方法でローカルのリベースを行うことで、本当に助けになります。

とはいえ、これはまだリベースなので、あなたはまだ歴史を書き換えています!したがって、すべての標準的な厳しい警告が引き続き適用されます。しかし、プライベート(つまり、非公開)ブランチで作業している場合は、それで問題ありません。

厳格な警告についてもう少し説明します。彼らは有効ですが、個人的に私はほとんどの人が少しだけtoogit rebaseが若い頃に寝室に忍び込み、妹を食べていたように、リベースについて妄想的ですか何か。それは本当にそれほど怖いものであってはなりません。

  • プライベートブランチの場合は、心ゆくまでリベース
  • reallyする必要がある場合を除いて、それがパブリックブランチである場合はリベースしないでください。そうする場合は、影響を理解していることを確認し、影響を受ける可能性のあるすべての人に適切に通知してください。完了したので、彼らは厄介な驚きを得ることがなく、何が起こったのかを理解するために多くの時間を浪費しません。

とても簡単です。そして、はい、私は、個人のブランチで定期的にgit rebase -iを行うように人々を積極的に奨励するまで行きます。パブリック/アップストリームのどこかにプッシュする前に履歴を磨くのは 良いこと です。なぜなら、「おっと、3つ前に犯した間違いを修正する」のようなコミットでいっぱいのプロジェクトの履歴をざっと見たくないからです。 (OTOH、完璧な歴史を求めてリベースに夢中にならないでください。私たちは人間です。私たちは間違いを犯します。それに対処してください。)

git pull --rebaseマジックに関する最後の観察。上流のパブリックブランチが賢明な方法でリベースされている場合(たとえば、コミットを押しつぶしたり修正したり、そこに置くべきではなかったコミットを削除したりする場合)、魔法は有利に機能します。ただし、アップストリームが誤ってリベースdroppedをコミットした場合、魔法により、それらが元に戻せなくなります。この場合、ドロップされたコミットを元に戻すには、代わりにgit fetch; git rebaseを使用する必要があります。

38
Adam Spiers