【问题标题】:Git is deleting an ignored file when i switch branches当我切换分支时,Git 正在删除一个被忽略的文件
【发布时间】:2021-02-17 16:13:15
【问题描述】:

我有一个忽略某个文件的分支(我们称之为B),而在其他一些分支(例如分支A)中不会忽略该文件。当我从分支 B 切换到分支 A,然后再切换回 B 时,文件已被删除。

这正常吗?我可以看到它是如何发生的,从某种意义上说,分支 B 认为它不存在,而分支 A 认为它存在,所以当我回到 B 时,它会“整理它”。但这有点烦人。

有什么建议吗?

【问题讨论】:

  • 有什么理由不能在所有分支中忽略它或将它包含在所有分支中?
  • 这里有个有趣的问题:如果你把它添加到分支A的.gitignore,然后又想把它添加到分支B的.gitignore,你必须checkout分支B,此时文件是已删除 - 在您有机会忽略它之前。您的工作目录中可能需要一个脏的 .gitignore,当您切换分支以避免文件被删除时,包含该文件
  • @Alison G:你的情况没有多大意义。为了使这一切发生,必须在分支 A 上跟踪文件。因此,您永远不会将其添加到分支 A 上的 gitignore。该文件被删除,因为它在一个分支上被跟踪,并且另一边不存在。忽略它的唯一影响是允许您从 B 转到 A 而不会被警告您正在覆盖工作树中的文件。
  • @Alison G - 是的,我认为这正是实际发生的事情。 @Jefromi 是的,也许这没有多大意义。我可能以错误的顺序处理事情。我有一个文件实际上列在 .gitignore 中,但也被跟踪。我注意到了这种差异,并将其从缓存文件列表中删除。然后我切换了分支,它从我切换到的分支中删除了它。
  • @ewall - 完全没有理由,当它发生时,我会在所有分支中忽略它。但它在我有机会之前删除了它。

标签: git


【解决方案1】:

由于唯一可行的解​​决方案是始终跟踪文件“f”,因此您只能在分支B 中添加smudge/clean processgitattributes filter driver

结帐时B:

  • 涂抹过程会改变:

    • f 的内容保存在一个临时文件中
    • f 的内容替换为一个fbis 文件(跟踪文件,对于分支B,将包含“Bf 内容”)
  • 干净的过程将:

    • f 内容(在B 中修改)保存在fbis 中(fbis 在分支f 的修改中提交f
    • 恢复f 内容(使用临时文件),这意味着f 未提交(在B 中被忽略)

您可以在分支B 中添加一个custom merge driver,这将在其他分支合并到B 时保护fbis
合并驱动程序将始终保留fbis 内容的B 版本,确保在签出分支B 时被忽略的文件f 恢复其内容。

由于这些驱动程序(过滤器和合并)未在其他分支中提交,因此文件“f”及其所有修改均在其他分支中提交。
在分支B 中,它的内容永远不会改变,但是只要签出B,对f 所做的“本地修改”仍然会恢复。

如果不需要恢复内容,则无需管理fbis
只要保留过滤器驱动程序,您就可以确保无论您对分支B 中的f 进行什么修改,这些更改都不会被提交,实际上会忽略f 的内容。

【讨论】:

  • 哇,@VonC 这是一个了不起的答案,非常感谢。我不确定我是否聪明到能理解它……等等,需要再来一杯咖啡……
  • 或者每个分支都有两个独立的工作目录,完全避免了结帐问题......类似于我所做的SVN分支模型。在不相关的注释上,有一段有趣的历史:blog.red-bean.com/sussman/?p=20
  • @DanielSokolowski 这实际上是可能的,因为 Git 2.5:stackoverflow.com/a/39626426/6309stackoverflow.com/a/30185564/6309
【解决方案2】:

这很正常,虽然我对它的一步感到有些惊讶。

当你从 B 切换到 A 时,git 看到文件必须更新以匹配 A 的版本,并默默地这样做,因为你忽略了它,说就分支 B 而言,文件没有事情。它必须这样做 - 唯一的选择是拒绝签出分支 A。(如果文件没有被忽略,它会拒绝,说“未跟踪的工作树文件''将被合并覆盖”。我真的很惊讶在这种情况下它也不会这样做。任何人都知道这是功能还是错误?)

当您切换回时,git 会看到分支 B 没有该文件,并将其删除。同样,它必须这样做。它无法读懂您的想法并意识到一分钟前被忽略的文件是您想要返回的文件 - 它只是为您提供分支 B 的内容,表明该文件不存在。

正如 ewall 在 cmets 中建议的那样,如果您希望文件在这些转换中幸存下来,则需要由所有分支跟踪它,或者在所有分支中忽略它。

【讨论】:

    【解决方案3】:

    回答

    如果你只忽略分支B中的文件,而不是分支A中的文件,那么当从A切换到B时,你无法阻止它被删除。

    但是,从您的 cmets 中,我看到您尝试忽略两个分支中的文件,但它仍然被删除。它可能仍在A 中跟踪。转到分支A 和 从索引中删除了被忽略的文件

    git rm --cached <file>
    

    如果您将分支 A 推送到您的存储库中,请小心。 This causes the file to get deleted on repository and other developers machines on their next git pull but not on your local。您可以在这些机器上拉取后添加文件。


    说明

    我遇到了完全相同的问题。这是发生在我身上的事情:

    1. 文件test.json 曾在B 中被跟踪。
    2. 我从B 创建了一个分支A(所以文件test.json 也在A 中跟踪)。
    3. 后来我忽略了分支B 中的文件test.json。但是 git 将继续跟踪任何已经被跟踪的文件。为了停止跟踪该文件,我将其从索引 git rm --cached foo/test.json 中删除。

    在这 3 个步骤之后,会发生以下情况:如果我在分支 B 中,则文件 test.json 存在。如果我切换到A,它仍然存在。如果我结帐回B,它就消失了。所以我注意到和你一样:

    从分支 B 的意义上说,我可以看到它会如何发生 认为它不存在,分支 A 认为它存在,所以当我去的时候 回到 B 它'收拾它'。但这有点烦人。

    我在分支A.gitignore 文件中添加了test.json,但在切换回B 时它仍然被删除。这是因为在我忽略它之前它是在A 中跟踪的。

    因此,您需要将其从分支A 中的索引中删除。然后它被AB 忽略和跟踪,当你从A 切换回B 时它不会被删除。

    【讨论】:

      【解决方案4】:

      忽略 git 中的文件并不意味着它们不再修订。您可以在 git 中签入和管理文件,并在 .gitignore 中忽略它。

      【讨论】:

        【解决方案5】:

        我遇到过类似的情况,我就是这样做的:

        我会调用 index.php 结帐时删除的文件。

        在您的 branch Abranch B 的 .gitignore 中删除忽略您的 index.php 的行,然后提交您的 .gitignore在两个分支中。

        branch A中,创建index.php的备份,删除并提交。

        branch A 中从您之前创建的备份中恢复 index.php 并在您的 .gitignore 中再次忽略 index.php 并提交这个。

        在你的 branch B 添加 index.php,忽略 .gitignore 中的文件,提交并开心。

        【讨论】:

          【解决方案6】:

          您可以将文件添加到文件夹中并忽略该文件夹。切换分支时文件不会被删除。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-03-11
            • 2021-03-27
            • 2016-12-18
            • 2018-12-29
            • 2011-02-12
            相关资源
            最近更新 更多