有没有一种方法可以在Git中“冻结”一个文件?

24

我现在面临一个情况,想把我的项目开源,但是有一个单独的源文件,我想发行一个“干净”的版本,但是在本地使用一个不同的版本。Git是否有这样一种功能,让我可以只提交一次文件,从此不再查找该文件的更改内容?

我尝试将文件添加到.gitignore中,但是第一次使用git add -fgit commit命令后,如果我继续编辑该文件,git status就会显示该文件已更改。理想的行为方式是,Git从现在开始不再显示该文件已更改,即使我对其进行了编辑。

我也很想知道其他人是如何在将代码库推送到开源仓库之前,在Git上清除私有代码/数据的,特别是如何处理这个问题。


иҝҷжҳҜGitеҶ…йғЁзҡ„еҺҹеӣ пјҢдҪҶжҳҜжҸҗдҫӣз»ҷдҪ еҸӮиҖғзҡ„жҳҜпјҢдҪ зҡ„.gitignoreжҠҖе·§жІЎжңүз”ҹж•Ҳзҡ„еҺҹеӣ жҳҜ.gitignoreеҢ№й…ҚеҸӘйҖӮз”ЁдәҺGitеңЁжҗңзҙўжңӘеҠ е…ҘзүҲжң¬жҺ§еҲ¶зҡ„ж–Ү件时гҖӮиҝҷж„Ҹе‘ізқҖе®ғе°ҶпјҲ1пјүеҮәзҺ°еңЁgit statusдёӯпјҢ并且пјҲ2пјүеңЁдҪ жү§иЎҢgit add .ж—¶иў«ж·»еҠ гҖӮ - Steven
工作流解决方案:为您的重要分支设置单独的存储库目录。现在,您可以使用文件浏览器在它们之间复制文件。 - nathanfranke
5个回答

22

你可以使用Git的稀疏检出功能来实现。在想要有一个特殊、未被跟踪的local.txt文件的仓库中运行以下命令:

git config core.sparsecheckout true
echo '*' >.git/info/sparse-checkout
echo '!local.txt' >>.git/info/sparse-checkout
git read-tree --reset -u HEAD

这将首先删除现有的local.txt文件。但现在从Git的角度来看,它被忽略了,因此您可以在那里放置一个特定于机器的文件,而Git不会打扰您。

然后,您可以从某个其他存储库添加和管理已发布的local.txt文件。Git将很乐意跟踪此文件并将其保留在存储库中,但在具有上述稀疏检出配置的计算机上,即使该文件与存储库中的内容不同,Git也将忽略该工作目录中的本地local.txt文件。


3
@foo:当然,编辑.git/info/sparse-checkout文件,删除!local.txt这一行,并重新运行git read-tree命令。 - Greg Hewgill
2
我发现这种方法非常健壮。比我见过的其他使用 git update-index --assume-unchangedgit update-index --skip-worktree 的方法更加可靠。干杯! - TheAmpersand

16

使用update-index命令,文档在这里

以下是一个基本示例,冻结文件foo.rb

git update-index --assume-unchanged foo.rb

然后,要将其取回:

git update-index --no-assume-unchanged foo.rb

或者为了简单起见,将其添加到.gitconfig中。

freeze = update-index --assume-unchanged
thaw = update-index --no-assume-unchanged
...
git freeze foo.rb
git thaw foo.rb

注意:这个答案最初是由@TheAmpersand在上面的评论中提供的。我认为这很重要,需要规范化。


6

Greg的方法非常充分和准确地回答了你的问题。

让我做一个补充,考虑到我推断你的高级目标:

  • 不要将本地数据发布到公共环境
  • 发布干净版本到公共环境

实现这一点最简单(也是我经验中最好的)的方法是使用以下结构:

已版本化的

./application.code
./config.code
./config.local.code.sample
./.gitignore

application.code

include('./config.code')
if is_file('./config.local.code')
  include('./config.local.code')
end

config.code

username = 'root'
password = 'password'

config.local.code.sample

username = 'replace with your local username and rename file to config.local.code'
password = 'replace with your local password and rename file to config.local.code'

.gitignore

config.local.code

不带版本号(可选)

./config.local.code # will not be picked up by git due to .gitignore

config.local.code

username = 'Suan'
password = 'myownpass'

结果

正如您所看到的,您可以避免将包含敏感信息的config.local.code发布到公共场合。默认配置(从远程克隆)将适用于一个合理但罕见的情况,其中用户名root和密码password是有效的。而名为config.local.code.sample的文件则提供了本地自定义说明。


这些文件在哪里? - ATL_DEV

0

一种方法是在本地分支中对文件进行更改。在该分支中完成工作,然后忽略您的更改将其重新合并到实际开发正在进行的分支中。


0

我曾经使用符号链接来解决Django配置文件中类似的情况。看起来你正在寻找版本控制能力而不是配置文件管理,但我相信这个小策略可以帮助你。以下是我通常采取的步骤:

假设你想要在本地更新(不共享)的文件名为'local.file',而你想要发布(在公共环境中)的文件名为'release.file'...你需要创建一个符号链接文件,我们称之为'actual.file'。符号链接文件将随时指向local.file或release.file(如果你刚刚克隆了repo,则为空)。

  1. gitignore local.file和actual.file,因为你不想跟踪这些文件或发布它们。actual.file始终指向你想要处理的文件。
  2. 当你在处理“非冻结”版本化文件时,使符号链接指向local.file。
  3. 当你想要手动更新它或仅从local.file复制更改到release.file时,使符号链接(actual.file)指向“冻结”的release.file。

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