首页 > 解决方案 > 使用本地 Git LFS 存储库检查是否有任何文件更改而无需在 .git 下复制

问题描述

我有一个包含很多二进制文件的文件夹。我想保存当前状态,进行一些更改,看看哪些文件被git status. 我认为使用 Git LFS 是个好主意,因为它只为每个文件保留 3 行的大小和哈希信息。

问题是该git add .命令需要大量时间并进行备份。是否可以只提交指针文件而不创建 LFS 对象?

我使用的命令:

$ git init
$ git lfs install
$ git lfs track "*"
$ echo ".gitattributes filter= diff= merge= text" >> .gitattributes
$ git add .
$ git commit -m "previous state"
$ rm -rf .git/lfs/objects/

如果没有瓷器解决方案,我可以接受低级(管道)命令。如果有人想知道如何使用 Git LFS 保存文件,FILENAME请按以下格式提交。

version https://git-lfs.github.com/spec/v1
oid sha256:$(sha256sum $FILENAME | awk '{print $1;}')
size $(du -b $FILENAME | awk '{print $1;}')

标签: gitgit-lfs

解决方案


移动.git文件夹后,文件显示为已修改git status,据我所知,解决这种情况的唯一方法是调用git add .,它会更新 git 索引文件。如果在修改文件时缺少目标文件,Git LFS 会重新创建目标文件,所以不幸的是,下面的解决方案与使用问题中的命令没有什么不同,除了这是多线程的。在 Windows 上,建议关闭实时保护以避免 Antimalware Service Executable 的 CPU 使用率过高。

#!/bin/bash
set -e

task() {
    REPO="$1"
    FILE="$2"
    BASE=$(cd $REPO; pwd)
    FILEPATH="$BASE/$FILE"
    SHA=$(sha256sum "$FILEPATH" | awk '{print $1;}')
    SIZE=$(du -b "$FILEPATH" | awk '{print $1;}')
    NEWFILE="$BASE.git/$FILE"
    cat > "$NEWFILE" <<-EOF
version https://git-lfs.github.com/spec/v1
oid sha256:$SHA
size $SIZE
EOF
    echo "  Wrote out $FILE"
}

if [[ $# -ne 1 ]]
then
    echo "Please provide the path"
    exit 2
fi
REPO="$1"

GITFILES=($(find "$REPO" -name ".git*" -exec basename {} \;))
if [[ ${#GITFILES[@]} -ne 0 ]]
then
    echo "The path contains .git files. Aborting..."
    echo "Path: $REPO"
    for GITFILE in "${GITFILES[@]}"
        do echo "  $GITFILE"
    done
    exit 2
fi
FILES=($(find "$REPO" -type f -exec basename {} \;))
echo "Found ${#FILES[@]} files"

N=$(nproc --all)
echo "Number of threads: $N"

BASE=$(cd $REPO; pwd)
echo "Creating directory $BASE.git"
mkdir "$BASE.git"
for FILE in "${FILES[@]}"
do
    (i=i%N); ((i++==0)) && wait
    task "$REPO" "$FILE" &
done
wait
WRITTEN=($(find "$BASE.git" -type f -exec basename {} \;))
if [[ ${#WRITTEN[@]} -ne ${#FILES[@]} ]]
then
    echo "${#WRITTEN[@]} out of ${#FILES[@]} files are written. Aborting..."
    exit 2
fi
echo "All files written"

echo "Committing the previous state"
cd "$BASE.git"
git init
git add .
git commit -m "previous state"

echo "Using Git LFS to track these files"
git lfs install
git lfs track "*"
echo ".gitattributes filter= diff= merge= text" >> .gitattributes
git add .
git commit -m "git lfs track all files"

echo "Moving .git to $REPO"
cp -r "$BASE.git/.git/" "$BASE/.git/"
cp "$BASE.git/.gitattributes" "$BASE/.gitattributes"
cd "$BASE"
git add $(git status --porcelain | awk '{print $NF;}')
echo "Erasing temporary folder $BASE.git"
rm -rf "$BASE.git"
echo DONE

推荐阅读