GIT - Удалить старые записи reflog
После большого перебазирования репозитория в соответствии с нашими последними потребностями, наш журнал reflog полон коммитов и веток. Мы достигли окончательного состояния нашей реорганизации.
Несмотря на то, что остались ветки и коммиты с большим количеством двоичных данных, репозиторий увеличился во много раз по сравнению с его исходным размером, мы решили очистить все старые записи и данные reflog.
Я копался в руководстве, но не стал намного умнее экспериментировать с истечением git-reflog
Это пример журнала (сокращенно)
-> <sha1> [development] ...
| <sha1> ...
| <sha1> ...
| <sha1> ...
| <sha1> ...
| <sha1> ...
| <sha1> ...
| <sha1> ...
-> <sha1> [master] ...
-> <sha1-old> ...
| <sha1-old> ...
| <sha1-old> ...
| <sha1-old> ...
| <sha1-old> ...
| <sha1-old> ...
| <sha1-old> ...
| <sha1-old> ...
-> <sha1-old> ...
Как вы можете видеть под веткой master, есть старые коммиты / ветки с указанием хранилища перед ребазой.
Мы ожидаем очистить reflog, чтобы хранилище выглядело как
-> <sha1> [development] ...
| <sha1> ...
| <sha1> ...
| <sha1> ...
| <sha1> ...
| <sha1> ...
| <sha1> ...
| <sha1> ...
-> <sha1> [master] ...
Чтобы мы ожидали уменьшить дисковое пространство, используемое хранилищем.
Как я могу это сделать?
Изменить (2019-03-02 12:20)
Пожалуйста, не упоминайте, чтобы удалить и повторно клонировать хранилище. Это не то, что я ищу.
Изменить (2019-03-02 12:30)
Что я пробовал до сих пор, но что не сработало
git reflog expire --expire=all
Ничего не произошло, поэтому я попытался быть умным и вызвал сборщик мусора
git gc --aggressive
Но подделка.
1 ответ
Вам нужно, в частности, --expire-unreachable
опция:
git reflog expire --expire=90.days.ago --expire-unreachable=now --all
например.
Какая разница?
Reflog - это журнал для ссылки (отсюда и название "reflog":-)). Ссылка или ссылка - это имя, начинающееся с refs/
, такие как refs/heads/master
, как имя ветви master
действительно хранится. Существует один дополнительный рефлог, для HEAD
сам, который (так как он не начинается с refs/
) технически не является ссылкой по определению, которое я связал в gitglossary, но затем в определении глоссария говорится, что есть некоторые специальные ссылки, которые не начинаются с refs/
Значит либо они в замешательстве, либо я.:-)
В любом случае, точка отсчета заключается в сохранении хеш-идентификатора (или в случае специального HEAD
ссылка, чтобы сохранить имя другой ссылки). Идентификатор хэша является значением. Вы можете обновить ссылку, которая изменяет сохраненное значение, поэтому со временем одно имя принимает несколько разных значений. Там текущее значение master
а затем есть один из одного изменения назад, master@{1}
и из двух изменений назад, master@{2}
, и так далее. (Для согласованности можно записать текущее значение master@{0}
если хотите.) Это все прописано в документации gitrevisions.
В журнале Git хранятся предыдущие значения. Reflog хранит не только предыдущее значение, но и время компьютера, когда оно было изменено, поэтому Git может обрабатывать синтаксис, например master@{3.days.ago}
найти любую запись, master@{0}
или же master@{1}
или же master@{2}
или что-то, представляет ценность master
было три дня назад. ("Три дня" означает 3 24-часовых дня: 72 часа, без минут и секунд, или ровно 259200 секунд назад. Если вы изменили master
несколько раз вчера, возможно, вам нужно быть более точным, чем просто master@{yesterday}
.)
В любом случае, предположим, что текущее значение master
является 1234567...
(какой-то большой некрасивый хэш-идентификатор), и это master@{1}
является 8888888...
в то время как master@{2}
является 3333333...
, Пока что все они похожи друг на друга. Но они не обязательно так:
1234567 <-- master
/
...--o--8888888 [master@{1}]
\
3333333 [master@{2}]
Разница между master@{1}
а также master@{2}
здесь - ну, кроме их значений и чисел внутри фигурных скобок {}
- важное отличие git reflog expire
это то, что мы можем найти master@{1}
начиная с master
(1234567
) и работает в обратном направлении. Если мы начнем с master
и вернуться на один коммит, мы приходим к master@{1}
, Если мы вернемся на следующий шаг, мы получим скучный коммит o
чей номер мы даже не знаем; мы пропускаем прямо совершить 3333333
,
В частности, в этом случае master@{2}
недоступен из текущего (1234567
) ценность master
, Таким образом, его истечение контролируется --expire-unreachable
аргумент, а не --expire
аргумент.
Если вы не выбираете конкретное значение, git reflog
будет использовать настроенный по умолчанию, если вы его настроили. При отсутствии настроенного значения по умолчанию значения по умолчанию составляют 90 дней для достижимых записей и 30 дней для недоступных записей. Так:
--expire=90.days.ago --expire-unreachable=30.days.ago
по умолчанию, если вы не изменили свои собственные значения по умолчанию. Если вы переопределите одно значение по умолчанию в командной строке, вы оставите другое значение по умолчанию в покое.
Rebase делает много недоступных
Ваш вопрос начинается с важного момента: вы сделали много перебазирования. Rebase работает, копируя коммиты, затем переключая имена веток, чтобы использовать новые (и предположительно улучшенные) коммиты. Старые все еще существуют и неизменно недоступны из новой ветки:
A'-B'-C' <-- branch
/
...--o--o
\
A--B--C [branch@{1}]
где A--B--C
это оригинальная цепочка (старые и непривлекательные коммиты) и A'-B'-C'
новые блестящие копии, которые вы хотите. Поскольку соединения всегда идут в обратном направлении, старые подсказки всегда недоступны из новых подсказок ветви, даже если они достижимы из некоторых других ссылок.