建议何时使用Git rebase与Git merge?
成功重新创建数据库后,是否仍需要合并?
建议何时使用Git rebase与Git merge?
成功重新创建数据库后,是否仍需要合并?
当前回答
简短版本
合并在一个分支中接受所有更改,并在一次提交中将它们合并到另一个分支。Rebase说我希望我的分支点转移到一个新的起点
那你什么时候用这两种?
合并
假设您创建了一个分支来开发单个功能。当您想将这些更改带回master时,可能需要合并。
回扣
第二种情况是,如果您开始进行一些开发,然后另一个开发人员进行了不相关的更改。您可能希望从存储库中提取并重新创建基础,以将当前版本的更改作为基础。
挤压:在这两种情况下都会保留所有提交(例如:“add feature”,然后是“typ”,然后“oops typ again”…)。通过挤压,可以将提交合并为单个提交。挤压可以作为合并或重基操作(--squash标志)的一部分完成,在这种情况下,通常称为挤压合并或挤压重基。
拉取请求:流行的git服务器(Bitbucket、GitLab、GitHub等)允许配置如何在每个回购基础上合并拉取请求。按照惯例,UI可能会显示“合并”按钮,但该按钮可以使用任何标志(关键字:合并、重基、挤压、快进)执行任何操作。
其他回答
Gitrebase用于使历史中的分支路径更清晰,存储库结构更线性。
它还用于将您创建的分支保持为私有,因为在重新创建基础并将更改推送到服务器之后,如果您删除了分支,则不会有您曾处理过的分支的证据。因此,您的分支现在是您的本地关注点。
在进行重新基化之后,我们还消除了一个额外的提交,这是我们用来查看是否进行正常合并的。
是的,在成功的rebase之后仍然需要进行合并,因为rebase命令只是将您的工作放在您在rebase过程中提到的分支之上,比如master,并将分支的第一次提交作为master分支的直接后代。这意味着我们现在可以进行快速合并,将更改从该分支带到主分支。
简短版本
合并在一个分支中接受所有更改,并在一次提交中将它们合并到另一个分支。Rebase说我希望我的分支点转移到一个新的起点
那你什么时候用这两种?
合并
假设您创建了一个分支来开发单个功能。当您想将这些更改带回master时,可能需要合并。
回扣
第二种情况是,如果您开始进行一些开发,然后另一个开发人员进行了不相关的更改。您可能希望从存储库中提取并重新创建基础,以将当前版本的更改作为基础。
挤压:在这两种情况下都会保留所有提交(例如:“add feature”,然后是“typ”,然后“oops typ again”…)。通过挤压,可以将提交合并为单个提交。挤压可以作为合并或重基操作(--squash标志)的一部分完成,在这种情况下,通常称为挤压合并或挤压重基。
拉取请求:流行的git服务器(Bitbucket、GitLab、GitHub等)允许配置如何在每个回购基础上合并拉取请求。按照惯例,UI可能会显示“合并”按钮,但该按钮可以使用任何标志(关键字:合并、重基、挤压、快进)执行任何操作。
信息图形总是有用的:)
合并:将一个分支重叠到另一个分支上
Assume the following history exists and the current branch is "master":
A---B---C topic
/
D---E---F---G master
Then "git merge topic" will replay the changes made on the topic branch since it
diverged from master (i.e., E) until its current commit (C) on top of master, and
record the result in a new commit along with the names of the two parent commits
and a log message from the user describing the changes.
A---B---C topic
/ \
D---E---F---G---H master
Rebase:将一个分支的更改移动到另一个分支末端
Assume the following history exists and the current branch is "topic":
A---B---C topic
/
D---E---F---G master
From this point, the result of either of the following commands:
git rebase master
git rebase master topic
would be:
A'--B'--C' topic
/
D---E---F---G master
NOTE: The latter form is just a short-hand of git checkout topic followed by git
rebase master. When rebase exits topic will remain the checked-out branch.
因此,我们基本上可以得出结论,合并是一个安全的选项,它可以保存存储库的整个历史,而重基化通过将特性分支移动到main的顶端来创建线性历史。
Credit:帮助页面gitmerge--help和gitrebase--help
TL;博士
如果您有任何疑问,请使用merge。
简短回答
重新基准和合并之间的唯一区别是:
生成的历史树结构(通常只有在查看提交图时才明显)不同(一个有分支,另一个没有分支)。合并通常会创建一个额外的提交(例如树中的节点)。合并和重新基础将以不同的方式处理冲突。Rebase将一次提交一个冲突,而merge将一次显示所有冲突。
因此,简单的答案是根据您希望的历史外观选择重新基准或合并。
长答案
在选择要使用的操作时,需要考虑以下几个因素。
您从中获得更改的分支是否与团队之外的其他开发人员共享(例如,开源、公共)?
如果是,请不要重新设置基准。Rebase会破坏分支,除非他们使用git pull-Rebase,否则这些开发人员将拥有损坏/不一致的存储库。这是一个很快让其他开发人员感到不安的好方法。
您的开发团队有多熟练?
回扣是一种破坏性操作。这意味着,如果不正确应用它,您可能会丢失已提交的工作和/或破坏其他开发人员存储库的一致性。
我曾在团队中工作过,这些团队中的开发人员都来自一个公司能够负担得起专门的员工来处理分支和合并的时代。这些开发人员对Git了解不多,也不想了解太多。在这些团队中,我不会因为任何原因而冒险建议重新定基。
分支本身是否表示有用的信息
一些团队使用每个功能的分支模型,其中每个分支表示一个功能(或错误修复或子功能等)。在这个模型中,分支帮助识别相关提交的集合。例如,可以通过恢复该分支的合并来快速恢复功能(公平地说,这是一个罕见的操作)。或者通过比较两个分支来区分一个特性(更常见)。Rebase会破坏分支,这并不简单。
我也曾在使用每个开发人员分支模型的团队中工作过(我们都去过)。在这种情况下,分支本身不传递任何附加信息(提交已经包含作者)。换基不会有什么害处。
是否出于任何原因要还原合并?
与恢复合并相比,恢复(如撤消)重基相当困难和/或不可能(如果重基发生冲突)。如果您认为有机会恢复,请使用merge。
你是团队成员吗?如果是的话,你愿意在这一分支机构采取“要么全有要么全无”的方法吗?
需要使用相应的git pull--Rebase来拉动Rebase操作。如果你是自己工作,你可能会记得在适当的时候应该使用哪一个。如果你在一个团队中工作,这将很难协调。这就是为什么大多数rebase工作流建议对所有合并使用rebase(以及git pull--rebase对所有合并)。
常见的神话
合并销毁历史记录(压缩提交)
假设您有以下合并:
B -- C
/ \
A--------D
有些人会说合并“破坏”了提交历史,因为如果只查看主分支(A-D)的日志,就会错过B和C中包含的重要提交消息。
如果这是真的,我们就不会有这样的问题了。基本上,除非您明确要求不要看到B和C(使用--firstparent),否则您将看到它们。这很容易自己尝试。
Rebase允许更安全/更简单的合并
这两种方法的合并方式不同,但并不清楚其中一种总是优于另一种,这可能取决于开发人员的工作流程。例如,如果开发人员倾向于定期提交(例如,当他们从工作过渡到家庭时,他们可能一天提交两次),那么给定分支可能会有很多提交。其中许多提交看起来可能与最终产品不太相似(我倾向于对每个特性进行一次或两次重构)。如果其他人正在处理一个相关的代码领域,他们试图重新调整我的更改,这可能是一个相当乏味的操作。
热巴更酷/更性感/更专业
如果您想将rm别名为rm-rf以“节省时间”,那么可能需要重新设置基准。
我的两美分
我一直认为有一天我会遇到这样一个场景,Git rebase是解决这个问题的绝佳工具。就像我认为我会遇到这样一个场景,Git reflog是一个很好的工具,可以解决我的问题。我已经在Git工作了五年多了。这还没有发生。
混乱的历史对我来说从来都不是一个问题。我从来没有像读一本令人兴奋的小说那样阅读我的承诺历史。大多数时候,我需要一段历史,无论如何,我都会使用Git责备或Git平分。在这种情况下,合并提交实际上对我很有用,因为如果合并引入了问题,那对我来说就是有意义的信息。
更新(2017年4月)
我觉得有义务提及我个人对使用rebase的态度有所软化,尽管我的一般建议仍然有效。我最近与Angular 2 Material项目进行了很多互动。他们使用rebase来保持非常干净的提交历史。这使我能够非常容易地看到是什么提交修复了给定的缺陷,以及该提交是否包含在发布中。它是正确使用rebase的一个很好的例子。
Pro Git的书在重新设置基础页面上有一个很好的解释。
基本上,合并将进行两次提交并合并它们。
一个重基将转到这两者的共同祖先,并在彼此之上逐步应用更改。这使得历史更加“清晰”和线性。
但当您重新创建基准时,您将放弃以前的提交并创建新的提交。因此,您永远不应该重新设置公共存储库的基础。其他在存储库中工作的人会恨你。
仅出于这个原因,我几乎完全合并了。99%的时候,我的分支机构没有太大的差异,所以如果有冲突,只会发生在一两个地方。