162306a36Sopenharmony_ci.. SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci 362306a36Sopenharmony_ci.. include:: ../disclaimer-zh_CN.rst 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci:Original: Documentation/maintainer/rebasing-and-merging.rst 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci:译者: 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci 吴想成 Wu XiangCheng <bobwxc@email.cn> 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci========== 1262306a36Sopenharmony_ci变基与合并 1362306a36Sopenharmony_ci========== 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci一般来说,维护子系统需要熟悉Git源代码管理系统。Git是一个功能强大的工具,有 1662306a36Sopenharmony_ci很多功能;就像这类工具常出现的情况一样,使用这些功能的方法有对有错。本文档 1762306a36Sopenharmony_ci特别介绍了变基与合并的用法。维护者经常在错误使用这些工具时遇到麻烦,但避免 1862306a36Sopenharmony_ci问题实际上并不那么困难。 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci总的来说,需要注意的一点是:与许多其他项目不同,内核社区并不害怕在其开发历史 2162306a36Sopenharmony_ci中看到合并提交。事实上,考虑到该项目的规模,避免合并几乎是不可能的。维护者会 2262306a36Sopenharmony_ci在希望避免合并时遇到一些问题,而过于频繁的合并也会带来另一些问题。 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci变基 2562306a36Sopenharmony_ci==== 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci“变基(Rebase)”是更改存储库中一系列提交的历史记录的过程。有两种不同型的操作 2862306a36Sopenharmony_ci都被称为变基,因为这两种操作都使用 ``git rebase`` 命令,但它们之间存在显著 2962306a36Sopenharmony_ci差异: 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci - 更改一系列补丁的父提交(起始提交)。例如,变基操作可以将基于上一内核版本 3262306a36Sopenharmony_ci 的一个补丁集重建到当前版本上。在下面的讨论中,我们将此操作称为“变根”。 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci - 通过修复(或删除)损坏的提交、添加补丁、添加标记以更改一系列补丁的历史, 3562306a36Sopenharmony_ci 来提交变更日志或更改已应用提交的顺序。在下文中,这种类型的操作称为“历史 3662306a36Sopenharmony_ci 修改” 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci术语“变基”将用于指代上述两种操作。如果使用得当,变基可以产生更清晰、更整洁的 3962306a36Sopenharmony_ci开发历史;如果使用不当,它可能会模糊历史并引入错误。 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci以下一些经验法则可以帮助开发者避免最糟糕的变基风险: 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci - 已经发布到你私人系统之外世界的历史通常不应更改。其他人可能会拉取你的树 4462306a36Sopenharmony_ci 的副本,然后基于它进行工作;修改你的树会给他们带来麻烦。如果工作需要变基, 4562306a36Sopenharmony_ci 这通常是表明它还没有准备好提交到公共存储库的信号。 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci 但是,总有例外。有些树(linux-next是一个典型的例子)由于它们的需要经常 4862306a36Sopenharmony_ci 变基,开发人员知道不要基于它们来工作。开发人员有时会公开一个不稳定的分支, 4962306a36Sopenharmony_ci 供其他人或自动测试服务进行测试。如果您确实以这种方式公开了一个可能不稳定 5062306a36Sopenharmony_ci 的分支,请确保潜在使用者知道不要基于它来工作。 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci - 不要在包含由他人创建的历史的分支上变基。如果你从别的开发者的仓库拉取了变更, 5362306a36Sopenharmony_ci 那你现在就成了他们历史记录的保管人。你不应该改变它,除了少数例外情况。例如 5462306a36Sopenharmony_ci 树中有问题的提交必须显式恢复(即通过另一个补丁修复),而不是通过修改历史而 5562306a36Sopenharmony_ci 消失。 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci - 没有合理理由,不要对树变根。仅为了切换到更新的基或避免与上游储存库的合并 5862306a36Sopenharmony_ci 通常不是合理理由。 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci - 如果你必须对储存库进行变根,请不要随机选取一个提交作为新基。在发布节点之间 6162306a36Sopenharmony_ci 内核通常处于一个相对不稳定的状态;基于其中某点进行开发会增加遇到意外错误的 6262306a36Sopenharmony_ci 几率。当一系列补丁必须移动到新基时,请选择移动到一个稳定节点(例如-rc版本 6362306a36Sopenharmony_ci 节点)。 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci - 请知悉对补丁系列进行变根(或做明显的历史修改)会改变它们的开发环境,且很 6662306a36Sopenharmony_ci 可能使做过的大部分测试失效。一般来说,变基后的补丁系列应当像新代码一样对 6762306a36Sopenharmony_ci 待,并重新测试。 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci合并窗口麻烦的一个常见原因是,Linus收到了一个明显在拉取请求发送之前不久才变根 7062306a36Sopenharmony_ci(通常是变根到随机的提交上)的补丁系列。这样一个系列被充分测试的可能性相对较 7162306a36Sopenharmony_ci低,拉取请求被接受的几率也同样较低。 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci相反,如果变基仅限于私有树、提交基于一个通用的起点、且经过充分测试,则引起 7462306a36Sopenharmony_ci麻烦的可能性就很低。 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci合并 7762306a36Sopenharmony_ci==== 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci内核开发过程中,合并是一个很常见的操作;5.1版本开发周期中有超过1126个合并 8062306a36Sopenharmony_ci——差不多占了整体的9%。内核开发工作积累在100多个不同的子系统树中,每个 8162306a36Sopenharmony_ci子系统树都可能包含多个主题分支;每个分支通常独立于其他分支进行开发。因此 8262306a36Sopenharmony_ci在任何给定分支进入上游储存库之前,至少需要一次合并。 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci许多项目要求拉取请求中的分支基于当前主干,这样历史记录中就不会出现合并提交。 8562306a36Sopenharmony_ci内核并不是这样;任何为了避免合并而重新对分支变基都很可能导致麻烦。 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci子系统维护人员发现他们必须进行两种类型的合并:从较低层级的子系统树和从其他 8862306a36Sopenharmony_ci子系统树(同级树或主线)进行合并。这两种情况下要遵循的最佳实践是不同的。 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci合并较低层级树 9162306a36Sopenharmony_ci-------------- 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci较大的子系统往往有多个级别的维护人员,较低级别的维护人员向较高级别发送拉取 9462306a36Sopenharmony_ci请求。合并这样的请求执行几乎肯定会生成一个合并提交;这也是应该的。实际上, 9562306a36Sopenharmony_ci子系统维护人员可能希望在极少数快进合并情况下使用 ``-–no-ff`` 标志来强制添加 9662306a36Sopenharmony_ci合并提交,以便记录合并的原因。 **任何** 类型的合并的变更日志必须说明 9762306a36Sopenharmony_ci*为什么* 合并。对于较低级别的树,“为什么”通常是对该取所带来的变化的总结。 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci各级维护人员都应在他们的拉取请求上使用经签名的标签,上游维护人员应在拉取分支 10062306a36Sopenharmony_ci时验证标签。不这样做会威胁整个开发过程的安全。 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci根据上面列出的规则,一旦您将其他人的历史记录合并到树中,您就不得对该分支进行 10362306a36Sopenharmony_ci变基,即使您能够这样做。 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci合并同级树或上游树 10662306a36Sopenharmony_ci------------------ 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci虽然来自下游的合并是常见且不起眼的,但当需要将一个分支推向上游时,其中来自 10962306a36Sopenharmony_ci其他树的合并往往是一个危险信号。这种合并需要仔细考虑并加以充分证明,否则后续 11062306a36Sopenharmony_ci的拉取请求很可能会被拒绝。 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci想要将主分支合并到存储库中是很自然的;这种类型的合并通常被称为“反向合并” 11362306a36Sopenharmony_ci。反向合并有助于确保与并行的开发没有冲突,并且通常会给人一种温暖、舒服的 11462306a36Sopenharmony_ci感觉,即处于最新。但这种诱惑几乎总是应该避免的。 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci为什么呢?反向合并将搅乱你自己分支的开发历史。它们会大大增加你遇到来自社区 11762306a36Sopenharmony_ci其他地方的错误的机会,且使你很难确保你所管理的工作稳定并准备好合入上游。 11862306a36Sopenharmony_ci频繁的合并还可以掩盖树中开发过程中的问题;它们会隐藏与其他树的交互,而这些 11962306a36Sopenharmony_ci交互不应该(经常)发生在管理良好的分支中。 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci也就是说,偶尔需要进行反向合并;当这种情况发生时,一定要在提交信息中记录 12262306a36Sopenharmony_ci*为什么* 。同样,在一个众所周知的稳定点进行合并,而不是随机提交。即使这样, 12362306a36Sopenharmony_ci你也不应该反向合并一棵比你的直接上游树更高层级的树;如果确实需要更高级别的 12462306a36Sopenharmony_ci反向合并,应首先在上游树进行。 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci导致合并相关问题最常见的原因之一是:在发送拉取请求之前维护者合并上游以解决 12762306a36Sopenharmony_ci合并冲突。同样,这种诱惑很容易理解,但绝对应该避免。对于最终拉取请求来说 12862306a36Sopenharmony_ci尤其如此:Linus坚信他更愿意看到合并冲突,而不是不必要的反向合并。看到冲突 12962306a36Sopenharmony_ci可以让他了解潜在的问题所在。他做过很多合并(在5.1版本开发周期中是382次), 13062306a36Sopenharmony_ci而且在解决冲突方面也很在行——通常比参与的开发人员要强。 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci那么,当他们的子系统分支和主线之间发生冲突时,维护人员应该怎么做呢?最重要 13362306a36Sopenharmony_ci的一步是在拉取请求中提示Linus会发生冲突;如果啥都没说则表明您的分支可以正常 13462306a36Sopenharmony_ci合入。对于特别困难的冲突,创建并推送一个 *独立* 分支来展示你将如何解决问题。 13562306a36Sopenharmony_ci在拉取请求中提到该分支,但是请求本身应该针对未合并的分支。 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci即使不存在已知冲突,在发送拉取请求之前进行合并测试也是个好主意。它可能会提醒 13862306a36Sopenharmony_ci您一些在linux-next树中没有发现的问题,并帮助您准确地理解您正在要求上游做什么。 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci合并上游树或另一个子系统树的另一个原因是解决依赖关系。这些依赖性问题有时确实 14162306a36Sopenharmony_ci会发生,而且有时与另一棵树交叉合并是解决这些问题的最佳方法;同样,在这种情况 14262306a36Sopenharmony_ci下,合并提交应该解释为什么要进行合并。花点时间把它做好;会有人阅读这些变更 14362306a36Sopenharmony_ci日志。 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci然而依赖性问题通常表明需要改变方法。合并另一个子系统树以解决依赖性风险会带来 14662306a36Sopenharmony_ci其他缺陷,几乎永远不应这样做。如果该子系统树无法被合到上游,那么它的任何问题 14762306a36Sopenharmony_ci也都会阻碍你的树合并。更可取的选择包括与维护人员达成一致意见,在其中一个树中 14862306a36Sopenharmony_ci同时进行两组更改;或者创建一个主题分支专门处理可以合并到两个树中的先决条件提交。 14962306a36Sopenharmony_ci如果依赖关系与主要的基础结构更改相关,正确的解决方案可能是将依赖提交保留一个 15062306a36Sopenharmony_ci开发周期,以便这些更改有时间在主线上稳定。 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci最后 15362306a36Sopenharmony_ci==== 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci在开发周期的开头合并主线是比较常见的,可以获取树中其他地方的更改和修复。同样, 15662306a36Sopenharmony_ci这样的合并应该选择一个众所周知的发布点,而不是一些随机点。如果在合并窗口期间 15762306a36Sopenharmony_ci上游分支已完全清空到主线中,则可以使用以下命令向前拉取它:: 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci git merge v5.2-rc1^0 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci“^0”使Git执行快进合并(在这种情况下这应该可以),从而避免多余的虚假合并提交。 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci上面列出的就是指导方针了。总是会有一些情况需要不同的解决方案,这些指导原则 16462306a36Sopenharmony_ci不应阻止开发人员在需要时做正确的事情。但是,我们应该时刻考虑是否真的出现了 16562306a36Sopenharmony_ci这样的需求,并准备好解释为什么需要做一些不寻常的事情。 166