【问题标题】:How to freeze a file in a repository如何冻结存储库中的文件
【发布时间】:2014-05-07 20:46:39
【问题描述】:

我们遇到了这样一种情况,即我们的 repo 中的文件应该被锁定在适当的位置,并且无法更改。

我已经将文件添加到.gitignore,但是当我在本地修改它时,git 仍然会跟踪它——我现在的理解是,在它们已经在 repo 中之后将文件/文件夹添加到 .gitignore 不起作用并且一种可能性是使用git rm --cached file 取消跟踪。

如果我这样做了,该文件是否将不再在 repo 中可供下一个克隆它的人使用?有没有更好的方法在 repo 中冻结这个文件?

【问题讨论】:

  • 因此,备份一个步骤 - 锁定文件是您尝试解决的特定问题的解决方案。那是什么问题?也就是说,为什么它需要锁定到位?
  • 它为我们的用户提供了一个基线配置,然后他们可以根据自己的喜好对其进行自定义(字体颜色等),但不需要与他人分享。

标签: git


【解决方案1】:

配置您自己的存储库并不难,因此他们永远不会对该路径进行更改,其他存储库的所有者将不得不在执行一些一次性配置命令的范围内进行合作。

这是你为自己的 repo 所做的:

  • 设置一个不会改变工作树或存储库中现有内容的内容过滤器。

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

    git 将执行 clean 命令来生成要放入 repo 的内容,只要你暂存 (git add) 此类文件。在这里,命令尝试显示文件已经提交的内容,如果这不起作用,如果没有任何内容提交,那么它们将采用您正在暂存的内容。同样,git 执行smudge 命令来生成应该在结帐时放入工作树的内容,这里使用任何已经存在的内容,否则将存储库中的内容作为默认值。

  • 宣传您希望以这种方式处理路径/到/文件

    echo path/to/file filter=pinned-content >>.gitattributes
    
  • 使处理适用于此 repo 中的所有未来签出/添加,即使是已经存在的提交

    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】:

    如果您想“冻结”文件(防止在 Git 中跟踪进一步的更改),您可以运行 git update-index --assume-unchanged somefile

    来自文档:

    当“假设不变”位打开时,用户承诺不改变 该文件并允许 Git 假设工作树文件匹配 索引中记录的内容。

    延伸阅读:git-update-index

    注意:这不会阻止其他人更改文件。如果您希望文件在 Git 中真正永远不会更改,则克隆 repo 的每个人都必须运行此命令。

    【讨论】:

    • 我需要反转这个命令,再次进行文件更改,有什么想法吗?!
    • 从文档中,git update-index --no-assume-unchanged somefile 恢复它。
    【解决方案3】:

    git rm --cached file 确实会从存储库中删除文件,因此 in 仅作为当前工作目录中的未跟踪文件存在。未来的克隆将不会包含该文件。

    Git 并没有真正提供冻结文件以使其无法修改的方法。您可以做的最好的事情是创建一个预提交挂钩,该挂钩在提交之前重置文件,或者最好在您自己重置文件之前中止提交。

    【讨论】:

    • 感谢(您和 vonbrand 都)确认这一点,以及提交前的建议。我在输入问题时想知道,“这在 git repo 中是否可能?”
    【解决方案4】:

    这成功了(根据this):

    # 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 之后在其他 PC 上键入 git update-index ... 命令

    【讨论】:

      【解决方案5】:

      .gitignore 所做的是告诉 git 在给定的命令中要忽略哪些文件,除非它们已经是存储库的一部分(或者您要求它覆盖)。

      例如我在我的.gitignore 中有*.png 用于我正在编写的讲义(一些图像被制作成PNG 以供包含),但存储库包含原始PNG 的图像。完全没问题,旧的被跟踪OK,通过重建创建的被忽略。更改old.png 只是一个git commit -m "Old image was changed" old.png。如果我想添加一个新的,只需git add -f some-new.png; git commit -m "Some new image" 即可。

      您不能通过在某处提及它们来排除存储库中已经存在的文件,并且从现在开始永远排除它们无论如何都行不通。

      【讨论】:

        猜你喜欢
        • 2011-10-31
        • 1970-01-01
        • 2019-12-06
        • 2015-05-08
        • 1970-01-01
        • 2011-11-06
        • 1970-01-01
        • 1970-01-01
        • 2021-03-17
        相关资源
        最近更新 更多