source

리누스 토르발스가 Git이 "절대로" 파일을 추적하지 않는다고 말하는 것은 무엇을 의미합니까?

ittop 2023. 5. 17. 23:27
반응형

리누스 토르발스가 Git이 "절대로" 파일을 추적하지 않는다고 말하는 것은 무엇을 의미합니까?

2007년 구글에서 열린 테크 토크(43:09)에서 Git가 처리할 수 있는 파일 수를 묻는 질문에 Linus Torvalds의 말을 인용합니다.

…콘텐츠를 추적합니다.파일 하나도 추적하지 않습니다.Git에서 파일을 추적할 수 없습니다.하나의 파일이 있는 프로젝트를 추적할 수 있습니다. 하지만 프로젝트에 하나의 파일이 있는 경우에는 추적할 수 있습니다. 하지만 10,000개의 파일을 추적하면 Git는 결코 개별 파일로 보지 않습니다.Git은 모든 것을 전체 내용으로 생각합니다.Git의 모든 역사는 전체 프로젝트의 역사를 기반으로 합니다.

(여기에 있는 대본)

하지만 Git 책을 들여다보면 Git의 파일이 추적되거나 추적되지 않을 수 있다는 것을 가장 먼저 듣게 됩니다.게다가 Git의 모든 경험은 파일 버전 관리에 맞춰져 있는 것 같습니다.사용 시git diff또는git status출력은 파일 단위로 표시됩니다.을 할 때git add파일 단위로 선택할 수도 있습니다.파일 기반으로 기록을 검토할 수도 있으며 매우 빠릅니다.

이 진술은 어떻게 해석되어야 합니까?파일 추적 측면에서 Git은 CVS와 같은 다른 소스 제어 시스템과 어떻게 다릅니까?

CVS에서 기록은 파일 단위로 추적되었습니다.분기는 고유한 버전 번호를 가진 고유한 다양한 버전의 다양한 파일로 구성될 수 있습니다.CVS는 개별 파일을 유사한 방식으로 추적하는 RCS(Revision Control System)를 기반으로 했습니다.

반면 Git는 전체 프로젝트의 상태를 스냅샷으로 만듭니다.파일은 독립적으로 추적 및 버전화되지 않습니다. 저장소의 개정판은 하나의 파일이 아닌 전체 프로젝트의 상태를 나타냅니다.

Git가 파일을 추적하는 것을 언급할 때, 그것은 단순히 프로젝트의 기록에 포함되어야 한다는 것을 의미합니다.Linus의 강연은 Git 컨텍스트에서 파일을 추적하는 것에 대한 것이 아니라 CVS 및 RCS 모델과 Git에서 사용되는 스냅샷 기반 모델을 대조하는 것이었습니다.

저는 브라이언 칼슨의 대답에 동의합니다: 리누스는 적어도 부분적으로는 파일 지향과 커밋 지향 버전 제어 시스템을 구별하고 있습니다.하지만 저는 그것보다 더 많은 것이 있다고 생각합니다.

정체되어 있고 결코 끝나지 않을 수도 있는 제 책에서, 저는 버전 관리 시스템에 대한 분류법을 생각해 내려고 노력했습니다.제 분류법에서 우리가 여기서 관심을 갖는 용어는 버전 제어 시스템의 원자성입니다.현재 22페이지 내용을 확인하십시오.VCS에 파일 수준 원자성이 있는 경우 실제로는 각 파일에 대한 기록이 있습니다.VCS는 파일의 이름과 각 지점에서 발생한 작업을 기억해야 합니다.

Git은 그렇게 하지 않습니다.Git에는 커밋 기록만 있습니다. 커밋은 원자성의 단위이며, 기록은 저장소의 커밋 집합입니다.커밋이 기억하는 것은 파일 이름과 각 파일과 함께 제공되는 콘텐츠로 가득 찬 데이터와 일부 메타데이터(예: 커밋을 만든 사용자, 시기 및 이유, 커밋의 상위 커밋의 내부 Git 해시 ID)입니다.(모든 커밋과 해당 커밋을 읽은 후 생성된 이 부모 및 지시된 순환 그래프가 저장소의 기록입니다.)

VCS는 커밋 지향이지만 데이터는 파일별로 저장할 수 있습니다.이는 구현 세부사항이지만 때로는 중요하지만 Git도 이를 수행하지 않습니다.대신 각 커밋은 파일 이름, 모드(즉, 이 파일이 실행 가능한지 여부)를 인코딩하는 트리 개체, 그리고 실제 파일 내용에 대한 포인터와 함께 트리를 기록합니다.내용 자체는 독립적으로 Blob 개체에 저장됩니다.커밋 개체와 마찬가지로 BLOB는 내용에 고유한 해시 ID를 얻지만 한 번만 나타날 수 있는 커밋과 달리 BLOB는 여러 커밋에 나타날 수 있습니다.따라서 Git의 기본 파일 내용은 BLOB로 직접 저장된 다음 해시 ID가 커밋 개체에 직접 또는 간접적으로 기록된 트리 개체에 간접적으로 저장됩니다.

다음을 사용하여 Git에 파일 기록을 표시하도록 요청하는 경우:

git log [--follow] [starting-point] [--] path/to/file

Git이 실제로 하고 있는 것은 Git이 가지고 있는 유일한 기록인 커밋 기록을 걷는 것입니다. 그러나 다음과 같은 경우에는 이러한 커밋을 보여주지 않습니다.

  • 커밋은 비폭력 커밋이며,
  • 해당 커밋의 상위 항목에도 파일이 있지만 상위 항목의 내용이 다르거나 커밋의 상위 항목에 파일이 전혀 없습니다.

이러한 중 인 (그러나이조중건일추통수수있다가습니정될해를부는러한그▁addition▁be▁(▁canitions다있수니▁via▁cond▁(습▁of▁modifiedal▁some▁these)을 통해 수정될 수 있습니다.git log옵션, 그리고 Git가 전적으로 이력에서 일부 커밋을 생략하도록 만드는 History Simplified라는 부작용을 설명하기 매우 어렵습니다.)여기 보이는 파일 기록은 어떤 의미에서 저장소에 정확히 존재하지 않습니다. 대신 실제 기록의 합성 부분 집합일 뿐입니다.이 다른 "파일 "를 당신은 ""git log옵션!

혼란스러운 부분은 다음과 같습니다.

Git은 결코 그것들을 개별 파일로 보지 않습니다.Git은 모든 것을 전체 내용으로 생각합니다.

Git는 종종 자체 저장소의 객체 대신 160비트 해시를 사용합니다.파일 트리는 기본적으로 각 파일(및 일부 메타데이터)의 내용과 연결된 이름 및 해시 목록입니다.

그러나 160비트 해시는 Git 데이터베이스의 우주 내에서 컨텐츠를 고유하게 식별합니다.따라서 해시를 콘텐츠로 사용하는 트리는 해당 상태의 콘텐츠를 포함합니다.

파일 내용의 상태를 변경하면 해시가 변경됩니다.그러나 해시가 변경되면 파일 이름의 내용과 관련된 해시도 변경됩니다.그러면 "디렉토리 트리"의 해시가 변경됩니다.

Git 데이터베이스가 디렉토리 트리를 저장할 때, 해당 디렉토리 트리는 모든 하위 디렉토리와 그 안에 있는 모든 파일의 모든 내용을 암시하고 포함합니다.

이는 블롭 또는 다른 트리에 대한 (불변의, 재사용 가능한) 포인터로 트리 구조로 구성되지만 논리적으로는 전체 트리의 전체 콘텐츠에 대한 단일 스냅샷입니다.Git 데이터베이스의 표현은 플랫 데이터 내용이 아니라 논리적으로 모든 데이터이며 다른 것은 없습니다.

트리를 파일 시스템에 직렬화하고 모든 .git 폴더를 삭제한 후 git에게 트리를 데이터베이스에 다시 추가하도록 지시하면 데이터베이스에 아무것도 추가하지 않게 됩니다. 요소는 이미 존재합니다.

git's hashs를 불변 데이터에 대한 참조 카운트 포인터로 생각하는 것이 도움이 될 수 있습니다.

이를 기반으로 응용프로그램을 작성했다면 문서는 여러 페이지로 구성됩니다. 페이지에는 여러 개의 레이어가 있고, 그룹이 있으며, 개체가 있습니다.

개체를 변경하려면 개체에 대해 완전히 새로운 그룹을 만들어야 합니다.그룹을 변경하려면 새 계층을 작성해야 하며, 새 페이지와 새 문서가 필요합니다.

개체를 변경할 때마다 새 문서가 생성됩니다.이전 문서가 계속 존재합니다.새 문서와 이전 문서는 대부분의 내용을 공유합니다. 페이지는 동일합니다(1 제외).한 페이지에 동일한 레이어가 있습니다(1 제외).해당 계층에 동일한 그룹이 있습니다(1 제외).해당 그룹에 동일한 개체(1 제외)가 있습니다.

논리적으로는 복사본을 의미하지만, 구현 측면에서는 동일한 불변 객체에 대한 또 다른 참조 포인터일 뿐입니다.

Git repo는 그것과 많이 비슷합니다.

즉, 지정된 Git changes 집합에는 커밋 메시지(해시 코드)가 포함되어 있고, 작업 트리가 포함되어 있으며, 상위 변경 사항이 포함되어 있습니다.

이러한 상위 변경사항에는 상위 변경사항이 포함됩니다.

역사를 포함하는 깃레포의 부분은 변화의 사슬입니다.이 일련의 변경사항은 "디렉토리" 트리 의 수준에서 변경됩니다. "디렉토리" 트리에서는 변경사항 집합과 변경사항 체인을 고유하게 가져올 수 없습니다.

파일에 무슨 일이 발생하는지 알아보려면 변경 집합의 해당 파일부터 시작합니다.그 변화 세트는 역사가 있습니다.해당 기록에는 동일한 이름의 파일이 존재하는 경우가 많으며, 내용이 동일한 경우도 있습니다.내용이 동일할 경우 파일에 변경 사항이 없습니다.만약 다르다면, 변화가 있고, 정확히 무엇을 해결하기 위해 일을 해야 합니다.

때때로 파일이 사라지지만 "디렉토리" 트리에 동일한 내용을 가진 다른 파일(동일한 해시 코드)이 있을 수 있으므로 이러한 방식으로 추적할 수 있습니다(참고: 이러한 이유로 커밋을 통해 편집할 파일과 별도로 파일을 이동할 수 있습니다).또는 동일한 파일 이름을 확인한 후 파일이 충분히 유사합니다.

따라서 "파일 히스토리"를 패치워크할 수 있습니다.

그러나 이 파일 기록은 파일 버전 간 링크가 아닌 "전체 변경사항 집합"의 효율적인 구문 분석에서 비롯됩니다.

"git don's track files"는 기본적으로 git의 커밋이 트리의 경로를 "blob"에 연결하는 파일 트리 스냅샷과 커밋 기록을 추적하는 커밋 그래프로 구성된다는 것을 의미합니다.다른 모든 것은 "git log" 및 "git deblock"과 같은 명령에 의해 즉시 재구성됩니다.이 재구성은 다양한 옵션을 통해 파일 기반 변경을 얼마나 어렵게 찾아야 하는지 알 수 있습니다.기본 경험적 접근법은 파일 트리에서 Blob이 변경되지 않고 변경되는 시기 또는 파일이 이전과 다른 Blob과 연결되는 시기를 결정할 수 있습니다.Git가 사용하는 압축 메커니즘은 BLOB/파일 경계에 대해 크게 신경 쓰지 않습니다.콘텐츠가 이미 어딘가에 있는 경우, 이렇게 하면 다양한 블롭을 연결하지 않고도 저장소 증가를 작게 유지할 수 있습니다.

이제 그것이 저장소입니다.Git에도 작업 트리가 있으며, 이 작업 트리에는 추적 및 추적되지 않은 파일이 있습니다.추적된 파일만 인덱스(스테이지 영역)에 기록됩니다.캐시?)를 추적해야 저장소에 저장됩니다.

인덱스는 파일 지향적이며 이를 조작하기 위한 몇 가지 파일 지향적 명령이 있습니다.그러나 저장소에 저장되는 것은 파일 트리 스냅샷, 관련 BLOB 데이터 및 커밋의 상위 항목 형태의 커밋일 뿐입니다.

Git는 파일 기록과 이름 변경을 추적하지 않으며 효율성은 파일 기록에 의존하지 않으므로, Git가 사소한 기록에 관심이 있는 기록/diffs/blacks를 생성할 때까지 다른 옵션을 사용하여 몇 번 시도해야 할 수도 있습니다.

그것은 역사를 재구성하는 것이 아니라 기록하는 서브버전과 같은 시스템과는 다릅니다.만약 그것이 기록에 없다면, 당신은 그것에 대해 들을 수 없습니다.

저는 한 번은 릴리스 트리를 Git에 체크하고 그 효과를 복제하는 스크립트를 생성함으로써 릴리스 트리를 비교하는 차등 설치 프로그램을 만들었습니다.때때로 전체 트리를 이동했기 때문에 모든 트리를 덮어쓰거나 삭제하는 것보다 훨씬 작은 차등 설치 프로그램을 생성했습니다.

Git는 파일을 직접 추적하지는 않지만 저장소의 스냅샷을 추적하며 이러한 스냅샷은 파일로 구성됩니다.

여기 그것을 볼 수 있는 방법이 있습니다.

다른 버전 제어 시스템(SVN, Rational ClearCase)에서는 파일을 마우스 오른쪽 버튼으로 클릭하여 변경 내역을 가져올있습니다.

Git에서는 이를 수행하는 직접 명령어가 없습니다. 질문을 참조하십시오.여러분은 얼마나 많은 다른 답들이 있는지에 놀랄 것입니다.Git는 SVN이나 ClearCase가 하는 방식이 아니라 단순히 파일을 추적하지 않기 때문에 간단한 답은 없습니다.

덧붙여서, "콘텐츠"를 추적하는 것이 빈 디렉토리를 추적하지 않는 원인이 되었습니다.
그렇기 때문에 폴더의 마지막 파일을 gitm하면 폴더 자체가 삭제됩니다.

항상 그런 것은 아니었고 Git 1.4(2006년 5월)만이 커밋 443f833으로 "콘텐츠 추적" 정책을 시행했습니다.

git 상태: 빈 디렉토리를 건너뛰고, 추적되지 않은 모든 파일을 표시하려면 -u를 추가합니다.

기본적으로 다음을 사용합니다.--others --directory내용 없이 흥미 없는 디렉터리를 표시합니다(사용자의 주의를 끌기 위해).
를 표시하는 , 빈디토리를표것의없통오시십과하로므으미가은시렉는하▁showing▁so오시ies▁do.--no-empty-directory그럴 때는.

-u(또는)--untracked사용자가 추적되지 않은 모든 파일을 가져올 수 있도록 하려면 이 정리를 사용하지 않습니다.

그것은 몇 년 후인 2011년 1월에 커밋 8fe533, Git v1.7.4와 함께 반향되었습니다.

이것은 일반적인 UI 철학인 git tracks 컨텐츠를 유지하며 빈 디렉토리가 아닙니다.

한편 Git 1.4.3(2006년 9월)을 사용하여 Git는 추적되지 않은 콘텐츠를 비어 있지 않은 폴더로 제한하고 2074cb0을 커밋합니다.

되지 않은디렉터리의 만 나열해야 ./').

콘텐츠 추적은 Git이 매우 이른 시기에 (Git 1.4.4, 2006년 10월, commite7f24) 성능을 향상시킬 수 있었던 원인입니다.

더 중요한 것은 내부 구조가 동일한 커밋에서 둘 이상의 경로를 사용할 수 있도록 하여 콘텐츠 이동(컷 앤 페이스트)을 보다 쉽게 지원하도록 설계되었다는 점입니다.

그것(내용 추적) 또한 Git 1.5.0과 함께 Git API에 추가하는 것입니다(2006년 12월, 커밋 366bfcb).

'git add'를 인덱스에 대한 1등급 사용자 친화적인 인터페이스로 만듭니다.

이것은 지수에 대해 전혀 이야기하지 않고 적절한 정신적 모델을 사용하여 지수의 힘을 앞으로 가져옵니다.
예를 들어 git-add man 페이지에서 모든 기술적 논의가 삭제된 방법을 참조하십시오.

커밋할 모든 콘텐츠를 함께 추가해야 합니다.
해당 콘텐츠가 새 파일에서 나왔는지, 수정된 파일에서 나왔는지는 중요하지 않습니다.
하거나 git-add를 사용하여 하여 "추가.-a(이미 알려진 파일의 경우만 해당).

그것이 동일한 Git 1.5.0(commit 5cde71d)으로 가능하게 만든 것입니다.

선택한 후 빈 줄로 응답하여 인덱스에서 선택한 경로에 대한 작업 트리 파일의 내용을 준비합니다.

또한 디렉터리에서 모든 내용을 재귀적으로 제거하려면 다음을 통과해야 합니다.-r션옵리, 터만이아니라<path>(그래도 Git 1.5.0, 커밋 9f95069).

commit 1de70db(Git v2.18.0-rc0, 2018년 4월)에 설명된 것과 같은 병합 시나리오를 허용하는 것은 파일 자체 대신 파일 콘텐츠를 보는 것입니다.

이름 바꾸기/추가 충돌과 함께 다음 병합을 고려합니다.

  • A면: 수정foo관련이 없는 련이없추를 합니다.bar
  • 바꾸기 B면: 이름바꾸기바foo->bar, 내용은 하지 마세요)

원 foo의 , A's foo, B's foo의 3자 병합bar인 의원하는경생다성니됩름이이로name▁a▁in▁of다▁result▁will를 생성합니다.bar에 대해 가지고 있던 한 모드foo.
있었고,즉, 따서라즉는, A파적모컨있고었올, 이존재했다니습경이름로바른와, 를한가고지츠텐드합에일즉name▁present▁thus(▁(다,, 올존▁for▁a재,▁andname▁the니했습▁the▁file▁had이,▁and▁had)이 존재했습니다.bar).

Commit 37b65ce, Git v2.21.0-rc0, 2018년 12월, 최근 충돌 갈등 해결을 개선했습니다.
또한 commit bbafc9c는 이름 바꾸기/이름 바꾸기(2:1) 충돌 처리를 개선함으로써 파일 내용을 고려하는 것의 중요성을 먼저 설명합니다.

  • 을 일을저대신에 collide_path~HEAD그리고.collide_path~MERGE되어 파일은기록됩니에 됩니다.collide_path.
  • 이름이 변경된 쪽에 존재하는 이름이 변경된 파일의 버전을 인덱스에 기록하는 대신(이름이 변경되지 않은 기록 쪽의 파일에 변경된 내용은 무시함), 이름이 변경된 경로에서 3방향 콘텐츠 병합을 수행한 다음 2단계 또는 3단계에 저장합니다.
  • 이름을 바꿀 때마다 내용 병합에 충돌이 있을 수 있으므로 이름이 바뀐 두 파일을 병합해야 하므로 충돌 마커가 중첩될 수 있습니다.

언급URL : https://stackoverflow.com/questions/55602748/what-does-linus-torvalds-mean-when-he-says-that-git-never-ever-tracks-a-file

반응형