如何在代码库中冻结文件

6
我们现在面临一个情况,我们的库中有一个文件需要锁定在原地,不能再更改。我已将文件添加到.gitignore中,但当我在本地修改它时,git仍然会追踪它 -- 现在我的理解是,在将文件/文件夹添加到repo之后才将它们添加到.gitignore中是不起作用的,而一个可能的解决方法是使用git rm --cached file将其从追踪列表中移除。
如果我这样做会不会导致下一个克隆它的人无法访问该文件?还有更好的冻结此文件的方法吗?

所以,退一步来说 - 锁定文件是你试图解决的特定问题的解决方案。那个问题是什么?也就是说,为什么需要将其锁定在原地? - Don Branson
它为我们的用户提供了一个基线配置,用户可以根据自己的喜好进行自定义(字体颜色等),但不需要与他人共享。 - larryq
5个回答

5
如果你想要“冻结”文件(防止Git继续跟踪更改),你可以运行git update-index --assume-unchanged somefile
根据文档:
当“假定未更改”位被打开时,用户承诺不更改该文件,并允许Git假设工作目录中的文件与记录在索引中的文件相匹配。
进一步阅读:git-update-index 注意:这并不能防止其他人更改文件。如果您希望文件在Git中真正永远不会更改,则克隆存储库的每个人都必须运行此命令。

我需要反转这个命令,以便再次更改文件,有什么想法吗?! - Yassine Sedrani
1
从文档中,git update-index --no-assume-unchanged somefile 可以将其恢复。 - Eneko Alonso

4

配置自己的代码库,使其不会对某个路径进行更改并不难,但其他代码库的所有者需要合作,执行一些一次性的配置命令。

以下是为自己的代码库所需执行的步骤:

  • set up a content filter that will not alter existing content either in the worktree or in the repository.

    git config filter.pinned-content.clean  'git show HEAD:%f 2>&- || cat'
    git config filter.pinned-content.smudge 'cat %f 2>&- || cat'
    

    git will execute the clean commands to generate the content to be put in the repo whenever you stage (git add) such files. Here, the commands try to show what's already committed for the file, and if that doesn't work, if nothing has been committed for it, then they'll take what you're staging. Likewise, git executes the smudge commands to generate the content that should be put in the worktree on checkout, here using whatever's already there as-is, otherwise taking the content from the repository as a default.

  • advertise that you want path/to/file treated this way

    echo path/to/file filter=pinned-content >>.gitattributes
    
  • make the treatment apply to all future checkouts/adds in this repo, even of already-existing commits

    mkdir -p .git/info
    echo path/to/file filter=pinned-content >> .git/info/attributes
    
这里有一种分发请求和协作指令的方法:
# commit the new .gitattributes and explain what you need by way of cooperation:

git add .gitattributes
git commit -F- -- .gitattributes <<EOD
How to set up to preserve existing file content

# set up a content filter that will not alter existing content
# either in the worktree or in the repository:

git config filter.pinned-content.clean  'git show HEAD:%f 2>&- || cat'
git config filter.pinned-content.smudge 'cat %f 2>&- || cat'

# make the treatment apply to all future checkouts/adds in this repo

mkdir -p .git/info
echo path/to/file filter=pinned-content >> .git/info/attributes

-------    
Please do the above configuration to avoid mistakenly committing local changes
to files marked with the `pinned-content` filter.  Currently path/to/file is 
marked in the committed `.gitattributes` to be treated this way, you can locally
mark files to be treated this way for even preexisting commits by adding a 
similar line to your repository's `.git/info/attributes` file.
EOD

%f 功能在1.7.4版本中被包含,所以已经过去了四年,可以合理地期望发行版已经具备此功能。

您可以通过git的稀疏检出实现非常相似的效果,但无法处理提供默认内容并且不能通过 .gitattributes 启用。


这已经通过了烟雾测试和数小时的测试,看起来不像我第一次尝试它的样子。


2

根据这个,最初的回答是这样的:

# Did some change in any file in the local repo
$ git commit anyFile
$ git update-index --skip-worktree myFile
$ git ls-files -v myFile
S myFile
$ git push

而且最棒的是,在git pull之后,我甚至不需要在其他计算机上输入git update-index ...命令。

最初的回答:


2

git rm --cached file可以从仓库中移除文件,使其只存在于当前工作目录中的未跟踪文件中。将来的克隆操作将不会包括该文件。

Git 并没有真正提供一种冻结文件防止其被修改的方法。最好的做法是创建一个 pre-commit 钩子,在提交之前重置文件,或者最好的做法是在您自己重置文件之前取消提交。


感谢您和vonbrand的确认,以及提出pre-commit建议。当我输入这个问题时,我在想,“这在git仓库中真的可能吗?” - larryq

1
.gitignore文件的作用是告诉git在执行命令时应该忽略哪些文件,除非它们已经是仓库的一部分(或者你要求覆盖)。例如,我正在编写讲义,*.png已经在我的.gitignore中了(某些图片会被转换为PNG格式以便包含在其中),但是仓库中包含原始PNG格式的图片。这没有任何问题,旧的被跟踪,重建生成的被忽略。更改old.png只需要执行git commit -m "Old image was changed" old.png命令。如果我想添加一个新的,只需要执行git add -f some-new.png; git commit -m "Some new image"命令即可。不能通过提及它们来排除已经在仓库中的文件,并且从现在开始永远排除它们也行不通。

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