Как извлечь подкаталог git и сделать из него подмодуль?

Я начал проект несколько месяцев назад и сохранил все в главном каталоге. В моем основном каталоге «Project» есть несколько подкаталогов, содержащих разные вещи: Проект /документ содержит документ, написанный на LaTeX Project /sourcecode /RailsApp содержит мое приложение rails.

«Проект» GITified и было много коммитов как в «paper», так и в «RailsApp» каталоге. Теперь, так как я хотел бы использовать cruisecontrol.rb для моего "RailsApp", мне интересно, есть ли способ сделать подмодуль из "RailsApp" без потери истории.

106 голосов | спросил patch 28 Maypm09 2009, 14:18:41

4 ответа


0

В настоящее время существует гораздо более простой способ сделать это, чем вручную с помощью git filter-branch: поддерево git

Установка

git clone https://github.com/apenwarr/git-subtree.git

cd git-subtree
sudo rsync -a ./git-subtree.sh /usr/local/bin/git-subtree

Или если вы хотите, чтобы справочные страницы и все

make doc
make install

Использование

Разделите большее на более мелкие куски:

# Go into the project root
cd ~/my-project

# Create a branch which only contains commits for the children of 'foo'
git subtree split --prefix=foo --branch=foo-only

# Remove 'foo' from the project
git rm -rf ./foo

# Create a git repo for 'foo' (assuming we already created it on github)
mkdir foo
pushd foo
git init
git remote add origin [email protected]:my-user/new-project.git
git pull ../ foo-only
git push origin -u master
popd

# Add 'foo' as a git submodule to `my-project`
git submodule add [email protected]:my-user/new-project.git foo

Подробную документацию (справочную страницу) см. в разделе git-subtree.txt.

ответил apenwarr 20 PM000000100000001031 2009, 22:22:10
0

Оформить заказ git filter-branch .

Examples раздел страницы руководства показывает, как извлечь подкаталог в собственный проект, сохраняя всю его историю и удаляя историю других файлов /каталогов (именно то, что вы ищете ).

  

Переписать репозиторий, чтобы он выглядел так, как если бы foodir/ был корнем его проекта, и отбросить всю другую историю:

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

Таким образом, вы можете, например, превратить подкаталог библиотеки в собственный репозиторий.
  Обратите внимание на --, который отделяет параметры filter-branch от параметры ревизии и --all для перезаписи всех веток и тегов.

ответил Pat Notz 30 Maypm09 2009, 21:28:55
0

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

В основном создайте копию хранилища, а затем используйте git filter-branch , чтобы удалить все, кроме файла /папок, которые вы хотите сохранить.

Например, у меня есть проект, из которого я хочу извлечь файл tvnamer.py в новый репозиторий:

git filter-branch --tree-filter 'for f in *; do if [ $f != "tvnamer.py" ]; then rm -rf $f; fi; done' HEAD

Использует git filter-branch --tree-filter для прохождения каждого коммита, запуска команды и повторной отправки содержимого результирующих каталогов. Это чрезвычайно разрушительно (поэтому вы должны делать это только с копией вашего хранилища!) И может занять некоторое время (около 1 минуты в хранилище с 300 коммитами и около 20 файлами)

Приведенная выше команда просто запускает следующий shell-скрипт для каждой ревизии, который вам, конечно, придется изменить (чтобы исключить ваш подкаталог вместо tvnamer.py):

for f in *; do
    if [ $f != "tvnamer.py" ]; then
        rm -rf $f;
    fi;
done

Самая большая очевидная проблема - это то, что он оставляет все сообщения коммита, даже если они не связаны с оставшимся файлом. Сценарий git-remove-empty-commits , исправляет это ..

git filter-branch --commit-filter 'if [ z$1 = z`git rev-parse $3^{tree}` ]; then skip_commit "[email protected]"; else git commit-tree "[email protected]"; fi'

Вы должны использовать принудительный аргумент -f filter-branch снова с чем-либо в refs/original/ (что в основном является резервной копией)

Конечно, это никогда не будет идеальным, например, если в ваших сообщениях о коммитах упоминаются другие файлы, но он настолько близок, насколько позволяет git current (насколько я знаю).

Опять же, когда-либо запускайте это только для копии вашего хранилища! , но в итоге, чтобы удалить все файлы, кроме "thisismyfilename.txt":

git filter-branch --tree-filter 'for f in *; do if [ $f != "thisismyfilename.txt" ]; then rm -rf $f; fi; done' HEAD
git filter-branch -f --commit-filter 'if [ z$1 = z`git rev-parse $3^{tree}` ]; then skip_commit "[email protected]"; else git commit-tree "[email protected]"; fi'
ответил dbr 30 Maypm09 2009, 22:29:23
0

Если вы хотите перенести некоторое подмножество файлов в новый репозиторий, но сохранить историю, вы в итоге получите совершенно новую историю. Это будет работать следующим образом:

  1. Создайте новый репозиторий.
  2. Для каждой ревизии вашего старого репозитория объедините изменения вашего модуля с новым репозиторием. Это создаст «копию» вашей существующей истории проекта.

Автоматизировать это должно быть довольно просто, если вы не против написать небольшой, но волосатый сценарий. Просто, да, но тоже больно. Люди делали переписывание истории в Git в прошлом, вы можете выполнить поиск.

В качестве альтернативы: клонируйте репозиторий и удалите бумагу из клона, удалите приложение в оригинале. Это займет одну минуту, это гарантированно сработает, и вы сможете вернуться к более важным вещам, чем пытаться очистить свою историю мерзавцев. И не беспокойтесь о месте на жестком диске, занимаемом избыточными копиями истории.

ответил Dietrich Epp 28 Maypm09 2009, 14:29:55

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132