자식 인덱스에는 정확히 무엇이 포함되어 있습니까?


178

Git 인덱스에는 정확히 무엇이 포함되어 있으며 인덱스의 내용을보기 위해 어떤 명령을 사용할 수 있습니까?


최신 정보

모든 답변에 감사드립니다. 인덱스가 준비 영역으로 작동하고 커밋 된 것은 작업 트리가 아니라 인덱스에 있다는 것을 알고 있습니다. 인덱스 객체가 무엇인지 궁금합니다. 파일 이름 / 디렉토리 이름, SHA-1 쌍, 가상 트리 종류 일 수 있습니까?

Git 용어 에는 인덱스의 내용을 나열하는 데 사용할 수 있는 배관 명령이 있습니까?



3
다이어그램을 읽고보아야합니다-매우 유용합니다 : gitguys.com/topics/whats-the-deal-with-the-git-index
kernix

1
@kernix 도메인이 만료되었습니다. 더 이상 도움이되지 않습니다.
narendra-choudhary

답변:


162

Git 책에는 색인 에 포함 된 내용에 대한 기사가 있습니다 .

인덱스는 .git/index경로 이름의 정렬 된 목록을 포함 하는 이진 파일 (일반적으로로 유지됨 )이며, 각각 권한과 BLOB 개체의 SHA1이 있습니다. git ls-files색인의 내용을 보여줄 수 있습니다.

$ git ls-files --stage
100644 63c918c667fa005ff12ad89437f2fdc80926e21c 0   .gitignore
100644 5529b198e8d14decbe4ad99db3f7fb632de0439d 0   .mailmap

선정적인 이눔 문제는 그 구조에 대한 좀 더 자세한 내용을 제공합니다 :

인덱스는 git에서 가장 중요한 데이터 구조 중 하나입니다.
경로 목록과 객체 이름을 기록하여 가상 작업 트리 상태를 나타내며 커밋 할 다음 트리 객체를 작성하기위한 준비 영역 역할을합니다.
상태는 작업 트리의 파일과 반드시 ​​일치 할 필요는 없으며 종종 일치하지 않아도된다는 점에서 "가상"입니다.


자세한 내용은 cf. " git / git / Documentation / technical / index-format.txt ":

Git 인덱스 파일의 형식은 다음과 같습니다

모든 이진수는 네트워크 바이트 순서입니다. 달리 명시되지 않는 한
버전 2 가 여기에 설명되어 있습니다.

  • 다음으로 구성된 12 바이트 헤더 :
    • 4 바이트 서명 :
      서명은 { ' D', ' I', ' R', ' C'}입니다 ( " dircache"의 약자 )
    • 4 바이트 버전 번호 :
      현재 지원되는 버전은 2, 3 및 4입니다.
    • 32 비트 인덱스 항목 수
  • 여러 개의 정렬 된 색인 항목 .
  • 확장 :
    확장은 서명으로 식별됩니다.
    Git이 이해하지 못하면 선택적 확장은 무시할 수 있습니다.
    힘내는 현재 캐시 트리를 지원하고 실행 취소 확장을 해결합니다.
    • 4 바이트 확장 서명. 첫 번째 바이트가 ' A'.. ' Z'인 경우 확장자는 선택 사항이며 무시할 수 있습니다.
    • 확장의 32 비트 크기
    • 확장 데이터
  • 이 체크섬 이전의 인덱스 파일 내용에 대한 160 비트 SHA-1

mljrg 의견 :

인덱스가 다음 커밋이 준비된 장소 인 경우 커밋 git ls-files -s후에 " "가 아무것도 반환 하지 않는 이유는 무엇입니까?

때문에 인덱스를 추적하는 것을 나타내고 , 오른쪽 커밋 후 마지막 (커밋 없습니다, 무엇을 추적하는 것은 동일하다 git diff --cached반환 아무것도).

그래서 git ls-files -s모든 파일을 추적 목록 (개체 이름, 모드 비트 및 출력에 단수).

해당 요소 (추적 된 요소) 목록은 커밋 내용으로 초기화됩니다.
분기를 전환하면 방금 전환 한 분기에서 참조하는 커밋으로 인덱스 내용이 재설정됩니다.


Git 2.20 (Q4 2018)은 IEOT (Index Entry Offset Table )를 추가합니다 .

참조 77ff112 커밋 , 3,255,089 커밋 , abb4bb8 커밋 , c780b9c 커밋 , 3b1d9e0 커밋 , 371ed0d 커밋 에 의해 (2018년 10월 10일) 벤 씩씩한를 ( benpeart) . Nguyễn Thái Ngọc Duy ( )의 commit 252d079 (2018 년 9 월 26 일)를
참조하십시오 . ( Junio ​​C Hamano의해 병합 - 커밋 e27bfaa , 2018 년 10 월 19 일)pclouds
gitster

ieot : IEOT (Index Entry Offset Table) 확장 추가

이 패치를 사용하면 캐시에로드 및 변환을 효율적으로 멀티 스레딩 할 수있는 인덱스에 추가 데이터를 추가하여 인덱스로드의 CPU 비용을 처리 할 수 ​​있습니다.

인덱스 파일의 캐시 항목 블록에 오프셋 테이블 인 (선택적) 인덱스 확장을 추가하여이를 수행합니다.

V4 인덱스에 대해이 작업을 수행하려면 캐시 항목을 쓸 때 이전 항목의 경로 이름이 완전히 다른 것처럼 현재 항목을 인코딩하여 접두사 압축을 주기적으로 "재설정"하고 IEOT에 해당 항목의 오프셋을 저장합니다. .
기본적으로 V4 인덱스를 사용하면 접두사 압축 항목 블록으로 오프셋을 생성합니다.

으로 새로운 index.threads 설정 설정 , 인덱스 로딩 이제 빠릅니다.


그 결과 ( IEOT 사용 ), 7bd9631을 커밋read-cache.c load_cache_entries_threaded() 하여 Git 2.23 (Q3 2019) 의 기능을 정리하십시오 .

참조 8,373,037 커밋 , d713e88 커밋 , d92349d 커밋 , 113c29a 커밋 , 커밋 c95fc72 , 7a2a721 커밋 , c016579 커밋 , 커밋 be27fb7 , 13a1781 커밋 , 7bd9631 커밋 , 3c1dce8 커밋 , cf7a901 커밋 , d64db5b 커밋 , 76a7bc0 커밋 에 의해 (2019 09 월) 제프 킹 ( peff) .
(의해 병합 Junio C 하마노 - gitster-커밋 c0e78f7 13 유월 2019)

읽기 캐시 : 스레드로드에서 사용되지 않은 매개 변수 삭제

load_cache_entries_threaded()함수는 src_offset사용하지 않는 매개 변수를 사용합니다. 이것은 77ff112 에서 시작된 이래로 계속되었습니다 ( read-cache: 작업자 스레드에 캐시 항목로드, 2018-10-10, Git v2.20.0-rc0).

메일 링리스트를 파고 들어, 그 파라미터는 시리즈초기 반복의 일부 였지만 코드가 IEOT 확장을 사용하도록 전환 할 때 불필요 해졌습니다.


6
Git 모델의 인덱스 인 경우의 중요성에 대해서는 stackoverflow.com/questions/1450348/…
VonC

위의 첫 번째 링크는 색인에 기사가없는 git-scm 버전을 가리 킵니다. 의도는 여기에 있다고 생각합니다. schacon.github.io/gitbook/7_the_git_index.html
Kris Giesing

1
@KrisGiesing 링크 감사합니다. 답변을 업데이트했습니다.
VonC

@VonC 인덱스가 다음 커밋이 준비된 장소라면, 왜 커밋 후에 "git ls-files -s"가 아무것도 반환하지 않습니까? 답변에 넣은 것보다 색인에 대해 더 많은 것이 있어야합니다.
mljrg

@mljrg 내가 당신을 따르지 않을 것입니다 : 커밋 커밋이 완료되었으므로 커밋이 준비된 단계가 비어있을 것입니다.
VonC

62

비트 별 분석

형식을 더 잘 이해하고 일부 필드를 자세히 조사하기 위해 약간의 테스트를하기로 결정했습니다.

결과는 Git 버전 1.8.5.2과 동일합니다 2.3.

확실하지 않거나 찾을 TODO수없는 포인트를 표시했습니다. 해당 포인트를 자유롭게 보완하십시오.

다른 사람들이 언급했듯이 인덱스는 .git/index표준 트리 개체가 아닌에 저장되며 형식은 이진이며 https://github.com/git/git/blob/master/Documentation/technical/index-format에 문서화되어 있습니다. txt

인덱스가 커밋을 만들기위한 캐시이므로 인덱스를 정의하는 주요 구조체는 cache.h 입니다.

설정

테스트 저장소를 시작할 때 :

git init
echo a > b
git add b
tree --charset=ascii

.git디렉토리 외모가 좋아 :

.git/objects/
|-- 78
|   `-- 981922613b2afb6025042ff6bd878ac1994e85
|-- info
`-- pack

그리고 우리가 유일한 객체의 내용을 얻는다면 :

git cat-file -p 78981922613b2afb6025042ff6bd878ac1994e85

우리는 얻는다 a. 이것은 다음을 나타냅니다.

  • index파일 내용에 대한 점은, 이후는 git add bBlob 객체를 생성
  • 단일 객체 만 있었기 때문에 메타 데이터를 트리 파일이 아닌 인덱스 파일에 저장합니다. Blob (일반 Git 객체의 경우 Blob 메타 데이터는 트리에 저장 됨)

HD 분석

이제 색인 자체를 살펴 보자.

hd .git/index

제공합니다 :

00000000  44 49 52 43 00 00 00 02  00 00 00 01 54 09 76 e6  |DIRC.... ....T.v.|
00000010  1d 81 6f c6 54 09 76 e6  1d 81 6f c6 00 00 08 05  |..o.T.v. ..o.....|
00000020  00 e4 2e 76 00 00 81 a4  00 00 03 e8 00 00 03 e8  |...v.... ........|
00000030  00 00 00 02 78 98 19 22  61 3b 2a fb 60 25 04 2f  |....x.." a;*.`%./|
00000040  f6 bd 87 8a c1 99 4e 85  00 01 62 00 ee 33 c0 3a  |......N. ..b..3.:|
00000050  be 41 4b 1f d7 1d 33 a9  da d4 93 9a 09 ab 49 94  |.AK...3. ......I.|
00000060

다음으로 결론을 내립니다.

  | 0           | 4            | 8           | C              |
  |-------------|--------------|-------------|----------------|
0 | DIRC        | Version      | File count  | ctime       ...| 0
  | ...         | mtime                      | device         |
2 | inode       | mode         | UID         | GID            | 2
  | File size   | Entry SHA-1                              ...|
4 | ...                        | Flags       | Index SHA-1 ...| 4
  | ...                                                       |

먼저 struct cache_header에 정의 된 헤더가옵니다 .

  • 44 49 52 43: DIRC. TODO : 왜 이것이 필요한가요?

  • 00 00 00 02: 형식 버전 : 2. 색인 형식이 시간이 지남에 따라 발전했습니다. 현재 최대 4 개의 버전이 있습니다. 베어 리포지토리는 인덱스를 저장하지 않기 때문에 GitHub의 다른 컴퓨터간에 협업 할 때 인덱스 형식에 문제가 없어야합니다. 인덱스는 복제시 생성됩니다.

  • 00 00 00 01: 인덱스의 파일 수 : 단 하나 b.

다음으로 struct cache_entry에 의해 정의 된 인덱스 항목 목록을 시작합니다 . 여기에 하나만 있습니다. 그것은 포함합니다 :

  • 8 바이트 ctime, 8 바이트 mtime및 4 바이트 : 장치, inode, 모드, UID 및 GID : 파일 메타 데이터의 무리 .

    참고 사항 :

    • ctimemtime(동일한 54 09 76 e6 1d 81 6f c6우리가 파일을 수정하지 않았기 때문에 예상대로)

      16 진수로 EPOCH 이후 첫 번째 바이트는 초입니다.

      date --date="@$(printf "%x" "540976e6")"
      

      제공합니다 :

      Fri Sep  5 10:40:06 CEST 2014
      

      내가이 예제를 만들었을 때입니다.

      두 번째 4 바이트는 나노초입니다.

    • UID 및 GID는 00 00 03 e81000으로 16 진수입니다. 단일 사용자 설정의 공통 값입니다.

    이 메타 데이터는 대부분 트리 개체에 존재하지 않으므로 Git은 전체 내용을 비교하지 않고 파일이 빠르게 변경되었는지 확인할 수 있습니다.

  • 줄의 시작 부분에서 30: 00 00 00 02: 파일 크기 : 2 바이트 ( a\nfrom echo)

  • 78 98 19 22 ... c1 99 4e 85: 항목의 이전 내용보다 20 바이트 SHA-1. 가정하는 것으로 유효한 플래그를 사용한 실험 에 따르면 이 플래그를 따르는 플래그는이 SHA-1에서 고려되지 않습니다.

  • 2 바이트 플래그 : 00 01

    • 1 비트 : 유효한 플래그를 가정합니다. 내 조사에 따르면 이름이 잘못 지정된이 플래그 git update-index --assume-unchanged의 상태는 다음과 같습니다. https://stackoverflow.com/a/28657085/895245

    • 1 비트 확장 플래그. 확장 플래그가 있는지 여부를 결정합니다. 0확장 플래그가없는 버전 2에 있어야합니다 .

    • 병합 중에 사용되는 2 비트 스테이지 플래그. 단계는 다음에 설명되어 있습니다 man git-merge.

      • 0: 일반 파일, 병합 충돌이 아님
      • 1:베이스
      • 2우리의 것
      • 3: 그들의 것

      병합 충돌 동안 1-3의 모든 단계가 색인에 저장되어 같은 작업을 수행 할 수 있습니다 git checkout --ours.

      이면 git add단계 0이 경로의 인덱스에 추가되고 Git은 충돌이 해결 된 것으로 표시되었음을 알게됩니다. TODO : 이것을 확인하십시오.

    • 다음과 같은 경로의 12 비트 길이 : 0 01: 경로 이후 1 바이트 만b

  • 2 바이트 확장 플래그. "확장 플래그"가 기본 플래그에 설정된 경우에만 의미가 있습니다. 할 것.

  • 62(ASCII b) : 가변 길이 경로. 길이는 여기에, 이전 플래그 단지 1 바이트를 결정 b.

그런 다음 00경로가 null로 끝나고 인덱스가 8 바이트의 배수로 끝나도록 1-8 바이트의 0 패딩이 제공됩니다. 이것은 인덱스 버전 4 이전에만 발생합니다.

확장이 사용되지 않았습니다. Git은 체크섬을 위해 파일에 충분한 공간이 남아 있지 않기 때문에 이것을 알고 있습니다.

마지막으로 ee 33 c0 3a .. 09 ab 49 94인덱스 내용에 20 바이트의 체크섬 이 있습니다.


1
매우 흥미로운. +1. 그것은 내 자신의 대답을 잘 보여줍니다. 그 결과가 최신 Git 2.1 이상으로 변경되는지 궁금합니다.
VonC

3
@NielsBom 그렇습니다. 프로그램을 해석 할 때는 두 가지 접근 방식을 선호합니다. 먼저 어떤 출력을 생성하는지 확인한 다음 소스 만 읽습니다. 그렇지 않으면 간단한 출력에는 나타나지 않는 소스 코드 엣지 케이스에 빠질 수 있습니다. 물론, 나는 소스 구조체를보고 나를 안내해 주었고, 모든 TODO는 그 구조체가 어떻게 조작되는지, 나의 어려운 부분 인 내 독서를 해결할 수 있습니다.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

1
@CiroSantilli 六四 事件 法轮功 纳米比亚 威 视 : 16 진수 편집기에서 색인을 수정하고 20 바이트 체크섬을 업데이트하면 다른 객체에 저장된 sha1을 업데이트하는 명령이 있습니까? (git은 sha1의 서명이 손상되었다고 불평합니다) . 또한 푸시 요청을 통해 전송 될 때 인덱스 데이터가 완전히 다른 방식으로 저장됩니다.
user2284570

1
@CiroSantilli 六四 事件 法轮功 纳米比亚 威 视 : 보안 목적. git 데이터베이스 / 객체에 적용된 잘 알려진 종류의 래스터 이미지 파일 공격을 찾으십시오. (물론 나는 대부분의 구현이 최근에 그 관점을 돌 보았지만 모두는 아니라는 것을 알고 있습니다.)  특히 배열의 길이를 알려주는 이진 데이터 구조를 찾고 있습니다. (텍스트 버퍼에 대해서는 null 종료가 행 수를 나타내는 표준 인 것 같습니다)
user2284570

1
에 대해서는 git add, 당 TODO: 당신은 정확합니다. 주어진 경로에 상위 단계 색인 항목 (충돌)이있는 경우 git add해당 경로에서 모든 상위 단계 색인 항목이 제거되고 작업 디렉토리 사본이 단계에서 추가됩니다 0. (충돌 해결).
Edward Thomson

11

Git 인덱스는 작업 디렉토리와 저장소 사이의 준비 영역입니다. 색인을 사용하여 함께 커미트 할 변경 사항 세트를 빌드 할 수 있습니다. 커밋을 만들 때 커밋 된 것은 작업 디렉토리에있는 것이 아니라 현재이 인덱스에있는 것입니다.

색인 내부의 내용을 보려면 다음 명령을 실행하십시오.

git status

git status를 실행하면 어떤 파일이 준비되었는지 (현재 색인에 있음), 수정되었지만 아직 준비되지 않았으며 완전히 추적되지 않은 파일을 볼 수 있습니다.

당신은 이것을 읽을 수 있습니다 . Google 검색은 많은 링크를 제공하며, 이는 충분히 자급 자족해야합니다.


7
git status색인의 모든 파일을 나열하지는 않습니다. 색인과 작업 디렉토리가 다른 파일 만 나열합니다. 색인의 모든 파일을 보려면을 사용해야 git ls-files합니다.
Akash Agrawal

1
@AkashAgrawal, git status 하지 에 상관없이 그들이 지수와 WORKDIR 사이에 차이가 있는지 여부, 사실의리스트 인덱스 파일에.
Acumenus 18시 37 분

3
예, 일부 색인 파일을 나열하지만 색인 내부의 모든 것을 표시하지는 않습니다. 상자 안에 2 개의 녹색 공과 3 개의 빨간 공이 있다고 말하는 것과 같습니다. 상자 안의 내용을 보려면 2 개의 녹색 공을 당겨 빼십시오. Akash가 말한 것이 가장 정확합니다. 색인의 모든 파일을 보려면 git ls-files를 사용하십시오.
dave4jr

3
과연. git status색인에있는 파일을 나열하지만 , 색인에있는 모든 파일을 나열하지는 않습니다 . git status 실제로 어떻게 작동 하는지 설명하는 것은 아마도 이것이 아닐지라도 어떤 질문에 대한 유익한 답변이 될 것입니다.
Edward Thomson

1
git status작업 트리 상태 (작업 트리와 색인의 차이)를 표시합니다. 실제로 색인을 표시하지 않습니다. git-scm.com/docs/git-status
wisbucky

1

다음은 정확히 필요한 것입니다.이 명령을 사용하십시오.

$ binwalk index

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
1717          0x6B5           Unix path: /company/user/user/delete.php
1813          0x715           Unix path: /company/user/user/get.php
1909          0x775           Unix path: /company/user/user/post.php
2005          0x7D5           Unix path: /company/user/user/put.php
3373          0xD2D           Unix path: /urban-airship/channel/channel/post.php
3789          0xECD           Unix path: /urban-airship/named-user/named-user/post.php
3901          0xF3D           Unix path: /user/categories/categories/delete.php
4005          0xFA5           Unix path: /user/categories/categories/get.php
4109          0x100D          Unix path: /user/categories/categories/put.php
4309          0x10D5          Unix path: /user/favorites/favorites/delete.php

0

Git 인덱스는 .git/index정렬 된 경로 이름 목록 (각각 권한과 BLOB 개체의 SHA1이 있음)을 포함 하는 이진 파일 (일반적으로로 유지됨 )입니다.

git ls-files색인의 내용을 보여줄 수 있습니다. 그 말을 유의하시기 바랍니다 index, stage그리고 cache힘내에서 같은 일이다 : 그들은 같은 의미로 사용됩니다.

여기에 이미지 설명을 입력하십시오

Git 인덱스 또는 Git 캐시에는 3 가지 중요한 속성이 있습니다.

  1. 색인에는 단일 (독특하게 결정된) 트리 오브젝트를 생성하는 데 필요한 모든 정보가 포함됩니다.
  2. 인덱스를 사용하면 정의한 트리 개체와 작업 트리를 빠르게 비교할 수 있습니다.
  3. 서로 다른 트리 개체 간의 병합 충돌에 대한 정보를 효율적으로 나타낼 수 있으므로 각 경로 이름을 트리 간 병합을 만들 수있는 관련 트리에 대한 충분한 정보와 연결할 수 있습니다.

출처 :

  1. https://mincong.io/2018/04/28/git-index/
  2. https://medium.com/hackernoon/understanding-git-index-4821a0765cf
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.