我对不想提交到存储库的文件进行了本地更改。它是用于在服务器上构建应用程序的配置文件,但是我想在本地使用不同的设置进行构建。自然地,当我执行“ git status”作为要上演的内容时,文件总是显示出来。我想隐藏此特定更改而不提交。我不会对该文件进行任何其他更改。
经过一些挖掘之后,我看到两个选项:“假定不变”和“跳过工作树”。这里的上一个问题讨论了它们,但并没有真正解释它们之间的差异。我的问题是:这两个命令有何不同?为什么有人要使用另一个?
我对不想提交到存储库的文件进行了本地更改。它是用于在服务器上构建应用程序的配置文件,但是我想在本地使用不同的设置进行构建。自然地,当我执行“ git status”作为要上演的内容时,文件总是显示出来。我想隐藏此特定更改而不提交。我不会对该文件进行任何其他更改。
经过一些挖掘之后,我看到两个选项:“假定不变”和“跳过工作树”。这里的上一个问题讨论了它们,但并没有真正解释它们之间的差异。我的问题是:这两个命令有何不同?为什么有人要使用另一个?
Answers:
你要skip-worktree
。
assume-unchanged
用于检查一组文件是否已被修改的开销很大的情况;当您设置该位时,git
(当然)假定与索引的该部分相对应的文件尚未在工作副本中被修改。这样可以避免一团糟stat
。只要索引中的文件条目发生更改(因此,当文件在上游更改时),该位就会丢失。
skip-worktree
不仅如此:即使git
知道文件已被修改(或需要用a reset --hard
或类似方法修改),它也会假装它没有被修改,而是使用索引中的版本。这一直持续到索引被丢弃为止。
这里有一个很好的总结,介绍了这种差异的后果以及典型的用例:http : //fallengamer.livejournal.com/93321.html。
从那篇文章:
--assume-unchanged
假定开发人员不应更改文件。该标志旨在提高未更改的文件夹(如SDK)的性能。--skip-worktree
当您指示git永远不要触摸特定文件时很有用,因为开发人员应该更改它。例如,如果上游主存储库托管了一些生产就绪的配置文件,而您又不想意外地将更改提交到这些文件,--skip-worktree
则正是您想要的。--skip-worktree
效果并取消设置标志,可以使用--no-skip-worktree
选项。工作原理完全相同。如果手滑了并且标记了错误的文件,或者情况发生了变化并且以前跳过的文件不应该再被忽略,则这很有用。
--skip-worktree
和.git/info/exclude
文件之间的区别在于,前者甚至可以用于当前跟踪的文件。.git/info/exclude
就像一样.gitignore
,只会防止意外地将未跟踪的文件添加到索引,而不会更改已经跟踪的文件。
注意:fallengamer在2011年做了一些测试(所以它们可能已经过时了),这是他的发现:
运作方式
git pull
:assume-unchanged
标志的文件:Git不会覆盖本地文件。相反,它将输出冲突并提供解决方案的建议skip-worktree
标志的文件:Git不会覆盖本地文件。相反,它将输出冲突并提供解决方案的建议git stash
git pull
skip-worktree
assume-unchanged
标志的文件:丢弃所有本地更改,没有任何可能恢复它们。效果就像' git reset --hard
'。“ git pull
”调用会成功skip-worktree
标志的文件:“隐藏”不适用于skip-worktree
文件。“ git pull
”将失败,并出现与上述相同的错误。开发人员必须手动重置skip-worktree
标志才能存储和完成失败pull
。git pull
assume-unchanged
assume-unchanged
标志的文件:内容已更新,标志已丢失。git ls-files -v
”表示标志已修改为H
(从h
)。skip-worktree
标志的文件:内容已更新,标志已保留。git ls-files -v
将显示与S
之前相同的标志pull
。git reset --hard
skip-worktree
assume-unchanged
assume-unchanged
标志的文件:文件内容已还原。标志重置为H
(从h
)。skip-worktree
标志的文件:文件内容完整无缺。标志保持不变。 他添加了以下分析:
看起来skip-worktree
是很努力维护您的本地数据。但这并不会阻止您在安全的情况下进行上游更改。再加上git不会将标志重置为pull
。
但是,reset --hard
对于开发人员而言,忽略' '命令可能会成为一个令人讨厌的惊喜。
Assume-unchanged
可能会丢失该标志,pull
并且此类文件内的本地更改对git似乎并不重要。
看到:
Junio(现任git维护者)关于的意图的评论assume-unchanged
,
特别是,Junio指出,assume-unchanged
可能会意外地提交对文件的更改:“如果Git可以确定标记为assume-unchanged
已更改的路径而不会产生额外的lstat(2)费用,它保留报告该路径
已被修改的权利(因此,git commit -a
可以自由地进行更改)。”
assume-unchanged
和之间的区别,skip-worktree
如添加skip-worktree
补丁后git邮件列表所述。
他得出结论:
实际上,两个标志都不足够直观。
assume-unchanged
假设开发人员不应该更改文件。如果文件已更改–那么该更改并不重要。该标志旨在提高未更改的文件夹(如SDK)的性能。
但是,如果没有兑现承诺,并且实际上已更改了文件,则git会将标志还原以反映实际情况。在通常不希望更改的文件夹中有一些不一致的标志可能是可以的。
另一方面skip-worktree
,当您指示git永远不要触摸特定文件时,它很有用。这对于已经跟踪的配置文件很有用。
上游主存储库托管一些可用于生产的配置,但是您希望更改配置中的某些设置以能够进行一些本地测试。而且您不想意外检查此类文件中的更改以影响生产配置。在这种情况下,skip-worktree
制作完美的场景。
在Git 2.25.1(2020年2月)中,上述“实际上两个标记都不足够直观”进一步阐明:
参见brian m的commit 7a2dc95和commit 1b13e90(2020年1月22日)。卡尔森(bk2204
)。
(由Junio C gitster
Hamano合并--在commit 53a8329中,2020年1月30日)
(Git邮件列表)
doc
:阻止用户尝试忽略跟踪的文件签字人:杰夫·金
签字人:brian m。卡尔森用户通常会忽略对Git跟踪的文件所做的更改。
这种情况的常见情况是IDE设置和配置文件,通常不应使用模板机制对它们进行跟踪,而应该从跟踪的文件中生成它们。
但是,用户了解假设不变和跳过工作树位,并尝试使用它们来执行此操作。
这是有问题的,因为设置这些位后,许多操作会按照用户期望的方式运行,但是当
git checkout
需要替换文件时,它们通常无济于事。在这种情况下,没有明智的行为,因为有时数据是宝贵的,例如某些配置文件,有时用户会乐意丢弃无关紧要的数据。
由于这不是受支持的配置,并且用户容易出于意料之外的目的滥用现有功能,从而引起普遍的悲伤和困惑,因此,让我们在文档中记录现有行为和陷阱,
git update-index
以便用户知道他们应该探索替代解决方案。另外,由于在许多环境中成功使用了众所周知的方法,因此让我们提供一种推荐的解决方案来处理配置文件的常见情况。
该git update-index
手册页现在包括:
用户经常尝试使用
assume-unchanged
和skip-worktree
位来告诉Git忽略对跟踪文件的更改。这不能按预期方式工作,因为在执行某些操作时,Git可能仍会根据索引检查工作树文件。通常,Git不提供忽略跟踪文件更改的方法,因此建议使用替代解决方案。例如,如果要更改的文件是某种配置文件,则存储库可以包含样本配置文件,然后可以将其复制到忽略的名称中并进行修改。该存储库甚至可以包含一个脚本,以将示例文件视为模板,并自动对其进行修改和复制。
.gitignore
用于类似目的。该解决方案对您有用吗?