Git Basics (3)
Resetting your commit
만약 커밋을 했는데 커밋 로그 메시지를 실수로 잘못 적었다고 해보자. 다음 커맨드를 실행하면 스냅샷을 건드리지 않고 이전 커밋 메시지를 수정할 수 있다.
git commit --amend
에디터를 통해 하고 싶지 않다면 다음과 같이 쓰면 된다.
git commit --amend -m "Updated log message"
커밋 메시지뿐만 아니라 커밋 또한 amend
flag를 사용하여 수정할 수 있다. 가장 최근의 커밋이 수정될 수 있다. 그리고 이는 새로운 커밋을 만드는 것보다 낫다.
NOTE: 커밋을 amend하면 커밋 자체가 새로운 커밋으로 교체된다 - 새로운 해시 값으로 바뀐다. (커밋 timestamp가 고려되기 때문에)
자, 이제 레포지토리에 만든 변경 사항을 취소하는 방법도 있지 않을까? 깃 커밋을 하다보면 실수를 할 수도 있고, 어떠한 변경 사항으로 인해 이슈가 발생할 수도 있고, 또는 이전 커밋이 전체적인 프로그램의 더 좋은 버전인 것이라고 생각할 수도 있을 것이다.
이전 커밋으로 undo(취소하여 이전 커밋으로 컴백)하기 위해서는 다음과 같은 커맨드를 쓴다.
git checkout <previous-commit>
git reset <previous-commit>
git reset
의 디폴트 인자는 --mixed
이다. git reset
의 인자, 즉 flag는 reset이 되었을 때 staging area와 working directory에 어떤 일이 일어나는지를 정의한다.
git reset --mixed <previous-commit> # Same as git reset <previous-commit>
--mixed
는 staging area의 모든 변경 사항들을 working directory로 옮긴다.
두 가지 옵션이 더 있다.
git reset --hard <previous-commit>
--hard
는 가장 위험하지만 많이 쓰인다. Reference 포인터 (i.e. HEAD)가 바뀌어 staging area와 working directory가 커밋 트리의 state와 같아지도록 reset된다. 즉, working directory와 staging area에 있는 변경 사항들을 모두 잃는다.
git reset --soft <previous-commit>
--soft
: Ref 포인터가 업데이트되지만 staging area와 working directory는 건드리지 않는다.
git reset
이 커밋을 삭제하는 일은 절대 없다는 것을 명심하자. 단지 커밋들을 “고아”로 만드는 것이다. (i.e. 그 커밋들에게 접근할 수 있는 직접적인 경로가 없다)
이러한 고아 커밋들은 git reflog
를 통해 찾을 수 있다. 이 커밋들은 git이 내부 가비지 컬렉터를 실행하면 삭제될 것이다. 디폴트로 git은 가비지 컬렉터를 30일에 한 번씩 돌린다.
Revert Instead?
좀 더 안전한 reset으로 git revert
가 있다. 이는 좀 다르게 동작한다. Git revert는 특정한 커밋을 그것의 이전의 커밋으로 revert(돌아가게)하고 그것이 새로운 커밋이 된다. 결과적으로 한 커밋에 대한 두 개의 동일한 카피가 있게된다. 특정 커밋을 카피하는 것이 쓸모 없다고 생각할 수는 있지만 장점도 있다. Git revert의 유즈 케이스로 특정 커밋의 어떠한 코드에 에러가 있어서, 그 커밋으로 돌아가서 이슈를 삭제하지 않고, 변경 사항을 역동작(invert)시켜 그 결과를 새로운 커밋으로 붙인다(append). 이렇게 함으로써 커밋 히스토리를 크게 손대지 않은 상태로 좀 더 안전한 방식으로 유지할 수 있다 - 리비전 히스토리의 무결성 및 신뢰성 높은 협업을 위해 중요하다.
git reset과 git revert의 차이점을 아래 참고 자료를 통해 좀 더 자세히 알아 볼 수 있다.
Stashing your changes
git stash
는 working 카피에 대해 만들어진 변경 사항들을 임시로 저장하여, 잠시 다른 것을 하다가 돌아와서 나중에 변경 사항들을 재적용할 수 있게 해준다. 만약 코드 변경 중 커밋을 할 준비가 안되었는데 빠르게 다른 context에서 일을 하다가 다시 돌아와야 할 때 유용하게 쓰인다. 즉 진행 중인 작업을 저장하고 나중에 다시 돌아올 수 있는 개념이다.
예를 들어, 코드 베이스에 몇 가지 변경을 만들었는데, 다른 브랜치에 보안 이슈가 발생하여 고쳐야 한다고 가정해보자. 그렇다면 우리는 변경 부분을 stash하여 잃지 않은 상태로, 다른 커밋으로 checkout하여 이슈를 고칠 수 있다.
git stash
이슈를 다 고친 후, 현재 working directory로 다시 checkout하여 만들어 두었던 변경 사항들을 모두 pop off할 수 있다.
git stash pop
각 stash에 메시지를 붙여 여러가지 다른 변경 사항들을 stash할 수 있다.
git stash save "Your message here"
모든 stash들을 나열할 수도 있다.
git stash list
메시지와 함께 서로 다른 모든 stash에게 stashID 또한 저장된다. 이 stashID는 1부터 증가하며 순서대로 할당되고, 특정 stash 서머리를 다음과 같이 조회할 수 있다.
git stash show <stashID>
Leave a comment