当前位置: 首页 > 知识库问答 >
问题:

Git - “假设不变”和“跳过工作树”之间的区别

锺伟志
2023-03-14

我对不想提交到存储库的文件进行了本地更改。它是用于在服务器上构建应用程序的配置文件,但我想使用不同的设置在本地构建。当然,当我执行“git status”作为要暂存的内容时,该文件总是会显示出来。我想隐藏此特定更改,而不是提交它。我不会对文件进行任何其他更改。

为了澄清,使用。gitignore不是我想要的,因为它只会阻止新文件的添加。我想忽略对存储库中已有文件的更改。

经过一番挖掘,我看到了 2 个选项:假设不变跳过工作树。前面的问题在这里谈到了它们,但并没有真正解释它们的差异。

这两个命令有何不同?为什么有人会使用其中一个?

共有3个答案

隗和裕
2023-03-14

使用跳过工作树,如下所示:

git update-index --skip-worktree changedfile.txt

确认文件状态:

 git ls-files -v
 S changedfile.txt

第一个字母S表示文件被标记为跳过工作树选项

原因:

“git-update-index--asury-未更改从来都不是为了忽略对跟踪文件的更改(只是为了节省一些统计数据)。所以不要建议将其作为实现这一目标的一种手段。”

参见:https://github.com/git/git/commit/936d2c9301e41a84a374b98f92777e00d321a2ea

--Skip-工作树解释:

此选项忽略对已跟踪文件的更改。git总是使用索引中的文件内容和属性,不管对工作目录中的文件做了什么修改。这允许您对不希望被推送到上游的文件进行更改。如上所示,使用此选项。

要取消设置此选项,请使用< code> - no-skip-worktree,如下所示:

git update-index --no-skip-worktree changedfile.txt

-假设-不变解释道:

例如,为了优化慢速文件系统上的资源使用,git不检查文件以查看有问题的文件是否更改,它假定文件在工作目录中没有被修改。每当文件在索引中的条目发生变化时,此标志就会丢失。例如,当文件在上游被修改时。

它的用法如下:

git update-index --assume-unchanged changedfile.txt

确认文件状态:

git ls-files -v
h changedfile.txt

第一个字母h表示文件被标记为假定不变选项要取消设置此选项,请使用-no-suxy-不变,如下所示:

git update-index --no-assume-unchanged changedfile.txt
益明朗
2023-03-14

注:法伦加默在2011年做了一些测试(所以它们可能已经过时了),以下是他的发现:

操作

  • 文件在本地存储库和上游
    git pull 中都发生了变化:
    Git 无论如何都会保留本地更改。
    因此,您不会意外丢失使用任何标志标记的任何数据。
    • 带有假定不变标志的文件:Git 不会覆盖本地文件。相反,它将输出冲突并建议如何解决冲突
    • 带有 skip-worktree 标志的文件:Git 不会覆盖本地文件。相反,它将输出冲突并建议如何解决冲突
    • 文件在本地存储库和上游都发生了更改,无论如何都会尝试提取
      git-stash
      git-pull
      使用跳过工作树
    • 带有的文件假定未更改标志:放弃所有本地更改,不可能恢复它们。效果类似于“<code>git reset--hard</code>”git pull'调用将成功
    • 带有跳过工作树标志的文件:Stash无法处理skip-worktreefilesgit pull'将失败,错误与上述相同。开发人员被迫手动重置跳过工作树标志,以便能够隐藏并完成失败的pull
    • 没有本地更改,上游文件更改
      git拉
      这两个标志都不会阻止您获得上游更改。Git检测到您违反了suxy-不变promise,并选择通过重置标志来反映现实。
      • 带有suxy-不变标志的文件:内容已更新,标志丢失。
        'git ls-file-v'将显示标志被修改为H(来自h)。
      • 带有跳过工作树标志的文件:内容已更新,标志保留。
        'git ls-file-v'将显示与拉取之前相同的S标志。
      • 随着本地文件的改变
        git重置--hard
        Git不会触摸Skip-WorkTree文件并反映现实(promise不变的文件实际上被改变了)为假设不变文件。
        • 带有假设不变标志的文件:文件内容被还原。标志被重置为H(来自h)。
        • 带有Skip-工作树标志的文件:文件内容完好无损。标志保持不变。

        他补充了以下分析:

        >

      • 它看起来像kip-工作树正在非常努力地保存您的本地数据。但是如果它是安全的,它并不阻止您获得上游更改。另外git不会重置上的标志。
        但是忽略'重置--hard'命令可能会成为开发人员的一个令人讨厌的惊喜。

        < code>Assume-unchanged标志可能会在< code>pull操作中丢失,并且此类文件中的本地更改似乎对git并不重要。

        请参见:

        >

      • Junio(当前git维护者)关于假设不变意图的评论,

        特别是,Junio指出,对假设未更改文件的更改可能会意外提交:“如果Git可以确定一个标记为assumentunchange的路径,而不会产生额外的lstat(2)成本,它保留报告该路径已被修改的权利(因此, 可以自由提交该更改)。”

        添加< code>skip-worktree补丁后,git邮件列表中讨论的< code>assume-unchanged和< code>skip-worktree之间的区别。

        他总结道:

        实际上,这两个标志都不够直观。

        >

      • 假设不变假定开发人员不应更改文件。如果文件已更改 - 则该更改并不重要。此标志旨在提高不更改文件夹(如 SDK)的性能。
        但是,如果promise被打破并且文件实际被更改,git 会还原标志以反映现实。在通常不打算更改的文件夹中有一些不一致的标志可能是可以的。

        另一方面,skip-worktree 在你指示 git 永远不要接触特定文件时很有用。这对于已跟踪的配置文件很有用。
        上游主存储库托管一些生产就绪的配置,但您希望更改配置中的某些设置以便能够进行一些本地测试。而且您不希望意外检查此类文件中的更改以影响生产配置。在这种情况下,skip-worktree可以制作完美的场景。

        在 Git 2.25.1(2020 年 2 月)中,上面提到的“实际上这两个标志都不够直观”得到了进一步澄清:

        请参阅提交 7a2dc95,提交 1b13e90(2020 年 1 月 22 日),作者:Brian M. Carlson (bk2204)。
        (由 Junio C Hamano -- gitster -- 合并于 提交 53a8329,2020 年 1 月 30 日
        (Git 邮件列表)

        签字人:Jeff King

        用户想要忽略对Git跟踪的文件的更改是很常见的。

        这种情况的常见方案是 IDE 设置和配置文件,通常不应跟踪它们,并且可能使用模板机制从跟踪的文件生成。

        但是,用户了解假设不变和跳过工作树位,并尝试使用它们来执行此操作。

        这是有问题的,因为当设置了这些位时,许多操作都会按照用户的预期进行,但当<code>git checkout</code>需要替换文件时,这些操作通常无济于事。

        在这种情况下没有明智的行为,因为有时数据很宝贵,例如某些配置文件,有时用户很乐意丢弃不相关的数据。

        由于这不是一种受支持的配置,而且用户很容易出于无意的目的滥用现有功能,从而导致普遍的悲伤和困惑,让我们在<code>git update index</code>的文档中记录现有行为和陷阱,以便用户知道他们应该探索其他解决方案。

        此外,让我们提供一个推荐的解决方案来处理配置文件的常见情况,因为在许多环境中成功使用了众所周知的方法。

        git 更新索引手册页现在包括:

        用户经常试图使用< code>assume-unchanged和< code>skip-worktree位来告诉Git忽略被跟踪文件的更改。这并不像预期的那样工作,因为在执行某些操作时,Git仍然可以根据索引检查工作树文件。一般来说,Git不提供忽略被跟踪文件更改的方法,所以建议使用替代解决方案。

        例如,如果您要更改的文件是某种配置文件,存储库可以包含一个示例配置文件,然后可以将其复制到忽略的名称中并进行修改。存储库甚至可以包含一个脚本,将示例文件视为模板,自动修改和复制它。

        最后一部分是我描述的基于污迹/清理脚本的典型内容筛选器驱动程序。

颛孙俊
2023-03-14

你想要跳过工作树

当您设置了这个位,git(当然)假定与索引的那一部分相对应的文件在工作副本中没有被修改,因此它避免了stat调用的混乱。每当文件在索引中的条目发生变化时(因此,当文件在上游发生变化时),这个位就会丢失。

< code>skip-worktree不仅仅是这样:即使< code>git知道文件已经被修改(或者需要通过< code>reset - hard之类的方式修改),它也会假装没有被修改,而是使用索引中的版本。这种情况一直持续到索引被丢弃。

这里很好地总结了这种差异的后果和典型用例:http://fallengamer.livejournal.com/93321.html。

从那篇文章中:

    --
  • aspute-unchanged 假设开发人员不应该更改文件。此标志用于提高不更改文件夹(如 SDK)的性能
  • --
  • skip-worktree 在指示 git 不要接触特定文件时很有用,因为开发人员应该更改它。例如,如果上游主存储库托管一些生产就绪的配置文件,并且您不想意外地将更改提交到这些文件,那么 --skip-worktree 正是您想要的。
 类似资料:
  • 本文向大家介绍图和树之间的区别,包括了图和树之间的区别的使用技巧和注意事项,需要的朋友参考一下 在编程中,数据类型表示打算由用户使用的数据的类型和性质。它是编译器或解释器要处理的数据类型,并在主存储器中提供相应的存储位置。现在,为了存储数据,我们根据数据的性质引入了不同的数据结构。由于数据主要分为线性和非线性类,因此专门针对非线性数据,存在图和树的概念来表示此类数据,以便更好地理解。 现在,由于用

  • 本文向大家介绍假脱机和缓冲之间的区别,包括了假脱机和缓冲之间的区别的使用技巧和注意事项,需要的朋友参考一下 在计算机性能方面,主要因素是多任务处理,即CPU如何在不同的输入输出子系统之间划分和执行进程。为了最有效地处理任务,计算机系统使用各种方法来计划任务,加快计算速度并改善Web浏览,其中假脱机和缓冲是主要方法。 以下是假脱机和缓冲之间的重要区别。 序号 键 假脱机 正在缓冲 1 定义 后台打印

  • 本文向大家介绍python中可变和不可变之间的区别?,包括了python中可变和不可变之间的区别?的使用技巧和注意事项,需要的朋友参考一下 Python定义了对象的各种数据类型。这些对象存储在内存中,对象的可变性取决于类型,例如列表和字典是可变的,这意味着我们可以更改其内容而无需更改其标识。其他对象,例如整数,浮点数,字符串和元组,都无法更改为索引分配的值。 List是可变的:List就像数组一样

  • 我已经使用<code>git-stash-pop<code>很久了。我最近发现了关于<code>git-stash-apply<code>命令的信息。当我尝试它时,它似乎与<code>git-stash-pop 和 有什么区别?

  • 我已经读了几遍这方面的文档,我仍然不能完全理解这些不同命令之间的区别。也许这只是我,但是文档可以更清晰: http://git-scm.com/docs/gitignore https://help.github.com/articles/ignoring-files 此外,许多关于这一主题的评论似乎使用了“索引”、“promise”和“跟踪”这几个词,这使得这三个词之间的区别不那么明显。 我目前

  • 我有一个文件,我已在签出时标记为假设不变。大多数命令(例如,、