Как мне сделать git-хук для изменения, а затем зеркального отображения репозитория git?

У меня есть репозиторий GitHub для моих точечных файлов здесь.

Он содержит скрипт installdotfiles.sh для установки точечных файлов с GitHub. Я хотел бы иметь еще один репозиторий git в GitLab для резервного копирования (и действительно крутую пользовательскую подсветку синтаксиса : P), отражающий этот репозиторий, за исключением запуска команды оболочки в репозитории:

grep -rl raw.githubusercontent . | 
      xargs sed -i ''
     's/raw.githubusercontent/gitlab/g'; grep -rl 'dotfiles/master' . |
      xargs sed -i '' 's/dotfiles\/master/dotfiles\/raw\/master/g'

который заменяет ссылки на Github соответствующими ссылками на GitLab.

По сути, если я нажимаю на свой репозиторий dotfiles GitHub, я бы автоматически обновлял свой репозиторий GitLab, за исключением того, что сначала запускал скрипт в репозитории, поэтому мой репозиторий GitLab содержит ссылки GitLab.

Как бы я реализовал такой хук?

Я слышал, что это можно реализовать с помощью Git Hooks, однако я с ними не знаком, и, читая о них, я не совсем понимаю, как это можно сделать.

P.S. Было бы хорошо, если бы это работало в обоих направлениях — поэтому, когда я нажимаю на GitLab, GitHub запускает другой скрипт, который заменяет ссылки GitLab на ссылки GitHub, так что всякий раз, когда я нажимаю на одну, обе обновляются соответственно.


person thepiercingarrow    schedule 21.03.2016    source источник


Ответы (2)


Самый простой подход — заставить ваш скрипт installdotfiles.sh использовать переменную, которую вы устанавливаете (перед вызовом скрипта) в зависимости от репо, из которого вы хотите получить свои файлы.

Например:

origin=github curl https://raw.githubusercontent.com/thepiercingarrow2/dotfiles/master/installdotfiles.sh | sh
# or
origin=gitlab curl https://gitlab.com/thepiercingarrow2/dotfiles/raw/master/.bash_profile | sh

Это означает, что ваш скрипт включает простой тест:

remote="raw.githubusercontent.com/thepiercingarrow2/dotfiles"
if [[ "${origin}" == "gitlab" ]]; then
   remote="gitlab.com/thepiercingarrow2/dotfiles/raw"
fi

#bash_profile
curl -# https://${remote}/master/.bash_profile > ~/.bash_profile

Другими словами, вам на самом деле не нужен git-хук. Любого вида.

person VonC    schedule 23.03.2016
comment
Это работает +1. Однако, если бы я должен был использовать хуки, как бы я это сделал? Или это невозможно? - person thepiercingarrow; 24.03.2016
comment
@MarkWright нет, это не для твоего случая. На стороне клиента вам понадобится сложный хук, чтобы изменить контент, который вы хотите отправить на удаленную сторону (GitHub или GitLab). На стороне сервера нельзя добавлять хуки, только вебхук (developer.github.com/webhooks) . Опять же, сложности того не стоят. Опрометчивый ответ ниже нельзя применить к удаленному репозиторию GitHub или GitLab. - person VonC; 24.03.2016
comment
Хорошо спасибо. Как мне использовать вебхук? Я смотрел на это, но я не мог понять, что поставить для моего URL и моего секрета (опять же, супер неопытный с git). - person thepiercingarrow; 24.03.2016
comment
@MarkWright Это другой вопрос, который не относится к вашей исходной теме. - person VonC; 24.03.2016
comment
Хорошо спасибо. Итак, если я использую этот метод, может ли скрипт как бы «пинговать» GitHub, если он отвечает, затем установить удаленный доступ к Github, а если он не работает, использовать GitLab в качестве резервной копии? - person thepiercingarrow; 24.03.2016
comment
@MarkWright, конечно, простого завитка может быть достаточно (stackoverflow.com/a/2924444/6309) - person VonC; 24.03.2016

Как бы я реализовал такой хук?

Вы можете выбрать любой понравившийся крючок и проверить ссылки в файлах.

Например, вы можете использовать что-то подобное и добавить свою строку скрипта после условия if.

pre-receive hook

#!/bin/sh

# Check to see if this is the first commit in the repository or not
if git rev-parse --verify HEAD >/dev/null 2>&1
then
    # We compare our changes against the previous commit
    against=HEAD^
else
    # Initial commit: diff against an empty tree object
    against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
fi

# Redirect output to screen.
exec 1>&2

# Get the list of files which were commits
# assuming the other files are already contains the right values and does not need to be updated
files = $(git diff-tree -r --name-only $against )

# ... do whatever you want to do with the files

P.S. Было бы хорошо, если бы это работало в обоих направлениях — поэтому, когда я нажимаю на GitLab, GitHub запускает другой скрипт, который заменяет ссылки GitLab на ссылки GitHub, так что всякий раз, когда я нажимаю на одну, обе обновляются соответственно.

Установите 2 хука, i в каждом репозитории с правильными ссылками с правильным значением в каждом репо.


Другой подход, не использующий хуки:

Если у вас может быть локальный код на стороне клиента, вы можете использовать эту функцию в git:

Оказывается, вы можете написать свои собственные фильтры для выполнения подстановок в файлах при фиксации/проверке. Они называются фильтрами clean и smudge.

введите здесь описание изображения

Прочитайте все об этом здесь:
https://git-scm.com/book/en/v2/Customizing-Git-Git-Attributes#Keyword-Expansion

person CodeWizard    schedule 23.03.2016
comment
+1 Спасибо за ответ! Это имеет смысл, но у меня нет опыта работы с git, и я не знаю, как бы я это сделал. Будет ли это выполнять замену всякий раз, когда он получает обновление в репозитории или локально при фиксации, или я полностью упускаю суть? Спасибо. - person thepiercingarrow; 24.03.2016