如何仅自动跟踪 git 分支上的特定文件

sti*_*ate 3 git version-control branch branching-and-merging

我有一个 master 分支和几个工作分支,每个分支都应该实现一个特定的功能,然后合并到 master 中并删除。

我遇到的问题是工作分支跟踪所有也在 master 上的文件,每当 master 更新时,我必须手动将 master 合并到所有其他工作分支以保持它们最新,即使没有与工作分支功能相关的文件受到影响。

是否有一种策略,我只能跟踪分支上的特定文件,而让其他文件可以自由地由其他分支更新?有没有比使用 .gitignore 更好的方法,它总是必须手动更新以忽略/包含特定文件?我只想自动跟踪那些在该分支上提交了更改的文件。

Mar*_*ger 5

无论出于何种原因,我看到越来越多关于此建议工作流程的问题。它总是会导致问题。我将讨论如何接近您的要求,但我还将讨论为什么它总是会导致问题。

首先让我们解决这个问题:你提到.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那样),您可以创建一个“主存储库”并使用子模块将每个项目联系起来。

在某些代码被共享的情况下,您仍然应该将每个“特定于分支”的代码集视为自己的项目(应该有自己的存储库),此外您应该将共享代码视为自己的项目。然后使用构建工具声明对来自特定项目的共享代码的依赖关系。

这不仅让您摆脱了与源代码控制工具的粒度相悖的工作(当您尝试解决不是源代码控制的问题时),它还为您提供了大量的能力(在构建复杂构建的能力方面)基础设施),您甚至可能没有意识到自己丢失了。