Как я Повторно базируюсь мерзавец repo к родительской папке при сохранении истории? [дубликат]

51
задан masonk 16 April 2019 в 10:14
поделиться

3 ответа

Что вам нужно, так это git filter-branch , который может переместить весь репозиторий в поддерево, сохраняя историю, делая так, как будто это всегда было так. Перед использованием сделайте резервную копию своего репозитория!

Вот и волшебство. В / foo / bar запустите:

git filter-branch --commit-filter '
    TREE="$1";
    shift;
    SUBTREE=`echo -e 040000 tree $TREE"\tbar" | git mktree`
    git commit-tree $SUBTREE "$@"' -- --all

Это сделает в репозитории / foo / bar еще один подкаталог bar со всем его содержимым на протяжении всей истории. Затем вы можете переместить все репо на уровень foo и добавить к нему код baz .

Обновление :

Хорошо, вот что происходит. Коммит - это ссылка на «дерево» (представьте себе SHA, представляющее содержимое всего подкаталога файловой системы) плюс некоторые «родительские» SHA и некоторые ссылки на метаданные автора / сообщение / и т. Д. Команда git commit-tree - это бит низкого уровня, который объединяет все это вместе. Параметр - commit-filter обрабатывается как функция оболочки и запускается вместо git commit-tree во время процесса фильтрации и должен действовать как он.

Я беру первый параметр, исходное дерево для фиксации, и создаю новый «объект дерева», который сообщает, что он находится во вложенной папке, с помощью git mktree , другой низкоуровневой команды git. . Для этого мне нужно передать в него что-то похожее на дерево git, то есть набор строк (режим SP type SP SHA TAB filename); таким образом, команда эха.Затем вывод mktree заменяется первым параметром, когда я подключаюсь к реальному дереву фиксации ; «$ @» - это способ передать все остальные параметры без изменений, убрав первый с помощью shift . См. git help mktree и git help commit-tree для получения информации.

Итак, если вам нужно несколько уровней, вы должны вложить несколько дополнительных уровней объектов дерева (это не тестировалось, но является общей идеей):

git filter-branch --commit-filter '
    TREE="$1"
    shift
    SUBTREE1=`echo -e 040000 tree $TREE"\tbar" | git mktree`
    SUBTREE2=`echo -e 040000 tree $SUBTREE1"\tb" | git mktree`
    SUBTREE3=`echo -e 040000 tree $SUBTREE2"\ta" | git mktree`
    git commit-tree $SUBTREE3 "$@"' -- --all

Это должно сдвинуть реальное содержимое вниз в a / b / bar (обратите внимание на обратный порядок).

Обновление : интегрированные улучшения Из ответа Мэтью Альперта ниже. Без - --all это работает только для текущей проверенной ветки, но, поскольку вопрос касается всего репо, имеет больше смысла делать это таким образом, чем ветвь за веткой.

25
ответ дан 7 November 2019 в 10:21
поделиться

Вместо того чтобы создавать новый репозиторий, переместите то, что находится в вашем текущем репозитории, в нужное место: создайте новый каталог bar в вашем текущем каталоге и переместите туда текущее содержимое (так ваш код окажется в /foo/bar/bar). Затем создайте каталог baz рядом с новым каталогом bar (/foo/bar/baz). mv /foo /foo2; mv /foo2/bar /foo; rmdir /foo2 и готово :).

Отслеживание переименований в Git'е означает, что ваша история будет работать, а хэширование содержимого в Git'е означает, что даже если вы перемещали вещи, вы все еще ссылаетесь на те же объекты в репозитории.

16
ответ дан 7 November 2019 в 10:21
поделиться

Вы можете создать git-репо в foo и ссылаться на baz и bar через git submodules.

Тогда и bar, и baz сосуществуют с сохранением полной истории.


Если вам действительно нужно только одно репозиторий (foo), с историей bar и baz в нем, тогда некоторые графты или стратегия слияния поддеревьев в порядке.

0
ответ дан 7 November 2019 в 10:21
поделиться
Другие вопросы по тегам:

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