Git: как удалить историю перед конкретным коммитом - PullRequest
10 голосов
/ 18 сентября 2011

Т.е., у меня есть:

root -- c1 -- c2 -- .. - c1000 -- c1001 -- c1002 -- .. -- c2000 -- top

и я хочу иметь:

root = c1000 -- c1001 -- c1002 -- .. -- c2000 -- top

Как?

(Я думаю, я могу сделать это через git filter-branch, но как именно?)

(Конечно, я знаю, что это означает переписывание истории ...)

Ответы [ 3 ]

9 голосов
/ 18 сентября 2011

Я нашел следующее полезное для создания новых репозиториев с другим корнем (это то, о чем я думаю, что вы спрашиваете, когда говорите удалить историю перед фиксацией):

git fast-export master~5..master | (cd ../newrepo.git && git init . && git fast-import && git checkout)

(вы можете сделать то же самое в том же репо)

4 голосов
/ 18 сентября 2011

Самый простой способ - с помощью мерзавца.Если вы редактируете файл .git / info / grafts, вы можете поместить строки в файл в формате

[ref] [parent1] [parent2] ...

Все коммиты, на которые ссылается левая сторона, затем обрабатываются так, как если быродители, указанные справа, являются родителями этого коммита.Таким образом, вы можете вставить строку типа

c1000

, и она будет рассматриваться так, как будто у нее нет родителей.Затем его можно «запечь в камне», запустив git-filter-branch.

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

Обратите внимание, что с 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)

См. commit a965bb3 , commit 25dd3e4 , commit 530ca19 , commit fdf31b6 , commit cd13762 , commit f129c42 , commit 1f30c90 , commit b93b81e , commit 4532be7 , commitf55c979 , коммит 843b9e6 (16 ноября 2018 г.) Элайджа Ньюрен (newren) .
(объединено Junio ​​C Hamano -gitster - in commit 4d59753 , 04 Jan 2019)

fast-export: добавьте параметр --show-original-ids для отображенияоригинальные имена

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

Кроме того, знание оригинальных имен (хэшей) больших двоичных объектов может позволить фильтровать по blob-id без необходимости повторного хэширования.содержимое BLOB-объекта и, таким образом, полезно в качестве небольшой оптимизации.

Как только мы добавим оригинальные идентификаторы как для коммитов, так и для BLOB-объектов, мы можем также добавить их для тегов для полноты.
Возможно, кто-то будетиспользовать для них.

Этот коммит учит новой опции --show-original-ids для быстрого экспорта, которая заставит его добавить строку 'original-oid <hash>' для BLOB-объектов, коммитов и тегов.
Это такжеучит fast-import анализировать (и игнорировать) такие строки.

Страница man теперь показывает:

--show-original-ids:

Добавить дополнительную директивук выводу для коммитов и BLOB-объектов original-oid <SHA1SUM>.
Хотя такие директивы, вероятно, будут игнорироваться импортерами, такими как git-fast-import, это может быть полезно для промежуточных фильтров (, например, для перезаписи сообщений фиксации, которые ссылаются наo более старые коммиты или для удаления BLOB-объектов по id ).

И:

fast-export: добавить --reference-excluded-parents, опция

git filter-branch имеет изящную функцию, позволяющую переписывать, например, только последние 8 коммитов линейной истории

 git filter-branch $OPTIONS HEAD~8..HEAD

Если вы попробуете то же самое с git fast-export, вы получите историю только 8 коммитовHEAD~7 переписывается в корневой коммит.

Существует две альтернативы:

  1. Не используйте отрицательную спецификацию ревизии, и когда вы фильтруете выходные данные для внесения изменений в последние 8 коммитов, просто будьте осторожны сне изменять каким-либо образом более ранние коммиты.
  2. Сначала запустите '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.
Обратите внимание, что полученный поток может использоваться только хранилищем, которое уже содержит необходимые родительские коммиты .

...