Как организовать несколько репозиториев git, чтобы все они были скопированы вместе?

98

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

Теперь у меня есть несколько репозиториев git для различных проектов, некоторые из которых находятся на github. У меня также есть упомянутый мной репозиторий SVN, импортированный с помощью команды git-svn ..

В принципе, мне нравится, когда весь мой код (не только проекты, но случайные фрагменты и сценарии, некоторые вещи, такие как мое резюме, написанные мной статьи, созданные мной веб-сайты и т. Д.) Находится в одном большом репозитории, который я могу легко клонировать на удаленный компьютер. машины или карты памяти / жесткие диски в качестве резервных копий.

Проблема в том, что это частный репозиторий, а git не позволяет извлекать из определенной папки (которую я мог бы отправить на github как отдельный проект, но изменения должны появиться как в главном репозитории, так и во вспомогательных. РЕПО)

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

В настоящее время у меня есть папка git-repos (например, ~ / code_projects / proj1 / .git / ~ / code_projects / proj2 / .git /), и после внесения изменений в proj1, которые я делаю git push github, я копирую файлы в ~ / Documents / code / python / projects / proj1 / и сделайте одну фиксацию (вместо множества в отдельных репозиториях). Тогда делай git push backupdrive1и git push mymemorystickт. Д.

Итак, вопрос: как ваш личный код и проекты с репозиториями git синхронизировать и поддерживать их в резервной копии?

dbr
источник

Ответы:

74

Я бы настоятельно не советовал помещать несвязанные данные в конкретный репозиторий Git. Накладные расходы на создание новых репозиториев довольно низки, и это функция, которая позволяет полностью разделять разные родословные.

Бороться с этой идеей означает закончиться излишне запутанной историей, что затрудняет администрирование и, что более важно, инструменты «археологии» менее полезны из-за возникающего в результате размытия. Кроме того, как вы упомянули, Git предполагает, что «единицей клонирования» является репозиторий, и это практически необходимо из-за его распределенной природы.

Одно из решений - сохранить каждый проект / пакет / и т. Д. как собственный пустой репозиторий (то есть без рабочего дерева) в благословенной иерархии, например:

/repos/a.git
/repos/b.git
/repos/c.git

После принятия нескольких соглашений становится тривиальным применение административных операций (резервное копирование, упаковка, веб-публикация) ко всей иерархии, которая выполняет роль, не совсем отличную от «монолитных» репозиториев SVN. Работа с этими репозиториями также становится чем-то похожей на рабочие процессы SVN с добавлением того, что можно использовать локальные коммиты и ветки:

svn checkout   --> git clone
svn update     --> git pull
svn commit     --> git push

У вас может быть несколько пультов дистанционного управления в каждом рабочем клоне для упрощения синхронизации между несколькими сторонами:

$ cd ~/dev
$ git clone /repos/foo.git       # or the one from github, ...
$ cd foo
$ git remote add github ...
$ git remote add memorystick ...

Затем вы можете извлекать / извлекать из каждого из «источников», работать и фиксировать локально, а затем нажимать («резервное копирование») на каждый из этих пультов, когда будете готовы с чем-то вроде (обратите внимание, как это подталкивает те же коммиты и историю к каждый из пультов!):

$ for remote in origin github memorystick; do git push $remote; done

~/dev/foo Вероятно, самый простой способ превратить существующий рабочий репозиторий в такой пустой репозиторий:

$ cd ~/dev
$ git clone --bare foo /repos/foo.git
$ mv foo foo.old
$ git clone /repos/foo.git

что в основном эквивалентно -, svn importно не отбрасывает существующую "локальную" историю.

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

Дэмиен Дидерен
источник
18
Тот факт, что я продолжаю создавать множество отдельных репозиториев и писать простые скрипты, помогающие управлять ими всеми, заставляет меня чувствовать, что в git чего-то не хватает. Я просто не могу точно решить, что это такое и что с этим делать.
DonGar
Ну, вы тоже управляете множеством отдельных проектов? Взаимодействие «один-к-одному» между проектами и репозиториями кажется разумным в распределенном мире, но я бы все же организовал голые репозитории в общем дереве каталогов для упрощения резервного копирования и администрирования. (Другими словами, Git / Hg / Bzr вынуждают вас отделить администрирование от задач проекта, в то время как большинство рабочих процессов SVN объединяют эти два; теперь часто можно увидеть, как люди делегируют административную часть GitHub или другим подобным провайдерам.)
Дэмиен Дидерен,
2
эта идея имеет смысл только в том случае, если вы размещаете свои собственные проекты и / или все они имеют открытый исходный код. В противном случае вам понадобится github, вам понадобятся неограниченные частные проекты, которые могут оказаться дорогостоящими
dkinzer
2
Вместо «для удаленного в источнике github memorystick; do git push $ remote; done» можно также настроить специальный пульт для отправки с помощью одной команды на множество пультов: stackoverflow.com/questions/36862/… . (В некоторых случаях может быть удобнее.)
imz - Иван Захарящев
2
Я думаю, что недостающая вещь - это способ, которым git может хранить свои объекты отдельно по поддереву, так что единый "репозиторий" может состоять из отдельных синхронизированных, хотя и разделяемых единиц (индивидуально загружаемых без остальных) таким образом, чтобы люди могли работать с определенными подмножества, не зная об остальном.
peterk 05
28

Я хочу добавить к ответу Дэмиена, где он рекомендует:

$ for remote in origin github memorystick; do git push $remote; done

Вы можете настроить специальный пульт для нажатия на все отдельные реальные пульты с помощью 1 команды; Я нашел его на http://marc.info/?l=git&m=116231242118202&w=2 :

Итак, для "git push" (когда имеет смысл нажимать одни и те же ветки несколько раз) вы действительно можете делать то, что делаю я:

  • .git / config содержит:

    [remote "all"]
    url = master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6
    url = login.osdl.org:linux-2.6.git
    
  • и теперь git push all masterотправим "главную" ветку в оба
    этих удаленных репозитория.

Вы также можете сэкономить, вводя URL-адреса дважды, используя конструкцию:

[url "<actual url base>"]
    insteadOf = <other url base>
imz - Иван Захарящев
источник
3

Мне также интересно узнать о предлагаемых способах решения этой проблемы, и я опишу текущую настройку, которую я использую (с SVN). Я в основном создал репозиторий, который содержит иерархию мини-файловой системы, включая ее собственные каталоги bin и lib. В корне этого дерева есть сценарий, который настроит вашу среду для добавления этих bin, lib и т. Д. Других каталогов в соответствующие переменные среды. Итак, корневой каталог по сути выглядит так:

./bin/            # prepended to $PATH
./lib/            # prepended to $LD_LIBRARY_PATH
./lib/python/     # prepended to $PYTHONPATH
./setup_env.bash  # sets up the environment

Теперь внутри / bin и / lib есть несколько проектов и соответствующие им библиотеки. Я знаю, что это не стандартный проект, но кому-то из моей группы очень легко проверить репо, запустить сценарий setup_env.bash и получить самые свежие версии всех проектов локально в своих проверять, выписываться. Им не нужно беспокоиться об установке / обновлении / usr / bin или / usr / lib, и это упрощает создание нескольких проверок и очень локализованную среду для каждой проверки. Кто-то может просто запустить весь репозиторий и не беспокоиться об удалении каких-либо программ.

У нас это работает нормально, и я не уверен, что мы это изменим. Проблема в том, что в одном большом репозитории много проектов. Есть ли стандартный способ git / Hg / bzr для создания подобной среды и разбиения проектов в их собственные репозитории?

Дэнни Джи
источник
3

, Я еще не пробовал встраивать репозитории git, потому что не сталкивался с ситуацией, когда мне это нужно. Как я читал на канале #git, кажется, что git запутался из-за вложения репозиториев, то есть вы пытаетесь выполнить git-init внутри репозитория git. Единственный способ управлять вложенной структурой git - использовать утилиту git-submoduleAndroid repo.

Что касается той ответственности за резервное копирование, которую вы описываете, я говорю делегировать ее ... Для меня я обычно помещаю "исходный" репозиторий для каждого проекта на рабочий сетевой диск, который регулярно поддерживается ИТ-специалистами с помощью их стратегии резервного копирования выбор. Это просто, и мне не о чем беспокоиться. ;)

Spoike
источник
2

Как насчет использования mr для одновременного управления несколькими репозиториями Git:

Команда mr (1) может проверять, обновлять или выполнять другие действия с набором репозиториев, как если бы они были одним объединенным репозиторием. Он поддерживает любую комбинацию репозиториев Subversion, git, cvs, mercurial, bzr, darcs, cvs, vcsh, fossil и veracity, а также можно легко добавить поддержку других систем контроля версий. [...]

Его очень легко настроить с помощью простых сценариев оболочки. Вот несколько примеров того, что он может делать:

[...]

  • При обновлении репозитория git извлеките из двух разных восходящих потоков и объедините их вместе.
  • Запускайте несколько обновлений репозитория параллельно, что значительно ускоряет процесс обновления.
  • Запомните действия, которые не удалось выполнить из-за того, что ноутбук отключен, чтобы их можно было повторить, когда он снова подключится к сети.
imz - Иван Захарящев
источник
1

Есть еще один метод создания вложенных репозиториев git, но он не решает проблему, которая вам нужна. Тем не менее, для тех, кто ищет решение, я был:

В репозитории git верхнего уровня просто скройте папку в .gitignore, содержащую вложенный репозиторий git. Это позволяет легко иметь два отдельных (но вложенных!) Репозитория git.

arxpoetica
источник