У меня есть Git-репозиторий с множеством коммитов, которые не относятся ни к одной конкретной ветке, я могу git show
их использовать, но когда я пытаюсь перечислить ветки, которые их содержат, он ничего не сообщает.
Я подумал, что это проблема с коммитом / деревом (в результате ветки -D), поэтому я сократил репозиторий, но после этого все еще вижу то же поведение:
$ git fetch origin
$ git fsck --unreachable
$ git fsck
Нет выхода, ничего не болтается (верно?). Но коммит существует
$ git show 793db7f272ba4bbdd1e32f14410a52a412667042
commit 793db7f272ba4bbdd1e32f14410a52a412667042
Author: ...
и он не доступен через любую ветку
$ git branch --contains 793db7f272ba4bbdd1e32f14410a52a412667042
не дает вывода.
Каково состояние этого коммита? Как я могу перечислить все коммиты в похожем состоянии? Как я могу удалить такие коммиты?
git
branch
git-dangling
Самер Буна
источник
источник
Ответы:
Обратите внимание, что коммиты, на которые ссылается ваш рефлог, считаются достижимыми.
Пройдите,
--no-reflogs
чтобы убедитьgit fsck
показать их вам.После истечения срока действия записей reflog эти объекты также будут очищены
git gc
.Истечение регулируется
gc.pruneexpire
,gc.reflogexpire
иgc.reflogexpireunreachable
настройки. Срgit help config
,Все значения по умолчанию вполне разумны.
источник
git help glossary
определяет это таким образом… тогда как его определение «достижимого» не сужается таким образом, поэтому они противоречивы. Забавно - так что то, что я сказал, на самом деле согласуется с путаницей вgitglossary
… Хотя не концепции сбивают с толку, а только терминология. Дело в том, что «висячие» коммиты - это те, на которые больше ничего не указывает. Будет ли это поможет , если я скажу «reflogs для иначе недостижимых фиксаций» ...?master
вы делаетеgit commit
, и получаете коммит000001
. Тогда вы делаетеgit commit --amend
, что дает вам совершить000002
. Больше нет меток или веток, указывающих на них000001
, и вы не сможете увидеть их в своем журнале без этой--reflog
опции, но при желании вы все равно можете получить к ней доступgit checkout 000001
. Теперь вопрос в том, оборванных совершить, или недостижим совершить, или ни, или оба?000001
Чтобы удалить все висячие коммиты и те, которые доступны из reflogs, сделайте это:
Но будьте уверены, что это то, что вы хотите. Я рекомендую вам прочитать страницы руководства, но вот суть:
git gc
удаляет недоступные объекты (коммиты, деревья, капли (файлы)). Объект недоступен, если он не является частью истории какой-либо ветви. На самом деле это немного сложнее:git gc
делает некоторые другие вещи, но они здесь не актуальны и не опасны.Недоступные объекты, которые моложе двух недель, не удаляются, поэтому мы используем,
--prune=now
что означает «удалить недоступные объекты, созданные ранее».Объекты также могут быть достигнуты через reflog. В то время как ветки записывают историю какого-либо проекта, повторные журналы записывают историю этих веток. Если вы исправляете, сбрасываете и т. Д. Коммиты удаляются из истории веток, но git сохраняет их на случай, если вы поймете, что допустили ошибку. Reflogs - это удобный способ выяснить, какие деструктивные (и другие) операции выполнялись на ветке (или HEAD), что упрощает отмену деструктивной операции.
Поэтому мы также должны удалить reflogs, чтобы фактически удалить все, что недоступно из ветки. Мы делаем это путем истечения срока действия
--all
reflogs. Опять же, git хранит немного reflogs, чтобы защитить пользователей, поэтому мы снова должны сказать ему не делать этого:--expire-unreachable=now
.Поскольку я в основном использую reflog для восстановления после деструктивных операций, я обычно использую
--expire=now
вместо этого, что полностью сбрасывает reflogs.источник
git reflog expire --expire-unreachable=now --all
сбрасывает все ваши тайники!У меня была та же проблема, но после того, как я следовал всем советам в этой теме:
Если это не рефлог и не ветка, ... это должен быть тег !
Я удалил теги с помощью
git tag -d <tagname>
и повторил очистку, и старые коммиты исчезли.источник
наверное просто нужно быть
также сообщать о филиалах с удаленных
источник
git push -d origin next
не помогаетgit fetch --prune
сделал свое дело. но во всех ответах мне не хватает проверки для тегов, которые ссылаются на этот коммит. Я до сих пор не знаю, как проверить теги с фиксацией (я удалил все).git fsck --unreachable
, фактически связываются по сети с удаленным, чтобы выяснить, какие коммиты достижимы?git fsck --unreachable
ему не нужно связываться по сети с удаленным, чтобы узнать, какие удаленные ветви содержат какие коммиты. Информация об удаленной ветви хранится локально, например, в.git/refs/remotes/origin
(или вpacked-refs
).У меня была похожая проблема. Я побежал
git branch --contains <commit>
, и ничего не получилось, как в вопросе.Но даже после запуска
мой коммит все еще был доступен с помощью
git show <commit>
. Это было связано с тем, что один из коммитов в его отдельной / оборванной «ветке» был помечен. Я удалил тег, снова выполнил вышеупомянутые команды, и я был золотой.git show <commit>
вернулсяfatal: bad object <commit>
- именно то, что мне было нужно. Надеюсь, это поможет кому-то, кто застрял так же, как и я.источник
Я случайно попал в ту же ситуацию и обнаружил, что мои тайники содержат ссылку на недостижимый коммит, и, следовательно, предполагаемый недостижимый коммит был доступен из тайников.
Это было то, что я сделал, чтобы сделать его действительно недоступным.
источник
git gc --prune=<date>
по умолчанию удаляет объекты старше двух недель назад. Вы можете установить более позднюю дату. Но команды git, которые создают свободные объекты, обычно запускают git gc --auto (который удаляет свободные объекты, если их число превышает значение переменной конфигурации gc.auto).Вы уверены, что хотите удалить эти коммиты? Установка по умолчанию в gc.auto гарантирует, что незакрепленные объекты не займут неоправданное количество памяти, и, как правило, хорошая идея - хранить незакрепленные объекты в течение некоторого времени. Таким образом, если завтра вы поймете, что ваша удаленная ветка содержит необходимый вам коммит, вы можете восстановить его.
источник