Reset Demystified
작성
git reset <옵션> <돌아가고싶은커밋>git checkout <브랜치> <옵션>
reset을 통해HEAD,Index,Working Directory을 관리한다.
세 개의 트리

| Tree | Role |
|---|---|
| HEAD (Repository) | 마지막 커밋 스냅샷, 다음 커밋의 부모 커밋 |
| Index Stage Staging Area | 다음에 커밋할 스냅샵 |
| Working Directory Local | Sandbox |
1. HEAD
- 현재 브랜치의 마지막 커밋을 가리키는 포인터
- 현재 커밋은 다음에 올 커밋의 부모 커밋이 된다.
HEAD가 가리키는 스냅샷 보기
$ git cat-file -p HEAD
tree cfda3bf379e4f8dba8717dee55aab78aef7f4daf
author Scott Chacon 1301511835 -0700
committer Scott Chacon 1301511835 -0700
initial commit
$ git ls-tree -r HEAD
100644 blob a906cb2a4a904a152... README
100644 blob 8f94139338f9404f2... Rakefile
040000 tree 99f1a6d12cb4b6f19... lib
2. The Index
- Proposed next commit.
git commit을 할 때,Git이 바라보는 공간이며Index는 새로운 커밋으로 변환된다.
3. The Working Directory
Staging Area에 커밋하기전에 자유롭게 수정하는 공간HEAD와Index는 효율적이지만 불편한 방식으로.git안에 저장한다.- The working directory unpacks them into actual files, which makes it much easier for you to edit them.
The Workflow
Git’s typical workflow is to record snapshots of your project in successively better states, by manipulating these three trees.

The Role of Reset (1)
주어진 상황

Step 1: Move HEAD (--soft)
HEAD브랜치를 이동시킴checkout처럼HEAD가 가리키는 브랜치를 이동시키지는 않음HEAD는 계속 현재 브랜치를 가리키고 있고, 현재 브랜치가 가리키는 커밋을 바꿈git reset 9e5e6a4will start by making master point to9e5e6a4.

git commit의 역할- 새로운 커밋 생성
HEAD가 가리키는 브랜치가 새로운 커밋을 가리키도록 업데이트
git reset- 가장 최근의
git commit을 되돌림
- 가장 최근의
git reset HEAD~HEAD~:HEAD의 부모 커밋, 직전의 커밋으로 되돌림
git reset --soft HEAD~Index,Working Directory는 그대로 놔두고, 브랜치가 가리키는 커밋만 이전으로 되돌림
Step 2: Updating the Index (--mixed)

git reset [--mixed] HEAD~git reset HEAD~디폴트 값Index를 현재HEAD가 가리키는 스냅샷으로 업데이트git commit과git add명령을 되돌리는 것과 같은 효과다.
Step 3: Updating the Working Directory (--hard)

git reset --hard HEAD~git add,git commit, 워킹 디렉토리의 내용까지 되돌림Git에는 데이터를 삭제하는 방법이 별로 없지만 그 중 하나의 명령어이니 유의한다.- 이 예제에서는
v3을 커밋했기 때문에,reflog를 이용해 복원할 수 있지만, 한 번도 커밋하지 않았다면Git이 덮어쓴 데이터를 복원할 수 없다.
정리
--soft:HEAD가 가리키는 브랜치를 옮긴다.[--mixed]:Index를HEAD가 가리키는 상태로 만든다.--hard: 워킹 디렉터리를Index의 상태로 만든다.
The Role of Reset (2)
- 경로를 주고
reset하기 - 경로를 주면
HEAD의 브랜치를 옮기는 단계는 생략되어, 현재HEAD가 가리키는 커밋에서 적용된다.HEAD는 포인터이기 때문에 경로에 따라 파일별로 기준이 되는 커밋을 부분적으로 적용하는 것이 불가능하기 때문이다.
Index, 워킹 디렉토리의 일부분 갱신할 수 있다.

git reset file.txtfile.txt을HEAD에서Index로 복사file.txt를Unstaged상태로 만듬

git add와 정확히 반대의 역할

- 특정 커밋을 명시하면
Git은HEAD에서 파일을 가져오는 것이 아니다. - 그 커밋에서 파일을 가져온다.
합치기 (Squash)
reset+commit으로 커밋들을 하나로 합칠 수 있다.
주어진 상황
- 두번째 커밋의
b파일은 아직 작업중이기 때문에 세번째 커밋과 합치고 싶다.

git reset --soft HEAD~2

HEAD포인터를 이전 커밋으로 되돌리기
git commit

a파일이 있는v1커밋이 하나 그대로 있고, 두번째 커밋에는v3버전의a파일과 추가된b파일이 있다.v2에는 더는 히스토리가 없다.
checkout
-
checkout도reset과 마찬가지로 세 트리를 조작한다. -
명령어에 파일 경로의 작성 여부와 동작이 다르다.
-
git reset --hard와는 달리 워킹 디렉토리를 안전하게 다룬다.- 저장하지 않는 것이 있으면 확인해서 날려버리지 않는다.
git reset --hard는 head를 업데이트 하지만,checkout은HEAD자체를 다른 브랜치로 옮긴다.
-
reset은HEAD가 가리키는 브랜치의 포인터를 옮기고,checkout은HEAD자체를 옮긴다.

요약
