建议何时使用Git rebase与Git merge?

成功重新创建数据库后,是否仍需要合并?


当前回答

一些与Gerrit用于审查和交付集成的大规模开发相关的实际示例:

当我将我的功能分支提升到一个新的远程主机时,我就合并了。这提供了最小的提升工作,并且很容易跟踪功能开发的历史,例如gitk。

git fetch
git checkout origin/my_feature
git merge origin/master
git commit
git push origin HEAD:refs/for/my_feature

我在准备交付提交时合并。

git fetch
git checkout origin/master
git merge --squash origin/my_feature
git commit
git push origin HEAD:refs/for/master

无论什么原因,当我的交付提交未能集成时,我都会重新启动,我需要将其更新为新的远程主机。

git fetch
git fetch <gerrit link>
git checkout FETCH_HEAD
git rebase origin/master
git push origin HEAD:refs/for/master

其他回答

在合并/重新基础之前:

A <- B <- C    [master]
^
 \
  D <- E       [branch]

git合并主机后:

A <- B <- C
^         ^
 \         \
  D <- E <- F

git rebase master之后:

A <- B <- C <- D' <- E'

(A、B、C、D、E和F为提交)

在Git基础教程中可以找到这个例子以及更多关于Git的详细信息。

当您正在处理分支并在其间合并了一些其他工作时,Rebase是有用的-合并将创建更改,从而使diff受到污染,因此更难阅读。

如果您重新设置分支的基值,那么您的提交将应用于要重新设置基值的分支的顶部,这使得查看更容易,并且diff输出更干净。

一些与Gerrit用于审查和交付集成的大规模开发相关的实际示例:

当我将我的功能分支提升到一个新的远程主机时,我就合并了。这提供了最小的提升工作,并且很容易跟踪功能开发的历史,例如gitk。

git fetch
git checkout origin/my_feature
git merge origin/master
git commit
git push origin HEAD:refs/for/my_feature

我在准备交付提交时合并。

git fetch
git checkout origin/master
git merge --squash origin/my_feature
git commit
git push origin HEAD:refs/for/master

无论什么原因,当我的交付提交未能集成时,我都会重新启动,我需要将其更新为新的远程主机。

git fetch
git fetch <gerrit link>
git checkout FETCH_HEAD
git rebase origin/master
git push origin HEAD:refs/for/master

TLDR:这取决于什么是最重要的——整洁的历史还是发展顺序的真实再现

如果一个整洁的历史是最重要的,那么你会先重新基址,然后合并你的更改,所以很清楚新代码是什么。如果你已经推送了你的分支,除非你能够处理后果,否则不要重新基址。

如果序列的真实表示是最重要的,那么您可以合并而不重定基础。

合并意味着:创建一个新的提交,将我的更改合并到目标中。注意:这个新的提交将有两个父级:一个是提交字符串中的最新提交,另一个是合并的另一个分支的最新的提交。

Rebase的意思是:使用我当前的一组提交作为提示,创建一系列新的提交。换言之,计算一下如果我从重新基准点开始进行更改,我的更改会是什么样子。因此,在重新基准之后,您可能需要重新测试您的更改,并且在重新基准期间,您可能会发生一些冲突。

既然如此,你为什么要重新基准?只是为了保持发展历史的清晰。假设您正在处理功能X,当您完成后,将您的更改合并到中。目标现在将有一个单独的提交,该提交内容类似于“添加的功能X”。现在,如果您重新创建基础,然后进行合并,那么目标开发历史将包含单个逻辑进程中的所有单独提交,而不是合并。这使得以后查看更改更加容易。想象一下,如果50名开发人员一直在合并各种功能,那么你会发现很难回顾开发历史。

也就是说,如果您已经将正在处理的分支推到了上游,那么不应该重新创建基础,而应该合并。对于尚未向上游推送的分支,请重新基址、测试和合并。

另一次您可能需要重新设置基值,是在向上游推送之前从分支中删除提交。例如:早期引入一些调试代码的提交和进一步清理代码的提交。实现这一点的唯一方法是执行交互式rebase:gitrebase-i<branch/commit/tag>

更新:当您使用Git连接到不支持非线性历史的版本控制系统(例如Subversion)时,还需要使用rebase。在使用git-svn桥时,非常重要的是,您合并回Subversion的更改是主干中最新更改之上的一系列更改。只有两种方法可以做到这一点:(1)手动重新创建更改;(2)使用rebase命令,这要快得多。

更新2:另一种考虑rebase的方法是,它可以从您的开发风格映射到您提交的存储库中接受的风格。你有一次提交来修复拼写错误,一次提交去清除未使用的代码等等。当你完成你需要做的事情时,你有一系列的提交。现在让我们假设您提交的存储库鼓励大量提交,因此对于您正在进行的工作,可能需要一次或两次提交。如何获取提交字符串并将其压缩到预期值?你可以使用一个交互式的rebase,将你的小提交压缩成更少的大块。如果需要相反的方式,情况也是如此——如果您的风格是几个大的提交,但存储库需要长串的小提交。你也可以使用rebase来实现这一点。如果您进行了合并,那么现在已经将提交样式移植到了主存储库中。如果有很多开发人员,你可以想象一段时间后,用几种不同的提交样式来跟踪历史会有多困难。

更新3:成功重新创建数据库后,是否仍需要合并?是的,你是这样做的。原因是重基基本上涉及到提交的“转移”。如上所述,这些提交是经过计算的,但如果从分支点开始有14个提交,那么假设您的重基没有任何问题,那么在重基完成后,您将提前14个提交(在您重基的点之前)。你在重新开始之前有一个分支。之后将有一个相同长度的分支。您仍然需要在发布更改之前进行合并。换言之,尽可能多次地重新设置基准(同样,只有在您没有将更改推到上游的情况下)。仅在重新基准后合并。

这句话的意思是:

总的来说,实现两个世界的最佳效果的方法是重新定位本地在推送更改之前,您已进行但尚未共享的更改为了整理你的故事,但千万不要重复你推送的任何内容在某处

来源:3.6 Git分支-重新分类、重新分类与合并