【问题标题】:Forgot to rm refs/original after git filter-branch在 git filter-branch 之后忘记 rm refs/original
【发布时间】:2016-01-07 11:36:02
【问题描述】:
我在git filter-branch 之后忘记了rm refs/original 并做了git gc,它清除了refs。我还提交了新的 repo,并希望保留这些提交。
提取的分支大小为几千字节,但.git 的权重仍为 80 MB,就像过滤之前一样。
现在refs 是空的,我不能再轻易删除refs/original。我怎样才能删除原件?如果可能的话,我想避免再次filter-branch。
【问题讨论】:
标签:
git
git-filter-branch
git-gc
【解决方案1】:
您的裁判已打包(git gc 运行 git pack-refs)。这不会对 refs 本身进行任何更改,除了不是将每个 refs 放在单独的文件中,它们都在“打包”文件中。
您只需删除 refs/origina/ 引用。理论上在每一个上使用git update-ref -d 应该可以工作,但如果有很多,在编辑器中打开.git/packed-refs 并手动删除所有refs/original/ 行可能更容易。
您可能还需要清除 reflog。
请参阅this StackOverflow answer 了解更多信息。
【解决方案2】:
git gc 运行 git pack-refs
如果您开始删除 refs,请确保使用 Git 2.24+(2019 年第三季度):“git pack-refs”可能会丢失在运行时创建的 refs,这正在得到纠正。
参见Sun Chao (sunchao)commit a613d4f(2019 年 7 月 31 日)。
(由 Sun Chao -- sunchao -- 合并于 commit a613d4f,2019 年 8 月 2 日)
pack-refs:获取锁文件后总是刷新
当一个打包的引用被删除时,整个打包引用文件被重写以省略不再存在的引用。
但是,如果另一个gc 命令正在运行并同时调用pack-refs --all,
刚刚更新的 ref 有可能丢失新创建的提交。
通过这些步骤,可以证明在新更新的 ref 上丢失提交:
# 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
虽然我们有打包引用锁定文件和松散引用锁定文件以避免更新冲突,但如果发生packed-refs 文件的 racy stat-validity ,引用将丢失其新提交。
最好的前进路径是在获取packed-refs文件的锁定文件后总是刷新。