Git: как удалить историю перед конкретным коммитом
Т.е. у меня есть:
root -- c1 -- c2 -- .. - c1000 -- c1001 -- c1002 -- .. -- c2000 -- top
и я хочу иметь:
root = c1000 -- c1001 -- c1002 -- .. -- c2000 -- top
Как?
(Я думаю, я могу сделать через git filter-branch
а как именно?)
(Конечно, я знаю, что это означает переписывание истории...)
2 ответа
Самый простой способ - с помощью мерзавца. Если вы редактируете файл.git / info / grafts, вы можете поместить строки в файл формата
[ref] [parent1] [parent2] ...
Любые коммиты, на которые ссылается левая сторона, обрабатываются так, как если бы перечисленные справа родители были родителями этого коммита. Таким образом, вы можете вставить строку, как
c1000
и к нему будут относиться так, как будто у него нет родителей. Затем его можно "запечь в камне", запустив git-filter-branch.
Я нашел следующее полезное для создания новых репозиториев с другим корнем (я думаю, вы спрашиваете об этом, когда говорите "удалить историю перед фиксацией"):
git fast-export master~5..master | (cd ../newrepo.git && git init . && git fast-import && git checkout)
(Вы можете сделать то же самое в том же репо)
Обратите внимание, что с Git 2.21 (Q1 2019, 7+ лет спустя), git fast-export
является более полным.
Это означает, что решение на основе git fast-export
/ import
Теперь можно сделать больше.
git fast-export master~5..master | \
(cd ../newrepo.git && git init . && git fast-import && git checkout)
Смотри коммит a965bb3, коммит 25dd3e4, коммит 530ca19, коммит fdf31b6, коммит cd13762, коммит f129c42, коммит 1f30c90, коммит b93b81e, коммит 4532be7, коммит f55c979, коммит 843b9e6 (16 ноября 2018 г.) от Elijah Newren ( newren
)
(Объединено Юнио С Хамано - gitster
- в коммите 4d59753, 04 января 2019 г.)
быстрый экспорт: добавьте опцию --show-original-ids для отображения оригинальных имен
Знание оригинальных имен (хэшей) коммитов может иногда включать пост-фильтрацию, которая в противном случае была бы трудной или невозможной.
В частности, желание переписать сообщения коммита, которые ссылаются на другие предыдущие коммиты (помимо того, что выполняется другая фильтрация), очень трудно без знания оригинальных имен каждого коммита.Кроме того, знание оригинальных имен (хэшей) BLOB-объектов может позволить
blob-id
без необходимости повторного хэширования содержимого большого двоичного объекта и, таким образом, полезно в качестве небольшой оптимизации.Как только мы добавим оригинальные идентификаторы как для коммитов, так и для больших двоичных объектов, мы можем также добавить их для тегов для полноты.
Возможно, кто-то будет использовать их.Этот коммит учит нового
--show-original-ids
опция быстрого экспорта, которая заставит его добавить 'original-oid <hash>
'линия для blob, коммитов и тегов.
Это также учитfast-import
анализировать (и игнорировать) такие строки.
Страница man теперь показывает:
--show-original-ids:
Добавьте дополнительную директиву к выводу для коммитов и BLOB-объектов,
original-oid <SHA1SUM>
,
Хотя такие директивы, скорее всего, будут игнорироваться импортерами, такими какgit-fast-import
, это может быть полезно для промежуточных фильтров (например, для перезаписи сообщений о коммитах, которые ссылаются на более старые коммиты, или для удаления больших двоичных объектов по идентификатору).
А также:
fast-export
: добавлять--reference-excluded-parents
вариант
git filter-branch
имеет отличную функцию, позволяющую переписать, например, только последние 8 коммитов линейной историиgit filter-branch $OPTIONS HEAD~8..HEAD
Если вы попробуете то же самое с
git fast-export
вы получаете историю только 8 коммитов, сHEAD~7
переписывается в корневой коммит.Есть две альтернативы:
- Не используйте отрицательную спецификацию ревизии, и когда вы фильтруете выходные данные для внесения изменений в последние 8 коммитов, просто будьте осторожны, чтобы не каким-либо образом изменить какие-либо более ранние коммиты.
- Первый забег '
git fast-export --export-marks=somefile HEAD~8
', тогда беги'git fast-export --import-marks=somefile HEAD~8..HEAD
".Оба они более подвержены ошибкам, чем хотелось бы (первый по понятным причинам; со вторым вариантом я иногда случайно включал слишком много ревизий в первую команду, а затем обнаружил, что соответствующие дополнительные ревизии не были экспортированы второй командой и, таким образом, не были изменены, как я ожидал).
Кроме того, оба бедны с точки зрения производительности.Добавить новый
--reference-excluded-parents
вариант, который вызоветfast-export
чтобы ссылаться на коммиты вне указанного диапазона rev-list-args по их sha1sum.
Такой поток будет полезен только в репозитории, который уже содержит необходимые коммиты (очень похоже на ограничение, налагаемое при использовании--no-data
).
Документация теперь включает в себя:
--reference-excluded-parents:
По умолчанию выполняется такая команда, как
git fast-export master~5..master
не будет включать коммитmaster~5
и сделаюmaster~4
больше не имеет master{tilde}5 в качестве родителя (хотя оба старыхmaster~4
и новыйmaster~4
будут все одинаковые файлы).использование
--reference-excluded-parents
вместо этого поток должен ссылаться на коммиты в исключенном диапазоне истории по их sha1sum.
Обратите внимание, что результирующий поток может использоваться только хранилищем, которое уже содержит необходимые родительские коммиты.