TechFeedTechFeed
개발자 작업환경

dubious ownership, safe.directory, 깃 소유자 | 클론한 폴더에서 깃이 멈추면?

dubious ownership은 명령을 실행한 사용자와 폴더 주인이 달라 깃이 저장소 설정을 읽지 않고 멈춘 상태입니다. 소유자를 맞추거나 전역 safe.directory에 그 경로만 넣습니다. 저장소 설정에 넣은 예외는 읽히지 않습니다. 푸시 거절, 소켓 권한과 줄을 가릅니다. Git, 도커, 한국 맥 개발. 2026년 9월 깃 문서.

by

dubious ownership은 커밋이 깨져서가 아니라, 명령을 실행한 사용자와 폴더 주인이 달라 깃이 그 설정을 읽지 않겠다고 멈춘 상태입니다. 푸시 전에 폴더 주인부터 보세요.


도커 볼륨을 컨테이너의 다른 계정이 열면 detected dubious ownership 이 납니다. 원격이 앞으로 감기를 거절한 것과는 다릅니다. 이쪽은 상태 조회조차 거부합니다.


내 파일이면 소유자를 맞추고, 나눠 쓰는 경로만 전역 설정에 예외로 넣습니다. 저장소 설정에 넣은 값은 깃이 믿지 않습니다. 근거는 git config와 깃허브 보안 안내입니다.


이 한 줄이 거절하는 것

다른 사람의 저장소 설정을 실행하지 않으려고 멈춘 것입니다. 깃 2.35.2 이후에는 작업 폴더의 소유자가 현재 사용자가 아니면, 그 저장소의 설정과 훅을 읽기 전에 죽습니다. 공유 폴더에 심은 설정이 내 계정으로 명령을 실행하는 일을 막기 위한 검사입니다.


그래서 git status, git pull, 서브모듈 갱신이 같은 문장으로 끝날 수 있습니다. 원격 브랜치와의 관계는 아직 묻지 않은 상태입니다. 메시지에 적힌 경로가 검사에 걸린 폴더이고, 바로 아래에 전역 설정으로 예외를 넣는 예시 명령이 따라옵니다.


예외를 아무 데나 넣으면 검사가 무력해집니다. 문서의 safe.directory 는 보호된 설정에서만 읽습니다. 시스템 설정, 전역 설정, 명령줄 -c 는 보고, 그 저장소의 .git/config 는 보지 않습니다. 공격자가 저장소 안에 예외를 써 넣는 길을 막은 규칙입니다.


먼저 확인할 것 | 메시지 경로에서 ls -ld 로 소유자와 id 로 내 사용자를 나란히 보세요. 숫자가 다르면 푸시 옵션을 바꾸기 전에 그 차이부터 정리합니다.


다른 계정으로 연 작업 폴더를 확인할 때의 장비
폴더 주인이 명령 사용자와 다르면 깃은 그 저장소 설정을 읽지 않는다

도커와 CI에서 주인이 갈릴 때

노트북에서 클론한 폴더는 보통 내 사용자 소유라 이 문장이 안 납니다. 이미지 안에서 소스를 볼륨으로 붙이고, 프로세스 사용자가 node(uid 1000)인데 파일 소유자는 root이면 컨테이너 안의 git만 거절합니다. 호스트의 터미널은 그대로 동작해서 더 헷갈립니다.


액션도 비슷합니다. 체크아웃은 한 사용자가 받고, 뒤 스텝이 다른 사용자로 같은 경로를 만지면 두 번째 스텝만 dubious ownership 으로 죽습니다. 서브모듈 경로는 따로 검사하므로, 상위 저장소는 넘어가도 하위 경로에서 같은 문장이 납니다.


윈도우와 WSL을 오가면 소유자 숫자가 달라 보이기도 합니다. 깃 배시의 깃과 WSL 안의 깃은 서로의 전역 설정을 공유하지 않을 수 있어, 한쪽에만 safe.directory를 넣으면 다른 쪽 터미널은 계속 멈춥니다. 멈추는 그 실행 파일의 전역 설정에 넣어야 합니다.


상황소유자가 갈리는 이유먼저 할 일
내 노트북 클론보통 소유자가 같음이 오류가 아니면 다른 글
도커 볼륨root 파일, 컨테이너 uid 1000사용자 맞추기 또는 예외 한 경로
액션 다음 스텝체크아웃 사용자와 다름같은 사용자로 이어서 실행
서브모듈하위 경로를 따로 검사메시지에 찍힌 그 경로

소유자와 내 사용자를 비교
# 메시지에 찍힌 경로를 그대로 넣는다 ls -ld /work/app id # 소유자 숫자와 uid 가 다르면 아래 둘 중 하나로 간다

safe.directory를 넣는 위치

예외는 전역이나 시스템 설정에 둡니다. git config --global --add safe.directory /work/app 는 내 계정의 ~/.gitconfig 에 한 경로를 추가합니다. --add 를 빼면 예전에 넣어 둔 다른 경로를 덮어쓸 수 있으니, 경로를 늘릴 때는 --add 를 유지하세요.


별표 하나는 모든 저장소를 예외로 둡니다. 문서도 그 값이면 소유자 검사를 통째로 끈다고 적습니다. 혼자 쓰는 개인 노트북의 로컬 디스크라면 이해가 되지만, 공유 드라이브나 여러 사람이 쓰는 러너에는 넣지 않는 편이 맞습니다. 검사가 생긴 이유가 그 공유 경로이기 때문입니다.


빈 값을 하나 넣으면 목록이 초기화됩니다. 시스템 설정에 별표가 이미 있고 다시 조이고 싶을 때, 전역에서 빈 값을 먼저 추가한 다음 허용할 경로만 적습니다. 경로는 저장소 최상위입니다. 베어 저장소면 깃 디렉터리 쪽을 넣습니다. 메시지에 찍힌 경로를 그대로 쓰는 것이 가장 덜 헷갈립니다.


한 경로만 전역 예외로 추가
git config --global --add safe.directory /work/app # 이 명령 한 번만 예외로 두고 설정 파일은 그대로 git -c safe.directory=/work/app status # 저장소 .git/config 에 넣어도 깃은 읽지 않는다
전역 깃 설정에 경로 예외를 넣기 전에 보는 작업 공간
예외는 전역 설정에 두고, 저장소 설정 파일에는 넣지 않는다

폴더 소유자를 맞추는 쪽

그 파일을 내 계정이 소유해야 맞다면 예외보다 소유자 변경이 낫습니다. sudo chown -R "$(id -u):$(id -g)" /work/app 는 그 트리의 주인을 지금 사용자로 바꿉니다. 호스트에서 편집기도 같이 쓰는 폴더라면, 컨테이너만 주인을 바꾸면 호스트 저장이 다시 root로 돌아갈 수 있습니다. 그때는 컨테이너 사용자를 호스트 uid와 같게 맞춥니다.


도커 소켓 권한이 없어 docker 명령 자체가 거절되는 문제와는 다릅니다. 그건 소켓 그룹이고, 이쪽은 소스 폴더의 소유자입니다. 소켓이 막히면 docker.sock 권한을 보고, 깃 문장만 나오면 폴더 주인을 보면 됩니다.


액션에서는 chown보다 사용자를 통일하는 편이 단순합니다. actions/checkout 이 받은 사용자로 다음 스텝도 돌리면 검사가 통과합니다. 이미지를 root로 돌려 소스에 쓰는 스텝이 있으면, 그 스텝이 남긴 파일 때문에 다음 잡의 깃이 다시 멈춥니다.


푸시 거절과 다른 점

non-fast-forward 는 원격이 커밋을 받은 뒤, 앞으로 감기가 아니라며 거절한 줄입니다. 로컬 status는 됩니다. dubious ownership 은 status부터 안 됩니다. 원격 브랜치를 병합하거나 리베이스해도 폴더 주인이 다르면 같은 문장이 남습니다. 푸시 거절은 non-fast-forward 글의 순서입니다.


훅이 커밋을 막는 경우도 문장이 다릅니다. 로컬 pre-commit 이 실패하면 훅 이름이 나오고, 원격이 거절하면 remote rejected 처럼 원격 이유가 붙습니다. 소유자 검사는 훅이 실행되기 전에 저장소 설정을 거절하므로, 훅 로그가 아예 없습니다.


포트가 이미 쓰여 서버가 못 앉는 줄과도 관계가 없습니다. 개발 서버의 EADDRINUSE는 포트 점유에서 프로세스를 찾으면 됩니다. 깃 문장에 repository at 경로가 있으면 그 경로의 소유자만 보면 됩니다.


문장막힌 곳손댈 것
dubious ownership로컬 폴더 주인chown 또는 전역 예외
non-fast-forward원격 브랜치 이력fetch 후 병합 또는 리베이스
remote rejected원격 훅, 보호 설정거절 이유 문구
docker.sock 권한소켓 그룹사용자 그룹, 소켓 모드

한국에서 맥과 도커를 같이 쓰는 경우에는 볼륨 주인이 root인지만 봐도 절반은 갈립니다. 호스트 터미널의 git status가 되면 저장소는 정상입니다. 컨테이너 안에서만 죽으면 그 프로세스의 uid를 보면 됩니다.


참고 자료


내부 연계: 푸시가 앞으로 감기가 아닐 때, 도커 소켓 권한, 포트 점유


설정 범위는 2026년 9월 깃 문서 기준입니다. 보안 수정의 시작은 2022년 4월 안내입니다.


자주 묻는 질문

저장소 .git/config에 safe.directory를 넣었는데 그대로입니다.

그 키는 보호된 설정만 봅니다. 저장소 설정은 신뢰하지 않으므로 효과가 없습니다. git config --global --add 로 내 전역 파일에 넣거나, 명령 앞에 git -c safe.directory=경로 를 붙이세요.


별표로 한 번에 꺼도 되나요?

모든 경로의 소유자 검사가 꺼집니다. 공유 디스크나 공용 러너에는 두지 마세요. 개인 노트북의 로컬 폴더만 문제라면 메시지에 나온 경로 하나만 --add 하는 쪽이 범위가 작습니다.


호스트에서는 되고 컨테이너에서만 멈춥니다.

볼륨 파일의 소유자와 컨테이너 사용자 숫자가 다른 경우입니다. 컨테이너 사용자를 호스트 uid와 맞추거나, 컨테이너 계정 전역에 그 경로만 예외로 넣으세요. 호스트 전역 설정은 컨테이너 홈에 복사되지 않습니다.


풀을 해도 같은 문장입니다.

원격 이력을 가져오는 단계까지 가기 전에 로컬 검사가 막은 것입니다. fetch나 리베이스로는 소유자가 바뀌지 않습니다. ls -ld 와 id 를 맞춘 다음에 풀을 다시 하세요.


상위 저장소는 괜찮은데 서브모듈만 실패합니다.

하위 경로를 따로 검사합니다. 메시지에 찍힌 서브모듈 경로의 소유자를 보거나, 그 경로를 safe.directory에 추가하세요. 상위 경로 예외가 아래로 자동으로 퍼지지는 않습니다.


푸시가 non-fast-forward로 거절된 것과 같나요?

다릅니다. 앞으로 감기 거절은 원격이 이력을 지키려고 푸시를 되돌린 것이고, 로컬 status는 됩니다. dubious ownership은 로컬 폴더 주인 검사라 명령을 시작조차 못 합니다.


이 문장은 명령을 실행한 사용자와 폴더 주인이 같은가만 보면 됩니다. 내 파일이면 소유자를 맞추고, 일부러 나눈 경로만 전역 safe.directory에 추가하세요. 저장소 설정에 넣은 예외는 읽히지 않습니다. 관련 글: 푸시 거절, 도커 소켓.


dubious ownershipsafe.directory깃소유자도커CI작업환경개발자
EXPLORE / 개발자 작업환경

이어서 읽어보기

전체 토픽 둘러보기 →