本文翻译自:Git - Difference Between 'assume-unchanged' and 'skip-worktree'
I have local changes to a file that I don't want to commit to my repository. 我对一个我不想提交到我的存储库的文件进行了本地更改。 It is a configuration file for building the application on a server, but I want to build locally with different settings. 它是用于在服务器上构建应用程序的配置文件,但我想在本地使用不同的设置进行构建。 Naturally, the file always shows up when i do 'git status' as something to be staged. 当然,当我将'git status'作为要上演的东西时,该文件总是显示出来。 I would like to hide this particular change and not commit it. 我想隐藏这个特定的更改而不是提交它。 I won't make any other changes to the file. 我不会对文件进行任何其他更改。
After some digging around, I see 2 options: 'assume-unchanged' and 'skip-worktree'. 经过一番挖掘后,我看到了两个选项:'假设未改变'和'跳过工作树'。 A previous question here talks about them but doesn't really explain their differences. 这里的前一个问题谈到了它们,但并没有真正解释它们之间的区别。 My question is this: how are the two commands different? 我的问题是:这两个命令有何不同? Why would someone use one or the other? 为什么有人会使用其中一个?
#1楼
参考:https://stackoom.com/question/vC0P/Git-假设未改变-和-跳过工作树-之间的区别
#2楼
You want skip-worktree
. 你想要skip-worktree
。
assume-unchanged
is designed for cases where it is expensive to check whether a group of files have been modified; assume-unchanged
是针对检查一组文件是否已被修改的情况而设计的; when you set the bit, git
(of course) assumes the files corresponding to that portion of the index have not been modified in the working copy. 当您设置该位时, git
(当然)假定在工作副本中尚未修改与该索引部分对应的文件。 So it avoids a mess of stat
calls. 所以它避免了一堆乱的stat
调用。 This bit is lost whenever the file's entry in the index changes (so, when the file is changed upstream). 只要索引中的文件条目发生更改(因此,当文件在上游更改时),此位就会丢失。
skip-worktree
is more than that: even where git
knows that the file has been modified (or needs to be modified by a reset --hard
or the like), it will pretend it has not been, using the version from the index instead. skip-worktree
:即使git
知道文件已被修改(或需要通过reset --hard
等修改),它也会假装它没有使用,而是使用索引中的版本。 This persists until the index is discarded. 这将持续到索引被丢弃。
There is a good summary of the ramifications of this difference and the typical use cases here: http://fallengamer.livejournal.com/93321.html . 这里有一个很好的总结分歧和典型用例: http : //fallengamer.livejournal.com/93321.html 。
From that article: 从那篇文章:
-
--assume-unchanged
assumes that a developer shouldn't change a file.--assume-unchanged
假定开发人员不应更改文件。 This flag is meant for improving performance for not-changing folders like SDKs. 此标志用于提高 SDK等不可更改文件夹的性能 。 -
--skip-worktree
is useful when you instruct git not to touch a specific file ever because developers should change it.--skip-worktree
当你指示git不要触摸特定文件时,--skip-worktree
非常有用,因为开发人员应该更改它。 For example, if the main repository upstream hosts some production-ready configuration files and you don't want to accidentally commit changes to those files,--skip-worktree
is exactly what you want. 例如,如果主存储库上游托管了一些生产就绪配置文件,并且您不想意外地提交对这些文件的更改,那么--skip-worktree
正是您想要的。
#3楼
Note: fallengamer did some tests in 2011 (so they may be outdated), and here are his findings : 注意: fallengamer在2011年进行了一些测试(因此它们可能已经过时),以下是他的发现 :
Operations 操作
- File is changed both in local repository and upstream 文件在本地存储库和上游都已更改
git pull
:git pull
:
Git preserves local changes anyway. 无论如何,Git都会保留本地更改。
Thus you wouldn't accidentally lose any data that you marked with any of the flags. 因此,您不会意外丢失任何标记有任何标志的数据。- File with
assume-unchanged
flag: Git wouldn't overwrite local file. 带有assume-unchanged
标志的文件:Git不会覆盖本地文件。 Instead it would output conflicts and advices how to resolve them 相反,它会输出冲突并建议如何解决它们 - File with
skip-worktree
flag: Git wouldn't overwrite local file. 带有skip-worktree
标志的文件:Git不会覆盖本地文件。 Instead it would output conflicts and advices how to resolve them 相反,它会输出冲突并建议如何解决它们
- File with
- File is changed both in local repository and upstream, trying to pull anyway 文件在本地存储库和上游都被更改,无论如何都要尝试拉
git stash
git pull
Usingskip-worktree
results in some extra manual work but at least you wouldn't lose any data if you had any local changes. 使用skip-worktree
导致一些额外的手动工作,但如果您有任何本地更改,至少不会丢失任何数据。- File with
assume-unchanged
flag: Discards all local changes without any possibility to restore them. 带有assume-unchanged
标志的文件:放弃所有本地更改,而无法恢复它们。 The effect is like 'git reset --hard
'. 效果就像'git reset --hard
'。 'git pull
' call will succeed 'git pull
'电话会成功 - File with
skip-worktree
flag: Stash wouldn't work onskip-worktree
files. 带有skip-worktree
标志的文件:Stash不适用于skip-worktree
文件。 'git pull
' will fail with the same error as above. 'git pull
'将失败并出现与上述相同的错误。 Developer is forced to manually resetskip-worktree
flag to be able to stash and complete the failingpull
. 开发人员被迫手动重置skip-worktree
标志,以便能够存储并完成失败的pull
。
- File with
- No local changes, upstream file changed 没有本地更改,上游文件已更改
git pull
Both flags wouldn't prevent you from getting upstream changes. 这两个标志都不会阻止您获得上游更改。 Git detects that you brokeassume-unchanged
promise and choses to reflect the reality by resetting the flag. Git检测到你打破了assume-unchanged
承诺,并选择通过重置标志来反映现实。- File with
assume-unchanged
flag: Content is updated, flag is lost. 带有assume-unchanged
标志的文件:内容已更新,标志丢失。
'git ls-files -v
' would show that flag is modified toH
(fromh
). 'git ls-files -v
'会显示该标志被修改为H
(来自h
)。 - File with
skip-worktree
flag: Content is updated, flag is preserved. 带有skip-worktree
标志的文件:内容已更新,标志已保留。
'git ls-files -v
' would show the sameS
flag as before thepull
. 'git ls-files -v
'将显示与pull
之前相同的S
标志。
- File with
- With local file changed 随着本地文件的改变
git reset --hard
Git doesn't touchskip-worktree
file and reflects reality (the file promised to be unchanged actually was changed) forassume-unchanged
file. Git没有触及skip-worktree
文件并且反映了assume-unchanged
文件的实际情况(承诺实际上未更改的文件已更改)。- File with
assume-unchanged
flag: File content is reverted. 带有assume-unchanged
标志的文件:还原文件内容。 Flag is reset toH
(fromh
). 标志重置为H
(从h
)。 - File with
skip-worktree
flag: File content is intact. 带有skip-worktree
标志的文件:文件内容完好无损。 Flag remains the same. 国旗保持不变。
- File with
He adds the following analysis: 他补充以下分析:
It looks like
skip-worktree
is trying very hard to preserve your local data . 看起来像skip-worktree
正在努力保存您的本地数据 。 But it doesn't prevent you to get upstream changes if it is safe. 但是,如果它是安全的,它不会阻止您获得上游更改。 Plus git doesn't reset the flag onpull
. 加上Git并不重置旗pull
。
But ignoring the 'reset --hard
' command could become a nasty surprise for a developer. 但忽略'reset --hard
'命令可能会成为开发人员的一个令人讨厌的惊喜 。Assume-unchanged
flag could be lost on thepull
operation and the local changes inside such files doesn't seem to be important to git. 在pull
操作中可能会丢失Assume-unchanged
标志,并且这些文件中的本地更改似乎对git不重要。
See: 看到:
Junio's (current git maintainer) comment regarding intent of
assume-unchanged
, Junio(当前的git维护者)关于assume-unchanged
意图的评论 ,In particular, Junio points out that changes to
assume-unchanged
files could accidentally be committed: "if Git can determine a path that is marked asassume-unchanged
has changed without incurring extra lstat(2) cost, it reserves the right to report that the path has been modified (as a result,git commit -a
is free to commit that change)." 特别是,Junio指出assume-unchanged
文件assume-unchanged
可能会被意外提交:“如果Git可以确定标记为assume-unchanged
的路径已更改而不会产生额外的lstat(2)成本,则它保留报告该权限的权利路径已被修改(因此,git commit -a
可以自由提交该更改)。“difference between
assume-unchanged
andskip-worktree
as discussed in git mailing list upon addition ofskip-worktree
patch .assume-unchanged
和skip-worktree
之间skip-worktree
如添加skip-worktree
补丁时在git邮件列表中所讨论的 。
He concludes: 他的结论是:
Actually neither of the flags is intuitive enough . 实际上这两个标志都不够直观 。
assume-unchanged
assumes that a developer shouldn't change a file.assume-unchanged
假定开发人员不应更改文件。 If a file was changed – then that change is not important. 如果文件已更改 - 那么该更改并不重要。 This flag is meant for improving performance for not-changing folders like SDKs. 此标志用于提高SDK等不可更改文件夹的性能。
But if the promise is broken and a file is actually changed, git reverts the flag to reflect the reality. 但是如果承诺被破坏并且文件实际被更改,git会恢复标志以反映现实。 Probably it's ok to have some inconsistent flags in generally not-meant-to-be-changed folders. 可能在一般意思不是要更改的文件夹中有一些不一致的标志是可以的。On the other hand
skip-worktree
is useful when you instruct git not to touch a specific file ever. 另一方面,当您指示git不要触摸特定文件时,skip-worktree
非常有用。 That is useful for an already tracked config file. 这对已经跟踪的配置文件很有用。
Upstream main repository hosts some production-ready config but you would like to change some settings in the config to be able to do some local testing. 上游主存储库托管一些生产就绪的配置,但您希望更改配置中的某些设置以便能够进行一些本地测试。 And you don't want to accidentally check the changes in such file to affect the production config. 并且您不希望意外检查此类文件中的更改以影响生产配置。 In that caseskip-worktree
makes perfect scene. 在这种情况下,skip-worktree
可以完美呈现场景。