Mac에서 button.js를 Button.js로 바꿨다고 해 봅시다. ls에는 새 이름이 보이는데 git status는 아무것도 보여 주지 않고, git add를 해도 커밋할 것이 없다고 합니다. 이 글을 읽고 나면 git이 지금 어느 이름을 기억하는지 두 명령으로 확인하고, 대소문자만 바꾼 이름을 커밋에 제대로 넣을 수 있습니다. 바꾸지 않는 편이 나은 설정 하나도 함께 봅니다.
예제는 2026-10-27, 2026-10-29, 2026-10-30에 macOS 27.0.1의 기본 APFS 볼륨에서 git 2.54.0(Apple Git-157)과 Node.js v24.21.0으로 실행했습니다. 사용자·시스템 git 설정은 읽지 않게 했고, button.js와 저장소는 설명을 위한 가상의 예입니다. 문서는 2026-10-27에 확인한 git-scm.com의 최신판 2.56.0(2026-09-28)을 기준으로 했고, core.ignoreCase 항목은 2.54.0 판과 같습니다. Linux, Windows, 대소문자를 구분하는 APFS 볼륨에서는 실행하지 않았습니다.
mv로 바꾸면 git은 조용합니다
저장소에는 button.js 하나와 그것을 부르는 파일 둘이 있습니다. main.mjs는 './button.js'를 import하고, lib/view.js는 번들러를 쓰는 프로젝트에서처럼 확장자 없이 '../button'을 import합니다. lib/view.js는 검색 대상으로만 두었고 실행하지 않았습니다. 이 상태로 첫 커밋을 하고 mv button.js Button.js로 이름을 바꿨습니다.
ls에는 Button.js가 보였지만 git status --short는 아무것도 출력하지 않고 끝났습니다. git ls-files는 여전히 소문자 button.js를 보여 주었습니다. git add Button.js 뒤에 커밋해도 "nothing to commit, working tree clean"이 나오고 종료 코드는 1이었습니다. 그런데 import를 './button.js'로 둔 채 실행한 node main.mjs는 x = 1을 출력했습니다. 이 디스크에서는 './button.js'로 불러도 Button.js가 열립니다.
다음 단계에서 일이 커집니다. 실험에서는 이름이 바뀐 것으로 보고 main.mjs의 import를 './Button.js'로 고쳐 커밋했습니다. git은 이 수정은 알아보고 커밋했습니다. 그 결과 커밋 안에는 파일 button.js와, 그 파일을 './Button.js'로 부르는 코드가 함께 들어갔습니다. 이 Mac에서는 그래도 잘 돌았습니다.

git이 기억하는 것은 인덱스의 이름입니다
git status가 보여 주는 것은 세 가지입니다. 마지막 커밋(HEAD)과 인덱스가 다른 경로, 인덱스와 작업 폴더가 다른 경로, 그리고 git이 추적하지도 무시하지도 않는 파일입니다. 인덱스는 다음 커밋에 들어갈 파일의 이름과 내용을 담아 두는 곳입니다. 이름이 바뀌었다고 보려면 폴더의 Button.js가 인덱스의 button.js와 다른 파일이어야 합니다.
이 판단을 바꾸는 설정이 core.ignoreCase입니다. APFS, HFS+, FAT, NTFS처럼 대소문자를 가리지 않는 파일 시스템에서 git이 제대로 일하도록 여러 우회 동작을 켜는 내부 변수입니다. 기본값은 false이지만 git init과 git clone이 저장소를 만들 때 파일 시스템을 살펴보고 필요하면 true로 정합니다. 실행에서도 git init 직후 값이 이미 true였습니다. 이 값이 true이면, 인덱스에는 button.js가 있고 폴더에는 Button.js가 있을 때 git은 둘을 같은 파일로 보고 인덱스의 이름을 계속 씁니다. 내용도 같으니 바뀐 것이 없다고 답한 것입니다.
디스크 쪽 사정도 같습니다. 이 Mac의 볼륨은 그냥 APFS였습니다. macOS의 디스크 유틸리티에서 'APFS(대소문자 구분)'는 따로 고르는 형식이고, 그냥 APFS는 그런 구분이 필요 없을 때 쓰는 형식입니다. 기본 APFS에서는 Button.js와 button.js가 같은 이름으로 통하므로 Node.js도 './button.js'로 Button.js를 찾았습니다.
문제는 이 커밋을 다른 컴퓨터에서 받을 때 드러납니다. Windows의 파일 시스템도 기본으로는 FOO.txt와 foo.txt를 같은 파일로 다루지만, Linux의 파일 시스템은 서로 다른 파일로 다룹니다. Linux에서 도는 CI나 서버가 이 커밋을 받으면 디스크에는 button.js가 생기고, './Button.js'를 부르는 import는 파일을 찾지 못할 수 있습니다. 이 장면은 실행하지 않았습니다. Mac에서 잘 돌았다는 것이 커밋 속 이름이 맞다는 뜻은 아닙니다.
git mv로 인덱스의 이름까지 바꿉니다
고치는 방법은 git mv button.js Button.js입니다. git mv는 파일의 이름을 바꾸고 인덱스를 갱신하며, 그 변경은 따로 커밋해야 합니다. 대소문자만 바꾸는 경우는 git-mv 문서에 따로 나오지 않아서 2.54.0에서 실행한 결과로 확인했습니다. 디스크의 이름이 이미 Button.js인데도 명령은 오류 없이 끝났고, git status --short에는 R 표시와 함께 button.js -> Button.js가 나타났습니다. 첫 칸의 R은 인덱스에 이름 바꿈이 올라갔다는 뜻입니다. 새 저장소에서 mv 없이 git mv만 실행했을 때도 디스크의 이름이 Button.js로 바뀌고 같은 R이 나왔습니다.
다만 -f 없이 쓰는 git mv가 이렇게 도는 것은 core.ignorecase가 true일 때입니다. 뒤에서 볼 Microsoft 안내대로 git config core.ignorecase false를 저장한 저장소에서는 mv를 했든 안 했든 git mv가 fatal: destination exists를 내고 종료 코드 128로 멈췄습니다. git config core.ignorecase true로 되돌리자 같은 명령이 R로 끝났습니다. 값을 지우면(git config --unset core.ignorecase) 기본값 false가 쓰여 같은 오류가 났습니다. 지금 값은 git config core.ignorecase로 볼 수 있습니다.
옛 이름을 부르던 import도 고쳐 이름을 바꾸는 커밋에 함께 넣는 것이 좋습니다. 그러면 이름만 바뀌고 import는 그대로인 커밋이 생기지 않습니다. 앞서 import만 고친 커밋은 역사에 그대로 남습니다. 이 예제에서는 git grep -n -E "/button(\.js)?['\"]"로 찾았습니다. 경로가 /button이나 /button.js로 끝나고 바로 따옴표가 오는 줄을 찾는 패턴입니다. 앞에서 놓친 lib/view.js의 '../button'이 나왔습니다.
여러 꼴의 import를 모은 파일에 따로 돌려 보니, '../components/button'이나 '@/components/button.js'처럼 폴더를 거치는 경로와 require("./button")까지 다섯 줄을 찾았고 './Button.js', './button-group', <button> 태그는 건너뛰었습니다. 같은 파일에서 git grep -n -F "./button"은 폴더를 거치는 두 줄을 놓치고 './button-group'을 잘못 골랐습니다. .ts, .jsx 같은 확장자나 다른 별칭을 쓴다면 패턴을 프로젝트에 맞게 고쳐야 합니다.
lib/view.js를 고쳐 같이 커밋하자 git show --name-status는 이 이름 바꿈을 R100으로 보여 주었습니다. R 뒤의 숫자는 옛 파일과 새 파일이 얼마나 같은지를 백분율로 나타낸 값이고, 이 예에서는 내용을 바꾸지 않아 100이 나왔습니다. 커밋의 파일 목록도 이제 Button.js입니다.
![git 2.54.0 실행 결과. git mv button.js Button.js 뒤 git status --short는 R button.js -> Button.js. git grep -n -E "/button(\.js)?['\"]"는 lib/view.js:1:import { x } from '../button';을 찾음. sed로 고쳐 git add lib/view.js 뒤 status는 R button.js -> Button.js와 M lib/view.js. 커밋 뒤 git show --name-status는 R100 button.js Button.js와 M lib/view.js. git ls-tree --name-only HEAD는 Button.js, lib, main.mjs, package.json. node main.mjs는 x = 1.](/images/ko/git-case-only-rename-run-02.png)
core.ignorecase를 false로 두고 add하면 이름이 둘이 됩니다
Microsoft의 WSL 안내는 git이 대소문자를 구분하게 하려면 git config core.ignorecase false를 쓰라고 적었습니다. 새 저장소에서 설정은 저장하지 않고, status·add·commit 세 명령에만 git -c core.ignorecase=false를 붙여 실행했습니다. -c로 넘긴 값은 그 명령에서 설정 파일의 값보다 먼저 쓰입니다. 그 밖의 명령은 뒤에 나오는 git rm --cached까지 저장소에 저장된 값 true로 실행했습니다.
mv 뒤에 이 설정으로 status를 보니 Button.js가 추적하지 않는 새 파일(??)로 보였습니다. 그대로 add -A하고 커밋하자 커밋 속에 Button.js와 button.js 두 이름이 생겼습니다. 디스크에는 파일이 하나뿐입니다. 인덱스의 button.js도 같은 파일로 찾아지니, git은 그 이름이 지워졌다고 보지 않은 것으로 보입니다. 이 저장소를 Mac에서 clone하자 두 경로가 부딪혀 작업 폴더에는 하나만 꺼냈다는 경고가 나왔고, 꺼낸 이름은 button.js였습니다.
이 값을 바꾸는 데에는 경고가 붙어 있습니다. git-config 문서는 git이 운영체제와 파일 시스템에 맞게 설정된 이 값을 믿고 움직이므로, 바꾸면 예상하지 못한 동작이 생길 수 있다고 적었습니다. Microsoft 안내도 대소문자를 가리지 않는 파일 시스템에서 false로 두면 헷갈리는 오류, 실제가 아닌 충돌, 중복 파일을 겪을 수 있다고 말합니다.
이미 두 이름이 커밋됐다면 옛 이름만 인덱스에서 빼면 됩니다. 설정 파일에 false를 저장해 두었다면 먼저 git config core.ignorecase true로 되돌립니다. git rm --cached button.js는 인덱스에서만 지우고 작업 폴더의 파일은 그대로 둡니다. .gitignore에 적은 파일이 계속 커밋되는 경우를 다룬 글에서 추적만 끊을 때 쓴 것과 같은 명령입니다. 커밋 뒤 목록에는 Button.js만 남았고, 새로 clone해도 경고가 나오지 않았습니다. false를 저장한 저장소에서 true로 되돌린 뒤 실행해도 Button.js만 남았습니다. 이 실험에서는 두 항목의 내용이 같았습니다. 내용이 다른 경우는 실행하지 않았으니, 빼기 전에 git show HEAD:button.js와 git show HEAD:Button.js로 두 내용을 비교해 보십시오.

두 이름을 맞추는 순서
개발 노트
대소문자만 바꿀 때 이름을 맞추는 순서
디스크의 이름과 인덱스의 이름이 같아져야 커밋에 들어갑니다
두 이름을 비교
git ls-files- ls는 디스크의 이름
- git ls-files는 인덱스의 이름
- 대소문자만 다르면 git은 바뀐 줄 모름
git mv로 이름 바꾸기
git mv button.js Button.js- core.ignorecase가 false면 먼저 true로 되돌림
- mv를 먼저 했어도 됨
- status에 R이 뜨면 인덱스에 반영
옛 이름 import도 고쳐 같은 커밋에
git grep -n -E "/button(\.js)?['\"]"- 경로 끝이 /button 또는 /button.js인 줄을 찾는 예
- 확장자·별칭은 프로젝트에 맞게
이름이 둘 다 커밋됐다면
git rm --cached button.js- core.ignorecase=false로 add한 경우
- 옛 이름만 인덱스에서 빼고 커밋
button.js는 가상 예제입니다. macOS 27.0.1 기본 APFS 볼륨에서 git 2.54.0으로 2026-10-27과 2026-10-29에 실행했습니다. Linux·Windows는 실행하지 않았습니다.
git이 바뀐 것이 없다고 하면 ls와 git ls-files를 나란히 보십시오. 디스크의 Button.js와 인덱스의 button.js처럼 대소문자만 다르면, git은 아직 옛 이름을 기억하고 있는 것입니다. 그때는 core.ignorecase를 true로 둔 채 git mv로 인덱스의 이름을 바꾸고, 옛 이름을 부르던 코드를 고쳐 함께 커밋하면 됩니다.
이 기록에 대화를 더해 주세요.
궁금한 점, 다른 접근, 직접 해 본 결과를 나눠 주세요.
로그인 상태 확인 중…
댓글을 불러오는 중…