Создайте репозиторий подмодулей из папки и сохраните его историю фиксации git


У меня есть веб-приложение, которое исследует другие веб-приложения особым образом. Он содержит некоторые веб-демо в demos папка и один из демо теперь должны иметь свой собственный репозиторий. Я хотел бы создать отдельный репозиторий для этого демонстрационного приложения и сделать его подпакетсубмодуль из основного репозитория без потери истории фиксации.

можно ли сохранить историю фиксации из файлов в репозитории папка и создать репозиторий из него и использовать его в качестве субмодуль вместо?

3 84

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 С --force

git push origin master --force

этап босса (см. Примечание ниже)

создать субмодуль С <git repository B> на <git repository A>

git submodule add <git repository B url>
git submodule update
git commit

проверьте, если все работает как ожидалось, и push

git 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'