回答:
あなたは使うべきgit pull --rebase
とき
確かに-では、なぜそうしないのですか?それはより明確で、コミットに論理的なグループ化を課しません。
わかりました、それはいくつかの説明が必要だと思います。Gitでは、おそらくご存じのとおり、分岐してマージすることをお勧めします。変更をプルするローカルブランチとリモートブランチは、実際には異なるブランチであり、git pull
それらをマージしようとしています。プッシュはそれほど頻繁ではなく、通常、完了した機能を構成する前にいくつかの変更を蓄積するため、それは合理的です。
ただし、場合によっては、何らかの理由で、リモートとローカルの2つが1つのブランチである方が実際には優れていると考える場合があります。SVNのように。ここが登場git pull --rebase
する場所です。マージする必要はなくなりました。実際には、リモートブランチの上でコミットします。それが実際の目的です。
危険かどうかは、ローカルブランチとリモートブランチを切り離せないものとして扱うかどうかという問題です。時にはそれが妥当な場合もあります(変更が小さい場合、または堅牢な開発の最初の段階で、重要な変更が小さなコミットによってもたらされる場合)。そうでない場合もあります(通常は別のブランチを作成しますが、それを行うのが面倒なので)。しかし、それは別の質問です。
git config --global pull.rebase preserve
(リベースを有効にすることに加えて、プリザーブはローカルでマージを行った場合にマージを保持しようとする)。
「git pull --rebase」が実際に何を意味するのかについて、別の見方をしたいと思います。
Subversion(またはCVS)を使用したことがある場合、「svn update」の動作に慣れている可能性があります。コミットする変更があり、変更が上流で行われたためにコミットが失敗した場合は、「svn update」を実行します。Subversionは、上流の変更を自分の変更とマージすることによって進行し、競合を引き起こす可能性があります。
Subversionが行ったことは、本質的には「プル-リベース」でした。ローカルの変更を新しいバージョンに関連するように再構成することは、その「リベース」の部分です。コミットが失敗する前に "svn diff"を実行し、その結果の差分を "svn diff"の出力と比較した場合、2つの差分の違いがリベース操作の実行結果です。
この場合のGitとSubversionの主な違いは、Subversionでは「自分の」変更は作業コピーのコミットされていない変更としてのみ存在するのに対し、Gitでは実際にローカルにコミットされていることです。言い換えると、Gitで歴史を分岐しました。あなたの歴史と上流の歴史は分かれていますが、共通の祖先があります。
私の意見では、ローカルブランチに上流のブランチを単純に反映させ、継続的な開発を行う通常の場合、正しいことは常に「--rebase」です。これは、意味的に実際に行っていることです。あなたと他の人たちは、ブランチの意図された線形の履歴にハッキングしています。他の誰かがあなたのプッシュしようとする少し前に偶然プッシュしたという事実は無関係であり、そのようなタイミングの事故のそれぞれが履歴にマージをもたらすことは逆効果です。
何かの理由で何かがブランチになる必要性を実際に感じた場合、それは私の意見では別の懸念事項です。しかし、変更をマージの形で表現したいという具体的で積極的な欲求がない限り、私の意見では、デフォルトの動作は「git pull --rebase」であるはずです。
あなたのプロジェクトの歴史を観察し、理解する必要がある他の人々を考慮してください。あちこちに何百ものマージが散らばっている履歴が欲しいですか、それとも意図的な発散的開発努力の実際のマージを表す少数のマージだけが欲しいですか?
git config --global branch.autosetupmerge always
ますか?
おそらくそれを説明する最良の方法は例を使用することです:
git checkout master && git pull
ます。マスターはすでに最新です。git checkout master && git pull
ます。マスターはすでに最新です。git merge topic-branch-A
git merge topic-branch-B
git push origin master
アリスの前に行いますgit push origin master
を実行しますが、早送りではないため拒否されます。git pull --rebase origin master
git push origin master
はそうし、将来ログを見るときに役に立たないマージコミットを読む必要がないことを誰もが喜んでいます。マージされる特定のブランチは例とは無関係であることに注意してください。この例のマスターは、リリースブランチまたはdevブランチと同じくらい簡単にできます。重要な点は、Alice&Bobがローカルブランチを共有リモートブランチに同時にマージしていることです。
git co master && git pull; git checkout topic-branch-A; git rebase master; git checkout master; git merge topic-branch-A; git push origin master
前に他人のマスターへのプッシュが起こった場合は繰り返します。私はあなたのレシピで簡潔な利点を見ることができますが。
git pull --rebase
同じブランチで他の人とコラボレーションするときに使用する必要があると思います。あなたはあなたの仕事→コミット→仕事→コミットサイクルにいます、そしてあなたがあなたの仕事をプッシュすることを決定したとき、あなたのプッシュは拒否されます、なぜなら同じブランチで並行した仕事があったからです。この時点で、私は常に行いますpull --rebase
。(コミットをフラット化するために)スカッシュを使用しませんが、余分なマージコミットを回避するためにリベースします。
Gitの知識が増えるにつれ、私が使用した他のバージョン管理システムよりもずっと歴史に目を向けることになります。小さなマージコミットが大量にある場合、履歴で発生している全体像の焦点を失うのは簡単です。
これが実際にリベース(*)する唯一の時間であり、私のワークフローの残りの部分はマージベースです。しかし、あなたの最も頻繁なコミッターがこれを行う限り、歴史は結局ずっと良く見えます。
(*)Gitコースの指導中に、特定の状況で機能ブランチをリベースすることも提唱したため、学生にこれについて逮捕されました。そして、彼はこの答えを読んだ;)そのようなリベースも可能ですが、それは常に事前に準備された/合意されたシステムに従う必要があり、そのため「常に」適用されるべきではありません。そして、その時私は通常pull --rebase
どちらもしません、それが問題です;)
使用しない理由はないと思いますpull --rebase
-特にGitにコードを追加して、git pull
コマンドが常にアップストリームコミットに対してリベースできるようにしました。
履歴を見るとき、機能に取り組んでいる人/ギャルが同期を停止した時期を知ることは決して面白くありません。それは彼/彼女がそれをしている間彼/彼女のためにそれは役に立つかもしれません、しかしそれはそれが何のreflog
ためであるかです。それは他のすべての人にノイズを加えるだけです。
pull --rebase
、必ず使用しなければならない、なぜしないpull
、デフォルトでそれを行いますか?
.gitconfig
のオプションを正しく行うためにいくつか持っています。私はgit rebaseがデフォルトでgitタグなどと同様に間違っていると思います...同意しない場合は、意見を正当化する必要はありません。
master
プルする場合、およびプルするブランチがまだ公開されていない場合、これは良いアドバイスのようです。一方、機能ブランチからその中に引っ張ると、逆master
のようになります:を使用する理由はありません--rebase
よね?それがデフォルトではない理由かもしれません。リベースは変更が階層の最上部から下にどのように渡されるかであり、マージはそれらが上に戻る方法であることがわかりました。 derekgourlay.com/blog/git-when-to-merge-vs-when-to-rebase
個人の好みに帰着すると思います。
変更をプッシュする前に、愚かな間違いを隠したいですか?もしそうなら、git pull --rebase
完璧です。後でコミットをいくつか(または1つ)のコミットに押しつぶすことができます。(プッシュされていない)履歴にマージがある場合、後でマージするのは簡単ではありませんgit rebase
。
私は個人的にはすべてのばかげた間違いを公開してもかまわないので、リベースするのではなくマージする傾向があります。