Как я могу объединить изменения из ветки, содержащей подмножество каталогов из другого?

Я попытаюсь сохранить эту краткую информацию.

У нас есть репозиторий git, который действует как зеркало SVN (управляется BitBucket). Этот репо содержит все проекты в компании с самого начала и каждый клон разработчика не является разумным запросом (25 + 33GiB полный клон и 15 + GiB неглубокий). Но даже тогда нам не нужен полный клон весь репозиторий, всего лишь подмножество каталогов внутри.

Используя git -subtree, мне удалось разделить все интересующие нас каталоги и подумали, что мы можем добавить эти каталоги в наши локальные репозитории, используя git -subtree add. Этот процесс прозрачен для репозитория svn. Это хорошо работает, и размер намного более управляемый (9 + 6GiB полный клон и 8GiB мелкий). Проблема в том, что я не знаю, как мы могли бы внести изменения в эти "частичные клоны" и объединить их обратно в главную ветвь.

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

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

Есть ли какая-то комбинация команд, которые я могу использовать, чтобы все это работало?


Здесь (измененные) сценарии, которые я использовал для разделения каталогов и проверки интересующих каталогов:

split_projects.sh
Я использовал git -subtree для разделения и воссоединения каталогов и использования git -replace для улучшения скорости повторного добавления (только для обработки новых коммитов). Обратите внимание, что rejoin не привязан к основному репо (я не хочу пытаться зафиксировать это, особенно с зеркалом svn).

initial_setup.sh
Это script для подготовки локального репо. Для использования пользователями Windows, многие из которых не имеют большого опыта работы с инструментами git или командной строки.

checkout_projects.sh
Фактическая проверка script.

Там другой, который извлекает обновления из разделенных подкаталогов, но я не включаю его здесь.

Ответ 1

Если вы не хотите, чтобы некоторые изменения были объединены назад, сделайте слияние --no-commit и отмените эти изменения в результате слияния перед фиксацией. Для нежелательных удалений просто git checkout желаемая версия. Для нежелательных изменений ханки git checkout --patch.

Другой вариант, который может оказаться проще, если он просто просто складывается в поддеревьях из верхнего уровня, отсутствующих в объединенной ветки, заключается в том, чтобы выполнить слияние и впоследствии изменить его, (git ls-tree @; git ls-tree @^1|grep ^04)|sort -usk4 | git mktree будет генерировать правильное дерево достаточно легко, поэтому

fixup=`(git ls-tree @; git ls-tree @^1|grep ^04)|sort -usk4|git mktree`

commit=`git show -s --pretty=%B @|git commit-tree -p @^1 -p @^2 $fixup`

git update-ref -m 'fold in missing subdirectories' @ $commit

после слияния, и все готово.

Ответ 2

в вашем случае, я боюсь, вам придется использовать вишневые подборки для перемещения изменений в исходный репозиторий

Ответ 3

Лучшее решение, которое у меня есть, - это выполнить следующие действия в разреженной проверке мелкого клонирования корневого репозитория:

git checkout -b branch-to-PR-in
git fetch remote-with-subtree-as-root
git merge -s recursive -X theirs -X subtree=path/in/root/to/subtree/ remote-with-subtree-as-root/master --allow-unrelated-histories -X theirs

Ответ 4

Если я правильно понимаю ваши сценарии:

внутри bigrepo, a $project имеет свою историю на ветке subdirs/$project, а ее содержимое в корневой директории репо
например: если вы запустите git checkout subdirs/$project в bigrepo, содержимое проекта находится в / (не в каком-то дополнительном подкаталоге).

Если это так:

Я думаю, что последовательность git subdir push -P $project должна работать:

  • один из любого "локального репо" в разделенное репо
  • один из разделенного репо на bigrepo