Pull to refresh

Comments 25

Если вам нужно перенести все 50 (60? 100?) бранчей, то данное решение...

автоматизируется скриптом :)
А разве команда
git subtree push --prefix folder-to-move remote-name branch-name 
не сделает то же самое?
Попробовал – делает то, что надо, спасибо! Укажу это в посте
Часто использую эту команду, чтобы задеплоить сборку веба на продакшн.
Не уверен, подтягивается ли история коммитов?

Могу порекомендовать тулзу BFG, она может удалять файлы из истории типа случайно закоммиченных паролей или просто огромных файлов, которые стали не нужны, но занимают место в истории. Она, к сожалению, не умеет выпиливать по правилу "все, кроме", но можно написать простенький скрипт, чтобы из git'а вытащить список всех файлов во всех бранчах, отсортировать, выбрав уникальные, вычеркнуть sed'ом те, которые планируется оставить, а потом скормить результат bfg.

А зачем в новом репозитории делать git remote add+git remote rm? Git спокойно принимает вместо названия remote значение, на которое это название ссылается.


К тому же, кажется, вы чего‐то накосячили при клонировании или pull’е: в документации filter-branch ясно сказано, что -- --all переписывает все тёги и ветки, вам нужно просто их все склонировать а потом так же все затянуть в новом репозитории, а не заниматься скриптописательством или рутинной работой.


И clone в первом шаге лучше делать локального репозитория — это быстрее, а git не будет что‐то в оригинале менять, хотя и воспользуется по возможности жёсткими ссылками. Ещё при желании можно cp -r локальные клоны делать, хотя лучше не надо — притянет мусорные изменения. Но все ветки и тёги, с которыми вы работали будут на месте точно.

Хотя я вижу: вы точно накосячили при pull и push: тянете только master, явно. Git даёт затянуть всё сразу:


  1. В new-repo делаете git checkout -b xxx-temporary-branch-xxx — вам нужна ветка, которой нет нигде, чтобы git не вопил, что он не может затянуть что‐то в текущую ветку.
  2. git fetch path/to/movement-example '*:*': затягиваете всё, но ничего не переименовывается.
  3. git checkout master: чтобы удалить ветку нужно перейти куда‐то ещё, не важно куда
  4. git branch -D xxx-temporary-branch-xxx
  5. git push origin '*:*': отправляете всё, что затянули при fetch.

Если не ошибаюсь, то с голыми репозиториями (git clone --bare) 1, 3 и 4 не нужны.

И вообще вы занимаетесь фигнёй: делайте git push 'git@github.com:<user_or_organization>/new-repo.git' '*:*' прямо из movement-example. Новый клон не нужен, создавать remote не нужно, временная ветка не нужна, push’ити всё сразу; потом сделаете себе клон для работы уже с нужными изменениями или сделаете pull с github из имеющегося.

С таким же успехом можно просто через github UI сделать то же самое – полная копия. Мне нужна одна конкретная папка

Какая ещё полная копия?! После filter-branch там уже только нужные коммиты. Или вы думаете, что изменения в ветке master магическим образом изменятся во время pull, из‐за чего мой вариант не эквивалентен использованию промежуточного репозитория?

Хотя одну вещь в моих советах нужно изменить: везде, где одна команда с '*:*' нужно использовать две: 'refs/heads/*:refs/heads/*' и 'refs/tags/*:refs/tags/*'. Иначе получите дополнительно всю оригинальную историю, т.к. filter-branch сохраняет её в refs/original.

Серьёзно думаю над обратным процессом. Как-то не стрельнула идея в SOA-приложении выделить каждый сервис в отдельный репозиторий, объединив их через submodule.

Попробуйте такой подход: https://habrahabr.ru/post/326132/#comment_10165486

Зависимые сервисы смогут пользоваться маленькими пакетами с кусочками вашего кода, а вы сможете коммитить в монолит.

Если нужно слить проекты в один монолитный репозиторий, может помочь моя давнишняя статья. Если предварительно потренироваться на кошках фейковых репозиториях или клонах, то всё достаточно просто получается.

Спасибо, нужная вещь. Ну и раз уж пошла тема спрошу свое, может подскажет кто.
Не так давно хотелось сделать в репе submodule, но что бы в него затягивался не весь целевой репозиторий, а одна папка, к примеру include из большого С/С++ проекта, пусть только в read-only, но с сохранением возможности обновления как обычный submodule. Возможно ли такое?
Гит в такое не играет, смотрите ниже как можно выкрутиться.
Git Subsplit

# This utility uses `git-subsplit`. If you don't have one, run this:
# pusd /tmp/ && git clone git@github.com:dflydev/git-subsplit.git && cd git-subsplit && ./instal.sh && popd
#
# This utility also uses linux "parallel"
# To install a fresh version, run:
# Ubuntu:
# apt-get -y install bzip2 make && (wget -O - pi.dk/3 || curl pi.dk/3/ || fetch -o - http://pi.dk/3) | bash
#
# MacOS:
# brew install parallel

git subsplit init git@github.com:your/big-project.git

modules_array=(
    'your/subfolder/to/split:git@github.com:your/new_microservice.git',
    'your/another/subfolder/to/split:git@github.com:your/other_microservice.git',
)

printf '%s\n' "${modules_array[@]}" | parallel "git subsplit publish --heads='master staging development' --no-tags"

rm -rf .subsplit/


Делаете other_microservice.git проектом с READ-ONLY доступом и можете спокойно коммитить в основной проект, запуская утилиту в CI-процессе автоматически. В --heads можно подставлять текущую ветку с помощью чего-то вроде

```$(git symbolic-ref --short HEAD)```

Пример аналогичного подхода: https://github.com/laravel/framework как основной код и https://github.com/illuminate/queue как пакет, автоматически вырезаемый из основного (наряду с другими)
Не раскрыта тема куда девается передвигаемая папка из первоначального репозитория. — Удаляется?
Нет, с ней ничего не происходит – остается на месте :)

А что с ней станет? С клоном же работаете, push в origin не просто не делается — origin вообще удалён на третьем шаге.

Всю статью можно сократить до трех шагов:

Создать клон в соседнем каталоге

git clone --no-local . "../movement-example"

Перейти туда

cd "../movement-example"

Оставить только внутренности каталога folder-to-move

git filter-repo --subdirectory-filter "folder-to-move/"

А пакет filter-branch объявлен устаревшим и не рекомендуется к использованию.

Дополню: sudo apt install git-filter-repo

Sign up to leave a comment.

Articles