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

我有一个我不想提交到我的仓库的文件的本地更改。 这是一个用于在服务器上构build应用程序的configuration文件,但是我想用不同的设置在本地构build。 当然,当我把'git status'作为上演的东西的时候,这个文件总是显示出来。 我想隐藏这个特定的变化,而不是提交。 我不会对文件做任何其他更改。

经过一番挖掘,我看到了两个选项:“假设 – 不变”和“跳跃工作树”。 以前的问题在这里讨论,但并没有真正解释它们的区别。 我的问题是这两个命令如何不同? 为什么有人会使用这个或另一个?

你想skip-worktree

assume-unchanged是针对检查一组文件是否被修改是昂贵的情况而devise的; 当你设置这个位的时候, git (当然)会假定在这个工作拷贝中没有修改对应于那个索引部分的文件。 所以它避免了stat调用的混乱。 只要文件在索引中的条目发生更改(因此,文件在上游发生更改时),该位就会丢失。

skip-worktree是这样:甚至在git 知道文件已被修改(或者需要通过reset --hard进行修改reset --hard等)的情况下,它将假装它没有被使用,而是使用来自索引的版本。 这一直持续到索引被丢弃。

有一个很好的总结这种差异的分歧和典型的用例在这里: http : //fallengamer.livejournal.com/93321.html 。

从那篇文章:

  • --assume-unchanged假定开发人员不应该更改文件。 这个标志是为了改善像SDK一样不变的文件夹的性能
  • --skip-worktree是非常有用的,因为开发人员应该改变它,所以当你指示git不要触摸特定的文件时。 例如,如果主存储库上游托pipe了一些生产就绪的configuration文件,而您不希望意外提交这些文件的更改,则--skip-worktree正是您想要的。

注意: fallengamer在2011年做了一些testing(所以他们可能已经过时),这里是他的发现 :

操作

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

  • 文件在本地存储库和上游都被改变,无论如何都试图拉动
    git stash
    git pull
    使用skip-worktree导致一些额外的手动工作,但是如果您有任何本地更改,至less不会丢失任何数据。
    • 具有assume-unchanged标志的文件:丢弃所有本地更改,无法恢复它们。 效果就像' git reset --hard '。 ' git pull '电话会成功
    • 使用skip-worktree标志的文件:Stash不适用于skip-worktree文件。 ' git pull '会失败,同上面的错误一样。 开发人员被迫手动重置skip-worktree标志,以便能够skip-worktree并完成失败的pull

  • 没有本地更改,上游文件更改
    git pull
    这两个标志不会阻止你获得上游的变化。 Git检测到你违背了承诺,并通过重新设置标志来反映现实。
    • assume-unchanged标志的文件:内容被更新,标志丢失。
      ' git ls-files -v '会显示该标志被修改为H (从h )。
    • 带有skip-worktree标志的文件:内容被更新,标志被保存。
      ' git ls-files -v '会显示与之前相同的S标志。

  • 随着本地文件更改
    git reset --hard
    Git没有触及skip-worktree文件,并且反映了对于assume-unchanged文件实际上(承诺实际上assume-unchanged文件)。
    • assume-unchanged标志的文件:文件内容被恢复。 标志重置为H (从h )。
    • 带有skip-worktree标志的文件:文件内容完好无损。 国旗保持不变。

他补充说:

  • 它看起来像skip-worktree正在努力保存您的本地数据 。 但是如果它是安全的,它并不妨碍你获得上游的变化。 加上git不会重置pull的标志。
    但是忽略“ reset --hard ”命令对于开发者来说可能会是一个令人讨厌的惊喜

  • pull操作中, Assume-unchanged标志可能会丢失,而这些文件中的局部变化对于git来说似乎并不重要。

看到:

  • Junio(现在的git维护者)对于assume-unchanged意图的评论assume-unchanged
  • 在git邮件列表中添加skip-worktree补丁时, assume-unchangedskip-worktree之间skip-worktree

他总结说:

其实这两个标志都不够直观

  • assume-unchanged假定开发者不应该改变文件。 如果一个文件被改变 – 比这个改变不重要。 这个标志是为了改善像SDK一样不变的文件夹的性能。
    但是,如果承诺被破坏,文件实际上发生了变化,那么git会将标志反转回现实。 在一般意义上不可改变的文件夹中可能有一些不一致的标志是可以的。

  • 另一方面,当你指示git不触及特定的文件时, skip-worktree是有用的。 这对已经跟踪的configuration文件很有用。
    上游主版本库提供了一些生产就绪configuration,但是您想要更改configuration中的某些设置以便能够进行一些本地testing。 而且您不希望意外检查此类文件中的更改以影响生产configuration。 在这种情况下, skip-worktree是完美的场景。