Забыл в 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
файл.