Git 문제 해결

가끔은 Git을 사용할 때 원하는 대로 작동하지 않을 수 있습니다. 다음은 Git의 문제를 해결하는 몇 가지 도움말입니다.

디버깅

Git의 문제를 해결할 때, 다음 디버깅 기술을 시도해보세요.

Git 명령에 사용자 정의 SSH 키 사용

GIT_SSH_COMMAND="ssh -i ~/.ssh/gitlabadmin" git <command>

복제 문제 디버깅

SSH를 이용한 Git의 경우:

GIT_SSH_COMMAND="ssh -vvv" git clone <git@url>

HTTPS를 이용한 Git의 경우:

GIT_TRACE_PACKET=1 GIT_TRACE=2 GIT_CURL_VERBOSE=1 git clone <url>

추적을 이용한 Git 디버깅

Git에는 Git 명령어의 디버깅을 위한 추적(traces)이 포함되어 있습니다. 예:

  • GIT_TRACE_PERFORMANCE=1: 각 git 호출에 걸리는 시간을 보여주는 성능 데이터의 추적을 활성화합니다.
  • GIT_TRACE_SETUP=1: git이 상호 작용하는 저장소와 환경에 대해 발견하는 내용을 추적합니다.
  • GIT_TRACE_PACKET=1: 네트워크 작업의 패킷 레벨 추적을 활성화합니다.

git push에서의 ‘Broken pipe’ 오류

‘Broken pipe’ 오류는 원격 저장소로 푸시를 시도할 때 발생할 수 있습니다. 보통 푸시할 때 다음과 같은 메시지가 표시됩니다:

Write failed: Broken pipe
fatal: The remote end hung up unexpectedly

이 문제를 해결하려면 다음과 같은 가능한 해결책이 있습니다.

Git에서 POST 버퍼 크기 증가

Git을 이용하여 HTTPS로 대용량 저장소를 푸시하려고 시도하면 다음과 같은 오류 메시지가 표시될 수 있습니다:

fatal: pack has bad object at offset XXXXXXXXX: inflate returned -5

이 문제를 해결하려면:

  • 로컬 Git 구성에서 http.postBuffer 값을 증가시킵니다. 기본값은 1MB입니다. 예를 들어, 500MB 저장소를 복제할 때 git clone이 실패하면 다음을 실행하세요:

    1. 터미널이나 명령 프롬프트를 엽니다.
    2. http.postBuffer 값을 증가시킵니다:

      # http.postBuffer 크기를 바이트 단위로 설정
      git config http.postBuffer 524288000
      

로컬 구성으로 문제가 해결되지 않으면 서버 구성을 수정해야 합니다. 이 때에는 조심히 해야 하며 서버 액세스 권한이 있을 때만 진행해야 합니다.

  • 서버 측의 http.postBuffer 값 증가:

    1. 터미널이나 명령 프롬프트를 엽니다.
    2. GitLab 인스턴스의 gitlab.rb 파일 수정:

      gitaly['configuration'] = {
        # ...
        git: {
          # ...
          config: [
            # http.postBuffer 크기를 바이트 단위로 설정
            {key: "http.postBuffer", value: "524288000"},
          ],
        },
      }
      
    3. 구성 변경 적용:

      sudo gitlab-ctl reconfigure
      

‘Stream 0 was not closed cleanly’

이 오류가 표시되면 인터넷 연결이 느릴 수 있습니다.

RPC failed; curl 92 HTTP/2 stream 0 was not closed cleanly: INTERNAL_ERROR (err 2)

SSH 대신 HTTP를 사용한다면 다음 중 하나를 시도해보세요:

  • Git 구성에서 git config http.postBuffer 52428800으로 POST 버퍼 크기를 증가시킵니다.
  • git config http.version HTTP/1.1으로 HTTP/1.1 프로토콜로 전환합니다.

이러한 접근 방법이 오류를 해결하지 못하는 경우 다른 인터넷 서비스 제공업체가 필요할 수 있습니다.

SSH 구성 확인

SSH를 통해 푸시하는 경우, ‘Broken pipe’ 오류가 때때로 SSH 관련 문제(예: 인증)로 인해 발생할 수 있습니다. SSH가 올바르게 구성되어 있는지 확인하고, SSH 문제 해결 설명에 따라 진행하세요.

서버 액세스 권한이 있는 GitLab 관리자인 경우, SSH ‘keep-alive’를 구성하여 세션 타임아웃을 방지할 수도 있습니다.

참고: 클라이언트와 서버 모두 구성하는 것은 불필요합니다.

클라이언트 측에서 SSH 구성하기:

  • UNIX의 경우, ~/.ssh/config를 편집(파일이 없는 경우 생성)하고 다음을 추가 또는 편집하세요:

    Host your-gitlab-instance-url.com
      ServerAliveInterval 60
      ServerAliveCountMax 5
    
  • Windows의 경우 PuTTY를 사용하는 경우 세션 속성으로 이동한 다음, “접속”으로 이동하여 “세션을 활성 상태로 유지하기 위해 널 패킷 보내기” 아래의 세션 간 주기(0으로 설정하면 비활성화)60으로 설정합니다.

서버 측에서 SSH 구성하기, /etc/ssh/sshd_config를 편집하고 다음을 추가하세요:

ClientAliveInterval 60
ClientAliveCountMax 5

git repack 실행

‘pack-objects’ 유형의 오류가 표시된다면, 다시 원격 저장소로 푸시하기 전에 git repack을 실행해볼 수 있습니다:

git repack
git push

Git 클라이언트 업그레이드

기존 버전의 Git(2.9 미만)을 실행 중이라면, Git 저장소로 푸시할 때 ‘Broken pipe’ 오류를 참고하여 2.9 이상으로 업그레이드하는 것을 고려해보세요.

ssh_exchange_identification 오류

Git을 SSH를 통해 푸시하거나 풀링하려고 시도할 때 사용자는 다음과 같은 오류를 경험할 수 있습니다:

Please make sure you have the correct access rights
and the repository exists.
...
ssh_exchange_identification: read: Connection reset by peer
fatal: Could not read from remote repository.

또는

ssh_exchange_identification: Connection closed by remote host
fatal: The remote end hung up unexpectedly

또는

kex_exchange_identification: Connection closed by remote host
Connection closed by x.x.x.x port 22

이 오류는 보통 SSH 데몬의 MaxStartups 값이 SSH 연결을 제한하는 것을 나타냅니다. 이 설정은 SSH 데몬에 대한 최대 동시, 인증되지 않은 연결을 지정합니다. 이는 모든 연결이 처음에는 ‘인증되지 않음’이기 때문에 SSH 키를 가진 사용자에게 영향을 줍니다. 기본값10입니다.

이는 호스트의 sshd 로그를 확인하여 검증할 수 있습니다. Debian 계열 시스템의 경우, /var/log/auth.log를 참조하고 RHEL 파생 버전의 경우 /var/log/secure에서 다음과 같은 오류를 확인할 수 있습니다:

sshd[17242]: error: beginning MaxStartups throttling
sshd[17242]: drop connection #1 from [CLIENT_IP]:52114 on [CLIENT_IP]:22 past MaxStartups

이 오류가 없다면 SSH 데몬이 연결을 제한하지 않으므로 기본 문제는 네트워크 관련일 것으로 예상됩니다.

인증되지 않은 동시 SSH 연결 수 증가

GitLab 서버에서 MaxStartups를 증가시켜라 /etc/ssh/sshd_config의 값을 추가하거나 수정함으로써:

MaxStartups 100:30:200

100:30:200은 제한 없이 최대 100개의 SSH 세션을 허용하며, 이후에는 연결의 30%가 버려지고 절대 최대값 200에 도달할 때까지입니다.

MaxStartups의 값을 수정한 후, 설정에 오류가 있는지 확인하십시오.

sudo sshd -t -f /etc/ssh/sshd_config

구성 확인이 오류 없이 실행되면 변경 사항이 적용되도록 SSH 데몬을 다시 시작하는 것이 안전합니다.

# Debian/Ubuntu
sudo systemctl restart ssh

# CentOS/RHEL
sudo service sshd restart

git push / git pull 중의 타임아웃

저장소에서 푸시/풀 작업이 50초 이상 걸릴 경우, 타임아웃이 발생합니다. 이는 수행된 작업 수와 해당 작업 시간을 로그로 포함하고 있는데, 아래 예제처럼 나타납니다:

remote: Running checks for branch: master
remote: Scanning for LFS objects... (153ms)
remote: Calculating new repository size... (cancelled after 729ms)

이를 통해 어떤 작업이 성능이 나쁜지 더 조사하고, GitLab에 서비스를 향상시키는 데 도움을 주는 정보를 제공할 수 있습니다.

오류: 작업이 타임아웃되었습니다

Git을 사용하는 중에 이와 같은 오류가 발생하면 일반적으로 네트워크 문제를 나타냅니다:

ssh: connect to host gitlab.com port 22: Operation timed out
fatal: Could not read from remote repository

기본 원인을 확인하는 데 도움을 얻으려면 다음을 수행하십시오:

  • 다른 네트워크를 통해 연결합니다(예: Wi-Fi에서 셀룰러 데이터로 전환) 국부 네트워크나 방화벽 문제를 제외하기 위해.
  • 다음 bash 명령을 실행하여 tracerouteping 정보를 수집하십시오: mtr -T -P 22 <gitlab_server>.com. MTR 및 그 출력을 읽는 방법에 대해서는 Cloudflare 문서 What is My Traceroute (MTR)?를 참조하십시오.

git clone 중에 “전송이 남아 있는 읽기 데이터로 닫혔습니다” 오류

이전이나 큰 저장소를 복제할 때 때로는 git clone을 실행할 때 다음과 같은 오류가 표시됩니다:

error: RPC failed; curl 18 transfer closed with outstanding read data remaining
fatal: The remote end hung up unexpectedly
fatal: early EOF
fatal: index-pack failed

이는 일반적으로 Git 자체에서 발생하는 문제로, 큰 파일 또는 대량의 파일을 처리할 수 없는 능력 때문입니다. Git LFS는 이 문제를 해결하기 위해 만들어졌지만, 이것에도 한계가 있습니다. 일반적으로 다음 중 하나 때문입니다:

  • 저장소에 있는 파일의 수
  • 이력에 있는 개정 수
  • 저장소에 큰 파일이 존재함

큰 저장소를 복제하는 경우 이 오류가 발생하면 복제 깊이를 줄이세요1로 설정하십시오. 예:

이 방법은 근본적인 원인을 해결하지는 않지만 저장소를 성공적으로 복제할 수 있습니다. 복제 깊이를 1로 줄이려면 다음을 실행하십시오:

  변수:
    GIT_DEPTH: 1

LDAP 사용자의 SSH로 Git fetch 시 비밀번호 만료 오류

git fetch가 GitLab의 자체 관리형 인스턴스에서 HTTP 403 Forbidden 오류를 반환하면 GitLab 데이터베이스의 이 사용자에 대한 암호 만료 날짜(users.password_expires_at)가 과거 날짜인 것입니다:

Your password expired. Please access GitLab from a web browser to update your password.

SSO 계정으로 수행된 요청 및 password_expires_atnull이 아닌 경우는 다음과 같은 오류가 발생합니다:

"403 Forbidden - Your password expired. Please access GitLab from a web browser to update your password."

이 문제를 해결하려면 다음 중 하나로 암호 만료를 업데이트할 수 있습니다:

  • GitLab Rails console을 사용하여 사용자 데이터를 확인 및 업데이트:

    user = User.find_by_username('<USERNAME>')
    user.password_expired?
    user.password_expires_at
    user.update!(password_expires_at: nil)
    
  • gitlab-psql을 사용하십시오:

    # gitlab-psql
    UPDATE users SET password_expires_at = null WHERE username='<USERNAME>';
    

이 버그는 이 이슈에서 보고되었습니다.

Git fetch 중의 “HTTP 기본: 액세스 거부” 오류

HTTP(S)를 통해 Git을 사용할 때 HTTP 기본: 액세스 거부 오류가 발생하면 이중 인증 문제 해결 가이드를 참조하십시오.

성공적인 git clone 중 기록된 401 오류

HTTP를 통해 저장소를 복제할 때 production_json.log 파일에 초기 상태가 401 (권한 없음)으로 설정되어 신속하게 200으로 변경되는 것이 기록될 수 있습니다.

{
   "method":"GET",
   "path":"/group/project.git/info/refs",
   "format":"*/*",
   "controller":"Repositories::GitHttpController",
   "action":"info_refs",
   "status":401,
   "time":"2023-04-18T22:55:15.371Z",
   "remote_ip":"x.x.x.x",
   "ua":"git/2.39.2",
   "correlation_id":"01GYB98MBM28T981DJDGAD98WZ",
   "duration_s":0.03585
}
{
   "method":"GET",
   "path":"/group/project.git/info/refs",
   "format":"*/*",
   "controller":"Repositories::GitHttpController",
   "action":"info_refs",
   "status":200,
   "time":"2023-04-18T22:55:15.714Z",
   "remote_ip":"x.x.x.x",
   "user_id":1,
   "username":"root",
   "ua":"git/2.39.2",
   "correlation_id":"01GYB98MJ0CA3G9K8WDH7HWMQX",
   "duration_s":0.17111
}

이것은 HTTP 기본 인증 작동 방식으로 인해 각 HTTP로 수행된 Git 작업에 대해 초기 401 로그 항목이 나타날 것으로 기대됩니다.

Git 클라이언트가 복제를 시작할 때, GitLab에 보내는 초기 요청은 인증 세부 정보를 제공하지 않습니다. GitLab은 해당 요청에 대해 401 Unauthorized 결과를 반환합니다. 수십 밀리초 후에 Git 클라이언트는 인증 세부 정보를 포함하는 후속 요청을 보냅니다. 이러한 두 번째 요청은 성공해야 하며 200 OK 로그 항목을 나타낼 것입니다.

401 로그 항목에 해당하는 200 로그 항목이 없는 경우, Git 클라이언트는 다음 중 하나를 사용하고 있을 확률이 높습니다:

  • 올바르지 않은 암호
  • 만료된 또는 철회된 토큰

이를 해결하지 않으면 HTTP를 통한 Git 작업 시 403 (금지됨) 오류에 직면할 수 있습니다.

HTTP를 통해 Git 작업을 수행할 때 403 오류

HTTP를 통해 Git 작업을 수행할 때, 403 (금지됨) 오류는 귀하의 IP 주소가 인증 실패로 인해 차단된 것을 나타냅니다:

fatal: unable to access 'https://gitlab.com/group/project.git/': The requested URL returned error: 403

403 오류는 production_json.log에서 확인할 수 있습니다:

{
   "method":"GET",
   "path":"/group/project.git/info/refs",
   "format":"*/*",
   "controller":"Repositories::GitHttpController",
   "action":"info_refs",
   "status":403,
   "time":"2023-04-19T22:14:25.894Z",
   "remote_ip":"x.x.x.x",
   "user_id":1,
   "username":"root",
   "ua":"git/2.39.2",
   "correlation_id":"01GYDSAKAN2SPZPAMJNRWW5H8S",
   "duration_s":0.00875
}

귀하의 IP 주소가 차단되었다면, 해당 로그 항목은 auth_json.log에 있습니다:

{
    "severity":"ERROR",
    "time":"2023-04-19T22:14:25.893Z",
    "correlation_id":"01GYDSAKAN2SPZPAMJNRWW5H8S",
    "message":"Rack_Attack",
    "env":"blocklist",
    "remote_ip":"x.x.x.x",
    "request_method":"GET",
    "path":"/group/project.git/info/refs?service=git-upload-pack"}

인증 실패로 인한 차단 제한은 자체 관리형 인스턴스 또는 GitLab.com을 사용하는 경우에 따라 다릅니다.