sti*_*ate 3 git version-control branch branching-and-merging
我有一个 master 分支和几个工作分支,每个分支都应该实现一个特定的功能,然后合并到 master 中并删除。
我遇到的问题是工作分支跟踪所有也在 master 上的文件,每当 master 更新时,我必须手动将 master 合并到所有其他工作分支以保持它们最新,即使没有与工作分支功能相关的文件受到影响。
是否有一种策略,我只能跟踪分支上的特定文件,而让其他文件可以自由地由其他分支更新?有没有比使用 .gitignore 更好的方法,它总是必须手动更新以忽略/包含特定文件?我只想自动跟踪那些在该分支上提交了更改的文件。
无论出于何种原因,我看到越来越多关于此建议工作流程的问题。它总是会导致问题。我将讨论如何接近您的要求,但我还将讨论为什么它总是会导致问题。
首先让我们解决这个问题:你提到.gitignore
. 它不会有帮助。如果您手动维护特定于分支的版本并不重要,它仍然无济于事。忽略规则只做一件事:它们保持未跟踪的文件未被跟踪(默认情况下)。它们不影响合并、获取、推送等。存储库中的内容不受.gitignore
.
所以...在 git 中,假设分支(尤其是将被合并的分支)是相同内容的不同版本。这或多或少意味着相同的文件集 - 而不是文件的子集。(“或多或少”,因为一个分支可能添加或删除了另一个分支中尚不存在的文件;但在这种情况下,假设后续合并将从另一个分支添加或删除该文件。)
我见过很多人尝试一种方法,在他们分支的地方,然后删除除一部分文件之外的所有文件。然后当他们合并时,这些文件被删除master
-当然会发生什么,他们告诉 git 分支工作包括删除这些文件。
一次提交是一个项目快照;这是 git 中的预期内容单位。(你可以争辩说对象是最基本的内容单元,在 git 的物理模型中我同意。但在 git 作为源控制的概念模型中,它是提交。)所以提交可以代表一致的项目的版本。您可以构建和测试任何提交。
(“但我可以独立构建每个分支上的代码子集!”那么你可能在同一个 repo 中有多个项目,应该重新审视它。稍后会详细介绍。)
所以在我进入“如何”讨论之前有几个问题:
您声明的担忧是您必须合并master
到所有分支以保持它们最新,即使该分支不关心修改后的文件。所以我的第一个问题是:为什么?如果分支不关心文件,它包含文件的过时版本有什么区别?当您合并或变基时,git 会知道分支版本已过时,因此似乎文件很重要(在这种情况下,您不能在分支上“没有它”)或不重要(在在这种情况下更新它不是合并的理由master
)。
我的第二个问题是:“那又怎样?”,因为即使你做决定合并master
,分支不会有该文件的冲突(因为它并不关心文件)。这是一个问题的唯一方法是,如果你在每次更新到 master 时抢先合并到每个分支......这会让我回到“为什么?”
不过还好。让我们假设您不相信并且有一个用例,您只需要拥有带有部分源代码的分支。
怎么做到呢?
正如我上面所说的,如果您从创建整个项目树开始,然后在分支上删除文件,那么您将度过一段糟糕的时光。合并 frommaster
将冲突,合并到master
,当它们不冲突时,将清除您仍然需要的文件master
。
您可以通过将分支创建为孤儿或作为“空”提交的子节点来做得更好master
。然后在相应的分支上创建每个子项目树。
现在,这更好,因为没有删除可以解决,但它仅在分支不相交时才有效 - 即不共享代码。如果他们要共享代码......你在哪里创建它?
在创建分支之前,您可以只在上创建共享代码master
。只有现在你有这样一种情况,共享代码的更新需要合并到分支,这将导致master
从其他分支合并的代码“溢出”,因为 git 逐渐将你纠正回所有与合并相关的分支的条件相同内容的版本。
这指向另一个问题:即使没有共享代码,您也无法合并master
到此模型中的分支(因为,再次,代码会“溢出”。因此,您还必须施加一些纪律,该代码仅被修改在分支上。如果您master
直接更新,或master
从外部源接收更新,您将无法将该更新应用到分支。
那么你应该怎么做呢?
在非常有限的情况下,每个分支都有一组不存在于其他分支中的文件,我已经概述了一个模型,该模型可能主要适用......但为什么要使用它?这没有意义。您拥有的是独立的代码库,因此只需将它们放在单独的存储库中即可。如果您希望一个协调分支将它们拉在一起(就像master
那样),您可以创建一个“主存储库”并使用子模块将每个项目联系起来。
在某些代码被共享的情况下,您仍然应该将每个“特定于分支”的代码集视为自己的项目(应该有自己的存储库),此外您应该将共享代码视为自己的项目。然后使用构建工具声明对来自特定项目的共享代码的依赖关系。
这不仅让您摆脱了与源代码控制工具的粒度相悖的工作(当您尝试解决不是源代码控制的问题时),它还为您提供了大量的能力(在构建复杂构建的能力方面)基础设施),您甚至可能没有意识到自己丢失了。