브랜치와 병합을 알아보기 전에 변경사항을 취소하는 checkout
(CLI)과 코드뭉치 버리기
(sourceTree) 기능을 간단히 알아보겠습니다.
checkout
을 이용하면 아주 쉽게 마지막 커밋으로 되돌아 갈 수 있다.
sourceTree의코드뭉치 버리기
기능을 사용하면 변경사항을 되돌릴 수 있다.
지난 글을 통해 간단한 git 사용 방법을 알아보았습니다. commit
은 변경사항을 내 컴퓨터에 저장하는 것이고, push
는 github 서버에 업로드 하는 것입니다.
이번에는 마지막 세이브로 돌아가는 방법에 대해 알아보겠습니다. 이는 git에서는 checkout
이라는 명령을 통해서 가능한데 sourceTree에서는 더욱 쉽게 가능합니다.
먼저 커밋하고 난 상태에서 아무 파일이나 열고 아무 내용을 입력합니다. 아래 그림은 기존의 hello.md 파일에서 10~14 라인을 지운 후 이상한 내용을 추가해보겠습니다.
내용 변경 후 sourceTree에 가면 커밋하지 않은 변경사항이 뜨며, 이를 클릭하면 아래 그림과 같이 오른쪽 아래에 hello.md의 변경사항이 나옵니다. 빨간색으로 음영표시 된 부분은 기존의 내용에서 제거된 내용이고, 노란색으로 음영표시 된 부분은 새로 추가된 내용입니다.
파일을 되돌리고 싶으시다면 변경사항에서 되돌릴 파일을 선택하고 코드 뭉치 버리기
를 선택하면 끝입니다.
브랜치 (branch) : 기능 변경을 하고 싶을 때 생성 및 사용
체크아웃 (checkout) : 저장소에서 특정 커밋이나 브랜치로 돌아가고 싶을 때 사용
이미 돌아가고 있는 프로그램에서 기능을 바꾸고 싶은 일이 생길 수 있습니다. 그럴때는 다음과 같은 시나리오대로 진행할 수 있습니다.
1. 기존 문서에 새로운 설명을 추가했다.
2. 내용이 마음에 안드니 다시 작업을 하고 싶다.
3. 혹시 모르니 기존 내용은 남겨 두고 싶다.
4. 새로 작업을 한 후에 비교해 보고 더 좋은 결과물로 반영하자.
현재 폴더에는 hello.md 파일이 있고 커밋까지 되어 있습니다. 커밋 로그는 아래 그림처럼 되어 있습니다. hello.md 파일을 생성하여 커밋 및 push를 하고, 마지막에 hello.md 파일의 내용을 수정한 것 입니다.
사실 우리는 브랜치라는 걸 이미 사용하고 있습니다. 아무 설정도 안 하고 git을 사용하면 위 그림 왼쪽의 굵은 글씨에 보이는 것처럼 main 브랜치라고 하는 기본 브랜치에서 작업을 하게 됩니다. 브랜치는 간단하게 말하자면 가상의 작업 환경입니다. 브랜치를 새로 생성하면 기존의 메인 브랜치의 내용은 그대로 보존하면서 새로운 작업 환경을 생성하는 거라고 이해하시면 될 것 같습니다.
새로운 브랜치의 이름은 'version2'로 붙이고, 마지막 커밋의 직전 커밋으로부터 생성을 해보겠습니다. 직전 커밋을 우클릭 -> 브랜치 -> 새 브랜치를 선택하여 브랜치를 생성해 봅니다. 생성 후에는 왼쪽에 version2 라는 브랜치가 생기는데, 소스트리의 기능으로 자동으로 현재 브랜치가 version2가 됩니다.
git에서는 한 번에 하나의 브랜치에서만 작업이 가능한데 이를 헤드(HEAD) 브랜치
라고 부릅니다.
즉, 방금 전에 생성한 브랜치 version2가 현재 헤드 브랜치 입니다. 브랜치를 변경하기 위해서는 checkout
을 사용합니다. 소스트리를 사용하면 정말 쉽게 브랜치 체크아웃을 할 수 있습니다. 왼쪽 메뉴의 브랜치 이름을 더블 클릭만 하면 체크아웃을 쉽게 하실 수 있습니다.
브랜치 체크아웃 할 때마다 파일의 내용이 변경되는 것도 볼 수 있습니다.
다시 version2 브랜치로 돌아와서 이번에는 실제 파일의 내용을 고쳐 보겠습니다. 다음과 같은 내용을 추가 해보겠습니다.
## 브랜치 변경하기
- 브랜치란 : 기능 변경을 하고 싶을 때 생성 및 사용. 즉, 기존 내용을 유지한 채 새로운 내용을 추가하고 싶을 때 사용한다.
- checkout : 특정 브랜치(혹은 커밋) 으로 돌아가고 싶을 때 사용.
- 소스트리의 체크아웃 : 브랜치 이름을 더블 클릭하는 것만으로도 체크아웃 가능
위와 같이 변경한 후에 스테이지에 변경 사항을 올리고 커밋을 하면 새로운 커밋이 하나 생깁니다. 그런데 아래 그림처럼 version2 브랜치만 새로 생긴 커밋을 가르키게 되고, main 브랜치는 변하지 않습니다.
이제 우리는 두 가지 버전이 생겼습니다. main 브랜치 버전과 version2 버전입니다. 각각의 브랜치로 체크아웃하면 각 브랜치의 내용으로 폴더안의 파일이 변합니다. 두 가지를 비교해 보고 고민 후에 최종적으로 하나를 선택하면 됩니다. 그럴 때 병합(merge)
을 합니다.
하나의 브랜치를 현재 브랜치와 합치는 것을 병합(merge) 이라고 합니다.
앞서 현재 브랜치를 헤드(HEAD) 브랜치 라고 한다고 했습니다. 병합을 하게 되면 헤드 브랜치가 아닌 브랜치의 내용이 헤드 브랜치에 반영되게 됩니다.
병합시 자주 발생하는 상황에 대해 알아보겠습니다.
가장 쉬운 상황
- 합치려는 브랜치가 헤드 브랜치로부터 시작되었다.
- 그 사이 헤드 브랜치에는 전혀 갱신이 없었다.
주로 혼자 작업을 할 때 발생하는 상황입니다.
위 그림은 헤드 브랜치(*
이 붙어있는)인 main에서 version2가 시작되고 두 번 커밋한 상태입니다. 여기서 병합을 하게 되면 단순하게 main 브랜치가 가르키는 커밋이 version2의 커밋으로 이동합니다. 이러한 상황을 fast-forward 병합이라고 합니다. 단순히 브랜치의 참조만 갱신되는 상황입니다.
두 번째 상황은 조금 복잡합니다. 원인은 다음과 같습니다.
1.과거의 커밋으로부터 브랜치를 생성해서 작업을 한 경우
2.새로운 브랜치 작업 이후에 헤드에 다른 새 커밋이 있는 경우
3.여러 브랜치를 동시에 작업하면서 병합을 시도할 경우
세 가지 경우 모두 종종 발생하는 상황입니다. 이 경우에도 기본이 되는 헤드 브랜치에서 타겟 브랜치를 병합하면 되긴 하는데, 이 때 여러 브랜치에서 동시에 변경한 파일이 있을 경우
충돌
이 발생할 수 있습니다.
혼자 작업하는 경우에는 충돌 해결은 쉬운 편입니다.
1.보통 가장 최신 내용 하나만 선택하면 되는 경우가 많다.
2.그리고 최신 내용은 보통 타겟 브랜치에 있는 경우가 많다.
소스트리와 에디터를 사용하면 어렵지 않게 충돌 해결이 가능합니다. 앞서 저희가 편집했던 브랜치들은 가지가 생겨난 경우입니다. 왜냐하면 마지막 커밋의 직전 커밋에서 새로운 브랜치인 version2를 생성했기 때문입니다. 이제 브랜치를 병합해 보겠습니다.
sourceTree를 사용해서 병합하는 방법은, 먼저 헤드 브랜치를 main 으로 checkout합니다. 이후 version2 우클릭 -> 병합을 누르시면 다음과 같은 창이 나옵니다.
확인을 누르시면 아마 충돌이 일어날 텐데, 이를 VSC에서 확인해 보면 다음과 같습니다.
충돌이 있는 부분에 Git 이 자동으로 위와 같이 충돌 정보를 포함하여 파일 내용을 변경합니다. 이 내용을 통해 어떤 브랜치에서 어떤 부분이 충돌되었는지 확인할 수 있습니다. 충돌이 일어난 부분은 이렇게 일일이 확인해서 수정해 주어야 합니다. 그럼 아래와 같이 파일 내용을 변경해 봅시다.
충돌 부분을 모두 수정했으므로, 다시 커밋합니다.
이번 병합은 충돌 부분을 수정했기 때문에 그 변화를 기록하는 병합 커밋이 새로 생성 되었습니다. 그리고 main 브랜치(HEAD)가 그 위치로 이동해 있는 것을 확인할 수 있습니다. 아래와 같은 방식을 non fast-forward 병합이라고 합니다.
version2 브랜치는 이제 더 이상 필요가 없으니 삭제를 할 수 있습니다. 왼쪽 브랜치 목록에서 version2를 우클릭 후 삭제 버튼을 누르시면 삭제가 됩니다.
상황 1도 연습해보겠습니다. 아래 그림과 같이 version3 브랜치를 새로 생성합니다.
그리고 에디터를 이용하여 hello.md에 Fast-forward에 대한 설명을 추가합니다. 이를 스테이지에 올리고 커밋한 후에 병합을 해보겠습니다. 병합하기 전 헤드 브랜치를 main
으로 바꿔주세요. 자세한건 아래 그림을 참고하시면 됩니다.
위 그림을 보시면 알겠지만 충돌이 일어나지 않았습니다. 이유는 version3 브랜치가 헤드 브랜치인 main으로부터 시작되었고, 헤드 브랜치에 변경사항이 없었기 때문에 Fast-forward 병합
이 되었기 때문입니다.
상황 2를 실습할 때 충돌이 일어났던 것을 기억하실겁니다. 이번에는 충돌 없이 병합을 해보겠습니다.
먼저 version3 브랜치로 checkout 한 후에, hello.md에 다음과 같은 내용을 추가하고 커밋해줍니다.
## 병합하기 2
- 과거의 커밋으로부터 브랜치를 생성해서 작업을 한 경우
- 새로운 브랜치 작업 이후에 헤드에 다른 새 커밋이 있는 경우
- 여러 브랜치를 동시에 작업하면서 병합을 시도할 경우
그렇다면 위 그림과 같이 되실텐데, 현재 main 브랜치에서는 '병합 상황 2'에 대한 내용이 없는 상태입니다.
이제 다시 main 브랜치로 돌아가서 새로운 파일 하나를 만들어보겠습니다. 아래 그림과 같이 에디터를 이용해서 temporary.md 라는 새로운 파일을 만들어 주고 커밋을 해보겠습니다.
새로운 가지가 생긴 모습을 확인하실 수 있습니다. 이제 두 브랜치를 병합을 해보겠습니다. 마찬가지로 main 브랜치로 checkout을 하고 다음 version3 브랜치를 병합합니다.
충돌이 일어나지 않고 병합이 되었습니다. 그 이유는 서로 다른 파일에서 작업을 했기 때문입니다. main 브랜치를 push하여 원격서버 상에서 확인을 하면, version3 에서 작성한 내용들은 hello.md에 추가되어 있고, main 브랜치에서 작성한 temporary.md 파일 또한 올라가 있는 것을 확인할 수 있습니다.
- Youtube에서 호눅스님의 영상을 보고 작성한 글입니다.
- 더 자세한 내용을 알고싶다면 Youtube에서 Honux Dev Channel을 검색해보시기 바랍니다.
꿀팁이네요~~