Git에서 HEAD, 작업 트리 및 인덱스의 차이점은 무엇입니까?


488

누군가 Git에서 HEAD, 작업 트리 및 색인의 차이점을 말해 줄 수 있습니까?

내가 이해 한 바에 따르면, 그들은 모두 다른 가지의 이름입니다. 내 가정이 맞습니까?


편집하다

나는 이것을 찾았다

단일 자식 저장소는 임의의 수의 분기를 추적 할 수 있지만 작업 트리는 그 중 하나 ( "현재"또는 "체크 아웃 된"분기) 와만 관련되며 HEAD는 해당 분기를 가리 킵니다.

이것은 HEAD와 작업 트리가 항상 동일하다는 것을 의미합니까?


26
편집과 관련하여 : 절대로 아닙니다. HEAD현재 브랜치 끝에있는 커밋입니다. 브랜치를 체크 아웃 한 경우 (예 : 수정 된 파일이없는 경우) 해당 컨텐츠는 작업 트리와 일치합니다. 아무것도 수정하면 더 이상 일치하지 않습니다.
Cascabel

6
나는 당신이 이것을 읽어야한다고 생각합니다 : think-like-a-git.net
Andrzej Duś

5
또한 Staging Area그 목록에를 추가 할 것입니다. 무엇 HEAD, Working Tree, IndexStaging Area
그린

2
당신은 아무것도 수정으로>로 곧, 작업 트리가 더 이상 HEAD 커밋 일치 : @ Jefromi의 마지막 문장으로 더 명확 것
starscream_disco_party

3
이 이제까지 자식 학습을위한 최고의 도구입니다 : 모든 이해 정말 최선의 방법으로 미래에이 글을 읽고 이러한 답변의 일부보고 느끼고 시각에 무슨 일이 일어나고 있는지 개념화하는 것입니다 onlywei.github.io/explain-git-with -d3 / # fetchrebase
BKSpurgeon

답변:


578

이러한 주제에 대한 몇 가지 좋은 참고 자료 :

대체 텍스트

색인을 검사 점 으로 사용합니다 .

내가 엉망이 될 수있는 변화를 만들려고 할 때 — 어떤 방향으로 탐색 할 수 있는지 또는 개념적으로 까다로운 리팩토링이나 표현 유형 — 작업을 색인에 체크 포인트합니다. 이것이 마지막 커밋 이후 처음으로 변경 한 경우 로컬 리포지토리를 검사 점으로 사용할 수 있지만 종종 작은 단계 집합으로 구현하는 개념적 변경 사항이 있습니다. 각 단계 후에 체크 포인트를 만들고 싶지만 테스트되고 작동하는 코드로 돌아갈 때까지 커밋을 저장하십시오.

노트:

  1. 작업 영역 (소스)의 디렉토리 트리 당신이 확인하고 수정할 수 있음을 파일.

  2. 인덱스 에 하나의 큰, 이진 파일입니다 <baseOfRepo>/.git/index현재의 모든 지점에있는 파일들이 나열, SHA1의 체크섬, 타임 스탬프 및 파일 이름을 - 그것의 파일의 사본을 다른 디렉토리가 아니다.

  3. 로컬 저장소는 숨겨진 디렉토리입니다 ( .git포함) objects압축 "덩어리"파일과의 repo에있는 모든 파일의 모든 버전 (현지 지사 및 원격 지점의 사본)을 포함하는 디렉토리.

위 이미지에 표시된 4 개의 '디스크'를 별도의 repo 파일 사본으로 생각하지 마십시오.

대체 텍스트

기본적으로 Git 커밋에 대한 참조입니다. 심판에는 태그와 헤드라는 두 가지 주요 유형이 있습니다.

  • 태그는 기록에서 특정 지점을 표시하는 고정 참조입니다 (예 : v2.6.29).
  • 반대로, 헤드는 항상 프로젝트 개발의 현재 위치를 반영하도록 움직입니다.

대체 텍스트

(참고 : Timo Huovinen이 언급 한 것처럼 화살표는 커밋이 가리키는 것이 아니며 워크 플로우 순서입니다 . 기본적으로 화살표 는 첫 번째 커밋 위치와 마지막 위치 로 화살표를 표시 합니다)1 -> 2 -> 3 -> 414

이제 우리는 프로젝트에서 무슨 일이 일어나고 있는지 알고 있습니다.
그러나 여기서 무슨 일이 일어나고 있는지 알기 위해 지금 HEAD라는 특별한 참조가 있습니다. 두 가지 주요 목적을 제공합니다.

  • 체크 아웃 할 때 파일을 가져갈 커밋을 Git에 알려줍니다.
  • 커밋 할 때 Git에게 새로운 커밋을 넣을 위치를 알려줍니다.

당신이 git checkout ref그것을 실행할 때 당신 HEAD이 지정한 심판을 가리키고 그것에서 파일을 추출합니다. 실행 git commit하면 새로운 commit 객체가 생성되어 current의 자식이 HEAD됩니다. 일반적으로 HEAD헤드 중 하나를 가리 키므로 모든 것이 잘 작동합니다.

대체 텍스트


20
git lot에 대해 여러 번 읽은 후에 나는 그것을 완전히 이해하지 못했습니다. 나는 정말 좌절했습니다. 그러나 커뮤니티에서 메신저! 머리를 언급했지만 위의 이미지에는 항상 나머지 머리가있는 단일 헤드가 있습니까? "일반적으로 HEAD는 헤드 중 하나를 가리 키므로 모든 것이 잘 작동합니다." 나는 이것을 Ur에게 설명 할 것을 간청한다.
Necktwi

12
@neckTwi HEAD는 현재 작업중 인 커밋 입니다 ( stackoverflow.com/a/964927/6309 ). 일반적으로 "분기 헤드"중 하나입니다 (분기에 의해 참조 된 커밋 중 하나는 분기의 을 나타냄 ). 그러나 커밋을 체크 아웃하고 작업 할 수 있습니다. (브랜치) 헤드 중 하나가 아닌 커밋을 체크 아웃하면 "분리 된 HEAD"모드입니다. stackoverflow.com/a/3965714/6309
VonC

1
@Imray 동의합니다,하지만 제가 5 년 전에 그 사진을 찾은 방법입니다 ( hades.name/blog/2010/01/28/… )
VonC

11
인덱스에 관해서는 @ ashraf-alam과 같이 "인덱스가 준비 영역의 또 다른 이름 일뿐"이라고 말할 수있는 가장 유용한 방법이라고 생각합니다. 토론에서 대부분의 경우 준비 영역이라고하며 느낌과 동일하므로 인덱스와 동일한 연결을 자동으로 연결하지 않았습니다.
Pete

1
@Pete 동의합니다. 캐시와 인덱스의 차이점에 대한 자세한 내용은 다른 답변 stackoverflow.com/a/6718135/6309
VonC

137

HEAD (현재 브랜치 또는 현재 브랜치에서 마지막 커밋 된 상태), 인덱스 (일명 스테이징 영역) 및 작업 트리 ( 체크 아웃 의 파일 상태 ) 의 차이점 은 "1.3 Git 기본 " 의 "3 가지 상태"섹션에 설명되어 있습니다. Scott Chacon 의 Pro Git 서적 (크리에이티브 커먼즈 라이센스).

이 장의 이미지는 다음과 같습니다.

로컬 작업-작업 디렉토리와 준비 영역 (인덱스) 및 자식 저장소 (HEAD)

위의 이미지에서 "working directory"는 "working tree"와 동일합니다. "staging area"는 git "index"의 대체 이름이며, HEAD 는 현재 체크 아웃 된 분기를 가리 킵니다. 자식 디렉토리 (저장소) "

참고 git commit -a변화를 준비하고 한 번에 커밋 것입니다.


1
"그림은 천 단어의 가치가있다". 감사합니다 Jakub. 그리고 링크 주셔서 감사합니다.
Joyce Babu

5
참고 : 요즘 working tree선호하는 것 같습니다 working directory. github.com/git/git/commit/…
VonC

3
준비 영역이 "index"라는 단일 파일에 포함되어 있고이 인덱스 파일이 .git 디렉토리의 루트에 있기 때문에이 그림은 정확하게 정확하지 않습니다. 따라서 repo를 .git 디렉토리로 정의하면 스테이징 영역은 기술적으로 repo 내부에 있습니다. 세 번째 열은 "HEAD의 루트 트리 개체"로 레이블이 지정되어 체크 아웃 된 파일이 커밋 개체에서 가져오고 커밋이 커밋 개체에 새 트리를 작성 함을 나타냅니다. 커밋 개체는 HEAD에서 가리 킵니다.
Jazimov

@Jazimov 당신은 아마 옳을 수도 있지만, 그가 쓴 것처럼, 그는 유명한 Pro Git 책에서 그 그림을 가져 갔으며, 그는 링크를 제공했습니다. 따라서 그림이 개선되거나 잘못 될 수 있다면 누군가 그 책의 저자에게 말해야합니다 ... 일반적으로, 나는 기꺼이 그렇게 할 것입니다. 그러나 솔직히 말하면, 저는 아직 초보자입니다. 당신이 말한 것을 이해했기 때문에 나는 그 경우에 분명히 틀린 사람입니다.
Binarus

@Binarus : 이와 같이 이미지를 도매로 재생하는 데 따르는 위험은 한 명의 저자 / 책이 ​​만든 "오해 표현"을 전파하는 역할을한다는 것입니다. 나는 이것이 리터럴 대 함수 해석의 경우라고 생각합니다. 리터럴 의미에서 리포지토리를 .git 폴더 아래의 모든 것으로 정의하면 실제로 리포지토리에 인덱스가 포함됩니다. 그러나 기능적인 의미에서 인덱스는 Git이 저장소에 DAG를 유지하는 데 도움이되며 외부에 있다고 생각할 수 있습니다.
Jazimov

64

귀하의 작업 트리가 현재 작업중인 한 파일에서 실제로 것입니다.

HEAD는 마지막 체크 아웃 한 브랜치 또는 커밋에 대한 포인터이며 새 커밋의 부모가됩니다. 예를 들어 master지점 에있는 경우을 HEAD가리키고 master커밋 할 때 해당 새 커밋은 master지정된 개정의 자손이 되며master 되고 새 커밋을 가리 키도록 업데이트됩니다.

지수는 새로운이 준비 커밋 준비 영역입니다. 기본적으로 인덱스의 내용은 새로운 커밋에 들어가는 것입니다 (그렇지 만 커밋 git commit -a하기 전에 Git이 인덱스에 대해 알고있는 파일의 모든 변경 사항을 자동으로 추가하므로 작업 트리의 현재 내용을 커밋합니다 ). git add작업 트리에서 색인으로 파일을 추가하거나 업데이트합니다.


Brian에게 설명해 주셔서 감사합니다. 따라서 작업 트리에는 커밋되지 않은 모든 변경 사항이 포함됩니다. git commit -a로 변경 사항을 커밋하면 특정 시간에 작업 트리와 인덱스가 동일합니다. 중앙 리포지토리로 푸시 할 때 세 개 모두 동일합니다. 제가 맞습니까?
Joyce Babu

3
@ 비 노드 Git이 알지 못하는 작업 트리에 파일을 포함 할 수 있고 파일을 커밋하지 git commit -a않아도 git add되므로 ( 와 함께 추가해야 함 ) 작업 트리에는 색인, 로컬 리포지토리 또는 원격 저장소에는 없습니다.
Brian Campbell

2
@Vinod : 작업 트리와 인덱스는 커밋하지 않고 동일해질 수 있습니다 (git add는 작업 트리에서 인덱스를 업데이트하고 git checkout <path>는 작업 트리를 인덱스에서 업데이트합니다). HEAD가장 최근의 커밋을 참조하므로 커밋 HEAD하면 인덱스와 일치하는 새 커밋으로 업데이트 됩니다. 푸시는 그다지 관련이 없습니다-원격 리포지토리의 브랜치를 로컬 리포지토리의 브랜치로 만듭니다.
Cascabel

45

작업 트리

작업 트리는 현재 작업중인 파일입니다.

힘내 색인

  • git "index"는 git 저장소에 커밋하려는 파일을 저장하는 위치입니다.

  • 인덱스는 캐시 , 디렉토리 캐시 , 현재 디렉토리 캐시 , 준비 영역 , 준비된 파일 이라고도 합니다 .

  • 파일을 git 저장소에 "커밋"(체크인)하기 전에 먼저 파일을 git "index"에 배치해야합니다.

  • 색인은 작업 디렉토리 가 아닙니다 :과 같은 명령을 입력 할 수 있으며 git status, git은 작업 디렉토리의 어떤 파일이 git 색인에 추가되었는지를 알려줍니다 (예 : git add filename명령 사용).

  • 인덱스는 git 리포지토리가 아닙니다. git 인덱스의 파일은 git commit 명령을 사용하면 git이 git 리포지토리에 커밋하는 파일입니다.


1
Git 2.5는 여러 작업 트리 를 가져옵니다 ( stackoverflow.com/a/30185564/6309 ). +1
VonC 2016 년

3
"색인이 작업 디렉토리가 아닙니다"가 100 % 정확하지 않습니다. 색인은 작업 디렉토리가 아니지만 다음에 커밋하려는 전체 작업 디렉토리 + 변경 사항을 포함합니다. 증명? git 저장소로 이동 reset --hard HEAD하여 인덱스 == 작업 트리인지 확인하십시오. mkdir history && git checkout-index --prefix history/ -a그 결과 : history/디렉토리 의 전체 작업 트리가 복제 됩니다. Ergo git index> = git 작업 디렉토리
Adam Kurkiewicz

3
색인은 작업 디렉토리가 아니며 작업 디렉토리를 포함하지 않아도됩니다. 인덱스는 커밋하려는 정보를 저장하는 git 저장소 내의 파일입니다.
Boon

3
""인덱스 "에는 작업 트리의 내용에 대한 스냅 샷이 있으며 다음 커밋의 내용으로 사용되는이 스냅 샷입니다. 따라서 작업 디렉토리를 변경 한 후 commit 명령을 실행하기 전에 add 명령을 사용하여 색인에 새 파일 또는 수정 된 파일을 추가해야합니다 "( git-scm.com/docs/git-add )
anth

3
@AdamKurkiewicz : and 단계 echo untracked-data > untracked-file전후에 증명이 실패 합니다. 당신은 발견 할 것이다 비 추적 파일이 없습니다 에서 디렉토리. 먼저 작업 트리를 건드리지 않고 인덱스를 수정하는 것이 어렵지만 (및를 사용해야 함 ) 인덱스와 작업 트리를 독립적으로 수정할 수도 있습니다 . git reset --HARDgit checkout-indexhistorygit update-index --index-info
torek
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.