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

ckb*_*ckb 400 git git-index

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

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

Bor*_*lid 588

你想要的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正是您想要的.

  • 一个小笔记,可以节省几秒钟的搜索和阅读时间.要取消`--skip-worktree`效果并取消设置标志,可以使用`--no-skip-worktree`选项.工作方式完全相同.如果手牌滑动且标记错误的文件,或者情况发生了变化并且以前跳过的文件不再被忽略,这非常有用. (87认同)
  • 回答上面我自己的问题,使用`--skip-worktree`和`.git/info/exclude`文件之间的区别在于前者甚至可以用于当前跟踪的文件.`.git/info/exclude`,如`.gitignore`,只会阻止意外地将未跟踪的文件添加到索引中,但不会对已经跟踪的文件进行更改. (14认同)
  • 这可以被推到遥控器并被所有克隆保存吗? (8认同)
  • 那讲得通.skip-worktree确实似乎是要走的路.谢谢! (3认同)
  • 您可以在[git-update-index(1)手册页](http://git-scm.com/docs/git-update-index)中找到有关这两个命令的更多信息. (3认同)
  • @CMCDragonkai如果您想要这样,只需.gitignore该文件并让开发人员在结账后从模板本地复制一次. (3认同)
  • 我发现将这些别名添加到我的 ~/.gitignore 文件中是值得的,以便它们在全球范围内可用。如果您编辑该文件,您可以将它们添加到 [alias] 部分。例如 ignore = update-index --skip-worktree (2认同)
  • 不幸的是,“-skip-worktree”和“-假定不变”都不允许切换到其他分支。我收到错误消息:`您对以下文件的本地更改将被checkout覆盖。详细信息[此处](/sf/ask/3544758591/) (2认同)
  • 只是[用法](https://medium.com/@igloude/git-skip-worktree-and-how-i-used-to-hate-config-files-e84a44a8c859),夫人:`git update-索引--skip-worktree <文件名>` (2认同)

Von*_*onC 95

注意:fallengamer在2011年进行了一些测试(因此它们可能已经过时),以下是他的发现:

操作

  • 文件在本地存储库和上游 都已更改
    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检测到你违反了承诺并选择通过重置标志来反映现实.
    git pull
    assume-unchanged
    • assume-unchanged标志的文件:内容更新,标志丢失.
      ' git ls-files -v'会显示该标志被修改为H(from h).
    • skip-worktree标志的文件:内容已更新,标志已保留.
      ' git ls-files -v'会显示与S之前相同的旗帜pull.

.

  • 随着本地文件的更改, Git不会触摸文件并反映文件的实际情况(实际上承诺保持不变的文件已更改).
    git reset --hard
    skip-worktreeassume-unchanged
    • assume-unchanged标志的文件:文件内容被还原.标志重置为H(从h).
    • skip-worktree标志的文件:文件内容完好无损.国旗保持不变.

他补充以下分析:

  • 看起来skip-worktree很努力维护您的本地数据.但是,如果它是安全的,它不会阻止您获得上游更改.加上git不会重置标志pull.
    但忽略这个reset --hard命令可能会成为开发人员的一个令人讨厌的惊喜.

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

看到:

他的结论是:

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

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

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

  • 如果你在文件上跳过了work -ree并且上游发生了变化,那么当你试图拉动时,你会得到"请提交或存储",即使git status没有将文件报告为已更改.你怎么能避免这种情况,所以当人们在原产地上进行生产设置时,本地变化会持续存在? (7认同)
  • 是的,我可以确认你这样做.这意味着拥有一个本地文件仍然非常困难,你只想保持与原点不同. (3认同)
  • @VonC如何解决“git pull”或“rebase”的“assume-changed”和“skip-worktree”,两者都会抛出**请提交或存储**,甚至“git status”什么也不显示 (2认同)

fri*_*itz 7

使用skip-worktree,如下所示:

\n
git update-index --skip-worktree changedfile.txt\n
Run Code Online (Sandbox Code Playgroud)\n

确认文件状态:

\n
 git ls-files -v\n S changedfile.txt\n
Run Code Online (Sandbox Code Playgroud)\n

第一个字母 S 表示该文件标有“skip-worktree”选项

\n

原因:

\n
\n

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

\n
\n

请参阅:https://github.com/git/git/commit/936d2c9301e41a84a374b98f92777e00d321a2ea

\n

--skip-worktree 解释:

\n

此选项会忽略对已跟踪文件的更改。无论对工作目录中的文件进行任何修改,git 始终使用索引中的文件内容和属性。\n这允许您对不希望推送到上游的文件进行更改。\n使用此命令选项如上所示。

\n

要取消设置此选项,请使用--no-skip-worktree以下命令:

\n
git update-index --no-skip-worktree changedfile.txt\n
Run Code Online (Sandbox Code Playgroud)\n

--假设不变解释:

\n

此选项是专门针对需要占用大量资源来检查某些文件是否已修改的用例而设计的。为了优化慢速文件系统上的资源使用,git 不会检查文件以查看有问题的文件是否已更改,它假定工作目录中的文件没有被修改。\n每当文件的索引中的条目发生变化。例如,当上游修改文件时。

\n

它的使用方法如下:

\n
git update-index --assume-unchanged changedfile.txt\n
Run Code Online (Sandbox Code Playgroud)\n

确认文件状态:

\n
git ls-files -v\nh changedfile.txt\n
Run Code Online (Sandbox Code Playgroud)\n

第一个字母 h 表示该文件标记有假定未更改的选项\n要取消设置此选项,请按\xe2\x80\x93no-assume-unchanged以下方式使用:

\n
git update-index --no-assume-unchanged changedfile.txt\n
Run Code Online (Sandbox Code Playgroud)\n

  • 这只会发生在你身上,对吧?其他开发人员也必须这样做。我的用例是一个 ENV 文件,其中包含开发人员必须为其个人设置填写的虚拟值。 (2认同)