git整合分支一般有两种方法——变基操作(git rebase)和合并操作(git merge),但是在你们实际的团队开发中,哪种方式用的最多,或者你们觉得那个好呢?
天蓬老师2017-05-02 09:46:25
現実はこんな感じだと思います:
git を使用する人の少なくとも半数は、(基本的な機能であっても) リベースの使用方法を知りません (この推定はおそらく非常に保守的です)
残念ながら、残りの半分だけがいつリベースを正しく行うべきかを本当に理解していません...
マージとリベースは、どちらかを選択するという問題ではなく、特定の状況に応じて選択する必要があります。実際には、ほとんどの開発者にとって、この「特定の状況」を 1 つずつ列挙するのは非常に難しいと言われています。チーム内の役割は比較的単一であり、頻繁に遭遇するものではないため、ここでは全員が理解し、遵守すべきガイドラインを 2 つだけ要約します。
リモートから pull
を実行するときは、常に rebase を使用してください (1 つの例外を除き、これについては後で説明します) pull
的时候,永远使用 rebase(除了一个例外,后面会讲)
当你完成了一个功能(假定你是单独开本地分支去做的)后打算合并到主干分支的时候,永远使用 merge
开发者应当理解:不同的合并策略影响的或许不是最终的代码结果,但却会影响 git 如何记录提交的历史(尽管很多时候这种理解只对个别人受益,而对自己没有什么影响)。其他的人在使用这些历史的时候(比如 code review 的时候,或者 bisect 的时候等等)会因为过去你做过的事情而感到无比幸福或痛苦。
第二点比较容易理解,把开发一个功能的具体细节隐藏在本地分支中,而把最终的结果作为一条完整的记录合并(merge)到主干分支去。
关键是第一点。大多数情况下大家会选择默认的 pull
,也就是 fetch + merge
,于是我们会看到主干上不停的出现 Merge commit xxx into xxx 之类的干扰信息。如果所有的人都图方便这么干,那就永远都别想有干净漂亮的历史树了,取而代之是类似这样的东西:
如果你去 clone 一个正确使用 git 的项目,你绝对不会看到上图这样乱七八糟的 master。为什么呢?答案就是:git pull --rebase
,这条命令会使用 rebase
来代替默认的 pull
对合并的历史树进行变基处理,就可以避免因为无法快进(fast forward)而产生的额外合并记录。
现在绝大多数的 git 客户端都允许设置 git pull
的默认行为是 --rebase
,所以掌握了这个诀窍可以让大部分的日常拉取操作都产生清爽漂亮的历史记录,但这并不是完美的结局。有一种例外是这样的:
在你使用 git merge
完成了一个功能分支向主干分支的合并之后(当然是 --no-ff
pull
(fetch + merge
) を選択するため、Merge commit xxx into xxx がトランクに常に表示されます。 /em> およびその他の不穏な情報。誰もが便宜のためにこれを行うと、クリーンで美しい履歴ツリーは決して得られず、代わりに次のようなものになります。
🎜🎜
🎜 git を正しく使用するプロジェクトをクローンすると、上の写真のような乱雑なマスターが表示されることはありません。なぜ?答えは、 git pull --rebase
です。このコマンドは、デフォルトの pull
の代わりに rebase
を使用して、マージされた履歴ツリーをリベースします。早送りできないため、追加のマージされたレコードを回避できます。 🎜
🎜現在、ほとんどの Git クライアントでは、git pull
のデフォルト動作を --rebase
に設定できるため、このトリックをマスターすれば、ほとんどの毎日の pull 操作が可能になります すべてが新鮮で美しい履歴レコードを生成します, しかし、これは完璧な終わりではありません。次のような例外があります: 🎜
🎜
🎜🎜 git merge
を使用して機能ブランチをトランク ブランチにマージした後 (もちろん --no-ff
) 🎜 git fetch
を実行すると、リモート トランクが数コミット先にあることがわかりますgit fetch
发现远程主干又领先你若干提交
此时你若 git pull --rebase
,你会发现你刚才合并功能分支的记录没了……
这是因为变基会忽略合并记录,因此变基命令会有一个特别的参数叫做:--preserve-merges
用于重建被忽略的合并记录。所以比 git pull --rebase
更好的方案就是用 git fetch
+ git rebase -p
代替之。
当然这个仅针对上面提到的特殊情况,随着 git 的升级说不好哪一天就不存在这种问题了也不一定。我一般都不会遇到这种情况,因为我都是这么做的:
完成功能分支之后先不 merge,而是回到主干分支去 git pull --rebase
如果主干有更新,rebase 更新的内容到功能分支来预检一下,看看在加入了最近别人的改动之后我的功能是否依然 OK(在这个过程中可能会有冲突处理,别怪我没提醒哦)
一切就绪之后再次 git fetch
主干看看有没有变动(因为在第二步的进行期间没准又有人 push 了新的变化),有的话重复第二步,没有则——
合并功能分支到主干然后 push,收工。
我这么做可以避免前面提到的意外,看似复杂了些但其实做熟练了之后也没什么难度,更重要的原因是 git rebase -p
是有缺陷的:
不能和 git pull
连用,一条命令分成俩,怎么都觉得“亏”了(虽说你可以写脚本,但最好不要因为习惯了之后反而有时候会害了你)
由于无法和 git pull
配合使用,所以你必须指明目标分支给 rebase,这一点比较烦人,特别是很多 GUI 客户端压根不支持 git rebase -p
的时候(我经常会在 CLI/GUI 之间切换环境使用 git)
ORIG_HEAD
会被破坏。
ORIG_HEAD
在很多情形下非常有用,比如说你可以用 git log -p -reverse ORIG_HEAD
来回看最近一次合并所产生的所有变化等等。--preserve-merges
git pull --rebase
を実行すると、マージしたばかりの機能ブランチのレコードがなくなっていることがわかります...🎜🎜
🎜これは、rebase がマージされたレコードを無視するためです。そのため、rebase コマンドには、無視されたマージされたレコードを再構築するために使用される --preserve-merges
という特別なパラメーターがあります。したがって、git pull --rebase
よりも良い解決策は、代わりに git fetch
+ git rebase -p
を使用することです。 🎜
🎜 もちろん、これは上記の特殊な状況に限ったものであり、git のアップグレードにより、この問題がいつかなくなるとは限りません。私はいつもこうしているので、通常はこのような状況には遭遇しません: 🎜
<オル>
🎜🎜関数ブランチの完了後、最初にマージせず、トランクブランチgit pull --rebase
に戻ります🎜🎜
🎜🎜トランクが更新された場合は、更新されたコンテンツを関数ブランチにリベースして、他の人の最近の変更を追加した後も自分の関数がまだ問題ないかどうかを事前チェックします (このプロセスでは競合が発生する可能性があります。私を責めないでください)思い出させてないよ) ああ)🎜🎜
🎜🎜すべての準備ができたら、再度トランクを git fetch
して、変更があるかどうかを確認します (第 2 ステップで誰かが新しい変更をプッシュした可能性があるため)。変更がある場合は、第 2 のステップを繰り返します。そうでない場合は、——🎜🎜
🎜🎜機能ブランチをトランクにマージしてプッシュしたら、これで終わりです。 🎜🎜
🎜これを行うことで、前述の事故を回避できます。少し複雑に見えますが、実際には、慣れれば難しくありません。より重要な理由は、git rebase -p
に欠陥があることです。 🎜
<オル>
🎜🎜 git pull
と組み合わせて使用することはできません。1 つのコマンドが 2 つに分割されているため、とにかく「失われた」ように感じられます (スクリプトを作成することはできますが、そうすることは避けた方がよいでしょう)。慣れると害を及ぼすこともあります) 🎜🎜
🎜🎜git pull
では使用できないため、リベースのターゲット ブランチを指定する必要がありますが、特に多くの GUI クライアントが git rebase -p
をサポートしていないため、これは非常に面倒です> (gitを使用するためにCLI/GUI間で環境を頻繁に切り替えます)🎜🎜
🎜🎜ORIG_HEAD
は破棄されます。 🎜🎜
🎜ORIG_HEAD
は、さまざまな状況で非常に役立ちます。たとえば、git log -p -reverse ORIG_HEAD
を使用して、最新のマージなどによって生じたすべての変更を確認できます。 --preserve-merges
を使用すると、それが指すはずの場所が失われるため、最初にそれを置き換える正しいハッシュを見つける必要がありますが、これは少し面倒な場合があります。 🎜
🎜 上記の答えは、初心者の場合、現実の複雑さは常に想像を超えるものであることを示しています。本当に git を使いたい場合は、日々の作業に基づいて git の動作原理を理解する必要があります。公式 Web サイトの電子書籍 (中国語版) にアクセスして、その中の git 内部セクションを注意深く読むと、どのコマンドを使用するかがわかります。 🎜追加のポイント: トランク ブランチ上の多くの重要でない干渉コミット レコードをチームが気にしない場合は、いつでもリベースを使用できます。これにより、少なくとも多くのフォークが発生しなくなります。また、それを適切に処理すれば、クリーンな (しかし冗長な) ブランチ履歴を取得できます。
淡淡烟草味2017-05-02 09:46:25
必須ではありませんが、プッシュ後にすべてのテストが緑色になる必要があります
(特に長いブランチはありません。ほとんどは 2 ~ 3 日以内にマージされますが、1 週間以上かかることはほとんどありません)
通常はマージの難易度に応じて誰もが選択しますが、違いがない場合はリベースが優先されます...見た目が良いためです