有时git clone
会导致脏工作树。我明白了,你用crlf
提交文本文件,你配置.gitattributes
来强制lf
,并将autocrlf
设置为true
-你是在自找麻烦。但是,为什么在相同的条件下,你有时会得到一个肮脏的工作树,有时-干净?
使用Git for Windows 2.40.1(确认不是特定于平台或版本 * 一般 *,但repro似乎是Windows特定的)。我唯一改变的设置是设置core.autocrlf=true
。下面是一个脚本,它反复克隆一个仓库并检查它是否是脏的。好吧,从技术上讲,它只是刷新了索引,但你可以用一个干净的克隆复制相同的,只是需要更长的时间。
#!/usr/bin/env bash
set -e
# Continuously reset a repo and check its status
REPO_URL="https://github.com/balakine/crlf.git"
REPO_DIR="crlf"
COUNT_TOTAL=0
# Clone the repository
rm -rf "$REPO_DIR"
git clone --branch master --single-branch --depth=1 "$REPO_URL" "$REPO_DIR"
cd "$REPO_DIR"
until git diff --quiet; do
((++COUNT_TOTAL))
# Reset the repository
git rm --quiet --cached -r .
git reset --quiet --hard
printf "\033[0;32mTotal: %s\033[0m\n" "$COUNT_TOTAL"
done
git status
字符串
这将需要一段时间,大约5,000次尝试在我的机器上,但你会得到一个干净的回购在某个时候。为什么呢?我有一个repo的例子,它克隆了clean 8/100,但它是专有的。
1条答案
按热度按时间dsf9zpds1#
这实际上可以在任何时候让Git执行任何转换时发生,包括行尾转换或涂抹/清理过滤器,例如Git LFS。原因是Git在索引中存储了某些信息,包括时间戳,文件大小,以及Unix上关于设备和inode的其他信息。
当Git注意到一个文件与索引中的版本具有相同的时间戳时,它不知道该文件是否在同一秒内被静默更新。这被称为the "racy Git" problem。因此,Git需要重新读取文件,这将重新执行任何转换。
通常,当你执行 checkout 时,Git会立即写入索引,所以所有的文件都会被正确地写入索引。但是,如果你遇到一个或多个文件的Git问题,而这些文件是Git提供的转换会导致它们被修改的(因为它们的行结尾不正确,或者它们没有正确地存储为Git LFS文件),那么它们会显示为已修改的。
由于我不知道的原因,这种情况在Windows上比在其他操作系统上更频繁地发生,但是如果您触摸工作树中的每个文件(例如,使用
git ls-files -z | xargs -0 touch
),那么您将看到所有受影响的文件,因为git status
必须重新读取和重新处理工作树中的每个文件。处理此问题的方法是按照文件应该存储的方式存储文件。对于文本文件,这意味着你需要将它们标记为
.gitattributes
中的文本(* text=auto
适用于很多情况),然后Git会始终将它们存储为LF在仓库中,并在 checkout 时使用你喜欢的行结尾(除非你指定eol=lf
或eol=crlf
)。