Этот вопрос основан на отсоединении подкаталога в отдельный Git-репозиторий
Вместо того, чтобы отсоединять один подкаталог, я хочу отсоединить пару. Например, мое текущее дерево каталогов выглядит так:
/apps
/AAA
/BBB
/CCC
/libs
/XXX
/YYY
/ZZZ
И я хотел бы это вместо этого:
/apps
/AAA
/libs
/XXX
--subdirectory-filter
Аргумент git filter-branch
не будет работать , потому что он избавляется от всего для данного каталога , за исключением в первый раз он запущен. Я думал, что использование --index-filter
аргумента для всех нежелательных файлов будет работать (хотя и утомительно), но если я попытаюсь запустить его несколько раз, я получу следующее сообщение:
Cannot create a new backup.
A previous backup already exists in refs/original/
Force overwriting the backup with -f
Любые идеи? ТИА
источник
--tag-name-filter cat
к своим параметрамРучные шаги с простыми командами git
План состоит в том, чтобы разделить отдельные каталоги на собственные репозитории, а затем объединить их. В следующих шагах вручную не использовались скрипты, предназначенные для использования, но были понятные команды, и они могли помочь объединить дополнительные N подпапок в другой репозиторий.
Делить
Давайте предположим, что ваш оригинальный репо: original_repo
1 - Разделить приложения:
2 - Сплит либс
Продолжить, если у вас более 2 папок. Теперь у вас будет два новых и временных git-хранилища.
Покори , объединяя приложения и библиотеки
3 - Подготовьте новый репо:
И вам нужно будет сделать хотя бы один коммит. Если следующие три строки должны быть пропущены, ваш первый репо появится сразу под корнем репо:
При фиксированном временном файле
merge
команда в следующем разделе остановится, как и ожидалось.Принимая во внимание обратную связь с пользователем, вместо добавления случайного файла, такого как
a_file_and_make_a_commit
, вы можете добавить или.gitignore
, иREADME.md
т. Д.4 - Слияние приложений репо первым:
Теперь вы должны увидеть каталог приложений внутри вашего нового хранилища.
git log
должен показывать все соответствующие исторические сообщения коммита.Примечание: как отметил Крис ниже в комментариях, для более новой версии (> = 2.9) git необходимо указать
--allow-unrelated-histories
с помощьюgit merge
5 - Объединить libs repo следующим образом:
Продолжайте, если у вас есть более 2 репо для слияния.
Ссылка: объединить подкаталог другого репозитория с git
источник
.gitignore
иREADME.md
файлы.git merge .. git read-tree
шаге, так как он записывает их как вновь добавленные файлы, и все мои git guis не устанавливают связь с их более ранними коммитами.Почему вы хотите запустить
filter-branch
более одного раза? Вы можете сделать все это за один раз, поэтому не нужно его форсировать (обратите внимание, что вам нужноextglob
включить его в своей оболочке, чтобы это работало):Это должно избавить от всех изменений в нежелательных подкаталогах и сохранить все ваши ветки и коммиты (если только они не влияют только на файлы в сокращенных подкаталогах, в силу
--prune-empty
) - никаких проблем с дублирующимися коммитами и т. Д.После этой операции нежелательные каталоги будут перечислены как неотслеживаемые
git status
.$(ls ...)
Необходимо улextglob
оценивается вместо вашей оболочки индексного фильтра, который используетsh
встроенную командуeval
(гдеextglob
не доступен). Смотрите Как включить опции оболочки в git? для более подробной информации об этом.источник
git
команды, и, следовательно, не так подвержен различиям в том, какls
интерпретируется в операционных системах, как обнаружил @Bae.Отвечая на мой собственный вопрос здесь ... после многих проб и ошибок.
Мне удалось сделать это с помощью комбинации
git subtree
иgit-stitch-repo
. Эти инструкции основаны на:Сначала я вытащил каталоги, которые хотел сохранить, в отдельный репозиторий:
Затем я создал новый пустой репозиторий и импортировал / сшил последние два в него:
Это создает две ветви,
master-A
иmaster-B
, каждая из которых содержит содержимое одного из прошитых РЕПО. Объединить их и очистить:Теперь я не совсем уверен, как / когда это произойдет, но после первого
checkout
иpull
второго кода этот код волшебным образом сливается с основной ветвью (любое понимание того, что здесь происходит, приветствуется!)Кажется, все работает так, как ожидалось, за исключением того, что, если я просматриваю
newRepo
историю коммитов, появляются дубликаты, когда набор изменений влияет как на, такapps/AAA
и наlibs/XXX
. Если есть способ удалить дубликаты, то это было бы идеально.источник
export PERL5LIB="$PERL5LIB:/usr/local/git/lib/perl5/site_perl/"
к моей конфигурации bash, чтобы он мог найти Git.pm. Затем я установил его с помощью cpan.git subtree add
для выполнения этой задачи. См stackoverflow.com/a/58253979/1894803Я написал фильтр git, чтобы решить именно эту проблему. Он имеет фантастическое имя git_filter и находится на github здесь:
https://github.com/slobobaby/git_filter
Он основан на превосходном libgit2.
Мне нужно было разбить большой репозиторий на множество коммитов (~ 100000), и решения, основанные на git filter-branch, заняли несколько дней. git_filter занимает минуту, чтобы сделать то же самое.
источник
Используйте расширение git 'split'
git splits
это скрипт bash, который является оболочкой,git branch-filter
которую я создал как расширение git на основе решения jkeating .Это было сделано именно для этой ситуации. В случае вашей ошибки попробуйте использовать
git splits -f
опцию принудительного удаления резервной копии. Посколькуgit splits
работает в новой ветви, она не будет перезаписывать вашу текущую ветку, поэтому резервное копирование постороннее. Смотрите readme для более подробной информации и обязательно используйте его на копии / клоне вашего репо (на всякий случай!) .git splits
.Разделите каталоги в местный филиал
#change into your repo's directory cd /path/to/repo #checkout the branch git checkout XYZ
#split multiple directories into new branch XYZ git splits -b XYZ apps/AAA libs/ZZZ
Создайте пустой репо где-нибудь. Предположим, мы создали пустой репозиторий
xyz
на GitHub с указанием пути:git@github.com:simpliwp/xyz.git
Нажмите на новый репо.
#add a new remote origin for the empty repo so we can push to the empty repo on GitHub git remote add origin_xyz git@github.com:simpliwp/xyz.git #push the branch to the empty repo's master branch git push origin_xyz XYZ:master
Клонировать только что созданный удаленный репо в новый локальный каталог
#change current directory out of the old repo cd /path/to/where/you/want/the/new/local/repo #clone the remote repo you just pushed to git clone git@github.com:simpliwp/xyz.git
источник
источник
for
Цикл стоит признать, так как другие подобные ответы не включать его. Если у вас нет локальной копии каждой ветви в вашем клоне,filter-branch
она не будет учитываться как часть ее перезаписи, что потенциально может исключить файлы, добавленные в другие ветви, но еще не объединенные с вашей текущей веткой. (Хотя это также стоит сделать дляgit fetch
любых веток, которые вы ранее проверили, чтобы убедиться, что они остаются актуальными.)Простое решение: git-filter-repo
У меня была похожая проблема, и после рассмотрения различных подходов, перечисленных здесь, я обнаружил git-filter-repo . Рекомендуется в качестве альтернативы git-filter-branch в официальной документации git здесь .
Чтобы создать новый репозиторий из подмножества каталогов в существующем репозитории, вы можете использовать команду:
Отфильтруйте несколько файлов / папок, объединяя их в цепочку:
Итак, чтобы ответить на исходный вопрос , с git-filter-repo вам просто понадобится следующая команда:
источник
Да. Принудительно перезаписать резервную копию, используя
-f
флаг при последующих вызовах,filter-branch
чтобы переопределить это предупреждение. :) В противном случае я думаю, что у вас есть решение (то есть, уничтожить нежелательный каталог одновременно сfilter-branch
).источник
Удалите резервную копию из каталога .git в refs / original, как показано в сообщении. Каталог скрыт.
источник