git 에는 3가지 로컬 트리가 있다.
1. 워킹 디렉토리(WD)는 버전 관리 중인(tracked) 디렉토리/파일들 이다. 흔히 버전관리 작업하는 로컬 디렉토리라고 생각하면 된다.
2. Index(staged) 는 바로 다음에 커밋될 자료들이다.
3. HEAD 는 현재 브랜치 마지막 커밋의 스냅샷(포인터)이다.
우리가 워킹 디렉토리에서 파일들을 생성하거나 수정하고 커밋을 하기 위해 add 명령으로 index 에 올린 후, 이 자료들은 commit 시 HEAD 가 된다.
위 3가지 로컬 트리를 이해했다면 reset 을 쉽게 이해할 수 있다.
reset 명령은 HEAD 를 이동시킬 수 있다.
HEAD 는 가장 마지막 커밋을 참조하는 포인터이지만 reset 명령으로 해당 브랜치의 다른 커밋으로 옮길 수가 있다. (아마도 대부분 이전으로 옮기겠지..)
reset 명령에는 3가지 옵션이 있다. (soft, mixed, hard)
$ git reset --soft HEAD~ | cs |
HEAD~ 는 HEAD 의 이전 커밋을 가리킨다. (HEAD~2... 등이나 체크섬 사용 가능)
이전 커밋으로 HEAD 를 옮기는데 --soft 하게.
로컬 트리의 HEAD 만 이전 커밋으로 변경하라는 명령이다.
그 후 새로 commit 을 실행하면 git commit --amend 명령과 동일한 결과가 된다.
amend 는 마지막 커밋을 수정하지만, reset 은 훨씬 이전의 커밋을 수정할 수 있다.
$ git reset --mixed HEAD~ | cs |
이전 커밋으로 HEAD 를 옮기는데 --mixed 하게. (mixed 가 default 이다.)
로컬 트리의 HEAD 와 index 를 이전 커밋으로 변경하라는 명령이다.
$ git reset --hard HEAD~ | cs |
이전 커밋으로 HEAD 를 옮기는데 --hard 하게.
로컬 트리의 HEAD 와 index, WD 모두를 이전 커밋으로 변경하라는 명령이다.
위 예제처럼 전체가 아닌 특정 파일(paths)들을 reset 할 수도 있다.
특정 파일 때문에 HEAD 포인터가 바뀌지는 않으므로 HEAD 는 상태 그대로 고정된다.
mixed 옵션으로 Index 나 WD 는 일부분 갱신할 수 있다.
$ git reset file.txt | cs |
위 명령은 tree-ish(commit, tag ...) 와 옵션을 생략한 git reset --mixed HEAD file.txt 의 줄임이다.
* 롤백하기
위 그림처럼 C4 까지의 커밋이 있었다고 치자.
원격 저장소의 origin/master 가 C4 를 가리키고 있었다고 치자.
그런데 C3 과 C4 의 내용이 잘못되어 C2 로 롤백해야 하는 상황이 발생했다고 치자.
이 경우 다음의 명령으로 롤백을 시킬 수 있다.
$ git reset --hard C2 | cs |
그리고 모든 팀원이 C3 과 C4 를 날리고 C2 의 새로운 가지에서 다시 작할 수 있도록 push 를 해보자.
우선 간단한 변경 사항을 만들어 commit(C5) 명령 후에 push 를 날려보자.
원격의 origin/master 는 C4 를 가리키고 있으므로 pull 을 받고 push 하라는 non-fast-forward 경고가 발생한다.
! [rejected] master -> master (non-fast-forward) | cs |
이 때 pull 을 받아 버리면 다시 로컬 저장소는 C4 를 가리키게 되므로 pull 을 받으면 안된다.
강제 push 로 C3 과 C4 를 날려버리고 origin/master 가 C5 를 가리키도록 아래와 같이 명령한다.
$ git push --force origin master ... + eaa2322...5efad42 master -> master (forced update) | cs |
! [remote rejected] master -> master (TF401027: Your account lacks the permission(s) required for the operation you are attempting. You need to have 'For error: failed to push some refs to ... | cs |
권한이 없다는 오류가 발생한다면, git 서버에 접속하여 다음 config 를 추가하면 된다.
$ git config receive.denyNonFastforwards false | cs |
서버 관리자에게 권한 거부 당한다면 ㅈ망 ^^
이상!
WRITTEN BY
- 손가락귀신
정신 못차리면, 벌 받는다.