【问题标题】:How can I make git ignore future revisions to a file?如何让 git 忽略对文件的未来修订?
【发布时间】:2010-12-03 18:23:49
【问题描述】:

我创建了一个包含在 git 存储库中的文件的默认版本。重要的是,当有人克隆存储库时,他们会获得此文件的副本。但是,我想设置 git 以便稍后忽略对此文件的更改。 .gitignore 仅适用于未跟踪的文件。

我的动机是该文件包含特定于机器的信息。我想提供默认值,同时允许人们进行不会被推回原始存储库的本地更改,从而在我们拉取新更改时产生合并冲突。

我们通常很懒惰并且经常使用git add .,所以我很确定如果我不能告诉 git 忽略这个文件,对它的更改最终会被提交和推送。

总结一下,

  1. 我想创建一个文件,将其命名为 default_values.txt,该文件将添加到我的 git 存储库中,并在有人克隆该存储库时包含在内。
  2. git add . 不应将 default_values.txt 添加到提交中。
  3. 应该将此行为传递给存储库的任何克隆。

【问题讨论】:

  • 如果修改的文件是 default_values.txt(比如说),你能利用 git 钩子来有一个 pre-commit 钩子来中止提交吗?
  • Git 纯粹主义者会说不要偷懒,正确使用暂存区,这就是它的用途。
  • Git 纯粹主义者会说使用涂抹/清洁脚本。这是最易于维护的解决方案。
  • Xint0:真。但是如何防止其他人不小心签到呢?

标签: git gitattributes


【解决方案1】:

正如许多其他人所提到的,一个好的现代解决方案是:

git update-index --skip-worktree default_values.txt

这将忽略对该文件的本地和上游更改,直到您决定再次允许它们:

git update-index --no-skip-worktree default_values.txt

您可以获取标记为已跳过的文件列表:

git ls-files -v . | grep ^S

请注意,与 --skip-worktree 不同,一旦拉取上游更改,--assume-unchanged 状态就会丢失。

【讨论】:

  • 如果其他人提取 repo 并编辑文件,是否会忽略其目录中的更改?我希望他们必须输入 --no-skip-worktree 来添加他们的更改。
  • 对他们所做的更改是由他们控制的。换句话说,如果他们不想推送他们的更改,他们将不得不在他们的 repo 中的文件上设置 skip-worktree。如果该文件旨在发送给所有人,然后忽略所有后续更改,则每个人都必须遵循这些相同的说明。
  • 请注意,如果同一文件在另一个分支中被跟踪,您可能必须先撤消文件的--skip-worktree 状态才能切换分支。
  • 嗯,它可以工作...在我对文件进行了一些更改后,它没有显示在git status 中,但是当我尝试结帐到不同的分支时,我得到了error: Your local changes to the following files would be overwritten by checkout: ,甚至-f 没有帮助error: Entry 'wix-stores-merchant-app/demo/credentials.js' not uptodate. Cannot merge.
  • 我将这些别名设置为 git ignoregit unignore
【解决方案2】:

您要搜索的是git update-index --assume-unchanged default_values.txt

有关详细信息,请参阅文档:http://www.kernel.org/pub/software/scm/git/docs/git-update-index.html

【讨论】:

  • 这不起作用。虽然它使 git add 。忽略本地分支上的文件,存档的克隆没有此行为(如果您更改克隆存档中的 default_values.txt,它将使用“git add.”添加到提交中)
  • 是的,因为您只是为本地存储库设置它。你不能推送这种信息。
  • @Indradhanush - 这个解决方案不满足标准 3 - “行为应该传递给存储库的任何克隆” - 这就是我不接受它的原因。并不意味着这不是一个好的答案。
  • 我从未注意到第三个标准。因为我不是在寻找它。 :)
  • 对于具有私有应用设置的本地配置文件,您可能希望使用skip-worktree 而不是assume-unchanged 更多信息stackoverflow.com/questions/13630849/…
【解决方案3】:

我通常看到的方法是创建一个具有不同名称的文件,例如:default_values_template.txt 并将 default_values.txt 放入您的 .gitignore。指示人们将 default_values_template.txt 复制到其本地工作区中的 default_values.txt 并根据需要进行更改。

【讨论】:

  • hmmm... 如果 default_values 不存在,也许我可以编写一个钩子来自动将 default_values_template 复制到 default_values?
  • 根据我的经验,这是解决此问题的最常见方法。这几乎是阻力最小的路径,因为它“正常工作”,您可以轻松地让您的代码检查本地配置文件是否存在,如果不存在则提供有用的错误。
  • 我认为解决方案确实是做这样的事情,最好是在拉取或克隆时执行脚本。一个想法是,任何具有特定扩展名(比如 .basefile)的东西都被复制到一个扩展名被删除的文件中,然后文件名被添加到该目录中的 .gitignore 中。所以我会创建一个文件 default_values.txt.basefile 并提交它。我没有 git 或 perl 能力来做这件事,但我会问一个有能力的朋友,让你知道它是如何工作的。
  • @AdamDymitruk:是的,在这种情况下可以使用 clean/smudge,但尚不清楚这是最佳选择。例如,如果人们真的想要更改文件,这将变得相当困难,因为清洁/涂抹会妨碍。我实际上更喜欢这里描述的方法。
  • 我从 git 本身(特别是 git 钩子)中得到启发,并使用 .sample 后缀。所以在你的情况下default_values.txt.sample
【解决方案4】:

看看涂抹/清洁脚本。这样您可以对文件进行版本控制,但是当它被检出时,您将通过用文件中的机器特定数据替换通用/占位符数据来“涂抹”它。

当您提交它时,您将通过用通用或占位符信息替换机器特定信息来“清理”它。

涂抹/清洁脚本必须具有确定性,因为以不同的顺序多次应用它们相当于只运行序列中的最后一个。

如果您需要公开您的存储库但内容可能包含敏感信息,则同样可以使用密码。

【讨论】:

  • 清洁和涂抹脚本是本地的还是回购的一部分?
  • 是的。 :) ...也就是说,您可以通过 repo 共享干净的污迹,但当它们包含敏感数据(如生产密码)时,这不是一个好主意。如果这不是问题,git 要求您显式启用脚本。否则,人们可能会通过 github 和其他共享 repos 对其他用户进行恶意操作。
  • 我需要阅读更多关于此的内容。基本上我想设置一个项目,它有一个默认的user.json,需要用每个开发人员的凭据覆盖,但我不希望开发人员意外签入他们的凭据。
  • 我会到处搜索干净的污迹示例脚本。看看会发生什么。另外,跳到 freenode 上的 git irc 房间。您会立即获得帮助。
【解决方案5】:

我已经通过定义“干净”过滤器来简单地在索引中对文件的内容进行分类来解决这个问题。

git show :path/to/myfile 应该只打印指定文件的索引内容,因此我们可以在脚本中使用它来将工作副本替换为索引中未触及的副本:

#! /bin/sh

git show :$1

将其设置为相关文件的“干净”过滤器(假设您已将其放在“discard_changes”中):

$ git config filter.ignore_myfile.clean "discard_changes path/to/myfile"
$ echo "path/to/myfile filter=ignore_myfile" >> .gitattributes

不幸的是,我无法找到一种方法将其推广到多个文件,因为无法从干净的脚本中判断我们正在处理哪个文件。当然,没有什么可以阻止您为每个文件添加不同的过滤规则,但它有点笨拙。

【讨论】:

  • 几乎可以理解。为什么,如果您已将过滤器添加到 .gitattributes 中的特定路径,您是否需要在命令“丢弃更改”中指定要操作的文件?为什么此命令不对您传入的任何文件进行操作?例如,如果在 .gitattributes 中,您将 */ProjectSettings.asset 指定为有问题的文件并应用了过滤器,则过滤器应该能够对 repo 中的任何该文件进行操作!如何做到这一点?
【解决方案6】:

我找到了适合我团队的解决方案。我们通过符号链接共享我们的 githooks,在将模板文件添加到 git 后,我​​添加了一个 pre-commit 挂钩,用于检查模板文件是否已被修改,如果是,我 git reset -- templatefile.txt。如果它是唯一更改的文件,我也会中止提交。

【讨论】:

    【解决方案7】:

    我建议研究子模块。如果您将机器特定的文件放在子模块中, git add 应该忽略它。

    【讨论】:

    • 这是个好主意,但是我也必须将单个文件存储库也放在 git 服务器上,这不是最佳的,只是因为我们使用的是 github 并且数量有限存储库。
    • @Marc 查看 Visual Studio Team Services、无限制的免费私人项目和 git 存储库。看板、工作项和错误跟踪、将签入与工作项相关联、管理 sprint(如果您进入 scrum 或其他项目类型)。除了它具有用于针对多个平台进行构建的出色构建工具之外,还有很多东西都是免费的。有些人抨击它是因为它的微软,但它在工具方面击败了 github 所提供的东西,而不仅仅是存储库托管。你可以免费做的事情是有限制的,但我很少超过。
    • @Marc 我发现真正方便的另一件事是我可以设置任意数量的帐户,所以如果我正在为想要拥有源代码控制的客户编写项目我可以创建一个帐户,用它来计划、设计和执行项目,完成后我可以将帐户的所有权传递给客户。
    猜你喜欢
    • 2014-10-24
    • 1970-01-01
    • 2010-10-13
    • 2014-11-12
    • 2010-12-07
    • 2012-03-21
    • 2011-07-17
    • 1970-01-01
    • 2021-09-16
    相关资源
    最近更新 更多