Создайте репозиторий подмодулей из папки и сохраните его историю фиксации git
У меня есть веб-приложение, которое исследует другие веб-приложения особым образом. Он содержит некоторые веб-демо в demos папка и один из демо теперь должны иметь свой собственный репозиторий. Я хотел бы создать отдельный репозиторий для этого демонстрационного приложения и сделать его подпакетсубмодуль из основного репозитория без потери истории фиксации.
можно ли сохранить историю фиксации из файлов в репозитории папка и создать репозиторий из него и использовать его в качестве субмодуль вместо?
3 ответа:
Подробное Решение
см. примечание в конце этого ответа (последний абзац) для быстрой альтернативы подмодулям git с использованием npm;)
в следующем ответе вы узнаете, как извлечь папку из репозитория и сделать из нее репозиторий git, а затем включить его в качестве субмодуль вместо папки.
вдохновленный статьей Герга Байера перемещение файлов из одного репозитория Git в другой Другой, Сохраняя Историю
в начале, у нас есть что-то вроде этого:
<git repository A> someFolders someFiles someLib <-- we want this to be a new repo and a git submodule! some filesв шагах ниже, я буду ссылаться на это
someLibкак<directory 1>.в конце концов, у нас будет что-то вроде этого:
<git repository A> someFolders someFiles @submodule --> <git repository B> <git repository B> someFolders someFilesсоздайте новый репозиторий git из папки в другом репозитории
Шаг 1
получить новую копию репозитория для разделения.
git clone <git repository A url> cd <git repository A directory>шаг 2
текущая папка будет новым репозиторием, поэтому удалите текущий пульт дистанционного управления.
git remote rm originШаг 3
извлеките историю нужной папки и зафиксируйте ее
git filter-branch --subdirectory-filter <directory 1> -- --allтеперь у вас должен быть репозиторий git с файлами из
directory 1в корне вашего РЕПО со всей связанной историей фиксации.Шаг 4
создайте свой онлайн-репозиторий и нажмите свой новый репозиторий!
git remote add origin <git repository B url> git pushвы можете нужно установить
upstreamветка для вашего первого толчкаgit push --set-upstream origin masterочистить
<git repository A>(необязательный, см. замечания)мы хотим удалить следы (файлы и историю фиксации)
<git repository B>С<git repository A>так что история для этой папки есть только один раз.это основано на удаление конфиденциальных данных из github.
заходим в новую папку и
git clone <git repository A url> cd <git repository A directory> git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch <directory 1> -r' --prune-empty --tag-name-filter cat -- --allзаменить
<directory 1>на папку, которую вы хотите удалить.-rбудет сделать это рекурсивно внутри указанного каталога :). Теперь нажмите наorigin/masterС--forcegit push origin master --forceэтап босса (см. Примечание ниже)
создать субмодуль С
<git repository B>на<git repository A>git submodule add <git repository B url> git submodule update git commitпроверьте, если все работает как ожидалось, и
pushgit push origin masterПримечание
сделав все это, я понял в моем случае, что было бы более уместно использовать npm чтобы управлять своими собственными вместо этого-зависимости. Мы можем указать URL-адреса и версии git, см. пакета.JSON git urls как зависимости.
если вы делаете это таким образом, репозиторий, который вы хотите использовать в качестве требования должны быть НПМ модуль поэтому он должен содержать или вы получите эту ошибку:
Error: ENOENT, open 'tmp.tgz-unpack/package.json'.tldr (альтернативное решение)
вы можете найти его проще использовать npm и управление зависимостями с помощью git URL-адреса:
- переместить папку в новый репозиторий
- run
npm initвнутри оба хранилища- run
npm install --save git://github.com/user/project.git#commit-ishгде вы хотите, чтобы ваши зависимости установлены
решение @GabLeRoux раздавливает ветви и связанные коммиты.
простой способ клонировать и сохранить все эти дополнительные ветви и коммиты:
1-Убедитесь, что у вас есть этот псевдоним git
git config --global alias.clone-branches '! git branch -a | sed -n "/\/HEAD /d; /\/master$/d; /remotes/p;" | xargs -L1 git checkout -t'2-клонируйте пульт, потяните все ветви, измените пульт, отфильтруйте каталог, нажмите
git clone git@github.com:user/existing-repo.git new-repo cd new-repo git clone-branches git remote rm origin git remote add origin git@github.com:user/new-repo.git git remote -v git filter-branch --subdirectory-filter my_directory/ -- --all git push --all git push --tags
решение Габлеру работает хорошо, за исключением того, если вы используете
git lfsи имеет большие файлы в каталог, который вы хотите отключить. В этом случае после шага 3 все большие файлы останутся указателей файлов, а не реальные файлы. Я думаю, это, вероятно, из-за.gitattributesфайл удаляется в процессе ветви фильтра.понимая это, я нахожу следующее решение работает для меня:
cp .gitattributes .git/info/attributesкопирование
.gitattributesкоторый git lfs использует для отслеживания больших файлов в.git/каталог, чтобы избежать удаления.когда фильтр-ветвь делается не забудьте положить обратно
.gitattributesЕсли вы все еще хотите использовать Git LFS для нового репозитория:mv .git/info/attributes .gitattributes git add .gitattributes git commit -m 'added back .gitattributes'