Як я можу перемістити один каталог із сховища git до нового сховища, зберігаючи історію?


110

Я успадкував сховище git, що містить декілька проектів в окремих каталогах. Я хотів би розділити сховище на нові окремі сховища, по одному для кожного проекту, а потім головне сховище міститиме проекти як підмодулі. Я хотів би зробити все це, зберігаючи історію перегляду окремих проектів, якщо це можливо.

Я міг би клонувати репозиторій для кожного проекту та видаляти всі інші проекти кожного разу, але це кращий спосіб уникнути наявності історії клонованості у кожному новому сховищі проектів?


2
Додано тег git-submodules, оскільки це дуже корисно для перетворення частини репо в підмодуль.
idbrii

Відповіді:


99

Ви можете використовувати git filter-branchдля переписування історії проекту. З документації:

Щоб переписати сховище, щоб він виглядав так, ніби foodir / був його коренем проекту, і видалити всю іншу історію:

git filter-branch --subdirectory-filter foodir -- --all

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


1
Що робити, якщо я хотів виключити foodir та вилучити все, що є в історії?
saeedgnu

1
Примітка: якщо ви хочете кілька каталогів, вам потрібно буде вказати --subdirectory-filterкілька разів. EG git filter-branch --subdirectory-filter foodir --subdirectory-filter bardirта ін. --subdirectoryНе прийматимуть декількох dir, але їх можна вказати кілька разів.
EnabrenTane

3
@Adam Якщо ви хочете зберегти історію foodirв оригінальному проекті, а не переписувати її історію, просто git rm -r foodirповинно бути достатньо (це також видалить копію з вашого робочого дерева; якщо ви цього не хочете, використовуйте --cached). Якщо ви хотіли повністю видалити його з історії (відповідаючи також на питання @ ilius), вам потрібно щось на кшталтgit filter-branch --index-filter 'git rm -r --cached --ignore-unmatched foodir' -- --all
Брайан Кемпбелл

2
@ilius Вибачте, я пропустив ваше запитання раніше, див. мою відповідь вище, щоб отримати відповідь про те, як видалити каталог та його історію.
Брайан Кемпбелл

2
@ilius Так, це теж працює. Для великого проекту --index-filterрішення швидше, ніж --tree-filter, оскільки не потрібно насправді перевіряти файли, воно може просто маніпулювати індексом безпосередньо. Однак це --tree-filterможе бути трохи простіше у використанні, оскільки ви можете використовувати звичайні операції з фільтрацією, а не працювати з операціями з маніпулювання індексами.
Брайан Кемпбелл

4

Щоб експортувати папку як новий сховище, вам потрібно:

  1. Для клонування сховища, де знаходиться папка, яку ви хочете експортувати.
  2. Щоб створити порожній сховище на своєму постачальнику хостингу як GitHub, для зберігання експортованої папки.
  3. Відкрийте папку клонованого сховища та запустіть цю команду:

    git subtree push --prefix=YourFolderNameToExport https://github.com/YourUserName/YourNewCleanRepoName master
    

1
git subtreeнедоступний як пакет Cygwin. Якщо вам це потрібно: stackoverflow.com/a/27116828/2484903
Джек Міллер

2

Суть git полягає в тому, що історія втілюється в кожному коміті, шляхом хешування батьківського комітету. Ви можете "повторно" повторити коміти (це, по суті, так працює svn-імпортер), в новий сховище і зберігати лише кожен підпроект. Це, однак, знищило б значення хеш-кодів. Якщо у вас немає проблем з цим, то так і буде.

У минулому я його просто клонував і рухався далі. Це робить речі більшими, але дисковий простір дешевий; мій час дорогий.

Я також не знаю жодних інструментів для складання каталогу. Я припускаю, що ви можете git-log у каталозі, щоб знайти всі коміти в ньому, а потім відтворити коміти чимось на зразок git-fast-export?


Я підтримав це, тому що це не заслуговувало на негатив - я, звичайно, не дотримувався б такого підходу, але бачу, що він намагався
Альвін
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.