Допустим, у меня есть настройки, которые выглядят примерно так
phd/code/
phd/figures/
phd/thesis/
По историческим причинам, все они имеют свои собственные репозитории git. Но я хотел бы объединить их в один, чтобы немного упростить вещи. Например, сейчас я могу сделать два набора изменений и сделать что-то вроде
cd phd/code
git commit
cd ../figures
git commit
Было бы (сейчас) приятно просто выполнить
cd phd
git commit
Кажется, есть несколько способов сделать это с помощью субмодулей или извлечения из моих суб-репозиториев, но это немного сложнее, чем я ищу. По крайней мере, я был бы счастлив с
cd phd
git init
git add [[everything that's already in my other repositories]]
но это не похоже на одну строку. Что-нибудь в git
этом может помочь мне?
Ответы:
Вот решение, которое я дал здесь :
Сначала сделайте полную резервную копию вашего каталога phd: я не хочу нести ответственность за ваши упущенные годы тяжелой работы! ;-)
Переместите содержимое
phd/code
вphd/code/code
и исправьте историю так, чтобы она выглядела так, как будто она всегда была там (используется команда git's filter-branch ):То же самое для содержимого
phd/figures
иphd/thesis
(просто заменитьcode
наfigures
иthesis
).Теперь ваша структура каталогов должна выглядеть так:
Затем создайте репозиторий git в корневом каталоге, вытяните в него все и удалите старые репозитории:
Наконец, теперь у вас должно быть то, что вы хотели:
Одной из приятных сторон этой процедуры является то, что она оставит не версионные файлы и каталоги на месте.
Надеюсь это поможет.
Только одно предупреждение: если в вашем
code
каталоге уже естьcode
подкаталог или файл, все может пойти не так (то же самое дляfigures
и,thesis
конечно же). Если это так, просто переименуйте этот каталог или файл перед выполнением всей этой процедуры:И когда процедура будет завершена, добавьте этот последний шаг:
Конечно, если
code
подкаталог или файл не версионирован, просто используйтеmv
вместо негоgit mv
и забудьте оgit commit
s.источник
mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"' HEAD
а потом все заработало!источник
Возможно, просто (аналогично предыдущему ответу, но с использованием более простых команд) сделать в каждом из отдельных старых репозиториев коммит, который перемещает содержимое в подкаталог с соответствующим именем, например:
а затем объединить три отдельных репозитория в одно новое, выполнив что-то вроде:
Тогда вы сохраните свои истории, но продолжите с одним репо.
источник
Вы можете попробовать стратегию слияния поддеревьев . Это позволит вам объединить репо B с репо A. Преимущество перед
git-filter-branch
ним заключается в том, что вам не нужно переписывать историю репо A (ломая суммы SHA1).источник
Решение git-filter-branch работает хорошо, но учтите, что если ваше git-репо происходит из SVN-импорта, оно может завершиться с таким сообщением:
В этом случае вам необходимо исключить начальную ревизию из ветви фильтра - т.е. изменить
HEAD
в конце на[SHA of 2nd revision]..HEAD
- см .:http://www.git.code-experiments.com/blog/2010/03/merging-git-repositories.html
источник
Решение @MiniQuark мне очень помогло, но, к сожалению, оно не учитывает теги, которые есть в исходных репозиториях (по крайней мере, в моем случае). Ниже мое улучшение ответа @MiniQuark.
Сначала создайте каталог, который будет содержать составные репо и объединенные репозитории, создайте каталог для каждого объединенного репо.
Извлеките каждый репозиторий и извлеките все теги. (Представление инструкций только для
code
подкаталога)(Это улучшение для пункта 2 в ответе MiniQuark). Переместите содержимое
new_phd/code
вnew_phd/code/code
и добавьтеcode_
префикс перед каждым тегом.После этого будет вдвое больше тегов, чем было до выполнения filter-branch. Старые теги остаются в репо и
code_
добавляются новые теги с префиксом.Удалить старые теги вручную:
Повторите пункт 2,3,4 для других подкаталогов
Теперь у нас есть структура каталогов, как в @MiniQuark anwser point 3.
Сделайте так же, как в пункте 4 MiniQuark anwser, но после выполнения pull и перед удалением
.git
dir извлеките теги:Продолжать..
Это просто другое решение. Надеюсь, это поможет кому-то, это помогло мне :)
источник
git-stitch-repo из ответа Аристотеля Пагальциса работает только для репозиториев с простой линейной историей.
Ответ MiniQuark работает для всех репозиториев, но он не обрабатывает теги и ветви.
Я создал программу, которая работает так же, как описывает MiniQuark, но она использует один коммит слияния (с N родителями), а также воссоздает все теги и ветви, чтобы указать на эти коммиты слияния.
Посмотрите репозиторий git-merge-repos для примеров, как его использовать.
источник
Я создал инструмент, который делает эту задачу. Используемый метод аналогичен (внутренне создает некоторые вещи, такие как --filter-branch), но более дружественен. Является ли GPL 2.0
http://github.com/geppo12/GitCombineRepo
источник
На самом деле, git-stitch-repo теперь поддерживает ветки и теги, в том числе аннотированные теги (я обнаружил, что есть ошибка, о которой я сообщил, и она исправлена). Что я нашел полезным, так это с тегами. Поскольку теги прикреплены к коммитам, а некоторые решения (например, подход Эрика Ли) не справляются с тегами. Вы пытаетесь создать ветку на основе импортированного тега, и она отменяет любые мерзкие слияния / перемещения и отправляет вас обратно, как если бы консолидированный репозиторий был почти идентичен репозиторию, из которого пришел тег. Кроме того, возникают проблемы, если вы используете один и тот же тег в нескольких репозиториях, которые вы «объединили / объединили». Например, если у вас есть репозиторий A ad B, оба имеют тег rel_1.0. Вы объединяете репо A и репо B в репо AB. Поскольку теги rel_1.0 находятся на двух разных коммитах (один для A и один для B), какой тег будет виден в AB? Либо тег из импортированного репо A, либо из импортированного репо B, но не оба.
git-stitch-repo помогает решить эту проблему, создавая теги rel_1.0-A и rel_1.0-B. Возможно, вы не сможете извлечь тег rel_1.0 и ожидать обоих, но по крайней мере вы можете увидеть оба, и теоретически вы можете объединить их в общую локальную ветвь, а затем создать тег rel_1.0 в этой объединенной ветке (при условии, что вы просто объединять, а не изменять исходный код). Лучше работать с ветками, так как вы можете объединять как ветки из каждого репо в локальные ветки. (dev-a и dev-b могут быть объединены в локальную ветку dev, которая затем может быть перенесена в источник).
источник
Последовательность, которую вы предложили
будет работать, но вы потеряете свою историю коммитов.
источник
Чтобы объединить второй проект с основным проектом:
А) Во втором проекте
Б) В основном проекте:
В этой ветке делайте все тяжелые преобразования, которые вам нужно сделать, и зафиксируйте их.
C) Затем вернемся к мастеру и классическому слиянию двух ветвей:
источник
Я тоже добавлю сюда свое решение. По сути, это довольно простая оболочка bash-скрипта
git filter-branch
. Как и другие решения, он переносит только основные ветви и не переносит теги. Но полная история генерации коммитов перенесена, и это короткий сценарий bash, поэтому пользователям должно быть относительно легко просматривать или настраивать.https://github.com/Oakleon/git-join-repos
источник
Этот bash-скрипт решает проблему с символами Sed Tab (например, в MacOS) и проблемой отсутствующих файлов.
Это сочетание miniquark , Marius-butuc и Райан сообщений. Приветствую их!
источник