Git 忽略对单行的更改

Git ignore changes to a single line

我知道如何使用 git 属性完全忽略 git 中的特定行(参见 How to tell git to ignore individual lines, i.e. gitignore for specific lines of code),但我将如何忽略 changes 到特定行?

我假设我们可以非常相似地使用过滤器,但我不知道我的 sed 脚本应该做什么来忽略对该行的更改。

举一个实际的例子,我正在编写一个 C# 库,它需要一个特定的构建输出路径,具体取决于它用作子模块的项目。因此,无论在何处使用它都必须手动配置,但不得将更改提交给库本身。

原文Library.csproj:

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    ...
    <OutputPath>bin\Debug\</OutputPath>
    ...
</PropertyGroup>

子模块 Library.csproj:

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    ...
    <OutputPath>..\Target\</OutputPath>
    ...
</PropertyGroup>

如何让 git 忽略对此行的更改?

使用git,无法忽略一行代码。一旦文件被跟踪,整个文件就会被索引。

调用您的项目的周围代码不应更改生成位置的输出,而应将生成的输出复制到正确的位置。这样你就不会破坏子模块的完整性。

如果您需要动态更改构建的输出位置,您可以使用在构建之前设置的环境变量。这样,您可以通过更改环境变量的值来更改该位置。

对于这种非常特殊的情况,您可以将清洁过滤器设置为 行替换为 标准默认值 行。也就是说,您将读取传入的 XML 数据流,找到一个项目,替换它,然后生成新流(生成为全新的 XML,或者在运行时即时生成).

虽然这整个想法很糟糕。这意味着用户的私人配置存储在他们现有的工作树中,在一个 Git 覆盖的文件中。也就是说,在某些情况下,Git会被告知不可挽回地销毁用户的配置,而Git会服从,销毁配置。要将其放回原处,您不仅需要 清洁过滤器,还需要 涂抹过滤器。涂抹过滤器必须从某处获取正确的配置数据——这个不能是正在被销毁并立即重新创建的文件——并将其放入数据流中。

因此,该配置必须存储在某些其他文件中,Git 不会 覆盖,要么完全在工作树之外,要么从未提交。在这种情况下,您还不如从其他文件中读取值。因此,只需使用该文件即可。有关此替代方案,请参阅

另一方面,考虑读取主要 XML 数据:

<OutputPath type="indirect">/etc/oursoftware.d/config.output</OutputPath>

例如,表示此处的输出 "path" 是另一个文件的名称 - 在本例中 /etc/oursofware.d/config.output - 用户将配置为包含输出路径。或者,如果环境变量可用:

<OutputPath type="envvar">$OURSOFTWARE_OUTPUT_PATH</OutputPath>

表示软件要运行为:

OURSOFTWARE_OUTPUT_PATH=/path/to/file.ext program

例如。 请注意,您必须更改 C# 程序,使其能够理解这些新的 XML 控件。

几个小时后,结合我此时的两个答案和我的解决方案的一些补充研究,这就是我到达的地方:

问题本身的答案:实际上不可能忽略对行的更改

您不能忽略对单行的更改。我在问题中引用的页面仅讨论如何从提交中删除一行,而不是忽略更改。最好的替代方法是挂钩一些东西,当你推动时用其他东西替换线,并且在你拉动时必须放回最初删除的东西,这是可能的但非常乏味。 (参见 Git Attributes Documentation 中的 "clean" 和 "smudge")


至于我选择用于构建问题的解决方案,我决定编写一个小的批处理脚本,运行 as Post Build Event,它将构建的文件复制到目标目录,其路径在文件中定义,从 git 忽略以允许模块化。


Luis Silva 提出的另一个不错的解决方案是使用 .csproj.template 文件并将 .csproj 添加到 gitignore。可以复制和修改模板以适应实施的需要。