양방향 미러링
Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated
양방향 미러링은 충돌을 일으킬 수 있습니다. 양방향 미러링은 두 리포지터리가 서로 pull하고 push하도록 구성합니다. 양방향 미러링을 구성하는 경우 리포지터리에서 충돌에 대비해야 합니다. 다운스트림 인스턴스의 push 이벤트 웹훅은 변경 사항을 더 자주 동기화하여 경쟁 조건을 줄이는 데 도움이 됩니다.
히스토리
- GitLab Premium 13.9로 이동됨.
양방향 미러링은 충돌을 일으킬 수 있습니다.
양방향 미러링은 두 리포지터리가 서로 pull하고 push하도록 구성합니다. 어느 리포지터리도 오류 없이 업데이트할 수 있다는 보장이 없습니다.
양방향 미러링에서 충돌 줄이기#
양방향 미러링을 구성하는 경우 리포지터리에서 충돌에 대비해야 합니다. 충돌을 줄이도록 구성하고 발생 시 처리 방법을 설정합니다:
- 보호된 브랜치만 미러링. 어느 원격에서든 미러링된 커밋을 재작성하면 충돌이 발생하고 미러링이 실패합니다.
- 미러링하려는 브랜치를 보호하여 두 원격 모두에서 히스토리 재작성으로 인한 충돌을 방지합니다.
- push 이벤트 웹훅으로 미러링 지연을 줄입니다. 양방향 미러링은 같은 브랜치에 거의 동시에 만들어진 커밋이 충돌을 일으키는 경쟁 조건을 만들 수 있습니다. push 이벤트 웹훅은 경쟁 조건을 완화하는 데 도움이 됩니다. GitLab에서 push 미러링은 보호된 브랜치만 push 미러링할 때 분당 한 번으로 속도가 제한됩니다.
- pre-receive 훅을 사용하여 충돌 방지.
GitLab으로 즉각적인 pull을 트리거하는 웹훅 구성#
다운스트림 인스턴스의 push 이벤트 웹훅은 변경 사항을 더 자주 동기화하여 경쟁 조건을 줄이는 데 도움이 됩니다.
사전 요구 사항:
다운스트림 인스턴스에서 웹훅을 만들려면:
-
API범위의 개인 액세스 토큰을 만듭니다. -
상단 바에서 Search or go to를 선택하고 프로젝트를 찾습니다.
-
왼쪽 사이드바에서 Settings > Webhooks를 선택합니다.
-
웹훅 URL을 추가합니다. 이 경우 pull 미러 API 요청을 사용하여 리포지터리 업데이트 후 즉각적인 pull을 트리거합니다:
https://gitlab.example.com/api/v4/projects/:id/mirror/pull?private_token=<your_access_token> -
토큰을 마스킹합니다.
-
Push Events를 선택합니다.
-
Add Webhook을 선택합니다.
통합을 테스트하려면 Test를 선택하고 GitLab이 오류 메시지를 반환하지 않는지 확인합니다.
pre-receive 훅을 사용하여 충돌 방지#
이 솔루션은 Git push 작업을 업스트림 Git 리포지터리로 프록시하기 때문에 Git push 작업 성능에 부정적인 영향을 미칩니다.
이 구성에서 하나의 Git 리포지터리는 권한 있는 업스트림으로 작동하고 다른 하나는 다운스트림으로 작동합니다. 이 서버 측 pre-receive 훅은 커밋을 업스트림 리포지터리로 먼저 push한 후에만 push를 수락합니다. 이 훅을 다운스트림 리포지터리에 설치합니다.
예를 들어:
#!/usr/bin/env bash
# --- Assume only one push mirror target
# Push mirroring remotes are named `remote_mirror_<id>`.
# This line finds the first remote and uses that.
TARGET_REPO=$(git remote | grep -m 1 remote_mirror)
proxy_push()
{
# --- Arguments
OLDREV=$(git rev-parse $1)
NEWREV=$(git rev-parse $2)
REFNAME="$3"
# --- Pattern of branches to proxy pushes
allowlist=$(expr "$branch" : "\(master\)")
case "$refname" in
refs/heads/*)
branch=$(expr "$refname" : "refs/heads/\(.*\)")
if [ "$allowlist" = "$branch" ]; then
# handle https://git-scm.com/docs/git-receive-pack#_quarantine_environment
unset GIT_QUARANTINE_PATH
error="$(git push --quiet $TARGET_REPO $NEWREV:$REFNAME 2>&1)"
fail=$?
if [ "$fail" != "0" ]; then
echo >&2 ""
echo >&2 " Error: updates were rejected by upstream server"
echo >&2 " This is usually caused by another repository pushing changes"
echo >&2 " to the same ref. You may want to first integrate remote changes"
echo >&2 ""
return
fi
fi
;;
esac
}
# Allow dual mode: run from the command line just like the update hook, or
# if no arguments are given, then run as a hook script:
if [ -n "$1" -a -n "$2" -a -n "$3" ]; then
# Output to the terminal in command line mode. If someone wanted to
# resend an email, they could redirect the output to sendmail themselves
PAGER= proxy_push $2 $3 $1
else
# Push is proxied upstream one ref at a time. It is possible for some refs
# to succeed, and others to fail. This results in a failed push.
while read oldrev newrev refname
do
proxy_push $oldrev $newrev $refname
done
fi
이 샘플에는 몇 가지 제한 사항이 있습니다:
- 수정 없이 사용 사례에 맞지 않을 수 있습니다:
- 미러에 대한 다양한 인증 메커니즘 유형을 고려하지 않습니다.
- 강제 업데이트(히스토리 재작성)와 함께 작동하지 않습니다.
allowlist패턴과 일치하는 브랜치만 프록시 push됩니다.
- 이 스크립트는
$TARGET_REPO업데이트가 ref 업데이트로 간주되고 Git이 그에 대한 경고를 표시하기 때문에 Git 훅 격리 환경을 우회합니다.
