忘记在git filter-branch 之后rm refs/original
Forgot to rm refs/original after git filter-branch
我在 git filter-branch
之后忘记了 rm refs/original
并做了 git gc
,这清除了 refs
。我也致力于新的回购协议,并希望保留这些承诺。
提取的分支有几千字节的大小,但.git
仍然有 80 MB 的权重,就像过滤之前一样。
现在 refs
是空的,我不能再轻易删除 refs/original
。我怎样才能删除原件?如果可能的话,我想避免再次 filter-branch
。
你的推荐人满了(git gc
运行 git pack-refs
)。这不会对 refs 本身进行任何更改,除了不是将每个 refs 都放在一个单独的文件中,而是它们都在 "packed" fie.
中
您只需删除 refs/origina/
引用。理论上在每个行上使用 git update-ref -d
应该可行,但如果有很多,在编辑器中打开 .git/packed-refs
并手动删除所有 refs/original/
行可能更容易。
您可能还需要清除引用日志。
有关更多信息,请参阅 this Whosebug answer。
git gc
runs git pack-refs
如果您开始删除 refs,请确保使用 Git 2.24+(2019 年第 3 季度):“git pack-refs
”可能会丢失在 运行 时创建的 refs已更正。
参见 commit a613d4f (31 Jul 2019) by Sun Chao (sunchao
)。
(由 Sun Chao -- sunchao
-- in commit a613d4f 合并,2019 年 8 月 2 日)
pack-refs: always refresh after taking the lock file
When a packed ref is deleted, the whole packed-refs file is rewritten to omit the ref that no longer exists.
However if another gc
command is running and calls pack-refs --all
simultaneously,
there is a chance that a ref that was just updated lose the newly created commits.
Through these steps, losing commits on newly updated refs can be demonstrated:
# 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
Though we have the packed-refs lock file and loose refs lock files to avoid updating conflicts, a ref will lost its newly commits if racy stat-validity of packed-refs
file happens.
The best path forward is just always refreshing after take the lock file of packed-refs
file.
我在 git filter-branch
之后忘记了 rm refs/original
并做了 git gc
,这清除了 refs
。我也致力于新的回购协议,并希望保留这些承诺。
提取的分支有几千字节的大小,但.git
仍然有 80 MB 的权重,就像过滤之前一样。
现在 refs
是空的,我不能再轻易删除 refs/original
。我怎样才能删除原件?如果可能的话,我想避免再次 filter-branch
。
你的推荐人满了(git gc
运行 git pack-refs
)。这不会对 refs 本身进行任何更改,除了不是将每个 refs 都放在一个单独的文件中,而是它们都在 "packed" fie.
您只需删除 refs/origina/
引用。理论上在每个行上使用 git update-ref -d
应该可行,但如果有很多,在编辑器中打开 .git/packed-refs
并手动删除所有 refs/original/
行可能更容易。
您可能还需要清除引用日志。
有关更多信息,请参阅 this Whosebug answer。
git gc
runsgit pack-refs
如果您开始删除 refs,请确保使用 Git 2.24+(2019 年第 3 季度):“git pack-refs
”可能会丢失在 运行 时创建的 refs已更正。
参见 commit a613d4f (31 Jul 2019) by Sun Chao (sunchao
)。
(由 Sun Chao -- sunchao
-- in commit a613d4f 合并,2019 年 8 月 2 日)
pack-refs: always refresh after taking the lock file
When a packed ref is deleted, the whole packed-refs file is rewritten to omit the ref that no longer exists.
However if anothergc
command is running and callspack-refs --all
simultaneously, there is a chance that a ref that was just updated lose the newly created commits.Through these steps, losing commits on newly updated refs can be demonstrated:
# 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
Though we have the packed-refs lock file and loose refs lock files to avoid updating conflicts, a ref will lost its newly commits if racy stat-validity of
packed-refs
file happens.
The best path forward is just always refreshing after take the lock file ofpacked-refs
file.