首页 > 解决方案 > 如何防止 git 提交一组特定的本地更改

问题描述

我经常面临这样的情况,即我必须保留我从未真正想要git提交的本地配置和小代码更改——例如API_BASE_URL,我当前正在处理的功能的不同或一些模拟数据。据我所知,它不仅限于.env文件能够涵盖的更改。

我主要是手动管理这些,但有时部分更改会滑入推送提交,这很烦人,并且可以通过更好的工具轻松避免。

有没有办法告诉git(或者可能是 Visual Studio Code/Spacemacs)这个?

嘿,伙计,我有这些本地更改,我一直在摆弄,不要费心进行或提交这些

谢谢!

标签: gitversion-control

解决方案


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 pathlstat

请注意,一旦您设置了这些标志之一,您所做的这一事实在很大程度上是不可见的。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更容易地跑去看他们了。


推荐阅读