Створіть сховище субмодулю з папки та збережіть його історію фіксації 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.