首页 > 解决方案 > Git LFS 不会推送 LFS 文件,除非我用 object-id 指定它们

问题描述

我在使用 LFS 的 Azure DevOps 上托管了一个存储库。推送提交时,不会推送新的 LFS 对象(如果我将更改拉到单独的存储库上,它会产生Smudge Error: Object does not exist on server [404])。

要推送 LFS 对象的唯一方法是通过指定对象 id 手动完成:

git lfs push origin --object-id ae488...

这是我的git config -l

$ git config -l
http.sslcainfo=C:/Users/200207121/AppData/Local/Programs/Git/mingw64/ssl/certs/ca-bundle.crt
http.sslbackend=openssl
diff.astextplain.textconv=astextplain
core.autocrlf=true
core.fscache=true
core.symlinks=false
core.editor="C:\\Program Files\\Notepad++\\notepad++.exe" -multiInst -notabbar -nosession -noPlugin
credential.helper=manager
filter.lfs.clean=git-lfs clean -- %f
filter.lfs.smudge=git-lfs smudge -- %f
filter.lfs.process=git-lfs filter-process
filter.lfs.required=true
user.email=<omitted>
user.name=<omitted>
alias.lg=log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit
http.sslverify=false
diff.tool=default-difftool
difftool.default-difftool.cmd=code --wait --diff $LOCAL $REMOTE
merge.tool=vscode
mergetool.vscode.cmd=code --wait $MERGED
core.repositoryformatversion=0
core.filemode=false
core.bare=false
core.logallrefupdates=true
core.symlinks=false
core.ignorecase=true
remote.origin.url=https://.../MyRepo/_git/MyRepo
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
branch.master.remote=origin
branch.master.merge=refs/heads/master
lfs.https://dev.azure.com/.../MyRepo.git/info/lfs.access=basic
lfs.https://dev.azure.com/.../MyRepo/info/lfs/objects/.access=basic
branch.7_1_0.remote=origin
branch.7_1_0.merge=refs/heads/7_1_0
branch.7_1_A.remote=origin
branch.7_1_A.merge=refs/heads/7_1_A
branch.atvcm01008318_text_class.remote=origin
branch.atvcm01008318_text_class.merge=refs/heads/text_class
branch.atvcm01008824.remote=origin
branch.atvcm01008824.merge=refs/heads/atvcm01008824
branch.atvcm01000423.remote=origin
branch.atvcm01000423.merge=refs/heads/atvcm01000423
gui.wmstate=normal
gui.geometry=1272x626+-5+0 254 315

为了防止特定分支被推送,我在pre-push钩子中添加了这些行。我目前没有在这个分支上签出,我尝试推送的 LFS 也不在这个分支上(所以我不怀疑它可能是由这个钩子引起的):

#!/bin/sh

### Prevent pushing test branch
if [[ `grep 'testing_AA'` ]]; then 
  echo "You really don't want to push this branch. Aborting."
  exit 1
fi
### End of edition

command -v git-lfs >/dev/null 2>&1 || { echo >&2 "\nThis repository is configured for Git LFS but 'git-lfs' was not found on your path. If you no longer wish to use Git LFS, remove this hook by deleting .git/hooks/pre-push.\n"; exit 2; }
git lfs pre-push "$@"

为什么我必须指定git lfs push --object-id <oid>要推送的 LFS?

标签: gitpushgit-lfs

解决方案


hook 的工作方式pre-push是从标准输入中读取行,这些行指示要推送哪些 ref 以及它们的旧值和新值是什么。像您的脚本一样,git lfs pre-push它作为预推送挂钩工作,并在其标准输入中期望此数据。然后它会根据它确定需要推送哪些 LFS 对象并推送它们。

你的pre-push钩子所做的是用grep. 然后它在没有输入的情况下调用git lfs pre-push。由于 Git LFS 认为没有要推送的引用(因为在其标准输入中没有提供任何引用),所以它什么也不推送。

如果您想在推送特定 ref 的情况下中止,那么您需要让 pre-push 钩子一次解析标准输入一行,如果匹配该行则中止,并将其附加到未来git lfs pre-push如果您不这样做,请输入。所以类似于以下内容:

#!/bin/sh

INPUT=""

while read line
do
    if echo $line | grep -qs 'testing_AA'
    then
        echo "You really don't want to push this branch. Aborting." >&2
        exit 1
    fi
    INPUT="$INPUT $line"
done

printf "%s %s %s %s\n" $INPUT | git lfs pre-push

推荐阅读