Забыл в rm refs/original после git filter-branch

Я забыл rm refs/original после git filter-branch и сделал git gc, который очищен refs, Я также принял участие в новом репо и хотел бы сохранить эти коммиты.

Извлеченная ветвь имеет размер несколько килобайт, но .git все еще весит 80 МБ, как и до фильтрации.

Сейчас refs пусто, и я не могу легко удалить refs/original больше. Как я могу все еще удалить оригиналы? Я хотел бы избежать необходимости filter-branch еще раз, если это возможно.

1 ответ

Ваши реферы упакованы (git gc работает git pack-refs). Это не вносит изменений в самих ссылок, за исключением того, что вместо того, чтобы иметь каждый в отдельном файле, они все в "упакованном" тьфу.

Вам просто нужно удалить refs/origina/ рефов. В теории с использованием git update-ref -d на каждом должен работать, но если их много, то, вероятно, легче открыть .git/packed-refs в вашем редакторе и вручную удалите все refs/original/ линий.

Вам также может понадобиться очистить reflogs.

Смотрите этот ответ Stackru для получения дополнительной информации.

git gc работает git pack-refs

Если вы начинаете удалять ссылки, обязательно используйте Git 2.24+ (Q3 2019): " git pack-refs "может потерять ссылки, созданные во время работы, что исправляется.

Смотрите коммит a613d4f (31 июля 2019 г.) от Sun Chao ( sunchao )
(Объединено Сунь Чао - sunchao - в коммите a613d4f, 02 августа 2019 г.)

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

Несмотря на то, что у нас есть файл блокировки упакованных ссылок и свободные файлы блокировок ссылок, чтобы избежать конфликтов обновлений, ссылка потеряет свои новые коммиты, если проверка достоверности статистики packed-refs файл случается.
Лучший путь вперед всегда обновляется после взятия файла блокировки packed-refs файл.

Другие вопросы по тегам