Git 문제 해결

가끔 Git을 사용할 때 의도한 대로 작동하지 않거나 예상대로 작동하지 않을 때가 있습니다. Git의 문제 해결 및 해결 방법에 대한 몇 가지 팁을 제공합니다.

디버깅

Git 문제 해결 시 이러한 디버깅 기술을 시도해보세요.

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

GIT_SSH_COMMAND="ssh -i ~/.ssh/gitlabadmin" git <명령어>

복제 문제 디버깅

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 명령어 디버깅을 위한 완전한 추적을 포함하고 있습니다.

  • 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 버퍼 크기 증가

SSH 대신 Git을 HTTP로 사용하는 경우, Git 구성에서 POST 버퍼 크기를 증가시켜 볼 수 있습니다.

클론 중에 오류가 발생한 예시: fatal: pack has bad object at offset XXXXXXXXX: inflate returned -5

터미널을 열고 다음을 입력하세요:

git config http.postBuffer 52428800

값은 바이트로 지정되며, 위의 경우 버퍼 크기가 50MB로 설정되었습니다. 기본값은 1MB입니다.

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

이 문제는 인터넷 연결이 느릴 때 발생할 수 있습니다. SSH 대신 Git을 HTTP로 사용하는 경우 다음 중 하나를 시도해볼 수 있습니다:

  • Git 구성에서 POST 버퍼 크기를 증가시키세요: git config http.postBuffer 52428800.
  • HTTP/1.1 프로토콜로 전환하세요: git config http.version 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를 사용하고 있다면 세션 속성으로 이동한 다음 “Connection”으로 이동하여 “Sending of null packets to keep session active” 아래에서 Seconds between keepalives (0 to turn off)60으로 설정하세요.

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

ClientAliveInterval 60
ClientAliveCountMax 5

git repack 실행

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

git repack
git push

Git 클라이언트 업그레이드

Git의 이전 버전(< 2.9)을 사용 중이라면 >= 2.9로 업그레이드하는 것을 고려해보세요 (Git 저장소로 푸시할 때 ‘Broken pipe’ 참조).

ssh_exchange_identification 오류

사용자는 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입니다.

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 clone을 통한 HTTP 전송 중 transfer closed with outstanding read data remaining 오류 발생

가끔 오래된이나 큰 저장소를 복제할 때 다음과 같은 오류가 발생할 수 있습니다:

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의 값으로 복제 깊이를 줄이세요. 예시:

    variables:
      GIT_DEPTH: 1
    
  • 로컬 Git 구성에서 기본 1MB 값보다 큰 값인 http.postBuffer 값을 저장소 크기보다 큰 값으로 늘릴 수 있습니다. 예를 들어, git clone이 500MB 크기의 저장소를 복제할 때 실패한다면, http.postBuffer524288000으로 설정해야 합니다:

    # http.postBuffer 크기를 바이트 단위로 설정
    git config http.postBuffer 524288000
    
  • 서버 쪽에서 http.postBuffer를 늘릴 수 있습니다:

    1. GitLab 인스턴스의 gitlab.rb 파일을 수정하세요:

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

      sudo gitlab-ctl reconfigure
      

예를 들어, 저장소에 매우 긴 이력이 있고 큰 파일이 없다면, 깊이를 줄이는 것으로 문제를 해결할 수 있습니다. 그러나 저장소에 매우 큰 파일이 있다면, 깊이가 1이라도 크기 때문에 postBuffer 변경이 필요할 수 있습니다. 로컬 postBuffer를 늘렸지만 백엔드의 NGINX 값이 여전히 작으면 오류가 계속됩니다.

서버를 수정하는 것은 항상 선택사항이 아니며 더 많은 잠재적인 위험을 안겨줍니다. 우선 로컬 변경을 시도하세요.

LDAP 사용자의 Git fetch 중 암호 만료 오류

만약 GitLab의 자체 관리 인스턴스에서 git fetchHTTP 403 Forbidden 오류를 반환한다면, GitLab 데이터베이스에서 이 사용자의 암호 만료 날짜 (users.password_expires_at)가 지나간 날짜로 설정되어 있습니다:

비밀번호가 만료되었습니다. 비밀번호를 업데이트하려면 웹 브라우저에서 GitLab에 접속하세요.

SSO 계정과 password_expires_atnull이 아닌 요청은 다음 오류를 반환합니다:

"403 Forbidden - 비밀번호가 만료되었습니다. 비밀번호를 업데이트하려면 웹 브라우저에서 GitLab에 접속하세요."

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

  • gitlab-rails console 사용:

     gitlab-rails console
     user.update!(password_expires_at: nil)
    
  • gitlab-psql 사용:

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

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

Git fetch 시 “HTTP Basic: Access Denied” 오류

HTTP(S)를 통해 Git을 사용할 때 HTTP Basic: Access denied 오류를 받는다면 이중 인증 해결 지침을 참조하세요.

성공적인 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
}

Git 작업마다 이러한 초기 401 로그 항목이 나타날 것으로 기대되며, 이는 HTTP 기본 인증의 작동 방식 때문입니다.

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

403production_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을 사용하는 경우에 따라 다를 수 있습니다.