03-1 브랜치란
고객과 협의를 거쳐 웹 사이트를 개발하고 완성했는데 고객이 새로운
기능 추가를 요구, 만약 새로운 기능을 추가 했을 때 오류가 발생한다면...
기존 소스는 그대로 둔 채 새 소스를 추가한 버전을 따로 만들어 관리,
완벽하게 완성한 다음 원래 소스에 병합. 이럴 때 사용하는 방법이
깃의 '브랜치(branch)'라는 기능이다.
모든 버전관리 시스템에는 브랜치(branch)라는 개념이 있다. 나뭇가지...
브랜치가 필요한 이유
브랜치 기능 살펴보기
깃을 버전 관리를 시작하면 기본적으로 master라는 브랜치가 생성
사용자가 커밋할 때마다 master 브랜치는 최신 커밋을 가리킴
즉, 브랜치는 커밋을 가리키는 포인터와 비슷
새 브랜치를 만들면 기존에 저장한 파일을 master 브랜치에 그대로
유지하면서 기존 파일 내용을 수정하거나 새로운 기능을 구현할 파일을
만들 수 있다. 이렇게 master 브랜치에서 뻗어 나오는 새 브랜치를
만드는 것을 '분기(branch)한다'고 한다.
A 분기-- -- a1 ---------> a2
: : 병합
master C1-----------------C2----------------------------> C3
: : 병합
B 분기--------- --------> b1
새 브랜치에서 원하는 작업을 다 끝냈다면 새 브랜치에 있던 파일을
원래 master 브랜치에 합칠 수 있다. 이렇게 분기했던 브랜치를
master 브랜치에 합치는 것을 '병합(merge)한다'라고 한다.
03-2 브랜치 만들기
실습 상황 설정하기
1. mkdir manual
cd manual
2. git init
ls -al
3. vi work.txt
'content 1' 입력 후 저장
4. git add work.txt
git commit -m 'work 1'
5. git log
6. vi work.txt <--'content 2' 추가
git commit -am 'work 2'
7. vi work.txt <--'content 3' 추가
git commit -am 'work 3'
8. git log
여기까지가 초기 사용 설명서를 만드는 작업
이제부터 여러 고객사에게 서로 다른 내용의
사용설명서를 제공해야 하는 상황이다.
브랜치를 사용하지 않는다면 각 고객사 디렉터리를 만들고
manual 디렉터리를 복사해서 사용, 곧 문제가 발생
새 브랜치 만들기
이제부터 직접 브랜치를 만들면서 우아한 방법으로 어떻게 처리
하는지 알아보자. 여기서는 apple, google, ms 고객사 참여
1. git branch
깃에서 브랜치를 만들거나 확인하는 명령
* master
master는 특별한 브랜치
저장소를 만들 때 기본적으로 master 브랜치가 만들어짐
우리는 그동안 master브랜치에서 작업했던거임
2. git branch apple
새로운 브랜치를 만드는 명령
3. git branch
apple
* master
'*'표시는 아직 우리가 master브랜치에서 작업하고 있다는 뜻
4. git log
commit 3d0b8b91dc84d7a18c13.... (HEAD -> master, apple)
Author: jyk <call1212@nate.com>
Date: Thu Nov 4 19:15:48 2021 +0900
work 3
apple 브랜치가 추가되어 바뀜(HEAD -> master, apple)
이 표시는 저장소에 2개의 브랜치가 있고 HEAD-> master이므로
현재 작업 중인 브랜치는 master 브랜치라는 의미
5. git branch google
git branch ms
git branch
브랜치 사이 이동하기(git checkout)
브랜치를 여러 개 만들었으면 각 브랜치를 오가면서 작업할 수 있어야...
1. git log
commit 3d0b8b91dc84... (HEAD -> master, ms, google, apple)
work 3
이것은 master브랜치 뿐만 아니라 ms, google, apple브랜치가
work3 커밋 상태에서 만들어졌음을 의미 즉, 각 브랜치들의 최신
커밋이 'work3'라는 뜻
2. vi work.txt <-- 'master content 4' 추가 후 저장
git commit -am 'master content 4'
3. git log --oneline
--oneline옵션은 한 줄에 한 커밋씩 표시
057a8f3 (HEAD -> master) master content 4
3d0b8b9 (ms, google, apple) work 3
4a5e2f9 work 2
efdc4ae work 1
최신 커밋인'master content 4'는 master브랜치에만 적용
ms, google, apple브랜치는 아직 'work3' 커밋 상태
- 그래프로 나뭇가지처럼 한 눈에 볼 수 있음
4. git checkout apple
현재 브랜치(master)에서 다른 브랜치로 이동하면 어떻게 변하는지...
브랜치 이동 checkout 명령 + 이름 사용 'apple 브랜치로 체크아웃 한다'
happycom@happyCom/SRC/Git/manual (master)
happycom@happyCom/SRC/Git/manual (apple)
$
master에서 apple로 변경: 현재브랜치가 apple 이라는 뜻
5. git log --oneline
3d0b8b9 (HEAD -> apple, ms, google) work 3
4a5e2f9 work 2
efdc4ae work 1
최신 커밋 해시에서 HEAD가 apple을 가리킴
6. cat work.txt
content 1
content 2
content 3
최신 커밋이 work3 이기 때문에 세 개의 행만 존재
master브랜치에서 분기 이후에 master브랜치에 추가된 커밋은
apple 브랜치 즉, 분기된 브랜치에 영향을 미치지 않았음
03-3 브랜치 정보 확인
여기서는 여러 브랜치에서 각각 커밋이 이루어질 때 커밋끼리 어떤 관계를
하고 있는지 확인하는 방법과 브랜치 사이의 차이점을 확인하는 방법 공부
새 브랜치에서 커밋하기
apple 브랜치에 새로운 커밋
1. vi work.txt <-- 'apple content 4' 입력 저장
2. vi apple.txt <-- 'apple content 4' 입력 저장
실제 업무에서 apple 고객사만을 위한 내용이 담긴 파일
3. git add .
git commit -m 'apple content 4'
4. 윈도우 창으로 해당 경로(E:\Lecture\01.강의자료\SRC\Git\manual)의
폴더를 보면 각 브랜치로 ceckout 할 때마다 파일이 변경된다.
master브랜치는 apple.txt 파일이 존재하지 않음
5. git log --oneline
f0848a5 (HEAD -> apple) apple content 4
3d0b8b9 (ms, google) work 3
4a5e2f9 work 2
efdc4ae work 1
현재 apple브랜치에 체크아웃한 상태, apple브랜치의 최신 커밋은
'apple content 4'이다.
6. git log --oneline --branches
각 브랜치의 커밋이 함께 표시
f0848a5 (HEAD -> apple) apple content 4
057a8f3 (master) master content 4
3d0b8b9 (ms, google) work 3
4a5e2f9 work 2
efdc4ae work 1
7. git log --oneline --branches --graph
* f0848a5 (HEAD -> apple) apple content 4
| * 057a8f3 (master) master content 4
|/
* 3d0b8b9 (ms, google) work 3
* 4a5e2f9 work 2
* efdc4ae work 1
부모 커밋을 찾아보면 'work 3'커밋
그 이후에 분기
브랜치 사이의 차이점 알아보기
브랜치마다 커밋이 점점 쌓여갈수록 브랜치 사이에 어떤 차이가 있는지
일일이 확인하기 어렵다. 이럴 때 브랜치 이름 사이에 마침표 두 개(..)
를 넣는 명령으로 차이점을 쉽게 확인 가능
$ git log master..apple
마침표 왼쪽에 있는 브랜치를 기준으로 오른쪽 브랜치와 비교
이렇게 하면 master브랜치에는 없고 apple브랜치에는 있는 커밋,
즉, 'apple content 4' 커밋을 표시
반대로 apple 브랜치를 기준 master브랜치와 비교하면
'master content 4' 커밋을 보여준다.
$ git lig apple..master
03-4 브랜치 병합
만들어진 각 브랜치에서 작업을 하다가 어느 시점에서는 브랜치 작업을
마무리하고 기존 브랜치와 합해야 한다. 이것을 '브랜치 병합(merge)'
라고 함. 브랜치와 브랜치를 병합하다 보면 여러 상황이 생길 수 있는데
각 상황마다 병합하는 방법을 알아보자. 그리고 병합하면서 브랜치 사이에
충돌이 있을 때 해결하는 방법도 함께 살피자.
1. 서로 다른 파일 병합하기
1. git init manual-2
cd manual-2
ls -al
2. vi work.txt <--'1' 입력 저장
git add work.txt
git commit -m 'work 1'
3. git branch o2
'o2'라는 브랜치 생성
4. vi master.txt <--'master 2' 입력 저장
git add master.txt
git commit -m 'master work 2'
5. git checkout o2
6. vi o2.txt <--'o2 2' 입력 저장
git add o2.txt
git commit -m 'o2 work 2'
7. git log --oneline --branches --graph
* cbfb24f (HEAD -> o2) o2 work 2
| * 29b7823 (master) master work 2
|/
* 516ca0b work 1
8. git checkout master
o2브랜치에서 작업이 다 끝났다고 가정하고, o2브랜치의 내용을
master블랜치로 병합해 보자. 브랜치를 병합하려면 먼저
master브랜치로 체크아웃해야 한다.
9. git merge o2
브랜치를 병합하려면 merge 명령 뒤에 가져올 브랜치 이름
10.자동으로 편집기 실행 'Merge branch o2'라는 커밋 메시지가 표시
커밋메시지를 수정할 수도 있고, 그대로 사용해도 된다.
11.ls -al
o2브랜치에 있던 o2.txt파일이 master브랜치에 합쳐졌음
12.git log --oneline --branches --graph
* 096002b (HEAD -> master) Merge branch 'o2'
|\
| * cbfb24f (o2) o2 work 2
* | 29b7823 master work 2
|/
* 516ca0b work 1
브랜치와 커밋들의 병합 확인(Merge branch 'o2' 커밋 새로 생성)
참고| 브랜치 병합 시 편집기 창 제어
$ git merge o2 --no-edit
편집기 창 열지않고 깃 지정 메시지 사용
$ git merge o2 --edit
커밋 메시지를 추가하거나 수정하고 싶을 때
2. 같은 문서의 다른 위치를 수정했을 때 병합하기
master 브랜치와 o2브랜치에는 똑같이 work.txt파일이 존재
양쪽 브랜치에서 work.txt문서를 수정하되 다른 위치를 수정한 후
브랜치를 병합했을 때 어떤 결과가 나오는지 확인하자
1. git init manual-3
cd manual-3
ls -al
2. vi work.txt
3. git add work.txt
git commit -m 'work 1'
4. git branch o2
5. vi work.txt
# title
content
master content 2
...
6. git commit -am 'master work 2'
8. git checkout o2
vi work.txt
...
# title
content
o2 content 2
** 같은 파일이지만 서로 다른 줄을 수정함!!!
9. git commit -am 'o2 work 2'
10.git checkout master
master브랜치와 o2브랜치 양쪽에서 work.txt 파일을 수정했지만
문서 안의 수정 위치는 다르다.
11.git merge o2
'Auto-merging work.txt'
12.cat work.txt
3. 같은 문서의 같은 위치를 수정했을 때 병합하기
깃에서는 줄 단위로 변경 여부를 확인, 그래서 각 브랜치에 같은 파일
이름을 가지고 있으면서 같은 줄을 수정했을 때 브랜치를 병합하면
브랜치 충돌(conflict)이 발생한다.
어떻게 해결해야 할까?
1. git init manual-4
cd manual-4
ls -al
2. vi work.txt
3. git add work.txt
git commit -m 'work 1'
4. git branch o2
5. vi work.txt
# title
content
master content 2
...
6. git commit -am 'master work 2'
7. git checkout o2
vi work.txt
# title
content
o2 content 2 <--- '같은 위치 수정'
...
8. git commit -am 'o2 work 2'
9. git checkout master
master브랜치와 o2브랜치 양쪽에서 work.txt파일을 수정했는데
문서 안의 수정 위치가 같다.
10.git merge o2
충돌이 생긴 문서는 자동으로 병합될 수 없으므로 사용자가 직접 충돌
부분을 해결한 후 커밋해야 한다.
11.vi work.txt
# title
content
<<<<<<< HEAD
master content 2 -----> 현재 브랜치에서 수정한 내용
=======
o2 content 2 ---------> 병합할 브랜치에서 수정한 내용
>>>>>>> o2
# title
content
양쪽 브랜치의 내용을 참고하면서 직접 내용을 수정해야 한다.
# title
content
o2 content 2
# title
content
12.git commit -am 'merge o2 branch'
이제 수정한 work.txt를 커밋하면 됨
이렇게 해서 o2 브랜치에서 병합한 work.txt의 충돌을 해결하고 병합
13.git log --oneline --branches --graph
* ebb812c (HEAD -> master) merge o2 branch
|\
| * effb0be (o2) o2 work 2
* | c6d4d47 master work 2
|/
* dcccb13 work 1
참고| 병합 및 충돌 해결 프로그램
프로젝트 규모가 클수록 브랜치가 많아 병합해야 할 일도 많다. 그만큼 충돌이
많이 발생, 그래서 깃의 블랜치 병합을 자동으로 처리해 주고 충돌을 해결해 주는
프로그램이 많다. 다음은 자주 사용하는 병합 자동화 프로그램이다.
P4Merge 무료/단축키 지원안됨
Meld 무료/오픈소스
Kdiff3 무료/한글깨짐
Araxis Merge 유료
병합이 끝난 브랜치 삭제하기
브랜치를 병합한 후 더 이상 사용하지 않는 브랜치는 깃에서 삭제 가능
1. git branch
2. git checkout master
3. git branch -d o2
브랜치를 삭제할 때는 -d 옵션
git branch
4. 삭제한 브랜치는 같은 이름으로 다시 브랜치를 만들면 예전에 작업했던
내용이 그대로 표시 즉, 브랜치를 삭제한다는 것은 완전히 저장소에서
없애는 것이 아니라 깃의 흐름 속에서 감추는 것
03-5 브랜치 관리
브랜치에서 checkout과 reset의 작동 원리
먼저 HEAD와 브랜치의 개념
1. git init test
cd test
2. vi c1.txt <-- '1'입력 저장
git add c1.txt
git commit -m 'c1'
3. git log
(HEAD->master)표시:
여기에서 HEAD는 현재 작업트리(워킹디렉터리)가 어떤 버전을 기반으로
작업 중인지를 가리키는 포인터이다. 그리고 브랜치는 기본적으로 브랜치에
담긴 커밋 중에서 가장 최근의 커밋을 가리킨다.
4. git branch sub
sub브랜치 또한 c1 커밋을 가리킴
5. vi c2.txt <-- '2' 입력 저장
git add c2.txt
git commit -m 'c2'
이제 master는 c2커밋을 가리키고 HEAD는 그대로 master 브랜치를 가리킴
6. git checkout sub
브랜치 이동을 위한 checkout 명령은 HEAD가 가리키는 것을 제어
HEAD가 sub브랜치를 가리킴
7. vi s1.txt <-- 's1' 입력 저장
git add s1.txt
git commit -m 's1'
이제 HEAD는 sub브랜치를 가리키고 sub는 s1 커밋을 가리킴
8. 브랜치가 여러 개 일때 reset 명령은 어떻게 사용?
앞에서는 reset명령으로 master브랜치에 있던 여러 커밋 중 하나를 골라서
되돌아감. 브랜치가 여러개일 때는 현재 브랜치가 아닌 다른 브랜치에 있는
커밋을 골라서 최신 커밋으로 지정할 수 있다.
예를 들어 sub브랜치에 있는 상태에서 master브랜치에 있는 c2 커밋을
sub브랜치의 최신 커밋으로 지정할 수 있다.
먼저 해시확인..
git log --oneline --branches
ce7d26c (HEAD -> sub) s1
f3ef1d1 (master) c2
6c10d32 c1
9. git reset f3ef1d1
c2 커밋의 해시를 입력
10.git log --oneline --branches --graph
* f3ef1d1 (HEAD -> sub, master) c2
* 6c10d32 c1
sub브랜치의 최신 커밋이 master브랜치의 최신 커밋인 c2로 바뀜
이렇게 git reset 명령을 사용하면 현재 브랜치가 가리키는 커밋을
여러 브랜치 사이를 넘나들면서 제어할 수 있다.
이제 sub브랜치는 c2커밋을 가리키고 있기 때문에 원래 가리키고 있던
s1 커밋은 연결이 끊기면서 삭제 된다.
git checkout 명령을 사용하면 HEAD를 제어해서 브랜치를 이동할 수 있다.
git reset 명령을 사용하면 HEAD가 가리키고 있는 브랜치의 최신 커밋을
원하는 커밋으로 지정할 수 있다. 이때 어떤 브랜치에 있는 커밋이든 지정할
수 있으며, 명령을 수행한 뒤 브랜치와 연결이 끊긴 커밋은 삭제 된다.
수정 중인 파일 감추기 및 되돌리기(git stash)
stash : 따로 떼어 감춰, 간수한다.
브랜치에서 파일을 수정하고 커밋하지 않은 상태에서 급하게 다른 파일을
커밋해야 할 경우 아직 커밋하지 않은 파일들을 그냥 두어도 상관없지만
계속 커밋하라는 메시지가 나타나 번거로움
실수로 다른 파일과 함께 커밋이 될 수도... 이럴때 아직 커밋하지 않고
작업 중인 파일들을 잠시 감춰둘 수 있다. 그리고 당장 필요한 작업들을
끝낸 후 다시 감춰둔 파일들을 꺼내오면 됨
1. git init st
cd st
2. vi f1.txt
git add f1.txt
git commit -m 'f1'
git stash 명령을 사용하려면 파일이 tracked 상태여야 한다. 즉 한 번은
커밋한 상태여야 함.
3. vi f2.txt
git add f2.txt
git commit -m 'f2'
4. vi f1.txt 수정
vi f2.txt 수정
5. git status
Changes not staged for commit:
modified: f1.txt
modified: f2.txt
6. git stash
Saved working directory and index state WIP on master: fb55dfc f2
이제 f1.txt 파일과 f2.txt 파일을 커밋하기 전에 다른 파일을 수정해야
한다고 가정하자. 커밋하지 않은 수정 내용을 어딘가에 보관하려면
git stash 명령을 사용한다.
7. git status
nothing to commit, working tree clean
조금 전에 표시되었던 modified 메시지가 사라짐
8. git stash list
stash@{0}: WIP on master: fb55dfc f2
같은 방법으로 여러 파일을 수정한 후 따로 보관 가능, 이렇게 감춘 파일들은
stash목록에서 확인. 가장 먼저 감춘 것은 stash@{0}에 들어있는데, 앞으로
다른 파일이 추가되면 기존 파일은 stash@{1}로 옮겨지고 새로 추가된 파일은
stash@{0}에 담긴다. 즉 가장 최근에 보관한 것이 stash@{0}에 담긴다. 스택(stack)
9. git stash pop
Changes not staged for commit:
modified: f1.txt
modified: f2.txt
급한 작업을 모두 마쳤다면 감춰둔 파일을 꺼내와 계속 수정하거나 커밋
stash pop 명령은 stash 목록에서 가장 최근 항목을 되돌린다. 여기에서는
f1.txt 와 f2.txt가 수정된 상태로 되돌아간다.
댓글