Git 인덱스 검사기
.git/index를 브라우저에서 읽습니다. 스테이징된 항목의 해시·모드·플래그, 충돌 스테이지, 확장, 끝 체크섬까지 확인하세요.
사용법
- 아무 저장소의 .git/index를 끌어다 놓으세요. 확장자가 없어 파일 관리자에서 숨겨질 수 있으니 선택 창에 경로를 직접 입력하거나 다른 곳에 복사해도 됩니다. 사본도 똑같이 읽힙니다.
- 요약부터 보세요. 형식 버전, 헤더가 밝힌 항목 수와 실제로 읽힌 수, 오브젝트 ID가 SHA-1인지 SHA-256인지, 끝 체크섬이 여전히 맞는지를 알 수 있습니다.
- 플래그 개수를 확인하세요. assume-unchanged나 skip-worktree가 0이 아니라면 git이 변경을 알아채지 못하는 파일이 있다는 뜻이고, intent-to-add는 -N으로 추가만 해 둔 경로를 뜻합니다.
- 항목 표에서 경로를 찾아 스테이징된 해시, 모드, 기록된 크기, 캐시된 수정 시각을 확인하세요. 아주 큰 인덱스는 앞쪽 수백 행만 표시하고 옆에 전체 개수를 함께 적습니다.
- 병합 뒤에는 충돌 구역을 보세요. 해결되지 않은 경로마다 base, ours, theirs 스테이지를 나란히 놓아 주고, 해결 취소 확장에는 이미 해결한 경로가 남아 있습니다.
자세한 설명
펼치기접기
저장소의 스테이징 영역인 .git/index를 git ls-files --stage --debug가 읽는 방식 그대로 바이트에서 직접 읽어, 전부 브라우저 안에서 보여 줍니다. 각 항목마다 스테이징된 블롭의 오브젝트 ID, 파일 모드, 병합 스테이지, git이 기록한 크기, 그리고 파일이 바뀌지 않았다고 판단할 때 lstat()과 비교하는 캐시된 수정 시각을 표시합니다. 이 캐시가 바로 이 파일에 얽힌 가장 흔한 수수께끼의 원인입니다. 방금 고친 파일을 git이 계속 그대로라고 우긴다면 대개 해당 항목에 assume-unchanged나 skip-worktree 비트가 붙어 있으며, 두 값 모두 항목별로 표시되고 intent-to-add와 함께 위쪽에서 개수로 집계됩니다. git update-index --index-info로 쓰인 항목은 stat 블록이 전부 0인데 이는 손상이 아니라 정상이므로, 1970년 날짜를 꾸며 내지 않고 stat 데이터 없음으로 표시합니다. 버전 2, 확장 플래그 워드가 붙는 버전 3, 그리고 경로를 앞 항목과의 공통 접두사로 압축하고 git 고유의 오프셋 varint를 쓰는 버전 4까지 모두 읽습니다. 버전 4는 잘못 해석해도 그럴듯한 경로가 나오기 때문에 실제 파일로 검증된 구현으로 읽어야 합니다. 헤더에는 저장소가 SHA-1을 쓰는지 SHA-256을 쓰는지 적혀 있지 않으므로 두 오브젝트 ID 길이를 모두 시도해 항목과 확장이 끝 체크섬에 정확히 맞아떨어지는 쪽을 택하고, 그 체크섬을 나머지 내용과 대조해 검증합니다. 항목 뒤에 붙는 확장은 크기와 함께, 쓸모가 있는 경우 내용까지 보여 줍니다. 캐시된 트리와 그중 아직 유효한 서브트리 수, 해결 취소 기록, 추적되지 않은 파일 캐시, 파일 시스템 모니터, 큰 인덱스를 병렬로 읽게 해 주는 오프셋 표가 그것입니다. 분할 인덱스도 그대로 알아봅니다. 경로가 모두 비어 있는 이유는 실제 항목이 .git/sharedindex에 있기 때문입니다. 다만 내용 자체는 알 수 없습니다. 항목은 블롭을 해시로 가리킬 뿐이고 블롭은 .git/objects라는 다른 파일에 있습니다.
자주 묻는 질문
방금 수정했는데 git이 계속 변경 없음이라고 하는 이유는 무엇인가요?
거의 항상 해당 항목에 assume-unchanged(git이 디스크에서 CE_VALID라 부르는 비트)나 skip-worktree가 붙어 있기 때문입니다. 둘 다 그 경로에 대해서는 인덱스를 믿고 lstat 비교를 건너뛰라는 뜻이며, 무언가가 지워 주기 전까지 인덱스에 그대로 남습니다. 그래서 증상이 영구적으로 보이고 편집기가 아니라 저장소를 따라다닙니다. 의미는 다릅니다. assume-unchanged는 느린 파일 시스템에 대해 사용자가 하는 약속이고, skip-worktree는 그 파일이 일부러 없거나 로컬에서 바뀐 상태이니 건드리지 말라는 선언입니다. 증상은 같지만요. 이 페이지는 둘을 세어 주고 해당 항목을 표시하므로, 문제의 경로에 git update-index --no-assume-unchanged나 --no-skip-worktree를 실행하면 됩니다.
항목에 들어 있는 stat 데이터는 무엇에 쓰이며 왜 0일 때가 있나요?
각 항목은 git이 작업 트리 파일을 마지막으로 확인했을 때의 ctime, mtime, 장치 번호, 아이노드, uid, gid, 모드, 크기를 캐시해 둡니다. 다음 status에서 git은 lstat()을 호출해 비교하고, 모든 필드가 그대로면 파일이 바뀌었을 리 없으므로 읽지도 해시하지도 않습니다. 큰 저장소에서 status가 빠른 이유가 이것입니다. 모든 필드는 32비트로 잘리므로 설계상 근사값입니다. stat 블록이 통째로 0인 항목은 실제 파일과 한 번도 비교된 적이 없다는 뜻이며, git update-index --index-info나 충돌 스테이지가 그런 항목을 만듭니다. 그래서 1970년 날짜를 지어내지 않고 stat 데이터 없음으로 표시합니다.
인덱스 버전이 2, 3, 4 사이에서 계속 바뀌는 이유는 무엇인가요?
버전 2가 기본입니다. 어떤 항목이든 확장 플래그 워드를 필요로 하는 순간 git은 버전 3으로 씁니다. skip-worktree와 intent-to-add가 들어갈 자리가 거기뿐이기 때문입니다. 그런 항목이 마지막으로 사라지면 조용히 2로 되돌아갑니다. 즉 파일 하나에 skip-worktree를 붙이는 것만으로 전체 파일이 다른 버전으로 다시 쓰입니다. 버전 4는 git update-index --index-version 4로 직접 켜는 선택 사항이며, 각 경로를 앞 경로와 비교해 압축합니다. 디렉터리가 깊은 저장소에서 실제로 공간을 아끼지만 파일을 앞에서부터만 읽을 수 있게 됩니다. 여기서는 세 버전을 모두 읽고, 버전은 추측하지 않고 헤더에서 가져옵니다.
.git/index가 수십 MB입니다. 안에 무엇이 들어 있나요?
항목 하나는 약 62바이트에 경로 길이를 더한 정도라서 파일 10만 개라도 몇 MB에 그칩니다. 그보다 훨씬 크다면 대개 확장 때문입니다. 추적되지 않은 파일 캐시(UNTR)는 버전 관리 밖의 모든 것을 디렉터리 단위로 기록하므로 작업 트리에 쌓인 잡동사니만큼 커집니다. 캐시된 트리(TREE)는 디렉터리마다 한 건씩 기록합니다. 파일이 아주 많은 저장소라면 git이 분할 인덱스를 쓰고 있을 수도 있는데, 이때 본체는 .git/sharedindex.<id>에 있고 열어 본 파일은 사실상 link 확장뿐입니다. 여기 확장 표가 각각의 크기를 보여 주므로 원인을 가장 빨리 찾을 수 있습니다.
인덱스 끝의 체크섬은 무엇을 막아 주나요?
마지막 20바이트(SHA-256 저장소라면 32바이트)는 그 앞의 모든 내용을 해시한 값이며 git이 파일을 다시 쓸 때마다 갱신합니다. 쓰기 도중 중단, 디스크 불량, 부분 복사 같은 잘림과 손상은 잡아내지만 고의적인 변조는 막지 못합니다. 파일을 고친 사람이 체크섬도 다시 계산할 수 있기 때문입니다. 값이 맞지 않으면 git은 그 인덱스를 아예 쓰지 않습니다. 다행히 복구할 수 있습니다. 인덱스 자체에는 내용이 없으므로 파일을 지우고 git reset을 실행하면 HEAD에서 다시 만들어집니다. 잃는 것은 어떤 경로가 스테이징돼 있었는지와 intent-to-add 항목 같은 배치이지, 이미 .git/objects에 있는 오브젝트가 아닙니다. 예외가 하나 있습니다. feature.manyFiles가 켜는 index.skipHash 설정에서는 git이 해시를 아예 계산하지 않고 이 자리에 0바이트 20개를 씁니다. 그래서 전부 0인 체크섬은 불일치가 아니라 계산하지 않음으로 표시됩니다.
파일이 어딘가로 업로드되나요?
아닙니다. 인덱스는 브라우저의 File API로 읽고 페이지 안의 자바스크립트가 해석하며, 보낼 서버 자체가 없습니다. 다른 형식보다 이 점이 더 중요합니다. .git/index는 비공개 저장소의 전체 경로 목록에 스테이징된 파일마다의 해시까지 담고 있어서, 웹 양식에 붙여 넣을 만한 것이 아니기 때문입니다. 페이지를 연 뒤 네트워크를 끊어도 모든 기능이 그대로 동작합니다.
관련 도구
Git 설정 우선순위 테스터
git 설정 파일을 붙여 넣으면 키마다 어떤 값이 이기는지, 그 값이 나온 범위·파일·줄, 무엇을 덮었는지, 어떤 includeIf가 걸렸는지 보여줍니다.
개발
자바 클래스 파일 분석기
컴파일된 .class 파일을 브라우저에서 바로 분석합니다. 클래스 파일 버전과 자바 릴리스, 접근 플래그, 상수 풀, 필드, 메서드, 참조 클래스를 보여줍니다.
파일
Ogg 컨테이너 검사기
.ogg, .oga, .opus를 페이지 단위로 분석합니다. 그래뉼 위치, 세그먼트 테이블, CRC32 검증, 그리고 컨테이너가 담은 논리 스트림까지 보여줍니다.
파일
Git 팩파일 뷰어 (.pack / .idx)
.pack과 .idx를 브라우저에서 읽어 객체마다 종류·크기·오프셋·델타 깊이와 베이스, 종류별 합계와 가장 큰 객체를 보여 줍니다.
파일
TAR 아카이브 검사기
.tar, .tar.gz, .tgz 파일을 풀지 않고 내부 항목을 전부 봅니다. 권한, 소유자, 크기, 시각, 링크 대상까지 표시합니다.
파일
xz(.xz) 스트림 분석기
xz 컨테이너를 읽습니다. 스트림 헤더, 블록 헤더와 필터 체인, 인덱스와 푸터, 그리고 압축을 풀지 않고 알아낸 실제 원본 크기까지.
파일