Будет ли git навсегда удалять файлы из индекса и истории, если файлы были добавлены и удалены в рамках ребаз с помощью squash? - PullRequest
0 голосов
/ 29 октября 2019

В ветке разработки кто-то добавил каталог, который не должен быть в нашем репозитории, и с тех пор я удалил файлы. Теперь, если я вернусь и сделаю ребаз и раздавлю коммиты, сделанные до добавления после добавления, это будет похоже на то, что файлы никогда не были добавлены в репо, или они все еще будут где-то в индексе или истории?

1 Ответ

1 голос
/ 29 октября 2019

Индекс никогда не бывает постоянным. В основном это временная структура данных, которую Git использует для создания следующего коммита, который вы делаете. Вы можете изменить его в любое время, используя git add или git rmgit checkout и подобные команды заполняют его из коммитов. Так что эта часть вопроса:

будут ли [файлы] по-прежнему в индексе

, на самом деле не является разумным вопросом.

Другая частьтем не менее, более полезно:

будут ли [файлы] все еще в ... истории где-нибудь?

История в Git - это commits;коммиты являются историей.

Ни один коммит не может быть изменен, но вы можете получить Git для забудь коммитов. Git находит коммиты, начиная с имен веток, имен тегов и других подобных ссылок: каждая ссылка содержит ровно один хэш-идентификатор некоторого базового объекта Git - в основном это объекты коммитов и иногда теговые объекты для аннотированных тегов. Объекты тегов содержат другой идентификатор хеша, обычно это коммит;Коммит-объекты содержат дополнительные хеш-идентификаторы коммитов, которые идентифицируют их коммиты-предшественники.

Следовательно, «история» состоит в том, чтобы начинаться с имени, подобного master, которое содержит хеш-идентификатор: некоторую большую уродливую строку букв и цифр, но давайте просто назовем это H:

        ... <-H   <-- master

Commit H сам содержит еще один большой уродливый хэш-идентификатор;давайте назовем это G:

     ... <-G <-H   <-- master

Commit G сам содержит еще один большой уродливый хэш-идентификатор. Давайте назовем это F:

... <-F <-G <-H   <-- master

и так далее, и так далее. Это история!

Чтобы найти историю в хранилище , мы просто начинаем со всех конечных точек и работаем в обратном направлении:

        D--E   <-- dev
       /
A--B--C
       \
        F--G--H   <-- master

Commit A - этосамый первый, поэтому он не связан ни с чем раньше. Коммиты A-B-C находятся на обеих ветвях. Фиксация E - это конец dev, фиксация H - это конец master. Начиная с E и работая в обратном направлении, мы посещаем пять коммитов. Начиная с H и работая в обратном направлении, мы посещаем шесть, три из них такие же, как те, которые мы посещаем с dev. Таким образом, всего существует восемь коммитов: три общих, два уникальных для dev и три уникальных для master.

Что делает git rebase, так это copy (некоторые) коммиты вновые и улучшенные. Допустим, мы перебазируем dev, чтобы иметь только один уникальный, но улучшенный коммит. Давайте назовем этот коммит I. Мы просто организуем для предшественника I - идентификатор хэша в коммите I, который позволяет нам / Git вернуться назад, - чтобы он был коммитом C:

        D--E   [abandoned]
       /
A--B--C--I   <-- dev
       \
        F--G--H   <-- master

Теперь их всего четырефиксирует dev.

фиксирует D и E все еще существуют . Мы не можем изменить их! Но мы также не можем найти их, потому что мы находим коммиты, начиная со всех имен и работая в обратном направлении. Никакие имена не приводят нас к E;никакие имена не приводят нас к D.

Git хранит некоторые дополнительные, скрытые записи журнала - в том, что Git называет reflogs - обход в течение некоторого времени на случай, если наша перебазировка была ошибкой. Хотя эти дополнительные записи reflog существуют, мы можем использовать git reflog dev или git reflog HEAD, чтобы найти хеш-идентификатор commit E и, возможно, непосредственно тот же, что и D. Таким образом, reflogs поддерживают коммиты.

ReflОГ записи в конце концов истекает. После истечения срока они удаляются. После удаления они больше не защищают коммиты. Как только вся защита снята, коммиты и связанные с ними моментальные снимки получают право на сборку мусора или GC. По умолчанию срок действия записи reflog составляет 30 дней и 90 дней: 90 дней - это время для достижимой записи и 30 дней для недоступной записи с определением достижимый основанный на текущем хеш-идентификаторе, сохраненном в ссылке, по которой существует этот конкретный журнал. В вашем случае, если перебрасывать dev, чтобы свернуть все старые коммиты до одной новой улучшенной замены, старые считаются недостижимыми и, следовательно, получают 30 дней.

Поскольку Git всегда создает новые объекты, на некоторые из которых в конечном итоге ссылаются и которые остаются, любой объект, которому по умолчанию не менее 14 дней, освобождается от сборщика мусора. Сборщик мусора также не работает постоянно: Git запускает git gc --auto до , автоматически , вызывает его всякий раз, когда кажется, что сборщик мусора будет прибыльным.

Поскольку 30 дней - это больше, чем 14дни, ваши старые коммиты будут собраны через 30 дней после ребазинга. Чтобы это произошло раньше, вы можете сразу же прекратить действие reflogs и вручную запустить последующий git gc. Но в основном вы должны просто позволить Git сделать это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...