2008-11-10 4 views
192

Допустим, у меня есть настройки, которые выглядят как-тоОбъединение нескольких репозиториев Git

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, которые могут мне помочь?

+0

Также рассмотреть этот большой подход: http://stackoverflow.com/questions/1425892/how-do-you-merge-two-git-repositories – 2013-10-01 18:19:03

+0

Также рассмотрим: https://saintgimp.org/2013/01/22/merging-two-git-repositories-in-one-repository-without-lose-file-history/ – ptim 2017-02-27 16:30:53

ответ

2

Последовательности вы предложили

git init 
git add * 
git commit -a -m "import everything" 

будет работать, но вы потеряете историю коммитов.

+0

Потеря истории не так уж плоха, но поскольку репозиторий предназначен для моей собственной работы (т.е. , это личное), там много чего, что я не хочу версировать или еще не версию. – 2008-11-10 05:20:32

76

git-stitch-repo будет обрабатывать вывод git-fast-export --all --date-order на Git репозитории данных в командной строке, и создать поток подходящий для git-fast-import, который будет создавать новое хранилище, содержащее все коммиты в новом фиксации дерева, уважающего историю всех исходных репозиториев.

+0

Ах, спасибо! Я надеялся, что есть команда, чтобы сделать это, но, как хорошо, иногда сложно узнать всю полноту функций git :) – 2008-11-10 05:23:07

+31

Эх, это сторонний инструмент, а не часть git ... :-) – 2008-11-10 05:33:40

+1

Действительно, сейчас вы говорите мне :) Ну, я полагаю, мне нужно было узнать, как установить пакеты CPAN один день ... – 2008-11-10 05:36:18

136

Вот решение, которое я дал here:

  1. Сначала сделать полную резервную копию вашего каталога PHD: Я не хочу, чтобы нести ответственность за свои убыточные годы напряженной работы! ;-)

    $ cp -r phd phd-backup 
    
  2. Переместить содержание phd/code в phd/code/code, и исправить историю так, что она выглядит, как он всегда был там (это использует filter-branch команду Git и):

    $ cd phd/code 
    $ git filter-branch --index-filter \ 
        'git ls-files -s | sed "s-\t-&code/-" | 
        GIT_INDEX_FILE=$GIT_INDEX_FILE.new \ 
        git update-index --index-info && 
        mv $GIT_INDEX_FILE.new $GIT_INDEX_FILE' HEAD 
    
  3. Same по содержанию phd/figures и phd/thesis (просто замените code на figures и thesis).

    Теперь ваша структура каталогов должна выглядеть следующим образом:

    phd 
        |_code 
        | |_.git 
        | |_code 
        |   |_(your code...) 
        |_figures 
        | |_.git 
        | |_figures 
        |   |_(your figures...) 
        |_thesis 
         |_.git 
         |_thesis 
          |_(your thesis...) 
    
  4. Затем создайте репозиторий в корневом каталоге, тянуть все в него и удалить старые хранилища:

    $ cd phd 
    $ git init 
    
    $ git pull code 
    $ rm -rf code/code 
    $ rm -rf code/.git 
    
    $ git pull figures --allow-unrelated-histories 
    $ rm -rf figures/figures 
    $ rm -rf figures/.git 
    
    $ git pull thesis --allow-unrelated-histories 
    $ rm -rf thesis/thesis 
    $ rm -rf thesis/.git 
    

    Наконец, вы должны теперь иметь то, что вы хотели:

    phd 
        |_.git 
        |_code 
        | |_(your code...) 
        |_figures 
        | |_(your figures...) 
        |_thesis 
         |_(your thesis...) 
    

Приятная сторона этой процедуры заключается в том, что она оставит не-версии файлы и каталоги на месте.

Надеюсь, что это поможет.


Только одно слово предупреждения, хотя: если ваш каталог code уже имеет code подкаталог или файл, все может пойти совсем не так (то же самое для figures и thesis конечно). Если это так, просто переименовать этот каталог или файл, прежде чем через всю эту процедуру:

$ cd phd/code 
$ git mv code code-repository-migration 
$ git commit -m "preparing the code directory for migration" 

И когда закончится процедура, добавить этот последний шаг:

$ cd phd 
$ git mv code/code-repository-migration code/code 
$ git commit -m "final step for code directory migration" 

Конечно, если code подкаталог или файл не версируются, просто используйте mv вместо git mv, и забудьте про git commit.

20

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

$ cd phd/code 
$ mkdir code 
# This won't work literally, because * would also match the new code/ subdir, but you understand what I mean: 
$ git mv * code/ 
$ git commit -m "preparing the code directory for migration" 

, а затем объединения трех отдельных сделок рЕПО в один новый, делая как л:

$ cd ../.. 
$ mkdir phd.all 
$ cd phd.all 
$ git init 
$ git pull ../phd/code 
... 

Тогда вы сохраните историю, но будет идти с одним репо.

6

Решение ГИТ-фильтр-филиал работает хорошо, но учтите, что если ваш мерзавец репо приходит из SVN импорта может произойти сбой с сообщением вроде:

Rewrite 422a38a0e9d2c61098b98e6c56213ac83b7bacc2 (1/42)mv: cannot stat `/home/.../wikis/nodows/.git-rewrite/t/../index.new': No such file or directory 

В этом случае необходимо исключить начальный редакция от фильтра-ветви - т.е. изменить HEAD в конце концов [SHA of 2nd revision]..HEAD - см:

http://www.git.code-experiments.com/blog/2010/03/merging-git-repositories.html

16

Вы можете попробовать subtree merge strategy. Это позволит вам объединить репо B в репо A. Преимущество более git-filter-branch - это не требует, чтобы вы переписывали свою историю (ломая суммы SHA1).

3

Я создал инструмент, который выполняет эту задачу. Используемый метод аналогичен (внутренне делайте некоторые вещи, такие как --filter-branch), но более дружелюбен. Является GPL 2.0

http://github.com/geppo12/GitCombineRepo

5

решения @MiniQuark помогло мне много, но, к сожалению, он не принимает во внимание тегов, которые находятся в исходных репозиториях (по крайней мере в моем случае). Ниже мое улучшение ответа @MiniQuark.

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

    $ MkDir new_phd
    $ MkDir new_phd/код
    $ MkDir new_phd/цифры
    $ MkDir new_phd/THESIS

  2. сделать притяжением каждого хранилища и извлечь все теги. (Представление инструкции только для code поддиректории)

    $ кд new_phd/код выборки
    $ мерзавец INIT
    $ мастер мерзавец тянуть ../../original_phd/code
    $ мерзавец ../. ./original_phd/code ссылки/теги/*: ссылки/теги/*

  3. (Это улучшение пункта 2 в MiniQuark ответа) Переместить содержимое new_phd/code в new_phd/code/code и добавить code_ prefeix перед каждым тег

    $ мерзавец фильтр-ветви --index Задает-фильтр «Git LS-файлы -s | sed "s- \ t \" * - & Код/- "| GIT_INDEX_FILE = $ GIT_INDEX_FILE.new git update-index --index-info & & mv $ GIT_INDEX_FILE.new $ GIT_INDEX_FILE '--tag-name-filter' sed «s -. * - code_ & -»»ГОЛОВА

  4. После этого будет в два раза больше тегов, как это было прежде, чем сделать фильтр-ветвь старых тегов остаются в репо и новых тегах с code_ префиксом. добавлено.

    $ мерзавец тег
    мойтег1
    code_mytag1

    Удалить старые теги вручную:

    $ Ls .git/ссылки/теги/* | grep -v "/ code_" | xargs гт

    Повторите пункт 2,3,4 для других подкаталогов

  5. Теперь мы имеем структуру каталогов, как и в @MiniQuark anwser пункте 3.

  6. Do, как в пункте 4 MiniQuark anwser, но после того, как делать тянуть и перед удалением .git реж, принеси теги:

    $ мерзавец принести каталог рефов/теги/*: ссылки/теги/*

    Продолжить ..

Это просто другое решение. Надеюсь, это помогает кому-то, это помогло мне :)

5

git-stitch-repo от Aristotle Pagaltzis' answer работает только для хранилищ с простой, линейной историей.

MiniQuark's answer работает для всех репозиториев, но не обрабатывает теги и ветки.

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

См. git-merge-repos repository примеры использования.

2

На самом деле git-stitch-repo теперь поддерживает ветки и теги, включая аннотированные теги (я обнаружил, что была ошибка, о которой я сообщал, и она исправлена). То, что я нашел полезным, - это теги. Поскольку теги привязаны к фиксации, а некоторые из решений (например, подход Эрика Ли) не справляются с тегами. Вы пытаетесь создать ветку с импортированным тегом, и это приведет к отмене любого git слияния/перемещения и отправит вас назад, как консолидированный репозиторий, который почти идентичен репозиторию, из которого пришел тэг. Кроме того, существуют проблемы, если вы используете один и тот же тег для нескольких репозиториев, которые вы объединили/консолидировали ». Например, если у вас есть объявление A объявления РЕ, оба имеют тег rel_1.0. Вы объединяете репо A и репо B в repo 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, которая затем может быть перенесена в исходное состояние).

1

Слить secondProject в MainProject:

А) В secondProject

git fast-export --all --date-order > /tmp/secondProjectExport 

В) В MainProject:

git checkout -b secondProject 
git fast-import --force < /tmp/secondProjectExport 

В этой отрасли делают все тяжелые преобразования вам нужно делать и совершать их.

C) Потом обратно к мастеру и классического слияния между двумя ветвями:

git checkout master 
git merge secondProject 
0

брошу мое решение здесь тоже. Это в основном довольно простая оболочка сценария bash около git filter-branch.Как и другие решения, он только переносит главные ветви и не переносит теги. Но полные истории фиксации хозяев переносятся, и это короткий сценарий bash, поэтому пользователям должно быть относительно легко просматривать или настраивать.

https://github.com/Oakleon/git-join-repos

Смежные вопросы