1. git reset을 하고 나서 돌아오려면?
git reset은 HEAD가 가리키던 브랜치가 가리키는 커밋을 바꾸는 커맨드라고 했다. git reset으로 뒤의 커밋으로 돌아가면, 이후의 커밋들은 어떻게 되는 걸까?
커밋 히스토리에서 가장 처음의 커밋으로 reset 해 보겠다.
calculator.py 파일의 내용을 보면 제일 처음 커밋했던 내용으로 돌아갔음을 확인할 수 있다.
커밋 히스토리를 보아도 가장 처음 커밋 하나만 출력되고 있다.
이때까지 한 커밋들은 삭제된 것처럼 보이지만, 사실은 아니다! reset 해도 그 이후의 커밋들이 삭제되는 건 아니다.
다시 이전의 커밋 히스토리를 보고 가장 최신의 커밋으로 reset 해 보겠다.
그런 다음 커밋 히스토리를 보아도 내역들이 모두 출력되고 calculator.py 파일의 내용도 최신 것으로 나오고 있다.
방금 본 것처럼 reset 해도 커밋들이 삭제 되는 것이 아니라, 단지 HEAD가 가리키던 브랜치가 새로운 커밋을 가리키게 될 뿐이다.
그런데 방금처럼 다시 최신의 커밋으로 reset 하려면 커밋 아이디를 알아야 한다. 방금은 커밋 히스토리 내역을 출력해놓아서 다시 돌아왔지만, 모른다면 어떻게 해야할까?
그럴땐 git reflog 커맨드를 사용하면 된다. reflog는 reference log의 줄임말로, 헤드가 이때까지 가리켜왔던 커밋들을 기록한 정보이다. 어떤 동작을 통해 HEAD가 가리키는게 바뀌었는지 모두 출력된다.
q를 눌러서 나간 후, 이를 참조하여 git reset --hard [커밋아이디] 를 입력하면 다시 돌아갈 수 있다.
혹은 커밋아이디 대신 HEAD@{num} 를 입력해도 된다.
2. 커밋 히스토리를 보는 다양한 방법
현재는 git history 커맨드를 넣어서 커밋 히스토리를 보고 있다. 그리고 이 커맨드는 git log --pretty=oneline 으로 alising 되어있는 상태이다.
그런데 현재 있는 브랜치 뿐만 아니라 다른 브랜치의 커밋 히스토리도 보고 싶으면 어떻게 해야 할까? 그럴땐 --all 옵션을 추가해주면 된다.
git log --pretty=oneline --all 을 입력하면, premium 브랜치 뿐만 아니라 main 브랜치의 커밋 히스토리도 모두 출력된다.
여기에 --graph 옵션을 주면 커밋 히스토리가 각 브랜치와의 관계가 잘 드러나도록 그래프 형식으로 출력된다.
음.. 뭔가 복잡해 보이는데 여기서 ☆ 하나가 커밋 하나를 뜻한다.
그리고 갈라진 모습은 (ex. | /) 여러 브랜치로 코드 관리 흐름이 갈라졌던 모습이다.
이 때 두선이 합쳐지는 부분을 보면 모두 merge 커밋임을 확인할 수 있다.
3. Git을 GUI 환경에서 사용할 수 있게 해주는 프로그램
우리는 이때까지 CLI(Command Line Interface) 환경에서 Git을 사용해왔다.
하지만 GUI(Graphic User Interface) 환경에서 Git을 사용하도록 도와주는 프로그램도 있다.
이 중에서도 꽤 널리 쓰이고 있는 Sourcetree의 사용방법을 간단히 보겠다.
Sourcetree는 Atlassian이라는 회사에서 만든 프로그램으로 깔끔하고 직관적인 UI로 유명하다.
먼저 Sourcetree 다운로드 페이지로 가서 Download for Windows 버튼을 클릭!
설치를 완료하고 나면 sourcetree에서 새로운 로컬 레포지토리를 만들 수도 있고, 원래 있던 로컬 레포지토리를 임포트(import)할 수도 있다. 이때까지 작업을 해온 MathTool이라는 로컬 레포지토리가 있으니까 이걸 임포트해보겠다.
Add 선택 후 MathTool 폴더를 추가해주면 이렇게 Sourcetree가 MathTool 디렉토리를 분석해서 준비한 화면이 나타난다.
각 영역에 대해 간단히 알아보겠다.
- : 아이콘을 클릭해서 커밋, 풀, 푸시 등의 작업을 할 수 있는 영역
- : 커밋 히스토리를 그래픽적으로 보여주는 영역(커밋 히스토리를 깔끔하게 보여주는 장점 때문에 이런 프로그램을 사용하는 경우가 많다.)
- : 커밋 히스토리 중에서 파란색으로 활성화된 커밋에 대한 정보를 보여주는 영역(해당 커밋 당시 생성되거나 수정된 파일 목록)
- : 커밋 히스토리 중에서 파란색으로 활성화된 커밋에 관해 '커밋을 한 사람, 커밋 메시지, 커밋 일시' 등의 정보를 보여주는 영역
- : (3)에서 선택한 파일의 구체적인 수정 내용을 보여주는 영역
이제 프로그램을 어떻게 사용할 수 있는지 간단하게 알아보겠다.
Sourcetree는 누구나 그래픽 요소(아이콘, 설명 등)만 보고도 바로 사용할 수 있을 정도로 직관적인 UI(User Interface)를 갖고 있다.
- 커밋(commit)하기 : 어떤 파일을 생성하거나 수정하고 나서 Sourcetree에서 커밋 메시지를 입력하고 커밋할 수 있다.
- 풀(pull)하기 : 리모트 레포지토리의 내용을 로컬 레포지토리로 가져와서 머지할 수 있다.
- 푸시(push)하기 : 로컬 레포지토리의 내용을 리모트 레포지토리로 보낼 수 있다.
- 페치(fetch)하기 : 리모트 레포지토리의 내용을 로컬 레포지토리로 가져올 수 있다.
- 브랜치(branch) 생성하기 : 새로운 브랜치를 생성할 수 있다.
- 브랜치 병합(merge)하기 : 현재 브랜치에서 다른 브랜치를 머지(merge)할 수 있다.
- 커밋 메시지를 기준으로 커밋 검색(search)하기 : 커밋 메시지에 관한 키워드 검색으로 특정 커밋을 찾을 수 있다.
- 브랜치 변경(checkout) 하기 : 다른 브랜치로 이동할 수 있다.
- 리모트 레포지토리의 브랜치 살펴보기 : 리모트 레포지토리에 있는 브랜치들도 살펴볼 수 있다.
이런 GUI 프로그램을 사용하면 git bash에 Git 커맨드를 치지 않아도 Git을 사용할 수 있다. CLI 환경에서 필요했던 커맨드를 몰라도 Git을 사용할 수 있다는 뜻이다. 또한 커밋 히스토리를 git bash에서 봤던 커밋 히스토리보다 더 깔끔한 모습으로 볼 수 있다는 장점도 있다.
4. 깔끔한 커밋 히스토리를 원할 땐 git merge 대신 git rebase
시험용으로 test 브랜치를 추가하고, premium 브랜치에 복잡한 함수를 먼저 추가하기 전에 test 브랜치에서 시험해보도록 하겠다.
우선 premium 브랜치의 calculator.py 파일에 나머지를 구하는 함수를 추가해주고 커밋까지 완료해준다.
그리고 test 브랜치에 두 수의 중간값을 구하는 get_Median 함수를 추가하고 커밋까지 완료한다.
그런 후 테스트가 잘 되어서 이 함수를 premium 브랜치에 추가하려면?? premium 브랜치에 test 브랜치를 머지하면 될 것 같다.
프리미엄 브랜치에서 git merge test 를 입력하면 conflict가 발생한다. 나는 함수 두 개를 모두 남기도록 하겠다.
그리고 커밋 히스토리를 살펴보면 두 브랜치가 머지된 것을 확인할 수 있다.
그런데 방금처럼 머지하지 않고 git rebase를 사용해도 된다. 우선 premium 브랜치를 머지 직전의 커밋으로 되돌린다.
그런 다음 git rebase test를 입력한다. rebase는 커밋을 재배치하다 는 의미로 즉 '프리미엄 브랜치의 베이스를 테스트 브랜치로 재지정한다' 고 보면 된다.
실행해보면 머지할 때 처럼 conflict가 발생한다.
그러면 머지할 때 처럼 필요없는 부분을 삭제해주면 된다.
그런 후, 머지처럼 커밋을 해주는 게 아니라 add 한 후 git rebase --continue 를 입력해준다. 이는 컨플릭트가 발생해서 제대로 진행되지 못한 리베이스를 계속 진행하라는 의미이다.
그리고 커밋 히스토리를 살펴보면.. 머지했을 때와는 다르다. 두 커밋이 합쳐서 하나의 새로운 커밋이 생긴 게 아니다.
merge 했을 때가 아래와 같은 그림이라면,
rebase 했을 경우는 premium 브랜치가 Add get_Median function 커밋을 거쳐온 것 처럼 커밋 히스토리의 구조 자체가 바뀐다. rebase 말 그대로 test 브랜치의 커밋을 premium 브랜치가 자신의 새로운 베이스로 만드는 것이다.
merge와 rebase의 차이를 정리해보면!!
- rebase는 새로운 커밋을 만들지 않는다.
- rebase로 만들어진 커밋 히스토리는 merge로 만들어진 커밋 히스토리보다 좀 더 깔끔
두 브랜치를 합쳤다는 정보가 커밋 히스토리에 꼭 남아야하는 경우는 merge, 커밋 히스토리를 깔끔하게 유지하는게 더 중요한 경우는 rebase를 사용하는게 좋다.
5. 작업 내용 임시 저장하기
프리미엄 브랜치에서 calculator.py 파일에 get_Abs 함수를 추가해보겠다. 그런데 코드를 작성하는 중에 무료 버전의 라이센스 정보를 당장 수정해달라는 공지를 받았다면!! 우선 파일을 저장하고 main 브랜치로 이동해야한다.
저장 후 main 브랜치로 이동하려는데 오류가 뜬다.
지금 상황에서 main 브랜치로 이동하면, working directory의 내용이 HEAD가 가리키던 master가 가리키는 커밋의 내용으로 바뀔 것이고, 방금 작성한 내용이 날라갈 수 있게 된다.
이런 상황에선 git stash 커맨드를 이용하면 된다. git stash를 사용하면 working directory에서 작업하던 내용을 깃이 따로 보관해준다. 이때 보관하는 장소를 stack이라고 한다.
git stash를 입력하면 stack에 저장되었다고 뜬다.
stack에 잘 저장되었는지 확인하려면 git stash list 를 입력하면 된다.
그런 후 calculator.py 파일을 확인해보면 get_Abs 함수를 추가하기 전 모습으로 돌아와 있다.
git stash를 하면 최근 커밋 이후로 작업했던 내용은 모두 스택에 옮겨지고 working directory 내부는 다시 최근 커밋의 상태로 초기화된다.
그런 후 git checkout main 을 입력하면 잘 이동된다! 다시 프리미엄 브랜치로 돌아와 스택에 저장된 내용을 불러오려면 git stash apply 를 입력하면 된다. 그러면 스택에 있는 내용을 다시 working directory로 가져와서 적용한다.
작성하던 코드를 마저 짜고 커밋까지 완료한다.
정리해보면! git stash는 어떤 브랜치에서 하던 작업을 아직 커밋하지 않았는데 다른 브랜치로 가야하는 상황에서 사용한다.
6. 잘못된 브랜치에서 작업하고 있었다면?
잘못된 브랜치에서 작업했을 때도 git stash를 사용한다.
우선 main 브랜치의 calculator.py 파일에 get_Percent 함수를 추가해준다.
그런데!! 알고보니 get_Percent는 무료버전이 아니라 프리미엄 버전에 있어야 하는 함수였다. 즉 프리미엄 브랜치에서 해야할 작업을 마스터 브랜치에서 한 상황이다. 이럴땐 git stash를 사용하면 쉽게 해결할 수 있다.
우선 git stash를 입력한 후 프리미엄 브랜치로 이동한다.
git stash list 를 입력해 스택에 저장된 내용을 보면, 방금 main 브랜치에서 저장한 작업이 잘 들어가있다. 여기서 git stash apply를 입력하면 더 최근에 저장된 작업 내용이 적용된다. 혹은 git stash [작업내용 아이디] 를 넣어줘도 된다.
그런데 conflict가 뜬다. calcualtor.py 파일을 살펴보겠다.
이는 원래 프리미엄 브랜치에 있던 calculator.py 파일의 내용과 방금 작업했던 내용 사이에 충돌이 생겼기 때문이다. 수정한 후에 저장하고 커밋까지 완료해준다.
브랜치 수가 많을 땐 종종 잘못된 브랜치에서 작업하는 실수를 하게 된다. 그럴땐
- git stash로 stack에 작업 내용을 저장한다
- 올바른 브랜치로 가서 다시 git stash apply를 한다.
그런데 stack에 작업 내용들이 쌓이면 알아보기 힘드므로, 이전 작업 내용들은 비워주는게 좋다.
스택에서 내용을 삭제할 땐 git stash drop [작업내용 아이디] 를 입력하면 된다.
모두 깨끗하게 비워주기 완료~
'1. 프로그래밍 > 1-1. Git' 카테고리의 다른 글
Git - [이전 커밋 이름 변경하기] (0) | 2022.02.26 |
---|---|
7. Git 자유자재로 활용하기 (2) (0) | 2021.09.07 |
6. Git 협업하기 (0) | 2021.09.05 |
5. 브랜치 사용하기 (2) - [ git reset / checkout / merge ] (0) | 2021.09.05 |
5. 브랜치 사용하기 - [ branch / merge ] (0) | 2021.09.05 |