忘记在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.