我在 bitbucket 上有一个使用 LFS 的存储库。由于使用了一段时间,我决定将存储库移回我控制的空间。我首先使用 LFS 的唯一原因是有效地将我的存储库大小限制加倍(因为 LFS 中的文件位于单独的存储桶中),但现在我正在移动它,我不再需要这样做。
我需要一种方法来遍历整个 git 历史记录,删除 git LFS 所做工作的所有痕迹(以便所有文件都“正常”提交)。完成此操作后,我打算强制推送到新存储库。
我做了相当多的搜索,并遇到了建议的解决方案,但我不明白如何实现/运行它们,因为它们是高级的。
如何告别 git LFS?
如果你想移除 LFS,但不太担心修复整个 git 历史记录,你可以执行以下操作;
git lfs uninstall
touch **/*
git commit -a
这将卸载 LFS 支持,触摸每个文件(以便 git 识别出文件已更改),然后将它们全部提交。如果您愿意,可以更具体(例如,
**/*.png
)。请注意,使用 **
需要启用扩展的 glob 支持(bash 上的 shopt -s globstar
)
这对我有用 - 但它会引发很多错误(我认为对于文件尚未添加到 LFS 的每个提交,我都会收到一个错误)并且需要很长时间(每个提交大约 2-3 秒)提交)。
git lfs uninstall
git filter-branch -f --prune-empty --tree-filter '
git lfs checkout
git lfs ls-files | cut -d " " -f 3 | xargs touch
git rm -f .gitattributes
git lfs ls-files | cut -d " " -f 3 | git add
' --tag-name-filter cat -- --all
它会卸载 git LFS 支持(理论上可以防止 LFS 弄乱索引),然后对于每次提交,它都会确保正确检出 LFS 文件,然后触及所有文件(因此 git 意识到它们已更改),删除找到的 LFS 设置在
.gitattributes
中,这样克隆时就不会一直尝试使用 LFS,然后将真实文件添加到索引中。
完成上述操作后,您需要用力推动。当然,这会让处理您的存储库的其他人陷入分离的状态 - 因此在代码冻结期间这样做是明智的。之后,让每个人都进行新的克隆可能是最简单的。
git lfs migrate export
来自
git lfs migrate help
:
导出
export模式将 Git 历史记录中存在的 Git LFS 指针文件迁移出来 Git LFS,将它们转换成相应的目标文件。
git lfs ls-files
验证您确实拥有 LFS 文件。filter=lfs
文件中删除所有 .gitattributes
行。 .gitattributes
可以生活在任何地方,因此请确保找到所有它们,否则这可能会导致以后出现迁移问题。.gitattributes
所做的任何更改。git status
确保您没有任何更改。git lfs migrate export --everything --include .
git status
以确保您没有任何更改。如果您将 .gitattributes
保留为 filter=lfs
,您现在可能会错误地进行更改。git lfs ls-files
验证之前列出的所有 LFS 文件均不再存在。filter=lfs
中删除所有 .gitattributes
行。.git/hooks
目录中的 LFS 保留:预提交、提交后、签出后、合并后。$GIT_TRACE=1
就应该没有 ...trace git-lfs: filepathfilter: accepting...
.gitattributes
touch myfile.bin
根据Shadow的回答,我稍微修改了整个历史更新。 对于那些不想保留 LFS 文件的人(就我而言,我没有保留,因为它们会很大)。
用途:
GIT_LFS_SKIP_SMUDGE=1 git filter-branch -f --prune-empty --tree-filter '
git lfs checkout
git lfs ls-files | cut -d " " -f 3 | xargs rm -f
git rm -f --ignore-unmatch .gitattributes
' --tag-name-filter cat -- --all
当提交中不存在 .gitattributes 时,它也不会失败,在我的情况下,这对于所有提交来说都是不正确的。
此外,存储库没有将原始 LFS 文件存储在远程,因此使用 GIT_LFS_SKIP_SMUDGE=1
这样,存储库不包含任何 LFS 引用和文件,这使得克隆存储库更快、更轻——这就是我的目标。无论如何,大文件用于测试,但由于代码已经改进了很多,运行那些旧的测试是无关紧要的。
我编写了一个脚本,可以从 git 存储库中完全删除 lfs。警告 - 它会重写您的历史。
#!/bin/zsh
git lfs install
git lfs fetch --all
git lfs checkout
lfs_dirs=()
echo "finding lfs files"
for lfs_file in $(git lfs ls-files | sed -r 's/^.{13}//'); do lfs_dirs+=($(dirname "$lfs_file")); done;
echo "found all lfs files"
unique_dirs=()
for unique_dir in ${(u)lfs_dirs}; do unique_dirs+=("$unique_dir/*"); done;
count=${#unique_dirs[@]}
if (($count == 0))
then
echo "No lfs dirs"
exit 0
fi
echo "There are $count unique lfs dirs"
printf -v migrate_paths ',%s' "${unique_dirs[@]}"
migrate_paths=${migrate_paths:1}
echo "performing: git lfs migrate export --include='$migrate_paths' --yes --verbose --everything"
git lfs migrate export --include="$migrate_paths" --yes --verbose --everything
git lfs uninstall
我想在@Doug Richardson 的回答中添加一条注释。 不知道为什么,但
git lfs migrate export --everything --include .
对我不起作用。
然后,我发现@simon-the-shark在这个git-lfs问题帖子中的答案是有效的。
这是他建议的 git 命令。
git lfs migrate export --include="*" --everything