忽略git中文件的特定更改,但不忽略整个文件

时间:2013-05-16 22:05:16

标签: git gitignore ignore

我在git存储库中有一个文件,它有一个本地更改。我想让git永远忽略本地更改,但不是文件。特别是,

  • 如果除了此更改之外未触及该文件,则git add .不应该暂存它。
  • 同样,git commit -a不应该提交它。
  • 如果我对文件进行了额外的更改,我应该可以暂存并提交更改 - 但是我忽略的更改应该上演并提交。

有办法做到这一点吗?做一些研究,我读到了“涂抹/清洁周期”,如果我读得正确,

  1. 文件将被标记为未更改
  2. 我结帐时所做的更改会被覆盖,
  3. 然后脚本会自动重新应用更改,然后再次将文件标记为未更改。
  4. 我是git和脚本编程的新手(虽然我是C#和Java经验的实习生),所以如果这就是我需要做的,请你发布详细的指示或链接到如何的教程设置涂抹/清洁循环?

    后台:我希望我的工作分支与主干不同步。有一个低优先级的错误只影响开发机器,所以我们只是评论出有问题的代码,而不是修复它。显然,我们不希望将此代码从生产中删除,它可以正常工作。

9 个答案:

答案 0 :(得分:37)

您可以使用skip-worktree位。打开它:

git update-index --skip-worktree <file>

之后,git永远不会为<file>暂存本地更改,如果git本身必须写入<file>(例如,在合并或结账时),它将失败(大声)。

如果您想要进行未来的更改,可以将其关闭,暂存新更改,然后重新打开:

git update-index --no-skip-worktree <file>
git add -p <file>
git update-index --skip-worktree <file>

虽然不完美,但这可能还不错。你应该注意到<file>有未分阶段的更改,因为git将不再告诉你

注意:我的原始建议是使用assume-unchanged。正如Git - Difference Between 'assume-unchanged' and 'skip-worktree'中所述,您真正需要skip-worktree。特别是, assume-unchanged是对Git的承诺,您不会更改该文件,如果违反该承诺,Git可以删除您的更改或提交它们!相比之下,Git不会删除或提交您的skip-worktree更改。

答案 1 :(得分:4)

Git的“补丁模式”非常适合仅从文件添加某些更改到您的提交。

要启动它,请键入git add -pgit commit -p(完成时直接提交消息)或git add --interactive(更多提示)。

它基本上会引导您完成git diff中显示的每个代码段,并询问您是否要暂存它。

当您达到更改时,请回答 n o或 e 以打开$ EDITOR中的补丁。

答案 2 :(得分:3)

我认为,您所描述的情况是:您希望维护一个与本地存储库不同的工作目录。

这是不可取的;因为这些更改未提交,如果文件被意外删除或以您不想要的方式更改,您将无法追索。

因此,建议您实际提交所有更改。如果您想要分离这些更改,您可以使用分支轻松完成。实施例

git checkout -b new-branch
# now you can change the file without affecting master
echo bar >> foo
git add
git commit
# and back to master
git checkout master

答案 3 :(得分:2)

注意:其他人说保持持续的局部变化是一个坏主意,我没有任何理由不同意。考虑其他选择。

以下是我喜欢的方法:

  1. 进行一些您希望保留在本地计算机上的更改。
  2. 使用git branch localgit checkout local为您的本地更改创建新分支。 (如果我没弄错的话,这些命令不会自动设置远程分支,因此新分支不会被推送。)
  3. 使用git commit提交更改。
  4. 进行您想要向上游推送的更改。
  5. 使用git checkout parent返回您想要推送的分支。
  6. 使用git commit提交此分支。
  7. 使用git push推送您的更改。
  8. 使用git checkout local返回当地分支机构。
  9. 使用git rebase parentparent的更改带入local。使用rebase会使您的本地更改保留在parent的更改之上。
  10. 返回第4步,重复广告恶心。
  11. 通过这种方式,您不必手动告诉git哪些更改是本地的,哪些更改不是每次要进行非本地更改。

答案 4 :(得分:2)

这些答案都很好,但可能不能最好地解决@Kevin的问题。我有一个类似的问题,经常编辑配置文件,所以我正在处理的应用程序将访问我自己的私人开发数据库而不是生产数据库。我不小心检查并推送这些配置更改只是时间问题!我只需要轻量级方式来忽略文件。这是我学到的东西:

  • 首先,对您的文件进行必要的更改。我会称之为my_config

  • 使用git diff >../somewhere-else/my_config.patch

  • 制作该更改的补丁文件
  • 现在告诉git忽略该文件(无需更改签入的.gitignore):git update-index --assume-unchanged my_config

现在,只要您不对 想要办理登机手续的my_config进行更改,您就可以自由工作。要停止忽略my_config,请执行git update-index --no-assume-unchanged my_config。在将其他人的更改提交到my_config之后,您可以使用git apply ../somewhere-else/my_config.patch轻松恢复您的私人更改,然后......再次假设未更改,如上所述,然后重新开始工作!

以下是您可以在~/.gitconfig中添加的一些有用的别名:

[alias]
    unchanged = update-index --assume-unchanged
    changed = update-index --no-assume-unchanged
    show-unchanged = !"git ls-files -v | sed -e 's/^[a-z] //p; d'"

答案 5 :(得分:1)

是的,这可能是使用涂抹/清洁过滤器完成的。但是,我强烈建议不要这样做,因为它会相当复杂且容易出错(例如,它会混淆许多基于git的工具,这会使问题难以调试等。)

此外,永久性的本地更改通常不是一个好主意。使用SCM的一个重要方面是您可以签出版本并立即使用它。这意味着您应该检查所需的一切。

我认为没有任何“好”方法可以做到这一点,无论是git还是大多数其他SCM。我建议你重新考虑你的要求。

问题似乎是你有一个带有“混合内容”的文件:某些内容总是相同的,有些内容需要在本地更改(特定于机器的选项?)。 处理此问题的推荐方法不是检入有问题的文件,而是检入“模板”文件,然后在构建时生成实际文件。试着调查一下。现在(可能)会有更多的工作,但会使事情变得更容易,特别是如果你需要支持更多的变化或者其他人想要在同一个项目上工作。

修改(根据评论中的信息)

您写道,您希望忽略仅对开发机器而非生产中所必需的本地代码更改。

在这种情况下,不是注释掉,而是将代码包装在某种条件下,以便它只在dev机器上运行(例如使用条件编译,或者读取配置文件或某些环境属性,或者.. (1))。然后你可以正常检查代码。

更好的是,修复bug。如果一个错误使开发变得困难,那么恕我直言,它是高优先级的。

只是评论代码不是一个好主意。这很容易出错,每次退房时都必须这样做。最重要的是,在开发和生产中运行不同的代码会遇到麻烦,应该尽可能避免。

(1)举个例子:在我们公司,我们有一个专门针对这种情况的环境变量。它指示代码是在开发,beta测试还是生产中运行,并由我们的构建和部署脚本设置。但是,它通常仅用于选择不同文件路径等简单事物。如上所述,不鼓励根据环境更改程序逻辑。

答案 6 :(得分:0)

如果您不能使用.gitignore,因为您需要在同一个文件中进行并行更改(如注释中所示),那么一个选项是git add -p使用此选项可以相应地添加或跳过。

这里使用上面的git命令的问题是,它将更像是一个手动过程。我想你可能找不到任何其他自动化方法来解决你的问题。

答案 7 :(得分:0)

从Git 2。5(2015年7月)开始,您可以使用git worktree

git worktree add -b patch-1 ../patch-1

这实际上只是创建一个分支,但它将新分支放入 父文件夹旁边的新文件夹。这很好,因为你可以继续工作 这个分支,即使没有提交,然后切换回主人干净 工作目录。

答案 8 :(得分:0)

如果你碰巧使用intellij作为你的IDE,那么它有一个简洁的功能(变更列表),我相信它正是OP所要求的。

您可以标记并命名本地差异的特定部分。如果内存服务,这将使这些更改与所有其他本地修改分开,并且只有在您主动选择时才会提交以进行提交 - 只要您从intellij提交。