Мне нравится думать, что я достаточно хорошо понимаю, как работает git под капотом, но эта проблема заставила меня почесать голову ...
У нас есть хранилище, которое было «воссоздано» давным-давно (до того, как я приехал), в этот момент они, кажется, создали коммит без родителя, удалили все свои ссылки на ветки и указали refs/heads/master
на новый коммит.
То, что они забыли, было то, что группа тегов все еще указывала на те предыдущие коммиты, поэтому git по-прежнему считала их «достижимыми» и поэтому со временем не очищалась. Проблема заключается в том, что у этих старых коммитов по-прежнему были большие файлы (не отслеживаемые LFS), и хотя их репо без этих предварительных коммитов составляет всего ~ 30 МБ, репо в целом (включая эти старые коммиты) по-прежнему ~ 800 МБ, поэтому я хотел бы избавиться от лишних данных.
Локально это достаточно просто, я просто запускаю git tag -d <tagname>
на всех устаревших тегах, затем запускаю git reflog expire --expire=now --all && git gc --prune=now --aggressive
и boom, репо ~ 30Mb.
Проблема заключается в попытке очистить репозиторий в облаке битбакетов, я попытался запустить git push origin :<tagname>
для каждого устаревшего тега, который удалил их из битбакета, и попросил службу поддержки Atlassian запустить git reflog expire --expire=now --all && git gc --prune=now --aggressive
на сервере, что они с радостью сделали для меня, однако, размер репо на bitbucket остался на уровне ~ 800 МБ.
Служба поддержки Atlassian попросила меня сделать голый клон репо (git clone --mirror <url>
), нажать и удалить метки на этом репо. Я не видел, какое это будет иметь значение, но решил все же попробовать. К счастью, я установил новый репо, чтобы сначала выдвинуть на первый план голого клона, чтобы иметь отдельную среду тестирования, потому что когда я запускал git push origin :<tagname>
для первого устаревшего тега в моем тестовом репо, к моему удивлению, git удалял все теги, и даже все ссылки на филиалы:
$ git push origin :v1.01
remote: error: refusing to delete the current branch: refs/heads/master
To bitbucket.org:user/repo.git
- [deleted] dev
- [deleted] prd
- [deleted] staging
- [deleted] uat
- [deleted] new-repo
- [deleted] v1.01
.... more tags
- [deleted] v6.0.0
! [remote rejected] master (deletion of the current branch prohibited)
error: failed to push some refs to 'git@bitbucket.org:user/repo.git'
Я удалил некоторые удаленные теги из вывода для удобства чтения, но, как вы можете видеть, я только попытался удалить ветку v1.01
, но git удалил все остальные теги, а также ссылки на ветки (dev
, prd
, staging
и uat
), он даже пытался удалить мастер, но это было отклонено пультом. Приведенная ниже команда показывает в локальном репо (в котором теги / ветви все еще существовали) разницу между ветками и ссылками на теги.
$ git show-ref
2cb2f87610d69d829c6800fef52751ff31d94377 refs/heads/dev
0ba963daa35dd312469eed6dddb5f4767edf792b refs/heads/master
a1ad1ec65060de4f28615beffafc42fd36dd7bea refs/heads/prd
9e910758162fae9bac595ff4bd418d52b1d2ed63 refs/heads/staging
f499abeab57af1871aa957fca69fcd0554c84ac9 refs/heads/uat
65c0509a6bb3702e46c6a908d5f1429622e53af3 refs/tags/v1.01
52368fdaa3a84ee2e5e7620abf5ddddc038e8989 refs/tags/v6.0.0
0ba963daa35dd312469eed6dddb5f4767edf792b refs/tags/new-repo
Для ясности: если я запускаю ту же команду (git push -d :v1.01
) на обычном (не --mirror
голое репо) клоне, они работают должным образом и удаляют только указанный тег.
Мне бы очень хотелось узнать, почему git ведет себя так в пустом хранилище.