Створіть сховище субмодулю з папки та збережіть його історію фіксації git


111

У мене є веб-додаток, який певним чином досліджує інші веб-програми. Він містить кілька веб-демонстрацій у demosпапці, і одна з демонстраційних версій повинна мати власне сховище. Я хотів би створити окремий сховище для цієї демонстраційної програми та зробити йогосубпакет підмодуль з основного сховища, не втрачаючи своєї історії комісій.

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


Я шукав, як перемістити каталог 1 із сховища Git A у сховище Git B. +1 для посилання на статтю.
— Четабахана


Так, це дійсно дуже схоже, рішення дещо відрізняються, дякую за те, що поділився цим
— GabLeRoux

Відповіді:


191

Детальне рішення

Дивіться примітку в кінці цієї відповіді (останній абзац) для швидкої альтернативи 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>INTO<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 URL-адреси як залежності .

Якщо ви робите це таким чином, сховище ви хочете використовувати в якості вимоги повинно бути модулем НПМ , тому він повинен містити package.jsonфайл , або ви отримаєте цю помилку: Error: ENOENT, open 'tmp.tgz-unpack/package.json'.

tldr (альтернативне рішення)

Можливо, вам буде простіше використовувати npm та керувати залежностями за допомогою git urls :

  • Перемістити папку до нового сховища
  • запустити npm initвсередині обох сховищ
  • бігайте npm install --save git://github.com/user/project.git#commit-ishтам, де хочете встановити ваші залежності

39
Крок "Очистити <git сховище A>" слід уникати. Виконуючи це, ви не можете повністю відновити / оформити попередні версії / комісії зі своєї історії. Вам слід просто git rm папку та додати підмодуль. Таким чином, ви гарантуєте наявність повністю працюючої копії під час перевірки старіших комісій.
— Cybot

Ви не повинні зробити cd someLibперед кроком 2? Ви кажете "Поточна папка буде новим сховищем", але насправді вона не буде; новий сховище (підмодуль) знаходиться у цій папці.
— Jago

1
підтверджуючи: так, він працює для більш ніж одного підмодуля. Велике спасибі за детальну відповідь. Також не потрібно було використовувати npm.
— Breno Inojosa

2
Я додам інформацію про те, refs/original/...що створено на кроці 3.
— Еміль Бержерон

6
GitHub зробив статтю про те, як домогтися вилучення папки в новий сховище: help.github.com/articles/…
— jrobichaud

9

Рішення від @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

3

Рішення GabLeRoux працює добре, за винятком випадків, коли ви використовуєте 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'
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.