독서

[지옥에서 온 관리자 깃&깃허브 입문] 3장. 깃과 브랜치

찐공log 2022. 1. 21. 12:04

2022.01.21 - [독서/IT・컴퓨터] - [지옥에서 온 관리자 깃&깃허브 입문] 2장. 깃으로 버전 관리하기

 

[지옥에서 온 관리자 깃&깃허브 입문] 2장. 깃으로 버전 관리하기

2022.01.21 - [독서/IT・컴퓨터] - [지옥에서 온 관리자 깃&깃허브 입문] 1장. 깃 시작하기 1. 깃 저장소 만들기 맨 처음 깃을 사용하기 위해 깃 저장소를 만들어봅시다. git init : 깃 저장소 초기화. 깃을

zzingonglog.tistory.com

 

1. 브랜치란?

깃으로 버전관리 시 기본적으로 master 라는 브랜치가 생성됩니다.

master브랜치를 유지하면서 기존 파일 내용을 수정하거나 새로운 기능을 구현할 파일을 만들 수 있습니다.

이렇게 master 브랜치에서 뻗어 나오는 새 브랜치를 만드는 것을 분기(branch)라고 합니다.

또한 새 브랜치에서의 작업을 원래 master브랜치와 합치는 것을 병합(merge)이라고 합니다.

기존의 작업중인 master 브랜치에서 고객사마다 다른 기능을 추가하게 될 때 브랜치 기능을 사용하여 코드들을 분기하게 됩니다.

 

 

 

2. 브랜치 만들기

(1) 실습 상황 설정하기

우선 테스트 환경을 설정해야겠죠.

실습을 위해 manual이라는 새 디렉터리를 생성하고 깃 저장소로 만듭니다.

 

manual 디렉터리에 work.txt 파일을 생성한 후 내용은 content 1 이라고 작성&저장 후 커밋합니다.

 

그리고 work.txt 파일을 두 번 더 커밋하여 커밋 메시지 work 1, work 2, work 3인 커밋들을 만듭니다.

각 커밋마다 추가된 내용은content 2, content3 내용이 추가되었습니다.

여기까지가 초기 기능을 개발하는 과정이라고 가정합니다.🙂

 

 

(2) 새 브랜치 만들기

이제 고객사 별로 브랜치를 생성해봅시다.

git branch : 깃에서 브랜치를 만들거나 확인하는 명령

git branch
 

git branch를 입력하면 저장소를 만들 때 기본적으로 master 브랜치가 만들어진 것이 보입니다.

 

apple 이름의 브랜치를 만들려면 git branch apple을 하면 됩니다.

git branch 브랜치이름
 
apple branch 만들기

위와 같이 apple 브랜치를 만든 후 다시 브랜치를 확인해보면 apple이 생성되었습니다.

그리고 * 표시는 현재 작업중인 브랜치를 뜻합니다.

브랜치가 추가된 후에는 커밋 로그 화면도 다르게 나타납니다. (HEAD -> master, apple) 로 변경되었으며, HEAD -> master이므로 현재 작업 중인 브랜치는 master브랜치라는 의미입니다.

HEAD는 작업 중인 브랜치를 가리키는 포인터라고 생각하면 됩니다.

 

구글, MS 브랜치도 만들어봅시다.

 

 

(3) 브랜치 사이 이동하기

현재 master브랜치의 work 3 커밋 상태에서 새 브랜치들을 만들었기 때문에, 모든 브랜치들의 최신 커밋은 work 3 입니다.

 

이 상태에서 커밋을 하나 추가하여 어떻게 달라지는지 확인해봅니다.

work.txt에 master content 4 문구를 추가하고 커밋한 후 git log --online을 해봅니다.

(--online 옵션은 한 줄에 한 커밋씩 나타내 주기 때문에 커밋을 간략히 확인할 때 편리합니다. )

최신 커밋인 master content 4는 master 브랜치에만 적용되어있습니다.

나머지 브랜치들은 work 3 커밋 상태입니다.

 

 

현재 브랜치에서 다른 브랜치로 이동하면 어떻게 변하는지 확인해봅시다.

다른 브랜치로 이동 명령어는 다음과 같습니다.

git checkout 브랜치이름
 

apple 브랜치로 전환되었다고 출력되며, 최신 커밋은 처음 분기된 work 3 커밋 그대로입니다.

work.txt 파일을 확인해보면 master content 4 커밋 내용은 없습니다.

즉, master 브랜치에서 분기된 이후에 master 브랜치에 추가된 커밋은 apple브랜치에 영향이 없습니다.

 

 

 

 

3. 브랜치 정보 확인하기

여러 브랜치에서 각각 커밋이 될 때 커밋끼리 어떤 관계를 이루는지 확인하는 방법과, 브랜치 사이의 차이점을 확인하는 방법을 알아봅니다.

 

(1) 새 브랜치에서 커밋하기

apple브랜치에서 apple.txt 와 work.txt 파일에 동일한 내용 (apple content 4)를 입력하고 저장합니다.

이때 git add . 명령을 이용해 수정된 2개의 파일을 스테이지에 한꺼번에 올릴 수 있습니다.

위 화면은 커밋까지 완료했습니다.

 

git log --oneline으로 확인을 해보면 apple 브랜치의 최신 커밋은 apple content 4 입니다.

git log 명령을 사용할 때 --branches 옵션을 사용하면 각 브랜치의 커밋을 함께 볼 수 있습니다.

git log --oneline --branches 
 

 

브랜치와 커밋의 관계를 그래프 형태로 표시하려면 git log 명령에 --graph 옵션을 함께 사용합니다.

git log --oneline --branches --graph
 

관계를 더 보기 쉽게 그래프 형태로 표시합니다.

수직선과 사선이 생성되고 선을 따라가면 부모 커밋을 찾아갈 수 있습니다.

 

 

(2) 브랜치 사이의 차이점 알아보기

두 브랜치 이름 사이에 (..) 마침표 두개를 넣는 명령으로 차이점을 쉽게 확인할 수 있습니다.

git log master..apple
 

마침표 왼쪽에 있는 브랜치를 기준으로 오른쪽 브랜치와 비교합니다.

이렇게 하면 master 브랜치에는 없고 apple 브랜치에만 있는 커밋, 즉 'apple content 4' 커밋을 보여줍니다.

반대로 apple 브랜치를 기준으로 master와 비교하면 apple에는 없고, master에만 있는 master content 4 커밋을 보여줍니다.

 

 

 

4. 브랜치 병합하기

각 브랜치에서 작업을 하다가 어느 시점에서는 브랜치 작업을 마무리 하고 기존 브랜치와 합해야 합니다.

이것을 브랜치 병합(merge)이라고 합니다. 또한 병합하면서 브랜치 사이에 충돌이 있을 때 해결하는 방법도 알아봅시다.

 

(1) 서로 다른 파일 병합하기

실습을 위해 새로운 저장소를 만듭니다.

git init 을 할 때 디렉토리명을 입력해주면 디렉토리 생성과 저장소를 초기화하는 것을 한꺼번에 할 수 있습니다.

git init 디렉토리명
 

work.txt 파일에 1을 입력하고 저장 후 work 1 메세지와 함께 커밋합니다.

 

 

새로운 브랜치 o2를 만든 후 master 브랜치에 master.txt파일을 만들고 master work 2 메시지로 커밋합니다.

 

그리고 o2 브랜치로 체크아웃 한 후 o2.txt 파일을 만들고 커밋합니다.

로그를 확인해보면 아래와 같습니다.

work 1은 master브랜치와 o2브랜치가 동일하게 갖고 있습니다.

master브랜치에는 master work 2 커밋이 생겼고, o2 브랜치에는 o2 work 2 커밋이 생겼습니다.

 

이제 o2브랜치에서 작업이 끝났다고 가정하고, o2브랜치 내용을 master 브랜치로 병합을 합니다.

브랜치를 병합하려면 먼저 master 브랜치로 체크아웃 해야합니다.

git checkout master
 

브랜치를 병합하려면 git merge 명령 뒤에 가져올 브랜치 이름을 적습니다.

master 브랜치에 o2 브랜치를 가져와 병합하려면 git merge o2 를 입력합니다.

git merge 브랜치이름
 

그러면 병합하겠다는 문구가 작성된 vim 편집기가 나타납니다.

저장하고 ls -al로 확인해보면 o2 브랜치에 있던 o2.txt파일이 master 브랜치에 합쳐져 있습니다.

 

위와 같이 git log --oneline --branches --graph 명령을 통해 병합을 확인할 수도 있습니다.

두 브랜치에서 서로 다른 파일을 병합하는 경우 이렇게 깃에서 간단히 해결할 수 있습니다.

 

 

 

🌀빨리 감기 병합

master 브랜치에서 브랜치를 분기한 후에 master브랜치에 아무 변화가 없다면 (새로운 커밋이 없다면) 분기한 브랜치를 병합하는 방법은 간단합니다. 분기한 브랜치에서 만든 최신 커밋을 master브랜치가 가리키게만 하면 되기 때문이지요. 이 경우에는 화면에 커밋 해시가 업데이트 되었다는 내용과 함께 fast-forward 라는 메시지가 나타납니다.

이런 병합을 빨리 감기 병합(fast-forward merge)이라고 합니다. 단순히 포인터를 움직인 것이기 때문에 커밋 메시지 창은 열리지 않습니다.

 

🌀브랜치를 병합할 때 편집기 창이 열리지 않게 하려면

git merge o2 --no-edit
 

브랜치를 병합할 때 편집기 창이 나타나지 않도록 설정한 경우, 커밋 메시지를 추가하거나 수정하고 싶다면 병합 명령에 --edit 옵션을 사용합니다.

git merge o2 --edit
 

 

(2) 같은 문서의 다른 위치를 수정했을 때 병합하기

master, o2 브랜치 각각엔 work.txt파일이 있습니다.

양쪽 브랜치에서 work.txt문서를 수정하되 서로 다른 위치를 수정한 후 브랜치를 병합한다면 어떻게 되는지 확인해봅시다.

 

 

새로운 깃 저장소 manual-3을 만들고 아래와 같이 work.txt파일을 생성 후 커밋합니다.

 

그다음 브랜치 o2를 생성하고, 양쪽 브랜치 모두에게 있는 work.txt 파일 내용을 위와 같이 각각 수정합니다.

즉, 브랜치들 양쪽에서 work.txt 파일을 수정했지만 문서 안의 수정 위치는 다르게 됩니다.

 

 

o2 브랜치를 master브랜치에 합치기 위해 master브랜치로 체크아웃한 후 git merge o2 명령을 입력합니다.

그러면 위 화면과 같이 자연스럽게 두개의 파일을 합쳐줍니다.

 

 

(3) 같은 문서의 같은 위치를 수정했을 때 병합하기

깃은 줄 단위로 변경 여부를 확인합니다.

그렇기 때문에 같은 줄을 수정하고 브랜치 병합을 한다면 충돌이 일어나게 됩니다.

충돌이 날 경우 어떻게 해결해야하는지 테스트로 확인해봅시다.

먼저 새로운 저장소 manual-4를 만들고 work 파일을 위와 같이 생성, 커밋합니다.

 

 

o2브랜치를 생성한 후 체크아웃하지는 말고 master브랜치의 work.txt 내용을 수정합니다.

 

o2브랜치로 체크아웃하여 work.txt 파일을 동일 라인에서 수정을 한 후 커밋합니다.

 

이제 master브랜치로 가서 o2브랜치와 병합을 합니다.

동일파일에 동일한 라인을 수정했기 때문에 충돌이 일어납니다.

즉, 충돌이 생긴 문서는 자동으로 병합할 수 없으므로, 사용자가 직접 충돌을 해결 한 후 커밋해야 합니다.

충돌이 생긴 work.txt를 확인봅시다.

<<<<<<< HEAD

master content 2 ← 현재 브랜치, 즉 master 브랜치에서 수정한 내용

=======

o2 content 2 ← 병합할 브랜치에서(o2 브랜치) 수정한 내용

>>>>>>> o2

 

텍스트의 <<<<<<< 나 ========는 삭제하고 내용을 원하는대로 수동 수정 한 후 저장합니다.

 

수정한 파일을 스테이지에 올리고 커밋하면 됩니다.

log 명령으로 지금까지 만든 브런치와 커밋의 관계를 확인할 수 있습니다.

 

🌀병합 충돌 해결 프로그램 : 병합알고리즘에는 2 way merge와 3 way merge가 있는데 3 way merge 가 훨씬 효율적이므로 해당 알고리즘을 지원하는 프로그램을 사용하는 것을 권장.

ex) P4Merger(무료), Meld(무료), Kdiff3(무료), Araxis Merge(유료)

 

 

(4) 병합이 끝난 브랜치 삭제하기

병합이 끝난 후 더 이상 사용하지 않는 브랜치는 삭제할 수 있습니다.

삭제하더라도 브랜치가 완전히 지워지는 것이 아니라 동일한 이름으로 재생성시 예전 내용들을 다시 볼 수 있습니다.

git branch 명령을 사용하여 현재 저장소에 어떤 브랜치가 있는지 이름을 확인한 후 삭제를 진행합니다.

또한 브랜치를 삭제하려면 master 브랜치에서 해야합니다.

git branch -d 삭제할 브랜치명
 

브랜치를 삭제한다는 것은 깃의 흐름속에서만 감출 뿐이지 완전한 삭제가 아닙니다.

 

 

 

5. 브랜치 관리하기

(1) 브랜치에서 checkout과 reset의 작동 원리

실습을 위해 test 저장소를 새로 만들고, c1.txt파일을 만들고 커밋합니다.

그리고 git log 명령을 실행합니다.

화면을 분석해보면 커밋로그 첫번째 줄에 (HEAD -> master) 표시가 있습니다 있습니다.

여기에서 HEAD 는 현재 작업 트리가 어떤 버전을 기반으로 작업 중인지를 가리키는 포인터입니다.

HEAD는 기본적으로 master 브랜치를 가리킵니다.

또한 master 브랜치는 기본적으로 브랜치에 담긴 커밋 중에서 가장 최근의 커밋을 가리킵니다.

지금은 c1 커밋을 만들었으니, HEAD는 master브랜치를 기리키고 master브랜치는 c1커밋을 가리키게 됩니다.

 

이 상태에서 sub브랜치를 만들어놓고, master브랜치에서 c2.txt 파일을 생성, c2 메세지로 커밋합니다.

이제 master는 c2커밋을 가리키게 됩니다. HEAD는 그대로 master브랜치를 가리키고 있습니다.

 

방금 만든 sub브랜치로 체크아웃한 후 s1.txt 문서를 만들고 커밋합니다.

그러면 이제 HEAD는 sub 브랜치를 가리키고 sub는 s1커밋을 가리키고 있습니다.

 

 

브랜치가 여러 개일때는 현재 브랜치가 아닌 다른 브랜치에 있는 커밋을 골라서 최신 커밋으로 지정할 수 있습니다.

예를 들면 sub 브랜치에 있는 상태에서 master 브랜치에 있는 c2 커밋을 sub 브랜치의 최신 커밋으로 지정할 수 있습니다.

먼저 git log --oneline --branches를 이용해서 c2 의 커밋 해시를 알아야합니다.

git reset [최신 커밋으로 지정하고자하는 커밋 해시]
 
다른 브랜치의 커밋을 지금 브랜치의 최신커밋으로 만들기

 

로그를 확인해보면 sub 브랜치의 최신 커밋이 master 브랜치의 최신 커밋인 c2로 바뀌었습니다.

그리고 HEAD는 그대로 sub브랜치를 가리키고 있습니다.

연결이 끊긴 s1커밋은 삭제됩니다.

 

정리를 해보면,

git checkout 은 HEAD를 제어해서 브랜치를 이동.

git reset 은 HEAD가 가리키고 있는 브랜치의 최신 커밋을 원하는 커밋으로 지정.

 

 

(2) 수정 중인 파일 감추기 및 되돌리기

수정 중인 파일이 있는데, 다른 파일을 급하게 커밋해야하는 경우가 있습니다.

그런 경우 작업 중인 파일들을 잠시 감출 수 있습니다.

실습을 위해 새 저장소 st를 만들고 f1.txt과 f2.txt파일을 생성하여 한번씩은 커밋을 한 후 각 파일을 다시 수정해봅니다.

f1.txt 와 f2.txt 파일을 커밋하기 전에 다른 파일을 수정해야 할 경우가 생깁니다.

그렇다면 현재 커밋하지 않은 수정 내용을 따로 보관하려면 git stash 명령을 사용하면 됩니다.

git stash
 

그리고 다시 git status 를 해보면 깨끗하다고 나온다.

이렇게 따로 보관된 파일들은 stash 목록에서 확인 가능합니다.

git stash list
 

가장 먼저 감춘 것은 stash@{0}에 들어있고, 그 후 다른 파일이 추가되면 기존 파일은 stash@{1}로 옮겨지고 새로 추가된 파일은 stash@{0}에 담깁니다.

즉, 가장 최근에 보관한 것이 stash@{0}에 담기게 됩니다.

먼저 감춘 것을 아래에, 가장 최근에 감춘 것을 위에 쌓아서 스택이라고 합니다.

 

급한 작업을 마쳤으면 스택에서 다시 꺼내올 수 있습니다.

pop 명령을 추가하면 stash 목록에서 가장 최근 항목을 되돌립니다.

git stash pop
 

 

참고)

🌀stash apply 와 stash drop

git stash apply
 

git stash apply : stash 목록에 저장된 수정 내용을 나중에 또 사용 할 때 사용. stash 목록에서 가장 최근 항목을 되돌리지만 저장했던 내용은 그대로 남겨둠.

git stash drop
 

git stash drop : stash 목록에서 가장 최근 항목을 삭제