Автоматически копировать файлы с одного хранилища GitHub в другой

У меня есть два репозитория GitHub.

Я хотел бы автоматически (возможно, используя hooks и/или github API) совершать и передавать файлы во второй репозиторий, когда они будут перенесены на первый.

Второй репозиторий не является клоном первого, их макет папки не обязательно одинаковый, есть только общая часть файлов.

Каков самый простой способ сделать это?

Бонусные баллы, если мне не нужно устанавливать HTTP-сервер или изучать perl:)

Ответ 1

Если вы ищете что-то надежное и простое в обслуживании, я бы посоветовал вам разработать решение для GitHub Webhooks. Да, вам потребуется развернуть HTTP-сервер, скажем, Node.js server, и для этого потребуется небольшая часть разработки ( ваши требования достаточно специфичны), но я думаю, что он окупится, если вам понадобится что-то надежное и малое обслуживание. Если вы решите, что этот подход к зеркалированию файлов по-прежнему остается правильным, рассмотрев подходы и усилия по настройке.

Пусть исходные репозитории (на GitHub) будут S1, S2... с (неперекрывающимися) файловыми наборами в зеркало F1, F2..., которые будут отправлены в целевую repo T (также на GitHub), где соответствующие файлы считаются доступными только для чтения. Ваши требования необычны в том, что Sn и T звучат так, как будто они не клонированы друг от друга, у них может даже не быть общего коммита, и в этом случае это не сценарий push/fetch. Вы также не гарантировали, что исходные файлы-обновления происходят один-на-фиксацию или даже сгруппированы, но изолированы от нереплицирующих изменений, поэтому это не касается комков фиксации вишни.

Триггер для репликации нажимает определенные файлы на S1, S2..., а не на какой-либо клон-разработчик этих репозиториев, поэтому клики на стороне клиента не помогут (и они могут неудобно поддерживать). Разумеется, GitHub не позволяет использовать общие крючки, поэтому Webhooks - ваше лучшее решение. Вы можете рассмотреть другой, опросный клон, который регулярно вытягивается из S1..., выполняя логику и затем фиксируя T, но это звучит неудобно по сравнению с Webhooks, что даст вам надежную доставку, возможность повторного воспроизведения, достойный аудит и др.

Потенциал роста заключается в том, что существует много уже построенной инфраструктуры для поддержки такого типа настройки, поэтому фактический код, который вам нужно написать, может быть довольно небольшим. Скажите, что вы используете установку типа Node.js:

  • Развернуть github-webhook-handler. Эта прохладная небольшая библиотека представляет собой предварительно построенный обработчик для GitHub Webhooks и обрабатывает проверку HMAC X-Hub-Signature и предоставляет простые крючки для прослушивания событий для всех событий Webhooks. У вас может быть одна конечная точка на S, или, возможно, легче включить их.
  • Имейте локальный файл (сохраните его в репозитории Git), который отображает Sn в Fn.
  • Зарегистрируйте обработчик для X-GitHub-Event: push и проверите repository/name и commits[]/modified[] для путей, соответствующих вашей локальной карте.
  • Развернуть node-github, реализация GitHub APIv3 для Node.js.
  • Для каждого файла соответствия:
    • Вызвать getBlob для чтения копии utf-8 или base64 файла из Sn.
    • Вызов createBlob для повторного создания этого файла в T.
    • Сделайте серию вызовов T на getReference (текущая фиксация), getTree, createTree (создайте новый из базы и нового блоба), createCommit и, наконец, updateReference. Этот один рабочий процесс - нижний столкновение - это разветвление/слияние.

Этот подход позволяет вам делать все, не используя локальный клон T. Вам может показаться, что лучше использовать локальный клон, я бы посмотрел, как легко начать с метода API.

enter image description here

Ответ 2

Два репозитория GitHub (без стороннего сервера, которые прослушивают события webhook) не могут отражать друг друга.

Вам нужно будет зарегистрировать webhook на одном репо GitHub, чтобы обнаружить событие push и нажать ко второму репо GitHub.

Это означает наличие сервера, который прослушивает webhook полезную нагрузку json.

Инструмент типа dustin/gitmirror может помочь (в Go).

Ответ 3

EDIT. Теперь я понимаю, что вопрос был о GitHub. Мой ответ о стандартном репозитории git, к которому у вас есть доступ к файлам.

Я предполагаю, что второй репо является клоном первого, создал что-то вроде этого

git clone --bare first.git second.git

Измените текущий каталог внутри репозитория first.git и добавьте second.git в качестве удаленного.

cd first.git
git remote add second ../second.git

Затем создайте файл в папке first.git/hooks/ с именем post-receive (вы уже можете переименовать файл post-receive.sample)

Содержимое должно быть таким

#!/bin/sh
git push second

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

Ответ 4

У нас была аналогичная проблема - мы хотели автоматически копировать файлы документации между репозиториями проекта и общей документации. Мы создали инструмент, который слушает GitHub webhooks, разбирает коммит и создает запрос Pull к выбранному пункту назначения. Схема Copycat Мы открыли его - https://github.com/livechat/copycat - его можно использовать на любом сервере платформы node.

Ответ 5

Поскольку у вас есть другое репо, вы можете попытаться применить коммиты один за другим, используя git -apply/git -am, а затем нажмите.

Предполагая, что у вас есть Repo1.git и Repo2 на сервере, Repo1.git - это голый репозиторий, Repo2 - это локальный клон второго хранилища.

Repo1/.git/hooks/post-receive

#!/bin/sh
t=$(mktemp)
repo2_directory=/some/place/you/cloned/repo2
error=
while read line; do
  ref1=$(echo "$line"|cut -d' ' -f1)
  ref2=$(echo "$line"|cut -d' ' -f2)
  for ref in $(git log --oneline $ref1..$ref2); do
    git show -p --no-color --binary $ref > $t
    if !(cd $repo2_directory && git am -q < $t || (git am --abort; false)); then
      echo "Cannot apply $ref" >&2
      error=1
      break
    fi
  done
  [ -n "$error" ] && break
done
rm -f $t
[ -z "$error" ] && (cd $repo2_directory && git push)

Ответ 6

Простым способом сделать это является добавление двух (или более) pushurl в origin (или некоторых других удаленных).

Например:

git remote set-url --add --push origin url1
git remote set-url --add --push origin url2

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

Если у вас много людей, работающих с одним и тем же репо, и чтобы их изменения отражались, попробуйте запустить script, чтобы назначить новый pushurl для каждого разработчика. В противном случае, боюсь, вам понадобится использовать hooks + server.