"델타 해결 중"이라고 말하면 실제로 git은 무엇을하고 있습니까?


187

저장소의 첫 번째 복제 동안 git은 먼저 객체를 수신하고 (충분히 명백한) "델타 해결"과 거의 같은 시간을 소비합니다. 이 복제 단계에서 실제로 어떤 일이 발생합니까?



1
힘내 2.20 (Q4 2018)보다 델타 섬을 위해, 참조 : stackoverflow.com/a/52458712/6309
VonC

답변:


54

Git은 델타 인코딩 을 사용 하여 일부 객체를 팩 파일에 저장합니다. 그러나, 당신은 매일 변화를 재생하고 싶지 않아 지금까지 힘내는 물론 저장된 파일 내용의 한 단면을 가지고 있으므로, 현재 버전을 얻기 위해 주어진 파일에. "델타 해결"은 모든 것을 일관성있게 유지하는 단계입니다.

다음 은 온라인으로 이용할 수있는 Pro Git 서적의 "Git Internals"섹션에있는 장입니다.


80
이 답변은 잘못되었습니다. Git이 아닌 Mercurial의 작동 방식을 설명하는 것 같습니다. 이 문제에 대한 Google 검색에서 제공되므로 답글이 필요하다고 생각합니다. Git은 커밋 간의 차이를 델타로 저장 하지 않습니다 . 힘내는 "전체 개체"저장소입니다. 따라서 Git은 델타에서 파일 히스토리를 재구성 할 필요가 없으므로 주어진 파일을 표시하기 위해 "스냅 샷"이 필요하지 않습니다. 그것이 Mercurial의 작동 방식입니다.
넥서스,

12
델타 인코딩이 작동하는 유일한 장소는 압축과 전송을위한 팩 파일에 있습니다. ( kernel.org/pub/software/scm/git/docs/v1.6.2.3/technical/… ) 정확한 답변은 아래 araqnid의 답변을 참조하십시오.
넥서스,

4
이 문맥에서 모든 "스냅 샷"은 델타 인코딩 버전이 아니라 파일 상태의 전체 사본임을 의미합니다. 언급했듯이 Git 팩 파일에서 델타 인코딩을 사용합니다. 아무도 그것이 "Git이 세상을 보는 방식을 바꾸는"것이라고 말하지 않았다. 자신의 가정 투사를 중단하십시오.
Amber

2
귀하의 답변은 여전히 ​​정확하지 않습니다. "Git은 때때로 파일 내용의 스냅 샷도 저장합니다." -맞지 않습니다. " '델타 해결'은 모든 것을 일관성있게 유지하는 단계입니다." -그것은 또한 정확하지 않습니다. 아래 araqnid의 답변은 정확합니다.
nexus는

1
위에서 언급 한 장에서 설명한 것처럼 Git은 항상 최신 버전의 전체 파일 내용을 저장합니다. 이전 버전은 "느슨한"파일 일 때 델타 코드 파일로 저장됩니다. git gcGit은 주기적으로 ( Git 을 호출 하거나 필요하다고 판단 할 때마다) 공간을 절약하기 위해 모든 "느슨한"파일을 packfile로 압축하여 해당 packfile에 인덱스 파일을 생성합니다. 따라서 zlib는 자체 델타 알고리즘으로 압축하지만 Git은 델타 인코딩을 사용하여 이전 버전을 저장합니다. 가장 일반적이고 빈번한 액세스는 최신 버전이므로 스냅 샷으로 저장됩니다.
BrionS

118

단계 git clone는 다음 과 같습니다.

  1. repo 데이터베이스에있는 모든 객체의 "팩"파일을받습니다.
  2. 수신 된 팩에 대한 색인 파일 작성
  3. 헤드 리비전을 확인하십시오 (비 베어 리포지토리의 경우).

"델타 해결"은 팩 파일을 색인화하는 두 번째 단계 ( "git index-pack")에 표시되는 메시지입니다.

팩 파일 에는 실제 객체 ID 가 없고 객체 내용 만 있습니다. 따라서 객체 ID가 무엇인지 확인하려면 git은 팩의 각 객체에 대해 압축 해제 + SHA1을 수행하여 객체 ID를 생성 한 다음 인덱스 파일에 기록해야합니다.

팩 파일의 객체는 델타, 즉 다른 객체를 변경하기위한 일련의 변경으로 저장 될 수 있습니다. 이 경우 git은 기본 객체를 검색하고 명령을 적용하고 결과를 SHA1해야합니다. 기본 개체 자체는 일련의 델타 명령을 적용하여 파생되어야합니다. (복제본의 경우에도 기본 개체가 이미 발생 했으므로 메모리에 캐시 된 제조 개체 수에 제한이 있습니다).

요약하면, "델타 해결"단계에서는 전체 리포지토리 데이터베이스의 압축을 풀고 체크섬하는 작업이 필요합니다. 아마도 SHA1의 압축을 풀고 계산하는 것은 실제로 델타 명령을 적용하는 것보다 더 많은 시간이 걸립니다.

후속 페치의 경우, 수신 된 팩 파일은 수신 git이 이미 가질 것으로 예상되는 다른 오브젝트에 대한 참조 (델타 오브젝트베이스로서)를 포함 할 수 있습니다. 이 경우, 수신 git은 실제로 수신 된 팩 파일을 다시 작성하여 참조 된 오브젝트를 포함하므로 저장된 팩 파일이 충분합니다. "델타 해결 중"메시지가 시작된 곳일 수 있습니다.


7
이것을 병렬화 할 수 있습니까?
brooksbp

이 델타 압축은 하나의 zlib 데이터 스트림에 여러 객체를 저장하는 것 이상입니까?
fuz

1
@FUZxxl 예, 두 개의 블롭을 비교하고 편집 스크립트를 생성하기 위해 diff 또는 xdelta와 같은 알고리즘을 사용합니다
araqnid

@brooksbp : 제한이 있습니다. ID가 103fa49 인 객체를 디코딩하려면 df85b51이 필요할 수 있지만 103fa49를받을 때 df85b51은 아직 없습니다 (팩 파일은 sha1 해시로 엄격하게 정렬 됨). 따라서 이미 존재하는 것만 참조하는 모든 것이 쉽지만, 다른 모든 것의 경우 수신 될 때까지 기다려야합니다. 그리고이 델타 압축은 중첩 될 수 있으므로 103fa49에는 4e9ba42가 필요할 수 있으며 29e945가 필요하며 c9e645a가 필요합니다 ... 그림을 얻습니다. [) 예, 나는 그것이> 사년이었다주의]
보도 Thiesen

2
@ brooksbp : 잘못된 것으로 나타났습니다. 팩 파일은 sha1 해시로 정렬 할 필요가 없습니다. 또한 git은 쓸 때 필요한 객체를 필요한 객체보다 먼저 씁니다. 따라서 실제로 병렬화 할 수 있어야합니다. 남아있는 단점 만 : 나중에 어떤 객체가 필요할지 모르기 때문에 몇 번이고 다시 만들어야합니다. 여기를보십시오 : kernel.org/pub/software/scm/git/docs/technical/…
Bodo Thiesen

4

Amber는 Mercurial 또는 이와 유사한 용도로 사용되는 객체 모델을 설명하는 것 같습니다. Git은 매번 후속 버전의 객체 사이에 델타를 저장하지 않고 객체의 전체 스냅 샷을 저장합니다. 그런 다음 델타 압축을 사용하여 이러한 스냅 샷을 압축하고 히스토리의 위치에 상관없이 사용할 델타를 찾습니다.


5
실제로 Git이 느슨한 객체를 저장할 수는 있지만 느슨한 객체를 삭제하고 압축 된 컨텐츠로 교체 할 수 있기 때문에 반드시 항상 그렇게 보관되지는 않습니다. 앰버의 대답이 후속 버전에 대해 아무 말도하지 않았다고 생각합니다.
AlBlue
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.