Извлечь поддерево, используя ветвь

Я использую git-subtree для извлечения каталога из моего проекта.

git subtree split --prefix=src/SubProject --branch=SubProject origin/master

Учитывая, что я хотел бы начать проект для начала (в частности, не --rejoin), как я могу разделить только изменения с origin/master на SubProject на последовательные прогоны?

Для небольших проектов это работает нормально. Я могу жить с ~ 5 секунд, чтобы разделить проект. Но на больших репозиториях это может занять довольно много времени. Я видел, что это занимает до пяти минут за раскол. Некоторые из проектов, с которыми я хочу работать, имеют более 45 вспомогательных проектов в одном хранилище.

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

  • Не нужно путать с origin/master любым способом (так что в большинстве случаев --rejoin не может быть и речи)
  • Он не должен добавлять дополнительные слияния (думаю: --ff-only при получении новых изменений из origin/master)
  • Репозиторий SubProject должен иметь стабильные идентификаторы фиксации. Это означает, что после одного или нескольких инкрементных обновлений до SubProject он должен иметь тот же идентификатор фиксации в своей истории, что и при повторном запуске исходной команды в верхней части этого сообщения.
  • Он должен быть автоматизирован и не требует ручного вмешательства

Я не боюсь сложного решения, но его нужно автоматизировать. Неудача из-за изменения истории прекрасна; в этот момент script может отступить, чтобы собрать все с нуля. В этом случае пользователь знает, что они сделали, чтобы они могли пройти через очень долгий процесс перестройки с нуля.:)

- воссоединиться

Я попытался использовать --rejoin и сохранить дополнительную копию origin/master вокруг, чтобы просто быть контейнером для измененной истории, добавленной --rejoin. Проблема, с которой я столкнулся, заключалась в том, что я не мог либо git rebase origin/master, либо git merge --ff-only origin/master без вмешательства. Мне нужно сделать это автоматическим способом, чтобы это было неприемлемо.

merge commits

Мне удалось заставить его работать так, как я хотел, с git merge origin/master, но это привело к фиксации слияния. Поскольку это коммитирование слияния никогда не будет идти вверх по ходу истории, буду, я думаю, невозможно предсказать, поэтому свежий git subtree split в первозданной среде не сможет воспроизвести ту же самую точную историю. Я мог ошибаться. Если да, объясните мне, как это будет безопасно.:)

диапазоны фиксации

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

Ответ 1

Реализовано патч для subtree split, чтобы упростить игру с этим. Теперь вы можете явно указать родителя, который заполняется, когда нет других родителей:

$ git init
$ for i in {1..100}; do
   echo $i >q
   git add q
   git commit -m $i
   mkdir -p qqq
   echo $i > qqq/w
   git add qqq/w
   git commit -m "qqq/$i"
done

$ # let do full split
$ /home/vi/src/git/git/contrib/subtree/git-subtree.sh split \
    --prefix=qqq --branch qqq HEAD
...7/200 (6)...58/200 (57)...142/200 (141)...176/200 (175)...
Created branch 'qqq'
f5120d3e676e2966802c8829b13a34c8d0c2dac4

$ # now let do partial split
$ /home/vi/src/git/git/contrib/subtree/git-subtree.sh split \
    --prefix=qqq --branch qqq2 HEAD~100
...20/100 (19)...
Created branch 'qqq2'
3632fb9fc5c7a7f0b4bf8c6743e2cd372a6d8e52

$ # Now let "continue the work" on qqq2
$ /home/vi/src/git/git/contrib/subtree/git-subtree.sh split \
   --prefix=qqq --branch qqq2 \
   --graft-parent=3632fb9fc5c7a7f0b4bf8c6743e2cd372a6d8e52 \
   HEAD~100..HEAD
Grafting 3632fb9fc5c7a7f0b4bf8c6743e2cd372a6d8e52\n
...10/100 (9)...
Updated branch 'qqq2'
f5120d3e676e2966802c8829b13a34c8d0c2dac4