忘记在git filter-branch之后rm refs/original



我在git filter-branch之后忘记了rm refs/original,而做了git gc,这样就清除了refs。我还提交了新的repo,并希望保留这些提交。

提取的分支的大小为几千字节,但.git的权重仍然为80 MB,就像过滤之前一样。

现在refs是空的,我不能轻易删除refs/original了。我怎样才能去掉原件?如果可能的话,我希望避免再次使用filter-branch

您的refs被打包(git gc运行git pack-refs)。这对refs本身没有任何改变,除了将每个refs放在单独的文件中,它们都在"打包"文件中。

你只需要删除refs/origina/参考。理论上,在每一行上使用git update-ref -d应该可以工作,但如果有很多行,可能更容易在编辑器中打开.git/packed-refs并手动删除所有refs/original/行。

您可能还需要清除refflogs。

git gc运行git pack-refs

如果你开始删除refs,请确保使用Git 2.24+ (Q3 2019):"git pack-refs"可能会丢失在运行时创建的refs,这正在得到纠正。

见commit a613d4f (31 Jul 2019) by孙超(sunchao)。
(由孙超—sunchao—在commit a613d4f中合并,2019年8月2日)

pack-ref:总是在获取锁文件后刷新

当一个已打包的ref被删除时,整个已打包的ref文件将被重写以省略不再存在的ref。
但是,如果另一个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

虽然我们有打包的refs锁文件和松散的refs锁文件来避免更新冲突,但如果packed-refs文件的统计有效性不正确,一个ref会丢失它的新提交。
最好的前进路径就是总是在获取packed-refs文件的锁文件后刷新。

相关内容

  • 没有找到相关文章

最新更新