Перерахування та видалення Git-комітетів, які не мають жодної гілки (звисання?)


146

У мене є сховище Git з великою кількістю комітетів, які не знаходяться під жодною гілкою, я можу git showїх, але коли я намагаюся перерахувати гілки, які їх містять, він нічого не повідомляє.

Я подумав, що це питання, що звисає до комітетів / дерева (внаслідок гілки -D), тому я підрізав репо, але все ще бачу таку поведінку після цього:

$ git fetch origin

$ git fsck --unreachable
$ git fsck

Немає виходу, нічого не звисає (правда?). Але комітет існує

$ git show 793db7f272ba4bbdd1e32f14410a52a412667042
commit 793db7f272ba4bbdd1e32f14410a52a412667042
Author: ...

і це недоступно через будь-яку гілку як

$ git branch --contains 793db7f272ba4bbdd1e32f14410a52a412667042

не дає виводу.

Який саме стан цього комітету? Як я можу перерахувати всі комісії у подібному стані? Як я можу видалити такі документи?


можливий дублікат Як видалити помилкові
Джош Лі

Відповіді:


75

Немає результатів, нічого не звисає (правда?)

Зауважте, що зобов’язання, на які посилається ваш рефлог, вважаються доступними.

Який саме стан цього комітету? Як я можу перерахувати всі комісії з подібним станом

Перейдіть, --no-reflogsщоб переконати, git fsckщоб показати їх вам.

Як я можу видалити такі документи?

Після закінчення терміну дії ваших записів на релогі, ці об'єкти також будуть очищені git gc.

Закінчення регулюється gc.pruneexpire, gc.reflogexpireі gc.reflogexpireunreachableнастройки. Ср. git help config.

За замовчуванням усі цілком розумні.


2
тож ви в основному говорите, що поповнення за звисаючими комісіями буде знято через деякий час автоматично?
MoralCode

2
В основному: так - за винятком того, що питання трохи плутається. Я кажу, що всі записи відмивання через деякий час видаляються автоматично, але ви можете змінити це через налаштування конфігурації. І тому, що робить тільки називається обірваним , коли він не має нічого вказує на нього - в те числі reflog записів - «reflogs для обірваних здійснюють» не річ. Це були б "відмови від недосяжних зобов'язань".
Арістотель Пагалціс

"Це були б" відмови від недосяжних зобов'язань "." Але ви сказали, що "зобов'язання, про які йдеться у вашому релозі, вважаються доступними". Тож як "річ відмови від недосяжних зобов'язань" може бути річчю? Я так розгубився.
LarsH

1
Так, я не був послідовним. Зазвичай люди не замислюються про відмову, і коли вони кажуть "недоступні", це означає "з відмови". Навіть git help glossaryвизначає це таким чином… тоді як визначення цього поняття «доступний» таким чином не звужується, тому вони суперечливі. Смішно - тому те, що я сказав, насправді узгоджується з плутаниною в gitglossary… Однак, це не ті поняття, які бентежать, а лише термінологія. Справа в тому, що «звисаючі» зобов’язання - це ті, на що більше нічого не вказує. Чи допоможе це, якщо я скажу «відмовляється від інших недосяжних зобов’язань»…?
Арістотель Пагалціс

Це все дуже заплутано. Давайте зробимо це простим. Коли на гілки master, ви робите git commit, і отримати Комміт 000001. Тоді ви робите git commit --amend, що дає вам зобов’язання 000002. Більше не вказуються теги чи гілки 000001, і ви не можете бачити їх у своєму журналі без --reflogможливості, але якщо хочете, ви все одно можете дістатися до нього git checkout 000001. Тепер питання полягає в тому, чи 000001є звисаючий вчинок, чи недосяжний вчинок, чи ні, чи те й інше?
chharvey

264

Щоб видалити всі звисаючі коміти та ті, які доступні з відхилень, виконайте це:

git reflog expire --expire-unreachable=now --all
git gc --prune=now

Але будьте впевнені, що цього ви хочете. Я рекомендую вам ознайомитися зі сторінками man, але ось суть:

git gcвидаляє недоступні об’єкти (коміти, дерева, краплі (файли)). Об'єкт недоступний, якщо він не є частиною історії якоїсь галузі. Насправді це трохи складніше:

git gc робить якісь інші речі, але вони тут не доречні і не небезпечні.

Недоступні об'єкти молодші двох тижнів не видаляються, тому ми використовуємо, --prune=nowщо означає "видалити недоступні об'єкти, які були створені раніше".

Об'єкти також можна досягти за допомогою рефлогу. У той час як філії записують історію деяких проектів, рефлоги записують історію цих гілок. Якщо ви змінюєте, скидаєте тощо, комісії видаляються з історії філії, але git зберігає їх у випадку, якщо ви зрозумієте, що ви допустили помилку. Reflogs - це зручний спосіб з’ясувати, які руйнівні (та інші) операції виконувались на гілці (або HEAD), полегшуючи скасування деструктивної операції.

Таким чином, ми також повинні видалити відхилення, щоб фактично видалити все, що недоступне з гілки. Ми робимо це шляхом закінчення терміну дії --allрефлог. Знову ж мерзотник тримає трохи з reflogs , щоб захистити користувачів , тому ми знову повинні сказати йому , щоб не зробити так: --expire-unreachable=now.

Оскільки в основному я використовую рефлог для відновлення після руйнівних операцій, я зазвичай використовую --expire=nowзамість цього, який повністю затримує рефлоги.


1
Я кажу вам, які команди використовувати, що не очевидно - чи не повинно бути gc достатньо? Якщо ви ніколи не використовували git-reflog раніше, не знаєте. Отже, тепер, коли ви знаєте, які команди вам належать використовувати, слід шукати згадані параметри на їхніх сторінках. Звичайно, я міг замість цього просто скопіювати цю інформацію звідти…
tarsius

1
Ну, власне, я точно кажу, що це робить: "видаліть усі звисаючі коміти та ті, які доступні з відходів". Якщо ви не знаєте, що таке відмови: ще раз прочитайте посібник.
Тарсій

7
Хоча наведена відповідь може бути правильною, @ erikb85 є правильним, вказуючи, що не було відомо про те, що вам сказали. Слідкувати за RTFM ще менш корисно. Так, ми всі повинні прочитати всю документацію. У деяких випадках, можливо, людина, яка проводить пошук, не накопичує документацію достатньо, щоб знати, що відбувається. Отже, трохи розуміння того, що виконують команди, було б корисно для всіх, хто знайде цю відповідь пізніше.
Лі Саферит

@LeeSaferite сподіваюся, що ви всі зараз щасливі :-)
tarsius

12
git reflog expire --expire-unreachable=now --allскидає всі свої стаси!
Всеволод Голованов

22

У мене виникло те саме питання, як і раніше, дотримуючись усіх порад у цій темі:

git reflog expire --expire-unreachable=now --all
git gc --prune=now
git fsck --unreachable --no-reflogs   # no output
git branch -a --contains <commit>     # no output
git show <commit>                     # still shows up

Якщо це не рефлог і не гілка, ... це повинен бути тег !

git tag                             # showed several old tags created before the cleanup

Я видалив теги за допомогою git tag -d <tagname>та очистив повторно, і старі комісії пішли.


Відповідь щодо тегів уже є ( stackoverflow.com/a/37335660/450127 ), і, схоже, це не додає нічого нового. Чи не слід це зняти на користь попередньої відповіді?
Ian Dunn

Дійсно, я якось не помітив цю відповідь. Хоча 4 людини вважають мою відповідь корисною, тож, можливо, це не так марно? Також я згрупував усі можливості в одну стислу відповідь.
jakub.g

1
Навіть якщо вона дублюється, ця сторінка може з’являтися в результатах Google, і вона одразу допомагає людям з тим же питанням, краще, ніж просто перенаправляти людей знову і знову на посилання, на які може бути правильна відповідь.
Олександр Т.

14
git branch --contains 793db7f272ba4bbdd1e32f14410a52a412667042

певно, просто треба

git branch -a --contains 793db7f272ba4bbdd1e32f14410a52a412667042

також звітувати про гілки з віддалених


дякую, тепер я знайшов своє віддалене / походження / наступне, яке все ще містить це зобов'язання. як її видалити? git push -d origin nextне допомагає.
iRaS


дякую - git fetch --pruneзробив трюк. але в усіх відповідях мені не вистачає перевірки тегів, на які посилається ця комітка. Я досі не знаю, як перевірити наявність тегів з фіксацією (я видалив усі).
iRaS

Але ... чи це означає, що комісії, які доступні лише з віддалених гілок (а не місцевих гілок), вважаються доступними, і тому git fsck --unreachableнасправді спілкується по мережі з віддаленим, щоб з'ясувати, які коміти доступні?
LarsH

1
Відповів на моє власне запитання ... так, комісії, доступні лише з віддалених гілок (а не місцевих гілок), вважаються доступними; але git fsck --unreachableне потрібно спілкуватися через мережу з дистанційним, щоб дізнатися, які віддалені гілки містять, які коміти. Інформація про віддалену гілку зберігається локально, наприклад, наприклад .git/refs/remotes/origin(або в packed-refs).
LarsH

8

У мене було подібне питання. Я побіг git branch --contains <commit>, і він не повернув результатів, як у питанні.

Але навіть після бігу

git reflog expire --expire-unreachable=now --all
git gc --prune=now

мій вчинок все ще був доступний за допомогою git show <commit>. Це було через те, що один із комітетів у його відокремленій / розвішаній "гілці" був позначений. Я видалив тег, запустив вищезазначені команди знову, і я був золотим. git show <commit>повернувся fatal: bad object <commit>- саме те, що мені було потрібно. Сподіваюся, це допомагає комусь іншому, який був настільки ж застряг, як і я.


як ви видалили тег?
бапор

@bapors Перелічіть усі теги, знайдіть те, що посилається на комітет, про який йдеться, та видаліть його. stackoverflow.com/questions/5480258/…
Ендрю Ларссон

4

Я випадково потрапив у ту саму ситуацію і виявив, що мої статки містять посилання на недосяжне зобов’язання, і, таким чином, припущенний недоступний вчинок був доступний від сховищ.

Це було те, що я зробив, щоб зробити це справді недосяжним.

git stash clear
git reflog expire --expire-unreachable=now --all
git fsck --unreachable
git gc --prune=now

2

git gc --prune=<date>за замовчуванням обрізати предмети старше двох тижнів тому. Ви можете встановити більш пізню дату. Але команди git, які створюють вільні об'єкти, як правило, будуть виконувати git gc --auto (які підрізають вільні об'єкти, якщо їх кількість перевищує значення змінної конфігурації gc.auto).

Ви впевнені, що хочете видалити ці зобов'язання? Настройка за замовчуванням gc.auto забезпечить, щоб вільні об'єкти не займали необгрунтовану кількість пам'яті, а зберігання сипучих об'єктів протягом певного часу, як правило, є хорошою ідеєю. Таким чином, якщо ви усвідомлите завтра, що видалена гілка містить необхідний вам зобов’язання, ви можете відновити її.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.