Я экспериментировал с использованием git поддерева и столкнулся со следующей ситуацией.
Я использовал поддерево git для добавления внешнего проекта в репозиторий, я намеренно сохранил всю историю для вышестоящего проекта, так как хочу иметь возможность ссылаться на историю проекта, а также вносить свой вклад в последующий проект позже.
Оказывается, другой участник вышестоящего проекта случайно поместил большой файл в основную ветку. Чтобы это исправить, вышестоящий проект переписал историю и принудительно перенес на мастер. При создании моего "monorepo" я включил этот коммит, и я также хотел бы удалить его.
Как я могу обновить свой репозиторий, чтобы отразить новую историю поддерева?
Моей первой попыткой было использование filter-branch для полного удаления поддерева и всей истории.
git filter-branch --index-filter 'git rm -rf --cached --ignore-unmatch upstream-project-dir' --prune-empty HEAD
Как только старая версия поддерева была удалена, я мог бы повторно добавить поддерево, используя новый основной канал восходящего потока. Однако это не сработало, потому что по какой-то причине история коммитов по-прежнему отображается в выходных данных журнала git.
Обновить
Я написал шаги, чтобы создать минимально воспроизводимый пример.
Сначала создайте пустой репозиторий git.
git init test-monorepo cd ./test-monorepo
Создайте начальный коммит.
echo hello world > README git add README git commit -m 'initial commit'
Теперь добавьте поддерево для внешнего проекта.
git remote add thirdparty git@github.com:teivah/algodeck.git git fetch thirdparty git subtree add --prefix algodeck thirdparty master
Сделай коммит на монорепо
echo dont panic >> algodeck/README.md git commit -a -m 'test commit'
Теперь попытайтесь использовать git filter-branch для удаления поддерева.
git filter-branch --index-filter 'git rm -rf --cached --ignore-unmatch algodeck' --prune-empty HEAD
Проверьте вывод журнала git, я ожидаю увидеть только мой начальный коммит.
git log
git gc --prune=now
удалять только коммиты, которые не отображаются вgit log
?git log
, без аргументов, и я все еще вижу старые коммиты.Ответы:
у вас уже есть плохой коммит в вашей истории, и вам нужно избавиться от него, прежде чем продолжить
давайте предположим, что вы
master
перенаправили последний коммит и не смогли ничего сделать (у меня действительно нет ваших ветвей в поле зрения, поэтому мне нужно предположить что-то для начала)Вы можете вернуться к предыдущему коммиту и отодвинуть маркер ветки на 1 шаг назад (или X шагов назад), который в любом случае будет безопасен, а затем снова потянуть
например
git checkout master~1
чтобы проверить родительский коммит мастера, git предупреждает, что мы отключеныgit branch master -f
чтобы заставить текущую проверку снова стать мастером, то есть она на самом деле перематывает ветку master к своему предыдущему коммиту (или X предыдущему коммиту), и отсюда не имеет значения, применил ли апстрим форс или нет, мы можем возобновить нормально, или даже вернитесь к шагу выше, если это необходимо, мы можем только извлечь мастер снова, не теряя ничего из апстрима (что для нас может быть доступно только для чтения, мы не будем ничего толкать для этого)git checkout master
чтобы быть в нашей "перемотанной" главной ветке, тот же коммит, на который мы пошли, но теперь вместо этого на веткеgit pull
снова вытащить хозяина (может быть с или без--prune
), если вверх по течению отвлечется, мы вернемся отсюда, если нет, мы получим то же, что и у нас, если мы получили то же самое и не предполагалось, возможно, мы необходимо вернуться к 1-му шагу выше и перемотать больше коммитов, напримерgit checkout master~5
или что-то еще (по мере необходимости)источник
git subtree
на вашем репо очистите историю коммитов для этого пульта:
если один из ваших собственных коммитов имеет коммит, включающий большой файл, переписайте свою историю, чтобы на этот большой файл больше не ссылались
С этими двумя шагами на большой файл больше не будет ссылаться ни один коммит в вашем репо.
Кроме того, он будет удален с вашего жесткого диска в некоторый момент времени, когда git запустит сборщик мусора и истечет время задержки для висячих больших двоичных объектов.
Если вам необходимо срочно удалить этот большой файл как можно скорее с жесткого диска:
Запустить вручную
источник