Удаленный файл из истории git все еще существует? - PullRequest
0 голосов
/ 08 января 2019

В одном старом коммите был добавлен большой файл. После нескольких коммитов он был удален, однако он остается в истории, поэтому я пытаюсь удалить этот файл из истории с помощью следующей команды:

git filter-branch -f --index-filter "git rm -rf --cached --ignore-unmatch src/main/resources/embed/linux/mongodb-linux-x86_64-3.2.0.tgz" --pru-tag-name-filter cat -- --all

результат этой команды следующий:

Rewrite 9e96a248322ba6e85efde1e41498db0d41c1ee79 (3026/5151) (13917 seconds passed, remaining 9773 predicted)    rm 'src/main/resources/embed/lib-linux-x86_64-3.2.0.tgz'
Rewrite 070cbe84ad8e1bc8f1ccec5294b600218d714e30 (4123/5151) (18963 seconds passed, remaining 4728 predicted)    rm 'src/main/resources/embed/lib-linux-x86_64-3.2.0.tgz'
Rewrite 1f5604b332d6d48169fa398b60fc5ac42124d63d (5151/5151) (24005 seconds passed, remaining 0 predicted)
Ref 'refs/heads/master' was rewritten
Ref 'refs/remotes/origin/master' was rewritten
....

как я понимаю из вывода, файл был удален из коммита 9e96a248322ba6e85efde1e41498db0d41c1ee79, поэтому я проверяю это:

git checkout 9e96a248322ba6e85efde1e41498db0d41c1ee79
ls src/main/resources/embed/linux/

результат mongodb-linux-x86_64-3.2.0.tgz. Таким образом, файл все еще существует в истории. Что я сделал не так? Как я могу удалить это послушно?

Ответы [ 2 ]

0 голосов
/ 08 января 2019

Ответ от ученика по коду в основном правильный, но немного уточним:

Невозможно изменить коммит. filter-branch (или любой механизм переписывания истории) создает новые коммиты, которые «похожи» на существующие коммиты, но с изменениями, которые вы запрашиваете. (например, ваши новые коммиты не содержат большого файла, но в остальном они выглядят как ваши старые коммиты)

Это имеет два важных следствия.

Во-первых, после того, как вы переписали историю ветки, любому, у кого есть копия этой ветки, нужно будет выполнить некоторые шаги восстановления. Вы можете узнать об этом в документации git rebase (в разделе «восстановление из исходной версии»). Если они делают не то, что нужно для восстановления, это отменит переписывание истории (поместив большой файл обратно в историю), поэтому вам нужно, чтобы все сотрудничали при переписывании истории. По этой причине иногда переписывать историю нецелесообразно. Для больших переписываний (особенно тех, которые влияют на сложную историю, множественные ветви и т. Д.) Часто лучше организовать обрезку, при которой каждый отбрасывает свои существующие клоны, а затем повторно клонирует из переписанного репо.

(Нюанс в том, что любой инструмент или документация, которая зависит от идентификаторов фиксации, также нарушается при перезаписи истории.)

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

Запуск git gc может быть частью решения, но этого недостаточно. Это потому, что сразу после переписывания в вашем репо все еще есть ссылки на старые коммиты, поэтому gc не видит их как мусор. Как минимум, вам нужно очистить флаги; могут быть и другие проблемы.

Есть способы сделать это, но обычно я обошёл проблему, просто сделав новый клон из переписанного репо. Этот клон не должен беспокоить копирование старой / удаленной истории. (Чтобы быть ясным - я не думаю, что есть какое-либо задокументированное требование, в котором говорится, что такой клон не может копировать историю несуществующей, но по моему опыту - по крайней мере, при использовании стандартной реализации git - это не ' т.) Затем вы можете уничтожить исходный репо и воссоздать его из полностью продезинфицированного клона.

0 голосов
/ 08 января 2019

как я понял из вывода файл был удален из коммита 9e96a248322ba6e85efde1e41498db0d41c1ee79

git filter-branch удалил файл, а создал новый коммит . Новый коммит имеет другой хеш, потому что его содержимое отличается. Исходный коммит с хешем 9e96a248322ba6e85efde1e41498db0d41c1ee79 все еще существует до тех пор, пока вы не запустите git gc. Обратите внимание, что если вы запустите git log | grep 9e96a, этот хеш не будет отображаться, потому что соответствующий коммит больше не будет в вашей истории.

Чтобы понять это более подробно, я предлагаю вам прочитать о том, как создается коммит. Эта статья блога объясняет это хорошо. И эта глава в Pro Git подробно описывает внутреннюю структуру git и то, как создается коммит.

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