Git - '假设未改变'和'跳过工作树'之间的区别

时间:2012-11-29 17:00:26

标签: git git-index

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

经过一番挖掘后,我看到了两个选项:'假设未改变'和'跳过工作树'。上一个问题here谈到了它们,但并没有真正解释它们之间的区别。我的问题是:这两个命令有何不同?为什么有人会使用其中一个?

2 个答案:

答案 0 :(得分:517)

您想要skip-worktree

assume-unchanged适用于检查一组文件是否已被修改的情况;设置该位时,git(当然)假定在工作副本中未修改与该索引部分对应的文件。所以它避免了一堆stat次电话。只要索引中的文件条目发生变化(因此,当文件在上游更改时),该位就会丢失。

skip-worktree不止于此:即使git 知道文件已被修改(或需要由reset --hard等修改),它会假装它没有,使用索引的版本代替。这种情况一直持续到索引被丢弃为止。

此差异的后果和典型用例有一个很好的总结:http://fallengamer.livejournal.com/93321.html

从那篇文章:

  • --assume-unchanged假设开发者不应更改文件。此标记用于提高性能,用于不更改SDK等文件夹。
  • --skip-worktree在您指示git不会触及特定文件时非常有用,因为开发人员更改它。例如,如果主存储库上游托管了一些生产就绪的配置文件,并且您不希望意外地提交对这些文件的更改,那么--skip-worktree正是您想要的。

答案 1 :(得分:84)

注意:fallengamer在2011年进行了一些测试(因此可能已过时),这是他的findings

<强>运营

  • 文件在本地存储库和上游中都已更改 的 git pull
    无论如何,Git都会保留当地的变化 因此,您不会意外丢失任何标记有任何标志的数据。
    • assume-unchanged 标记的文件:Git不会覆盖本地文件。相反,它会输出冲突并建议如何解决它们
    • skip-worktree 标记的文件:Git不会覆盖本地文件。相反,它会输出冲突并建议如何解决它们

  • 文件在本地存储库和上游都被更改,无论如何都试图拉 的 git stash
    git pull
    使用skip-worktree会产生一些额外的手动工作,但如果您有任何本地更改,至少不会丢失任何数据。
    • 带有 assume-unchanged 标记的文件:放弃所有本地更改,而无法恢复它们。效果就像'git reset --hard'。 “git pull”通话将成功
    • 带有 skip-worktree 标记的文件:Stash不适用于skip-worktree个文件。 “git pull”将失败并出现与上述相同的错误。开发人员被迫手动重置skip-worktree标志,以便能够存储并完成失败的pull

  • 没有本地更改,上游文件已更改
    git pull
    这两个标志都不会阻止您获得上游更改。 Git检测到您违反了assume-unchanged承诺并选择通过重置标志来反映现实。
    • 带有 assume-unchanged 标记的文件:内容已更新,标记已丢失 “git ls-files -v”会将该标记修改为H(来自h)。
    • 带有 skip-worktree 标记的文件:内容已更新,标记已保留 “git ls-files -v”会显示与S之前相同的pull标记。

  • 本地文件已更改
    git reset --hard
    Git没有触及skip-worktree文件,反映了assume-unchanged文件的实际情况(承诺实际上未更改的文件已更改)。
    • 带有 assume-unchanged 标记的文件:文件内容已恢复。标记重置为H(来自h)。
    • 带有 skip-worktree 标记的文件:文件内容完好无损。国旗保持不变。

他补充了以下分析:

  • skip-worktree 似乎非常努力地保留您的本地数据。但是,如果它是安全的,它不会阻止您获得上游更改。加上git不会重置pull上的标志 但忽略“reset --hard”命令可能会成为开发人员的一个令人讨厌的意外

  • Assume-unchanged标志可能会在pull操作中丢失,而这些文件中的本地更改似乎对git不重要。

请参阅:

他总结道:

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

  • assume-unchanged 假定开发人员不应更改文件。如果文件被更改 - 那个更改并不重要。此标志用于提高SDK等不更改文件夹的性能 但是如果承诺被破坏并且文件实际被更改,git会恢复标志以反映现实。可能在一般意思不是要更改的文件夹中有一些不一致的标志是可以的。

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