Git 中的分支特定行

Branch specific lines in Git

抱歉,我的问题太模糊了,但我真的不知道如何最好地描述这种情况。

在我的存储库中,README 文件包含一个 link,其中包含各个分支的分支名称 masterdevelop(只有这两个分支受到影响,我真的不在乎不同分支的处理方式)。我现在想要的是,如果我将 develop 合并到 master 中,这个差异将被保留。

到目前为止我所做的是使用

git merge --no-commit develop

并手动修复 link。这里的问题是,develop 有一个独立的 master 历史。因此,来自 develop 分支的 git describe 不包含 master 上的最新标签。然而,我使用它来进行版本控制,所以拥有它是必不可少的。解决方法是将 master 合并回 develop

git merge --no-commit master

然而,这导致了一个混乱的历史,因为我有很多这些空的反向合并。

我也尝试了 ,我在其中添加了 README.rst merge=ours。但是,这会忽略 所有 README 的更改,因此我必须手动更新 README 文件。

不知道有没有合适的方法。有没有办法告诉 GitHub 忽略 links(例如通过正则表达式)?或者可能是一些扩展到分支名称的命令?

你不能(完全)得到你想要的。您可能能够获得所需的东西,具体取决于您需要的地方。考虑使用 涂抹过滤器 在文件检出时更改文件。您需要相应的 clean filter 来去除污迹,以便实际提交中的内容是 un-smudged.

有关设置污迹和清洁过滤器的更多信息,请参阅 the gitattributes documentation

背景

首先,请记住 b运行ch name 只是指向(单个)提交的可移动指针。人们还使用 b运行ch 这个词来指代其他东西,即:一系列由特定提交结束的提交。 有关更多信息,请参阅 What exactly do we mean by "branch"?

一般来说,Git所做的是添加提交。你查了一些b运行ch name:

$ git checkout master

然后做一些工作(在 work-tree 中的文件上,然后将其复制到 暂存区 又名index 使用 git add 覆盖已经在索引中但与当前提交匹配的副本——我们稍后会回到所有这些):

... edit ...
$ git add README.rst

最终,你 运行 git commit,其中:

  • 收集您的日志消息;
  • 打包所有现在索引中的文件;和
  • 使用这些(加上您的姓名、电子邮件和时间)进行新的提交。

新提交的 parent 提交是您在 运行 git checkout master 签出的 提交。当您 运行 git checkout master。所以 name master 现在指向 new 提交,它指向回 master 提交只是一个刚才:

...  <-previous-tip-of-master  <-new-tip-of-master   <--master

您一次只能检出一个 b运行ch,git committhat b运行 上进行新提交ch——具体来说,通过使 name 指向刚刚提交的新提交 Git。所有其他 b运行ch 名称均未更改:它们仍然指向其他一些提交。

使用 git merge 仍然只是进行新的提交!这个新提交和 git commit 所做的其他新提交之间的区别在于这个新提交有 两个 parents:它像往常一样指向上一个提交,但它也指向您在 运行 git merge 时选择的提交。在任何情况下,这个新提交仅 on 你所在的 b运行ch:

...--B--...--o--C--M   <-- master
      \           /
       o--...-o--D   <-- develop

其中 M 是新的合并提交。这个新的合并提交有所有文件的快照,就像每个其他提交都有所有文件的快照一样,所以 M 中的 README.rst 文件是通过对 M 中的快照做一些事情来构建的=32=]——刚才是master的提示——还有D中的快照的东西,它仍然是develop的提示。这些 "somethings" 基于 CD 自快照中的 merge base 提交版本 README.rst 以来的变化提交 B.

利用它:涂抹和清洁过滤器

现在,除了关于创建者、创建时间以及使用何种日志消息的元数据外,每个 commit 都简单地记录索引中的所有源文件 / staging-area当时你运行git commit。当你 git checkout <thing-that-specifies-commit> 时得到的是 这个快照派生出来的,但不一定 这个快照相同。

所有这些细节都很重要! Git 会将 M 中的提交提取到索引 / staging-area 中。这个索引 / staging-area 中的内容此时 完全匹配 M 中的任何内容。但这不是您在 work-tree 中看到的。您在 work-tree 中看到的内容是通过 运行ning 通过您定义的任何 smudge 过滤器 复制到索引中的任何内容 Git 获得的。

默认的涂抹滤镜基本上是"leave everything unchanged"。您可以在此时进行 end-of-line 调整。从技术上讲,这与污迹过滤器是分开的,但它都是这个污迹过程的一部分。如果您使用此默认设置,则 work-tree 中的内容与索引中的内容相匹配。

不过,假设您定义了一个涂抹滤镜以专门应用于 README.rst。进一步假设您编写此涂抹过滤器以查找带有 link 的行,该行应该提到 b运行ch、masterdevelop。将您的污迹过滤器写入这一行替换为正确link。例如,也许您提交的行应该是:

blah blah link:!replace this part! blah

你的污迹过滤器说:

sed -e "s/!replace this part!/actual link using $branch/"

(使用 Linux/Unix/GNU sed 命令,但您可以随意编写)。使您的污迹过滤器代码找出要使用的 b运行ch 名称,例如 运行ning git rev-parse --abbrev-ref HEAD.

这意味着文件 README.rst 的 work-tree 中的内容将不再与实际 com 中的内容匹配itted.

不过,要使其正常工作,您需要让 git add 写成 thing-to-be-committed,一行内容为:

blah blah link:!replace this part! blah

要自动执行此操作,请自己编写一个 clean 过滤器来查找污迹线(无论您选择如何做)并替换它,例如,使用 sed , 带有 !replace this part! 文本。

现在当你 运行:

$ git add README.rst

Git 将 运行 work-tree 文件通过你的清理过滤器得到 README.rst 的版本写入索引 / staging-area.

这在合并时也有效:合并将 "see" 文件的 cleaned 版本,并合并您所做的任何更改,b运行ch,使用清理后的文本。具有实际 link 的 "dirty"(污迹)版本仅出现在 work-tree 中。它永远不会进入任何提交。

这是否满足您的需要取决于读取 link 的内容。如果读取 link,通过提取对 work-tree 的提交并使用涂抹过滤器,那么读取文件的那个东西将读取 dirtied-up 实际的 link。如果读取文件的东西以某种方式绕过所有这些并获取原始提交的内容,它将看到 "cleaned" link.

如果将清理过的link存储为适合大多数用途的版本,并且在使用时只需要指向develop而不是master的脏版本work-tree,即使在这种情况下,这也适用。