在rm --cached之后无法阻止git修改文件

问题描述 投票:1回答:1

我试图运行'git rm -rf --cached'。以及'git add'。删除现在列在.gitignore中的缓存文件。我在Windows计算机上使用Visual Studio,并且更喜欢在这种特定情况下保留行结尾。

我尝试使用git config命令将core.autocrlf设置为false。我尝试使用'* -text'行创建一个.gitattributes,运行.git / index,然后运行git reset。到目前为止,每次我添加文件时,我都会得到一个庞大的修改文件列表。

编辑:文件中的更改实际上不是行结尾,它是文件权限的更改,我没有请求。

windows git
1个回答
1
投票

编辑:剩下的问题是文件模式显然没有在Windows系统中正确存储(另请参阅What is git's "filemode"?)。要保存和恢复它们,需要一个脚本和原始数据:

git ls-files --stage > /tmp/original

要恢复模式,这个相当粗糙的管道应该工作:

< /tmp/original \
awk -F$'\t' '/^100755 / { print "git update-index --chmod=+x \"" $2 "\"" }' |
sh

这将尝试通过以下序列删除的chmod +x文件,因此如果有任何此类文件,您可能会遇到一些错误消息。 (它还假设没有文件名称中有双引号。)


假设您还没有.gitattributes文件,这是一个应该工作的六步过程:

  1. 像你一样创建.gitattributes文件
  2. 运行rm .git/index
  3. 运行git checkout HEAD -- .
  4. 运行git rm -r --cached .
  5. 运行git add .
  6. 运行git rm .gitattributes(你可以保留这个,直到验证它一切正常)。之后运行git commit

我没有(也没有使用)Windows因此无法测试这一点,但这里有理由为什么它应该工作,因此为什么有这些步骤。

Git的实际数据存储格式是一种特殊的,仅限Git,压缩(有时是高度压缩)的格式。以这种格式存储的文件主要仅对Git本身有用。这种格式存储原始的,未解释的字节流:文件不必分成“文本”和“数据”等等,它们只是原始字节流(因此被视为“数据”/“非文本”)。数据一旦存储,就是只读的,并被分配一个哈希ID(当前是SHA-1,虽然未来的Git可能使用SHA-256)。 Git调用以这种方式存储的文件blob,即a term stolen from the database world

您的计算机的有用文件存储格式当然是不同的,并且可能(并且在Windows上)区分“文本”和“数据”。文本可能有编码(例如ISO-8859-1,UTF-8,UTF-16等)。这些文件通常都是可读写的,计算机上的任何文件都可以处理它们(在某种程度上,取决于编码)。

Git必须从提交中提取文件,将它们从blob转换为可以使用的文件。这些文件存在于您的工作树中。你和他们一起工作,然后git add他们让Git有机会重新给他们带来斑点。

在这些特殊的Git-blob和工作树之间,Git需要一个存储blobbed数据的地方,这与commit-write不同,但是就像提交一样,文件采用特殊的Git格式。这个“介于两者之间”的地方是Git的索引。各种Git文档有时将其称为暂存区域或缓存。

Git使用每个文件的索引副本(或blob,真的)来进行新的提交。运行git add时,Git会读取工作树文件,将其编码为blob格式,然后将其井号ID保存在索引中。运行git commit时,Git只是将索引副本冻结为已提交的副本。

当您运行git checkout以切换到某个提交时,Git会将提交提取到索引中(填充所有blob哈希ID),并将blob提取到工作树中,以便它们处于有用的格式并且您可以处理它们。当您运行git add时,Git会将工作树文件压缩为其blob格式并替换该文件的索引条目。

将blob转换为工作树文件(反之亦然)是Git进行所需转换的理想场所,例如将换行符转换为CRLF行结尾。这就是Git所做的事情:git checkout填充索引并扩展并转换为工作树,git add压缩 - 取消 - 从工作树转换为索引,为下一个git commit做好准备。 (任何你不接触的文件,保持压缩状态并准备就绪,安全地隐藏在索引中。)

您已经知道跟踪文件是索引中的文件,而未跟踪文件是工作树中但不在索引中的文件。你的目标是使用现有的.gitignore来使当前在索引中的文件远离索引,如果它们是.gitignore-ed。您正在使用的过程是:

  • git rm -r --cached .:从索引中删除所有内容,以便整个工作树不被跟踪
  • git add .:从工作树中的任何内容生成索引中的所有新blob,同时忽略.gitignore中列出的任何文件。

这里的问题是工作树中的内容已经被“blob转换为工作树”转换,并且将被“工作树转换为blob”转换为“未转换”。用.gitattributes创建一个* -text文件告诉Git:要做的转换根本就没有转换。“

不幸的是,现在为时已晚:你先前运行的git checkout,将这个提交到工作树中,已经进行了一些转换。

所以在这里,我们使用第1步创建一个.gitattributes文件,表示不进行转换。第2步,rm .git/index,完全删除索引。 Git现在不知道工作树中究竟是什么。这个步骤可能是不必要的,但我用它来强制Git在第3步中执行,它告诉Git:将HEAD提交中的每个文件提取到索引和工作树中。这会重新创建索引,并重新填充工作树,这次不进行转换。

步骤4和5与以前一样,但这次,工作树文件都与HEAD提交中的blob匹配,因为步骤3使用.gitattributes指令进行操作。第6步是确保您不提交“do no conversions”指令。

© www.soinside.com 2019 - 2024. All rights reserved.