Разделение набора файлов в репозитории git на отдельный репозиторий с сохранением соответствующей истории

Возможный дубликат:
Как разделить репозиторий git с сохранением подкаталогов?

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

Читая, что другие сделали для разделения кода, я смотрел на filter-branch и выполнял --index-filter или --tree-filter с rm командами для файлов, которые мне не нужны. Я не хочу использовать --subdirectory-filter, так как это не подходит для подкаталога, содержащего мой код, в качестве верхнего каталога (также мы разделили один подкаталог). Ситуация усложняется тем, что некоторые файлы из исходного репозитория со временем немного перемещались, а некоторые файлы были созданы, а затем удалены. Это делает разработку списка rm немного... сложной задачей.

Я ищу способ отфильтровать все /кроме/ списка файлов/каталогов. Кто-нибудь знает, как это сделать?


person jkeating    schedule 14.05.2011    source источник
comment
Спасибо. Сделал это с git filter-branch --prune-empty --index-filter 'git ls-tree -r --name-only --full-tree $GIT_COMMIT | grep -v "^src/pyfedpkg$" |grep -v "^src/fedpkg" |grep -v "^git-changelog" | xargs git rm --cached -r' -- --all   -  person jkeating    schedule 14.05.2011
comment
Не то же самое, что stackoverflow.com/questions/2797191/ (ИМХО), поскольку он запрашивает сохранение определенного набора разреженных файлов.   -  person rogerdpack    schedule 19.09.2016
comment
Это не дубликат! Предоставленный там вопрос/ответ (2797191) относится только к файлам в одном каталоге. Этот вопрос задает набор файлов, излишне сгруппированных в одном каталоге.   -  person jxy    schedule 07.02.2017


Ответы (1)


Просто чтобы замкнуть цикл на этом, чтобы он выглядел как ответ.

Используя index-filter или tree-filter, а затем применяя обратную логику, такую ​​как git ls-tree, переданную в (несколько) grep -v, переданную в xargs для git rm, вы действительно можете удалить все, что не соответствует узкому набору имен файлов/каталогов. Вот команда, которую я использовал для разделения моих конкретных файлов:

git filter-branch \
    --prune-empty \
    --index-filter '
        git ls-tree -z -r --name-only --full-tree $GIT_COMMIT \
        | grep -z -v "^src/pyfedpkg$" \
        | grep -z -v "^src/fedpkg" \
        | grep -z -v "^git-changelog" \
        | xargs -0 -r git rm --cached -r
    ' \
    -- \
    --all
person jkeating    schedule 15.05.2011
comment
Когда файл помещается в дерево в коммите сам по себе, grep | xargs git rm приведет к ненулевому коду выхода и --index-filter завершится ошибкой. Мне пришлось дополнить xargs опцией -r или --no-run-if-empty (расширение GNU). Я предлагаю дополнить ответ как таковой. - person lkraav; 20.07.2013
comment
У меня это не получается, так как pathspec «SomeDir/SomeSubDir» не соответствует ни одному файлу. SomeSubDir — это только первая часть имени подкаталога, содержащая пробел. Так что, похоже, это решение не работает с репозиториями с подкаталогами, содержащими пробелы. Любой возможный обходной путь? - person Mark Edington; 24.05.2014
comment
Я создал скрипт bash с sed 's/ /\\ /g' и вставил его после последнего grep. Я использовал скрипт, чтобы избежать проблем с одинарными кавычками. Это помогло, но у меня все еще остались пустые коммиты. - person Mark Edington; 24.05.2014
comment
Вы захотите использовать -0 с xargs и -z с git ls-tree и grep, если хотите, чтобы он надежно работал со всеми возможными именами файлов. - person ssokolow; 02.07.2014
comment
По какой-то причине я избавился от пустых коммитов, многократно повторяя git filter-branch -f --prune-empty -- --all. - person Torsten Bronger; 29.08.2014
comment
Добавление -q к команде git rm также помогает избежать переполнения вывода rm '...' строками журнала. - person Simon Sapin; 27.11.2014
comment
Вау, в git есть один лайнер для всего :) - person enobayram; 05.12.2014
comment
Спасибо! успешно использовал эту команду для разделения каталога и двух имен файлов. - person Daniel Himmelstein; 25.10.2016
comment
В то время как это работает в некоторых репозиториях, я получил fatal: ambiguous argument 'refs/remotes/origin/master^0': unknown revision or path not in the working tree. в другом - person Hubbitus; 26.06.2018
comment
Мне пришлось добавить --ignore-unmatch к git rm, чтобы избежать сбоя файла, который был добавлен в середине истории. (git rm по умолчанию выдаст ошибку, если будет предложено удалить несуществующий файл.) - person mb7744; 01.08.2019