git - 如何防止 git 提交一组特定的本地更改
问题描述
我经常面临这样的情况,即我必须保留我从未真正想要git
提交的本地配置和小代码更改——例如API_BASE_URL
,我当前正在处理的功能的不同或一些模拟数据。据我所知,它不仅限于.env
文件能够涵盖的更改。
我主要是手动管理这些,但有时部分更改会滑入推送提交,这很烦人,并且可以通过更好的工具轻松避免。
有没有办法告诉git
(或者可能是 Visual Studio Code/Spacemacs)这个?
嘿,伙计,我有这些本地更改,我一直在摆弄,不要费心进行或提交这些。
谢谢!
解决方案
Git 内置的主要机制在这里可以提供帮助是使用涂抹和清洁过滤器。请参阅ElpieKay 在评论中链接的问答、分支之间的 git smudge/clean filter或直接跳转到VonC 的答案。
您的涂抹和清洁过滤器可以做任何您喜欢的事情:它们只是通用的文本过滤器。
当 Git 将文件从索引复制到您的工作树时,它将通过您的涂抹过滤器运行文本。污迹的文本将在您的工作树中可见。
当 Git 将文件从工作树复制到索引时,它将通过 clean 过滤器运行文本。清理后的文本将出现在文件的索引副本中。1 文件的索引副本将被提交。
当您从这个提交切换到其他提交时,如果该文件的另一个提交的副本与该提交的副本不同,Git 将首先将文件从另一个提交复制到索引(再次参见脚注 1),然后从工作树的索引,将提取的文本推送到涂抹过滤器。
该.gitattributes
文件列出了哪些文件通过哪些过滤器运行,您的主文件.git/config
或~/.gitconfig
文件描述了可用的过滤器程序。
另一种可能不适合您的特定情况的机制是,在从某个提交中提取文件到索引和您的工作树之后 - 即,在一些初始之后git checkout
- 您可以使用git update-index
特别标记文件的索引副本. 从此时起,比较索引副本和工作树副本的Git操作大多只是假设索引副本是正确的并且与工作树副本匹配。
您可以在此处设置的标志称为假定不变并跳过工作树。要设置一个这样的标志,您将使用. 这两个标志主要做同样的事情,但它们的内部用途不同:假设-未更改用于调用非常慢的系统,跳过它们,而跳过工作树用于稀疏结帐功能。如果您实际上使用的是稀疏结帐,Git 会自行打开和关闭这些位,因此您需要使用另一个标志。否则,一般建议是使用 skip-worktree 标志(但实际上两者实际上都一样)。git update-index --skip-worktree path
lstat
请注意,一旦您设置了这些标志之一,您所做的这一事实在很大程度上是不可见的。2 你必须记住你做到了。如果你忘记了,它会产生非常令人费解的行为。以这种方式使用这些位非常痛苦,因为在 Git确实需要替换文件的索引副本的情况下——例如,当切换到文件副本与当前加载到索引中的副本不匹配的提交时——Git确实需要覆盖索引副本,这意味着 Git 也想覆盖工作树副本。如果设置了标志并且工作树副本存在并且与索引副本不匹配,Git 将拒绝继续。要让 Git 继续运行,您通常需要关闭标志,以某种方式处理文件,切换提交,再次处理文件,再次打开标志,然后继续工作。
1索引中文件的“副本”实际上是存储库中的副本,以blob对象的形式存在。索引保存对 blob 对象的引用。如果并且当您进行新提交时,新提交将包含对同一 blob 对象的引用(通过树对象)。当你运行时git add
,Git 会清理文件,从结果中构建一个临时 blob 对象,找到它的 blob 哈希 ID,并确定该对象是否已经存在。如果对象已经存在,那么git add
基本上就完成了:我们只需要它的哈希 ID,并将其放入索引中。如果对象不存在,git add
将对象放入对象数据库中,现在我们完成了:新对象的哈希 ID 进入索引。
这意味着当您git add
在提交之前多次提交文件时,您可能会产生一些垃圾:未使用的 blob。垃圾最终会通过 Git 的git gc
. Git 一直在自己制造垃圾对象,因此无需担心这一点。此规则的例外情况是,如果您不小心添加了一些大文件,例如 500 GB 的文件。默认情况下,该垃圾对象将持续至少两周,从而占用大量磁盘空间。
2我编写了一个脚本 ,git-flagged
来查找(并且可以选择取消标记)我的文件。有时我发现自己处于一个恼人的境地,我不得不用 skip-worktree 标记一些文件一段时间,并记住它们在哪里是痛苦的,因此是脚本。现在我可以git flagged
更容易地跑去看他们了。