我在rm refs/original
之后忘记了git filter-branch
并且忘了git gc
refs
。我也致力于新的回购,并希望保留这些提交。
提取的分支大小为几千字节,但.git
仍然重80 MB,就像过滤之前一样。
现在refs
为空,我不能轻易删除refs/original
。我怎么还能删除原件?如果可能的话,我想避免再次filter-branch
。
答案 0 :(得分:1)
你的裁判已被打包(git gc
运行git pack-refs
)。这不会改变裁判本身,除了不是将每一个都放在一个单独的文件中,它们都在"打包" FIE。
您只需要删除refs/origina/
引用。理论上,使用每个git update-ref -d
应该有效,但如果有很多,则可能更容易在编辑器中打开.git/packed-refs
并手动删除所有refs/original/
行。< / p>
您可能还需要清除reflog。
有关详情,请参阅this StackOverflow answer。
答案 1 :(得分:0)
git gc
运行git pack-refs
如果您开始删除引用,请确保使用Git 2.24+(2019年第三季度):“ git pack-refs
”可能会丢失在运行时创建的引用,此问题将得到纠正。
请参见commit a613d4f的Sun Chao (sunchao
)(2019年7月31日)。
(由Sun Chao -- sunchao
--在commit a613d4f中合并,2019年8月2日)
pack-refs:始终在获取锁定文件后刷新
删除打包引用后,将重写整个打包引用文件,以省略不再存在的引用。
但是,如果另一个gc
命令正在运行并同时调用pack-refs --all
, 刚刚更新的引用有可能会丢失新创建的提交。通过这些步骤,可以证明丢失对新更新的引用的提交:
# step 1: compile git without `USE_NSEC` option
Some kernel releases do enable it by default while some do
not. And if we compile git without `USE_NSEC`, it will be easier
demonstrated by the following steps.
# step 2: setup a repository and add the first commit
git init repo &&
(cd repo &&
git config core.logallrefupdates true &&
git commit --allow-empty -m foo)
# step 3: in one terminal, repack the refs repeatedly
cd repo &&
while true
do
git pack-refs --all
done
# step 4: in another terminal, simultaneously update the
# master with update-ref, and create and delete an
# unrelated ref also with update-ref
cd repo &&
while true
do
us=$(git commit-tree -m foo -p HEAD HEAD^{tree}) &&
git update-ref refs/heads/newbranch $us &&
git update-ref refs/heads/master $us &&
git update-ref -d refs/heads/newbranch &&
them=$(git rev-parse master) &&
if test "$them" != "$us"
then
echo >&2 "lost commit: $us"
exit 1
fi
# eye candy
printf .
done
尽管我们拥有打包的refs锁定文件和宽松的refs锁定文件,以避免更新冲突,但是如果
packed-refs
文件的racy stat-validity发生,ref将会丢失其新提交。
前进的最佳途径就是在获取packed-refs
文件的锁定文件后始终刷新。