为什么git clone是不确定的?

1bqhqjot  于 2023-08-01  发布在  Git
关注(0)|答案(1)|浏览(112)

有时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,但它是专有的。

dsf9zpds

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=lfeol=crlf)。

相关问题