InfoGrab DocsInfoGrab Docs

양방향 미러링

요약

양방향 미러링은 충돌을 일으킬 수 있습니다. 양방향 미러링은 두 리포지터리가 서로 pull 하고 push 하도록 구성합니다. 양방향 미러링을 구성한다면 리포지터리가 충돌에 대비하도록 준비합니다. 다운스트림 인스턴스의 push 이벤트 웹훅은 변경 사항을 더 자주 동기화하여 경쟁 조건을 줄이는 데 도움이 됩니다.

히스토리
  • 13.9에서 GitLab Premium으로 이동되었습니다.
Warning

양방향 미러링은 충돌을 일으킬 수 있습니다.

양방향 미러링은 두 리포지터리가 서로 pull 하고 push 하도록 구성합니다. 어느 리포지터리도 오류 없이 업데이트된다는 보장은 없습니다.

양방향 미러링에서 충돌 줄이기#

양방향 미러링을 구성한다면 리포지터리가 충돌에 대비하도록 준비합니다. 충돌을 줄이도록 구성하고, 충돌이 발생했을 때 해결하는 방법을 정합니다.

  • 보호된 브랜치만 미러링합니다. 어느 쪽 원격에서든 미러링된 커밋을 재작성하면 충돌이 발생하고 미러링이 실패합니다.
  • 히스토리 재작성으로 인한 충돌을 막으려면 미러링할 브랜치를 두 원격 모두에서 보호합니다.
  • push 이벤트 웹훅으로 미러링 지연을 줄입니다. 양방향 미러링은 같은 브랜치에 비슷한 시점으로 만들어진 커밋이 충돌을 일으키는 경쟁 조건을 만듭니다. push 이벤트 웹훅은 이 경쟁 조건을 완화하는 데 도움이 됩니다. 보호된 브랜치만 push 미러링할 때 GitLab의 push 미러링은 분당 한 번으로 속도가 제한됩니다.
  • pre-receive 훅을 사용하여 충돌을 방지합니다.

GitLab으로 즉시 pull을 트리거하는 웹훅 구성#

다운스트림 인스턴스의 push 이벤트 웹훅은 변경 사항을 더 자주 동기화하여 경쟁 조건을 줄이는 데 도움이 됩니다.

사전 요구 사항:

  • 업스트림 GitLab 인스턴스에서 push 미러와 pull 미러를 구성해 두어야 합니다.

다운스트림 인스턴스에서 웹훅을 만들려면 다음과 같이 진행합니다.

  1. API 범위를 가진 개인 액세스 토큰을 만듭니다.

  2. 상단 바에서 Search or go to를 선택하고 프로젝트를 찾습니다.

  3. 왼쪽 사이드바에서 Settings > Webhooks를 선택합니다.

  4. 웹훅 URL을 추가합니다. 이 경우에는 리포지터리 업데이트 후 즉시 pull을 트리거하도록 pull 미러 API 요청을 사용합니다.

    https://gitlab.example.com/api/v4/projects/:id/mirror/pull?private_token=<your_access_token>
    
  5. 토큰을 마스킹합니다.

  6. Push Events를 선택합니다.

  7. Add Webhook을 선택합니다.

통합을 테스트하려면 Test를 선택하고 GitLab 이 오류 메시지를 반환하지 않는지 확인합니다.

pre-receive 훅을 사용하여 충돌 방지#

Warning

이 방법은 Git push 작업이 업스트림 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 훅 격리 환경을 우회합니다.

관련 주제#

양방향 미러링

GitLab v19.5
Tier: Premium, Ultimate
Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated
원문 보기

요약

양방향 미러링은 충돌을 일으킬 수 있습니다. 양방향 미러링은 두 리포지터리가 서로 pull 하고 push 하도록 구성합니다. 양방향 미러링을 구성한다면 리포지터리가 충돌에 대비하도록 준비합니다. 다운스트림 인스턴스의 push 이벤트 웹훅은 변경 사항을 더 자주 동기화하여 경쟁 조건을 줄이는 데 도움이 됩니다.

히스토리
  • 13.9에서 GitLab Premium으로 이동되었습니다.
Warning

양방향 미러링은 충돌을 일으킬 수 있습니다.

양방향 미러링은 두 리포지터리가 서로 pull 하고 push 하도록 구성합니다. 어느 리포지터리도 오류 없이 업데이트된다는 보장은 없습니다.

양방향 미러링에서 충돌 줄이기#

양방향 미러링을 구성한다면 리포지터리가 충돌에 대비하도록 준비합니다. 충돌을 줄이도록 구성하고, 충돌이 발생했을 때 해결하는 방법을 정합니다.

  • 보호된 브랜치만 미러링합니다. 어느 쪽 원격에서든 미러링된 커밋을 재작성하면 충돌이 발생하고 미러링이 실패합니다.
  • 히스토리 재작성으로 인한 충돌을 막으려면 미러링할 브랜치를 두 원격 모두에서 보호합니다.
  • push 이벤트 웹훅으로 미러링 지연을 줄입니다. 양방향 미러링은 같은 브랜치에 비슷한 시점으로 만들어진 커밋이 충돌을 일으키는 경쟁 조건을 만듭니다. push 이벤트 웹훅은 이 경쟁 조건을 완화하는 데 도움이 됩니다. 보호된 브랜치만 push 미러링할 때 GitLab의 push 미러링은 분당 한 번으로 속도가 제한됩니다.
  • pre-receive 훅을 사용하여 충돌을 방지합니다.

GitLab으로 즉시 pull을 트리거하는 웹훅 구성#

다운스트림 인스턴스의 push 이벤트 웹훅은 변경 사항을 더 자주 동기화하여 경쟁 조건을 줄이는 데 도움이 됩니다.

사전 요구 사항:

  • 업스트림 GitLab 인스턴스에서 push 미러와 pull 미러를 구성해 두어야 합니다.

다운스트림 인스턴스에서 웹훅을 만들려면 다음과 같이 진행합니다.

  1. API 범위를 가진 개인 액세스 토큰을 만듭니다.

  2. 상단 바에서 Search or go to를 선택하고 프로젝트를 찾습니다.

  3. 왼쪽 사이드바에서 Settings > Webhooks를 선택합니다.

  4. 웹훅 URL을 추가합니다. 이 경우에는 리포지터리 업데이트 후 즉시 pull을 트리거하도록 pull 미러 API 요청을 사용합니다.

    https://gitlab.example.com/api/v4/projects/:id/mirror/pull?private_token=<your_access_token>
    
  5. 토큰을 마스킹합니다.

  6. Push Events를 선택합니다.

  7. Add Webhook을 선택합니다.

통합을 테스트하려면 Test를 선택하고 GitLab 이 오류 메시지를 반환하지 않는지 확인합니다.

pre-receive 훅을 사용하여 충돌 방지#

Warning

이 방법은 Git push 작업이 업스트림 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 훅 격리 환경을 우회합니다.

관련 주제#