Git Basics (3)

2 minute read

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>

참고 자료

https://www.atlassian.com/git/tutorials/undoing-changes

Categories:

Updated:

Leave a comment