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 버퍼 크기 증가
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 대신 HTTP를 통해 Git을 사용하는 경우 다음 중 하나를 시도해 볼 수 있습니다:
-
git config http.postBuffer 52428800
를 사용하여 Git 구성에서 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를 사용하는 경우 세션 속성으로 이동한 다음 “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로 업그레이드하는 것을 고려해 보세요 (Broken pipe when pushing to Git repository 참조).
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 서버의 /etc/ssh/sshd_config
에 값을 추가하거나 수정하여 MaxStartups
를 증가시킵니다:
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에 서비스를 개선하는 데 더 많은 정보를 제공할 수 있습니다.
HTTP를 통한 git clone
이 outstanding read data
오류로 실패하는 경우
가끔 오래된 또는 큰 리포지터리를 복제할 때 다음과 같은 오류가 발생합니다.
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 구성에서 http.postBuffer 값을 기본 1MB에서 리포지터리 크기보다 큰 값으로 증가시킬 수 있습니다. 예를 들어, 500MB의 리포지터리를 클론하려고 할 때
git clone
이 실패한다면,http.postBuffer
를524288000
으로 설정해야 합니다:# http.postBuffer 크기를 바이트 단위로 설정합니다 git config http.postBuffer 524288000
-
서버 측에서
http.postBuffer
를 증가시킬 수 있습니다:-
GitLab 인스턴스의
gitlab.rb
파일을 수정합니다:gitaly['configuration'] = { # ... git: { # ... config: [ # http.postBuffer 크기를 바이트 단위로 설정합니다 {key: "http.postBuffer", value: "524288000"}, ], }, }
-
이 변경을 적용한 후 구성 변경을 적용합니다:
sudo gitlab-ctl reconfigure
-
예를 들어, 리포지터리에 매우 긴 이력이 있고 큰 파일이 없는 경우, 깊이를 조정하는 것으로 문제를 해결할 수 있습니다. 그러나 리포지터리에 매우 큰 파일이 있는 경우 1의 깊이도 너무 크므로 postBuffer
변경이 필요할 수 있습니다. 로컬 postBuffer
를 증가시켜도 NGINX의 값이 여전히 너무 작으면 오류가 계속됩니다.
서버를 수정하는 것이 항상 선택사항이 아니며 더 큰 잠재적 위험을 가져올 수 있습니다. 우선 로컬 변경을 시도하세요.
LDAP 사용자의 SSH를 통한 Git fetch에서 비밀번호 만료 오류
git fetch
로 GitLab의 Self-managed 인스턴스에서 HTTP 403 Forbidden
오류가 발생하면, GitLab 데이터베이스의 해당 사용자의 비밀번호 만료 날짜(users.password_expires_at
)가 과거 날짜로 설정되어 있습니다:
비밀번호가 만료되었습니다. 비밀번호를 업데이트하려면 웹 브라우저를 통해 GitLab에 액세스하세요.
SSO 계정으로 만들어진 요청 및 password_expires_at
이 null
이 아닌 경우에는 다음과 같은 오류가 발생합니다:
"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
(인가되지 않음)로 기록될 수 있습니다. 이는 HTTP 기본 인증 작동 방식 때문에 발생합니다.
Git 클라이언트가 복제를 시작하면, GitLab에 보내는 초기 요청은 인증 정보를 제공하지 않습니다. GitLab은 해당 요청에 대해 401 Unauthorized
결과를 반환합니다. 몇 밀리초 후, Git 클라이언트가 인증 정보를 포함하는 후속 요청을 보냅니다. 이 두 번째 요청은 성공해야 하고 200 OK
로그 항목이 되어야 합니다.
만약 401
로그 항목에 해당하는 200
로그 항목이 없다면, Git 클라이언트가 다음 중 하나를 사용하고 있습니다:
- 잘못된 암호.
- 만료됨 또는 취소된 토큰.
이를 수정하지 않으면 403 (Forbidden) errors가 나타날 수 있습니다.
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"}
인증 실패 차단 제한은 Self-managed 인스턴스나 GitLab.com을 사용하는 경우에 따라 다릅니다.