유니티 프로젝트 push가 100MB 제한에 막힐 때: 큰 파일을 Git LFS로 넘기기
GitHub Desktop에서 유니티 프로젝트를 커밋하고 Push를 눌렀더니 github가 거절합니다. 오류 내용 끝에는 파일 이름과 함께 “this exceeds GitHub’s file size limit of 100.00 MB”가 찍혀 있습니다. 검색해 보면 답은 하나로 모입니다. 100MB를 넘는 파일은 Git LFS로 넘기라는 것입니다.
그런데 시키는 대로 Git LFS를 설치하고 git lfs track까지 했는데, 다시 Push하면 똑같은 메시지가 뜨는 경우가 많습니다. GitHub 커뮤니티에도 LFS를 설치하고 추적까지 했는데 전과 같은 오류가 난다는 유니티 사용자의 글이 올라와 있습니다. LFS를 분명히 켰는데, 왜 같은 파일이 또 걸릴까요?
이 글은 다섯 가지를 차례로 짚습니다. 기준은 GitHub와 git-lfs 공식 문서입니다. 명령의 동작은 git 2.38과 Git LFS 3.2로 120MB짜리 파일을 만들어 직접 돌려 본 결과입니다. 끝에는 내 상황에 맞는 명령을 만들어 주는 도구를 붙였습니다.
- 1. 거절 메시지에서 걸린 파일 찾기
- 2. LFS로 넘길 파일 고르기
- 3. .gitattributes 설정하기
- 4. 이미 커밋한 큰 파일 처리하기
- 5. 무료 용량과 팀원 쪽 확인
1. github 거절 메시지에서 걸린 파일부터 찾습니다
GitHub는 50MiB가 넘는 파일에는 경고만 띄우고 push를 받아 줍니다. 100MiB가 넘는 파일이 하나라도 있으면 push 전체를 거절합니다. 거절될 때 나오는 내용은 대략 이렇습니다. 파일 이름과 크기는 예시입니다.
remote: error: GH001: Large files detected. You may want to try Git Large File Storage - https://git-lfs.github.com.
remote: error: File Assets/Textures/Rock_4K.psd is 120.00 MB; this exceeds GitHub's file size limit of 100.00 MB
! [remote rejected] main -> main (pre-receive hook declined)
볼 곳은 File 뒤의 경로입니다. 경로가 어느 폴더로 시작하느냐에 따라 할 일이 갈립니다.
| 경로가 이렇게 시작하면 | 정체 | 할 일 |
|---|---|---|
| Assets/ | 내가 넣은 원본 에셋(텍스처, 모델, 오디오, 영상) | Git LFS로 넘김(이 글) |
| Library/, Temp/, Logs/ | 유니티가 만든 캐시 | 올리지 않음. .gitignore로 제외 |
| Build/, Builds/ 같은 빌드 폴더 | 빌드 결과물(.exe, .apk 등) | 올리지 않음. 배포는 GitHub Releases |
캐시와 빌드 결과물은 언제든 다시 만들 수 있습니다. 이런 파일을 LFS로 올리면 무료 용량만 빨리 닳습니다. 큰 빌드 파일을 나눠 줘야 한다면 GitHub 문서는 저장소 대신 Releases에 올리라고 권합니다. 그래서 이 글이 다루는 것은 Assets 안의 원본뿐입니다.
2. LFS로 넘길 파일은 확장자로 고릅니다
큰 파일을 저장소에 직접 넣지 않고 다른 창고에 맡긴 뒤, 저장소에는 “창고 몇 번 칸에 있음”이라는 쪽지만 남긴다고 생각하면 쉽습니다. 쪽지에는 버전, 파일 해시, 크기 세 줄만 적혀 있습니다. Git LFS가 바로 이 방식이고, 이 쪽지를 포인터 파일이라고 부릅니다.
어떤 파일을 창고로 보낼지는 파일 이름 패턴으로 정합니다. 파일 하나만 지정할 수도 있습니다. 하지만 확장자로 지정해야 나중에 들어올 큰 파일까지 함께 잡힙니다. 유니티 프로젝트에서 100MB를 넘기 쉬운 종류는 다음과 같습니다.
| 종류 | 확장자 예 | LFS로 |
|---|---|---|
| 텍스처 원본 | .psd .tif .tga .exr | 넘김 |
| 3D 모델 | .fbx .blend .obj | 넘김 |
| 오디오 | .wav .mp3 .ogg | 넘김 |
| 영상 | .mp4 .mov | 넘김 |
| 압축 파일 | .zip .7z | 넘김 |
| 유니티 텍스트 파일 | .unity .prefab .mat .meta | 넘기지 않음 |
씬과 프리팹을 Force Text로 저장하면 UnityYAMLMerge로 병합할 수 있습니다. 기본 LFS 규칙은 diff=lfs와 merge=lfs를 쓰므로 UnityYAMLMerge가 자동으로 연결되지는 않습니다. -text는 줄바꿈 변환을 끄는 표시입니다. 별도 병합 설정이 없는 이 절차에서는 씬·프리팹·.meta 파일을 일반 Git에 둡니다.
목록을 다 외울 필요는 없습니다. 내 프로젝트에 실제로 큰 파일이 어떤 확장자인지 보면 됩니다. Git Bash에서 프로젝트 폴더로 가 아래를 실행하면 50MB가 넘는 파일이 나옵니다. 50MB를 기준으로 잡은 것은 GitHub가 경고를 띄우기 시작하는 크기라서입니다.
find Assets -type f -size +50M
확장자의 대소문자도 확인합니다. Git LFS 공식 FAQ는 .gitattributes 패턴이 대소문자를 구분한다고 설명합니다. .fbx와 .FBX가 섞여 있다면 두 패턴을 모두 지정하거나 *.[fF][bB][xX]처럼 적습니다. Windows에서만 확인한 결과로 Linux 팀원까지 같은 동작이라고 판단하지 않습니다.
3. .gitattributes 설정: 큰 파일보다 규칙이 먼저입니다
GitHub Desktop(깃허브 데스크탑)을 설치하면 Git LFS도 함께 설치됩니다. 다만 어떤 파일을 LFS로 보낼지는 Desktop 화면에서 정할 수 없습니다. GitHub 문서도 추적 설정은 명령줄로 하라고 적습니다. Desktop의 Repository 메뉴에서 명령 프롬프트나 Git Bash를 열고, Assets 폴더가 보이는 프로젝트 맨 위 폴더에서 실행합니다. Git을 찾을 수 없다는 창이 뜨면 Git for Windows를 먼저 설치합니다.
git lfs install
git lfs track "*.psd" "*.tif" "*.fbx" "*.wav"
git add .gitattributes
git commit -m "Track large files with Git LFS"
git lfs install은 LFS를 git에 연결하는 준비 명령입니다. git lfs track은 규칙을 .gitattributes라는 파일에 한 줄씩 적습니다. 실행 뒤 이 파일을 열면 이런 줄이 보입니다.
*.psd filter=lfs diff=lfs merge=lfs -text
.gitattributes는 큰 파일보다 먼저 커밋합니다. 이 규칙이 저장소에 들어 있어야 팀원 컴퓨터에서도 같은 파일이 LFS로 처리됩니다. 그다음 평소처럼 GitHub Desktop에서 큰 파일을 커밋합니다. Push하기 전에 한 번 확인합니다.
git lfs ls-files
넘긴 파일이 목록에 나오면 LFS로 들어간 것입니다. 파일 이름 앞의 *는 작업 폴더에 실제 파일이 있다는 뜻이고, -는 포인터만 있다는 뜻입니다.
새로 시작하는 프로젝트라면 여기까지로 끝납니다. 처음 질문의 상황은 다릅니다. 큰 파일을 이미 커밋한 뒤에 LFS를 켰습니다. 목록에도 분명히 나오는데, Push는 왜 또 거절될까요?
4. LFS를 켰는데도 거절된다면: 커밋 기록에 남은 원본
같은 순서를 그대로 재현했습니다. 120MB짜리 PSD를 평소처럼 커밋했습니다. 그 뒤 git lfs track으로 규칙을 만들고, PSD를 다시 add해 커밋했습니다. git lfs ls-files에도 PSD가 나왔습니다. 그런데 push할 커밋 세 개를 하나씩 열어 보니 결과가 달랐습니다.
커밋 3 (PSD를 다시 add) → PSD 134바이트 (포인터)
커밋 2 (.gitattributes 추가) → PSD 125,829,120바이트
커밋 1 (PSD 처음 커밋) → PSD 125,829,120바이트
push는 마지막 커밋만 보내지 않습니다. 아직 올라가지 않은 커밋을 모두 보냅니다. 그러니 커밋 1 안의 120MB 원본도 함께 갑니다. GitHub가 거절하는 것은 바로 그 원본입니다.

LFS 규칙은 앞으로 할 커밋에만 적용되고, 이미 커밋된 기록 속 원본은 그대로 남습니다.
그래서 기록 자체를 고쳐야 합니다. 먼저 Unity를 닫고 숨김 폴더 .git까지 포함해 프로젝트를 다른 곳에 백업합니다. 커밋하지 않은 변경 사항은 커밋하거나 stash로 보관하고 git status로 작업 폴더가 정리됐는지 확인합니다. 기록 변경 결과를 확인하기 전에는 push하지 않습니다. 그다음 내 상황이 둘 중 어디인지 봅니다.
push가 거절된 상태라면
거절된 push에만 큰 원본이 있고 원격 기록에는 없다면, 기본 migrate로 현재 브랜치의 미전송 커밋을 바꿉니다. 확장자는 1절에서 찾은 것으로 바꿉니다.
git lfs migrate import --include="*.psd,*.fbx"
migrate import는 지정한 확장자의 파일을 기록 전체에서 포인터로 바꾸고, .gitattributes도 알아서 고칩니다. git-lfs 매뉴얼에 따르면 기본으로는 지금 브랜치에서 아직 원격에 없는 커밋만 고칩니다. 실험에서는 커밋 3개가 모두 다시 쓰였습니다. 세 커밋의 PSD가 전부 134바이트 포인터로 바뀌었습니다. 이 상태에서 Push origin을 누르면 LFS 업로드가 먼저 진행되고 push가 끝납니다.
확장자 대신 –above=100MB처럼 크기로 고르는 옵션도 있습니다. 하지만 실험해 보니 .gitattributes에 확장자가 아니라 그 파일의 경로 한 줄만 적혔습니다. 다음에 새로 넣는 큰 FBX는 잡히지 않습니다. 확장자로 지정하는 편이 뒤탈이 없습니다.
migrate 뒤에 큰 파일 몇 개가 134바이트로 줄어 보여도 놀라지 않아도 됩니다. git-lfs 매뉴얼은 이것을 정상이라고 적고, git lfs checkout으로 채우라고 안내합니다. 실험에서도 110MB FBX가 이 명령으로 돌아왔습니다. Unity는 파일 크기가 돌아온 것을 확인한 뒤에 엽니다.
큰 파일이 이미 GitHub에 올라가 있다면
50~100MB 사이 파일은 경고만 받고 올라갔을 수 있습니다. 이런 파일을 LFS로 옮기려면 GitHub에 있는 기록까지 고쳐야 합니다. 기본 migrate는 이미 올라간 커밋을 건드리지 않습니다. 실험에서도 다시 쓰인 커밋이 0개였습니다. –everything은 모든 참조에서 도달 가능한 기록을 조사하지만 원격 저장소를 직접 바꾸지는 않습니다. 팀원과 브랜치·태그·보호 브랜치를 먼저 확인합니다. 아래는 로컬 변환과 확인까지만 하는 예시입니다.
git lfs migrate import --everything --include="*.wav"
git lfs checkout
git lfs ls-files
git log --oneline
기록을 다시 쓰면 커밋 ID가 바뀌어 일반 push가 거절될 수 있습니다. 변환된 파일·커밋·참조를 먼저 확인하고, 실제로 바뀐 브랜치만 원격에 반영합니다. 강제 push가 필요한 공유 브랜치는 관리자와 협의하세요. –all로 모든 로컬 브랜치를 일괄 덮어쓰지 않습니다. 태그와 보호 브랜치는 별도로 처리해야 합니다.
기록 변경 뒤에는 팀원의 로컬 저장소도 새 기록에 맞춰야 합니다. 옛 기록에서 이어 push하면 원본이 다시 섞일 수 있습니다. 새로 clone하는 것이 단순한 방법이지만, 팀원의 미전송 커밋과 작업 파일을 먼저 보관하고 새 기록으로 옮겨야 합니다. 기존 폴더는 새 저장소와 에셋을 확인하기 전까지 지우지 않습니다.
5. 무료 용량과 팀원 쪽 확인
LFS 창고는 무제한이 아닙니다. 개인 계정(GitHub Free, Pro)의 무료 몫은 저장 10GiB, 내려받기 대역폭 월 10GiB입니다. Team과 Enterprise Cloud는 둘 다 250GiB입니다. 파일 하나의 상한은 Free와 Pro가 2GB입니다. 계산 방식은 이렇습니다.
| 항목 | 계산 방식 | 유니티 작업에서는 |
|---|---|---|
| 저장 | push한 버전마다 파일 전체 크기 | 500MB 파일을 1바이트만 고쳐 다시 push해도 500MB가 더 쌓임 |
| 대역폭 | 내려받을 때마다 저장소 주인 몫에서 | 팀원의 clone·pull, GitHub Actions의 다운로드도 포함 |
| 삭제 | 파일을 지워도 쓴 용량이 줄지 않음 | 완전히 없애려면 저장소를 지우고 다시 만들어야 함 |
무서운 것은 큰 파일 하나보다 자주 고치는 큰 파일입니다. 300MB PSD를 매일 고쳐 커밋하면 열흘 만에 저장 3GB가 찹니다. 결제 수단 없이 저장 한도를 넘기면 clone은 되지만 포인터만 받고, 새 파일은 push할 수 없습니다. 대역폭을 넘기면 다음 달까지 LFS가 꺼집니다. 레이어 작업 중인 PSD는 마무리될 때까지 커밋 횟수를 줄이는 편이 낫습니다.
이제 팀원 쪽입니다. 팀원이 GitHub Desktop으로 clone하면, Desktop은 .gitattributes에서 LFS 규칙을 찾아 Git LFS를 초기화하라는 창을 띄웁니다. 여기서 초기화해야 실제 파일을 받습니다.
LFS 없이 받으면 어떻게 될까요? 실험에서 LFS 다운로드를 끄고 clone하자, 120MB PSD 자리에 134바이트짜리 파일이 남았습니다. 열어 보면 이 세 줄뿐입니다.
version https://git-lfs.github.com/spec/v1
oid sha256:0f028f2de5ce1b26dc027e9bb467f4b941a8b499428ddee0a89e5a0389cd8496
size 125829120
이 텍스트는 이미지도 모델도 아니니 유니티가 텍스처나 모델로 읽을 수 없습니다. 팀원 쪽에서 특정 텍스처나 모델만 비어 보이면, 먼저 그 파일의 크기를 봅니다. 몇백 바이트라면 포인터입니다. 이때는 프로젝트 폴더에서 git lfs pull을 실행합니다. 실험에서도 이 명령 뒤에 원래 크기로 돌아왔습니다.
파일 크기가 정상인데도 텍스처가 빠진다면 LFS 문제가 아닙니다. 유니티라면 에셋마다 붙는 .meta 파일이 함께 올라갔는지 볼 차례입니다. 팀원 PC에서 깨지는 쪽이 마야 씬이라면 마야 씬을 다른 PC에서 열 때 텍스처 경로 확인하기를 보세요.
내 프로젝트용 Git LFS 명령 만들기
프로젝트에 있는 큰 파일 종류와 지금 상황을 고르면, 실행할 명령이 순서대로 나옵니다. 명령은 Assets 폴더가 보이는 프로젝트 맨 위 폴더에서 실행합니다.
한 줄 정리
Git LFS 규칙은 앞으로 할 커밋에만 적용되니, 이미 커밋한 큰 파일은 git lfs migrate import로 기록부터 넘겨야 push가 통과합니다.
vfx 잡학지식


댓글 0
첫 댓글을 남겨보세요.