git - 是否可以将文件从`git push`排除,但在本地存储库中保留它们?

45

在我的主目录中,我有一个本地的git仓库,因为我想将所有文件都纳入版本控制。

其中大部分文件我想要推送到一个远程仓库,但有一些我想要仅在本地仓库中保留(因为它们包含一些轻微敏感的信息)。

我该如何在git中实现这一点?我可以配置一个“.gitignore-for-push”文件吗?我不能使用本地的.gitignore文件,因为这样会完全排除这些文件的跟踪。

注:我知道问题“是否有一个与排除文件等效的...”,但其中的答案涉及到我不能使用的.gitignore文件。另一个问题“在推送到特定的git仓库时排除特定文件”仅回答了一个git+heroku的特定情况,而不是单独使用git的情况。


我不这么认为。你最好使用git submodule来将敏感信息与远程仓库分离开来。 - simont
7个回答

49

你可以追踪这些文件(除去敏感信息),然后使用:

git update-index --assume-unchanged <file>

对于每个文件进行处理。接着,你可以在每个文件中添加敏感信息,但 Git 不会将该文件视为已更改,因此不会尝试提交(从而推送)那些敏感信息。

要让 Git 再次更新信息,你需要使用:

git update-index --no-assume-unchanged <file>


2
这种方法的缺点是它无法跟踪文件的更改;但了解这个选项还是很有用的。 - echristopherson
1
我一直在寻找一种方法,在不修改存储库或gitignore文件(这会影响其他人)的情况下忽略本地文件。我尝试修改全局git ignore配置和.git/info/exclude下的文件,但都没有起作用,但是这个方法解决了我的问题。谢谢! - ThinkBonobo

16

这是不可能的。如果您已经提交了一个文件,那么它将会被推送。推送行为仅适用于提交,而不是基于文件的。

但您可以使用子模块来处理敏感数据,并将此子模块保留在本地计算机上,同时将常规 Git 存储库推送到远程计算机。


2
是的,我之前就怀疑了。submodule 的想法很有趣 - 我会去看看的。不过我的当前解决方案使用了第二个目录(参见我的回答https://dev59.com/m2ct5IYBdhLWcg3wsPZ5#12019595),所以有点像作弊,我知道。 - halloleo

7
我最终解决了这个问题的方式是:将敏感信息放在一个子目录中,该子目录有自己的git仓库,并将文件的符号链接指回旧位置。
例如,在您的家目录(~)中有一个名为.creds的文件,您不希望它出现在公共存储库中。将此文件移动到名为protected的子目录中,并从~创建一个指向protected/.creds的符号链接。当然,不要将此文件夹包含在您的~存储库中,而是在protected文件夹中创建一个新的存储库,以跟踪.creds。如果您根本不公开推送此存储库,则设置完成。
我知道这个解决方案有点赖皮:我的问题表明该文件与同一目录中的其他文件共存,但对我来说符号链接很有效。

6
这里的git-update-index意为:将工作区文件内容注册到索引中。
git update-index --assume-unchanged <PATH_OF_THE_FILE>

例:-

git update-index --assume-unchanged somelocation/pom.xml

请查看更多详细信息。这里。

1

git update-index --skip-worktree directory/fileName.js

这将修改索引或目录缓存。提到的每个文件都将更新到索引中,并清除任何未合并或需要更新的状态。 有关更多参考,请查阅以下网址。https://git-scm.com/docs/git-update-index


2
虽然这可能是一个回答问题的方法,但最好解释一下这个命令的作用。仅仅给出代码的答案通常不被接受。 - MeanGreen

1
创建一个本地分支,从该分支中删除敏感文件,然后仅将该分支推送到远程存储库是否是最简单的方法? 如果它们很少更改,当您在本地合并时,它们应该保持在新分支中而无需要求您确认。 此外,专门用于远程推送的分支使您可以通过查看文件系统内容清晰地了解正在推送的内容,而不必担心特定文件或文件夹是否真的是链接或子模块等。

0

不要提交您想要排除的文件。

例如,如果您有两个文件ab在本地代码库中,但您只想提交其中一个文件,请使用:git add a添加其中一个文件。然后使用git commit进行提交(不包括-a标志)


1
这将防止文件被完全纳入版本控制,对于大多数配置文件、敏感代码等来说,这是一个最糟糕的解决方案。git submodule 可能是更好的解决方案。 - simont

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接