推送到远程时强制 git 忽略或截断大文件

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

我需要将

hostA
上托管的多个 git 存储库“镜像”到
hostB
上的存储库中。我对
hostA
上的存储库具有只读访问权限,并拥有
hostB
上的存储库,但我没有
hostB
上的管理权限。

我在引号中写了“镜像”,因为我只需要跟踪主分支及其上的标签。唯一的要求是,在主分支上的每个标记提交中,代码都基于

hostA
hostB
匹配。

通过中间跳转(我的计算机)执行此操作的一种简单方法是:

git clone hostA:repo1.git
cd repo1
git remote add hostB:repo1.git

然后每次我想同步时:

git pull hostA main
git push hostB main
git push --tags hostB main

这在大多数情况下都可以正常工作,除了一些存储库中包含大型二进制文件,并且

hostB
有最大文件大小限制,而
hostA
没有。
hostB
确实有 git LFS,而
hostA
没有。因此,如果不采取一些措施排除大文件,我就无法将这些存储库推送到
hostB

我已经确定的一些可能的解决方案路径:

  1. 从存储库中删除
    hostA
    上的大文件:这显然是正确的事情(TM),但由于超出本问题范围的各种原因,这不会发生。
  2. 使用 git LFS:这需要取消跟踪大文件并将它们添加到 git LFS。这意味着在推送到
    hostB
    之前进行本地更改,之后我不再在没有冲突的情况下从
    hostA
    拉取。
  3. 使用 git filter-repo 删除大型二进制文件:这主要保留历史记录(我对大文件不感兴趣),但显然这是一个核选项。由于它完全重写了历史,我也不再退出
    hostA
    (我想 - 我可能做错了......)。

我目前正在使用选项(2),每次我想要同步时,我都会克隆一个新副本,对其进行过滤,然后强制推送到

hostB
,但这远非理想。

理想情况下,我正在寻找一种方法将二进制文件截断为零字节大小,并让 git 在从

hostA
拉取(即 git 没有看到冲突)并将空文件推送到
hostB 时忽略该文件
无怨无悔。

我不确定这是否可能,所以我也对其他解决方案持开放态度。同步大约每月一次,因此解决方案可能有点复杂。

git gitlab git-lfs git-filter-repo
1个回答
0
投票

在我看来这是不可能的,因为您无法即时更改要推送的内容(镜像)。

您只能避免推送大于指定大小的文件,例如使用 git hook,如下所示:

#!/bin/bash

# Located in .git/hooks/pre-push

MAX_SIZE=1024

human_size() {
    awk -v sum=$1 'BEGIN {
        hum[1024^3]="GB";hum[1024^2]="MB";hum[1024]="KB";
        for (x=1024^3; x>=1024; x/=1024) {
            if (sum>=x) { printf "%.2f %s\n", sum/x, hum[x]; break }
        }
    }'
}

files_to_push=$(git diff --cached --name-only --diff-filter=ACM)

for file in $files_to_push; do
    
    if [ ! -e "$file" ]; then
        continue
    fi

    size=$(du -k "$file" | cut -f1)
    if [ $size -gt $MAX_SIZE ]; then
        echo "Error: File $file is larger than the allowed size of $(human_size $((MAX_SIZE * 1024)))."
        exit 1
    fi
done

# If we're here, all files are of an allowed size
exit 0

我认为唯一真正的解决方案是通过 BFG Repo-Cleaner 过滤和清理你的源代码库。

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