Git과 CLI (4) - CLI로 체크아웃과 병합 하기
브랜치 체크아웃 및 새 커밋 작성
이전 장에서 만든 mybranch1 브랜치로 체크아웃하고, 새로운 커밋을 생성한 뒤에 결과를 확인한다.
yegang@yegangs:~/hello-git-cli$ git branch
* master
mybranch1
# 현재 HEAD 브랜치는 `master`이다. 이제 mybranch1로 체크아웃한다.
yegang@yegangs:~/hello-git-cli$ git checkout mybranch1
Switched to branch 'mybranch1'
# git checkout [브랜치명] 으로 체크아웃했다.
yegang@yegangs:~/hello-git-cli$ git branch
master
* mybranch1
# HEAD가 mybranch1로 이동한 것을 확인할 수 있다.
yegang@yegangs:~/hello-git-cli$ git log --oneline --all
7240873 (HEAD -> mybranch1, origin/master, master) Second
commit
f3d91a3 First commit
# HEAD 변경 확인
yegang@yegangs:~/hello-git-cli$ cat file1.txt
hello test
second
# 파일 내용 확인
yegang@yegangs:~/hello-git-cli$ echo "third - mybranch1" >> file1.txt # 파일에 내용 추가
yegang@yegangs:~/hello-git-cli$ cat file1.txt
hello test
second
third - mybranch1
# 파일 내용 확인. third 내용을 추가했다.
yegang@yegangs:~/hello-git-cli$ git status
On branch mybranch1
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: file1.txt
no changes added to commit (use "git add" and/or "git commit -a")
# 스테이지 상태를 확인한다. 하나의 파일이 변경되었다.
yegang@yegangs:~/hello-git-cli$ git add file1.txt # 스테이지에 변경사항을 추가했다.
yegang@yegangs:~/hello-git-cli$ git commit -m "mybranch1의 첫 번째 커밋"
[mybranch1 0e4f33b] mybranch1의 첫 번째 커밋
1 file changed, 1 insertion(+)
# 커밋메시지와 함께 커밋을 추가했다.
yegang@yegangs:~/hello-git-cli$ git log --oneline --all
0e4f33b (HEAD -> mybranch1) mybranch1의 첫 번째 커밋
7240873 (origin/master, master) Second commit
f3d91a3 First commit
# 커밋 히스토리를 확인한다.커밋 히스토리를 확인하면, master 브랜치는 '7240873'을 가리키고, mybranch1 브랜치는 '0e4f33b'을 가리킨다.
이제 master 브랜치로 병합을 하기 위해서는 먼저 master 브랜치로 체크아웃을 한 다음에 master 브랜치와 mybranch1 브랜치를 병합한다. 우선 mybranch1 브랜치에서 추가로 한 번 더 커밋을 하겠다.
yegang@yegangs:~/hello-git-cli$ echo "fourth - mybranch1" >> file1.txt
yegang@yegangs:~/hello-git-cli$ cat file1.txt
hello test
second
third - mybranch1
fourth - mybranch1우선 file1.txt에 "fourth - mybranch1" 내용을 추가하였다.
git status 명령으로 스테이지 상태를 확인해 보겠다. 내용이 변경되었으나 스테이지되지 않은 file1.txt 내용이 확인되어야 한다.
yegang@yegangs:~/hello-git-cli$ git status
On branch mybranch1
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: file1.txt
no changes added to commit (use "git add" and/or "git commit -a")'modified: file1.txt' 내용이 확인된다. 이제 스테이지에 파일을 추가하고 커밋해 보겠다.
yegang@yegangs:~/hello-git-cli$ git add file1.txt
yegang@yegangs:~/hello-git-cli$ git commit -m "mybranch1의 두 번째 커밋"
[mybranch1 db8ebff] mybranch1의 두 번째 커밋
1 file changed, 1 insertion(+)커밋되었다. 이제 git log 명령을 이용하여 커밋로그를 확인해 보겠다.
yegang@yegangs:~/hello-git-cli$ git log --oneline --all --graph --decorate
* db8ebff (HEAD -> mybranch1) mybranch1의 두 번째 커밋
* 0e4f33b mybranch1의 첫 번째 커밋
* 7240873 (origin/master, master) Second commit
* f3d91a3 First commitHEAD가 mybranch1의 두 번째 커밋을 가리키고 있다. 그리고 mybranch1에서 2개의 커밋 내용도 확인되고 있다. 다음으로는 master 브랜치의 2개의 커밋 내용이 확인된다.
Fast-Forward 병합하기
이제 mybranch1에서 두 개의 커밋을 작성하였으니, master 브랜치로 이동하여 병합을 하려고 한다. master 브랜치로 이동하기 위해 git checkout 명령을 사용한다.
yegang@yegangs:~/hello-git-cli$ git checkout master
Switched to branch 'master'
Your branch is up to date with 'origin/master'.`성공적으로 체크아웃되었다. 이전과는 다르게 'Your branch is up to date with 'origin/master' .' 라는 내용이 추가되었다. 이게 무슨 내용이냐면, "원격 저장소와 현재 로컬 저장소 브랜치가 모두 최신 상태로 동일하다"는 뜻이다. 아까전에 mybranch1을 만들어서 checkout 했을 때 표시되지 않았던 이유는 원격 저장소에 없는 브랜치를 만들었기에 표시되지 않은 것이다.
이제 file1.txt 파일을 열어보겠다. mybranch1에서 추가한 커밋 2개는 아직 보이지 않을 것이다.
yegang@yegangs:~/hello-git-cli$ cat file1.txt
hello test
second예상대로 파일이 이전 버전으로 돌아갔다. 왜냐하면 새로 추가한 두 개의 내용은 mybranch1에만 존재하기 때문이다. 이제 mybranch1의 내용을 master로 병합해 보겠다. 병합은 git merge 명령을 애용하여 병합한다. 이 명령은 현재 브랜치로 대상 브랜치를 병합시키는 명령이다.
yegang@yegangs:~/hello-git-cli$ git merge mybranch1
Updating 7240873..db8ebff
Fast-forward
file1.txt | 2 ++
1 file changed, 2 insertions(+)병합이 성공적으로 완료되었다. 'Fast-forward'는 "빨리감기"를 의미한다. 작업의 흐름이 하나였기 때문이 빨리감기 병합으로 완료된다.
로그를 확인하면 HEAD가 master를 가리키고, 아까 mybranch1의 최신 커밋 내용이 반영되어 있을 것이다.
yegang@yegangs:~/hello-git-cli$ git log --oneline --graph --all
* db8ebff (HEAD -> master, mybranch1) mybranch1의 두 번째 커밋
* 0e4f33b mybranch1의 첫 번째 커밋
* 7240873 (origin/master) Second commit
* f3d91a3 First commit예상대로 HEAD는 master를 가리킨다. 그런데 왜 mybranch1이 그대로 남아 있을까? 그건 mybranch1을 생성하고 커밋을 올리고 병합하였지만 mybranch1을 삭제하지 않았기 때문에 여전히 mybranch1이 남아 있는 것이다. 추후 해당 브랜치로 이동을 할 수 있게끔 말이다.
그렇다면 정말로 병합이 잘 되었는지 file1.txt 파일을 확인해 보겠다.
yegang@yegangs:~/hello-git-cli$ cat file1.txt
hello test
second
third - mybranch1
fourth - mybranch1third, fourth 내용이 다 들어있으니 정상적으로 병합이 된 것을 확인할 수 있다.
hard reset으로 브랜치 되돌리기
온라인 게임을 즐기거나 서버 운영 경험이 있다면 '하드 리셋' 이라는 단어에 익숙할 것이다. git에서 hard reset은 현재 브랜치를 특정 커밋으로 되돌릴 때 사용한다. 명령은 git reset --hard <커밋체크섬> . 이 명령을 실행하면 현재 브랜치를 지정한 커밋으로 옮긴 후 해당 커밋의 내용을 작업 폴더에도 반영한다.
그러나 이 명령을 사용하기 위해서는 반드시 커밋 체크섬을 알아야 한다. git log를 통해 커밋 체크섬을 확인하는 방법도 나쁘진 않지만, HEAD~ 또는 HEAD^로 시작하는 약칭을 사용할 수 있다.
HEAD~<숫자>: 헤드의 부모 커밋, HEAD~2는 헤드의 할아버지 커밋을 말한다. HEAD~n은 n번째 위쪽 조상이라는 뜻이다.HEAD^<숫자>: 헤드의 부모 커밋이다. 다만 HEAD^2는 두 번째 부모를 뜻한다. 병합 커밋처럼 부모가 둘 이상인 커밋에게만 의미가 있다.
우선 master를 두 커밋 이전 커밋으로 옮겨 보겠다.
yegang@yegangs:~/hello-git-cli$ git reset --hard HEAD~2
HEAD is now at 7240873 Second commit
yegang@yegangs:~/hello-git-cli$ git log --oneline --graph --all --decorate
* db8ebff (mybranch1) mybranch1의 두 번째 커밋
* 0e4f33b mybranch1의 첫 번째 커밋
* 7240873 (HEAD -> master, origin/master) Second commit
* f3d91a3 First commit
yegang@yegangs:~/hello-git-cli$ cat file1.txt
hello test
second # 두 커밋 이전의 내용log 명령을 확인하자 HEAD가 가리키는 커밋이 '7240873'가 된 것을 확인할 수 있다.
여기서 한 가지 의문이 들 수 있다. reset --hard 명령과 checkout 명령과 비슷하다고 느껴질 것이다. 다만 차이가 있다면 checkout을 하는 경우 master 브랜치는 그 자리에 그대로 있고 HEAD 포인터만 옮겨지는 것이다. 그래서 결국 master 브랜치와 HEAD를 연결하기 위해서는 아래의 명령을 입력하면 된다. 결국 reset --hard 명령은 아래 세 줄의 명령을 수행하는 것이다.
git checkout HEAD~2
git branch -f master
git checkout master빨리감기 병합 상황에서 rebase
git rebase <대상브랜치> 명령은 현재 브랜치에만 있는 새로운 커밋을 대상 브랜치 위로 재배치시킨다. 그런데 현재 브랜치에 재배치할 커밋이 없을 경우 rebase는 아무런 동작을 하지 않는다. 또한 빨리감기 병합이 가능한 경우에는 rebase 명령을 수행하면 빨리감기 병합을 한다.
우선 mybranch1로 checkout 한 뒤, master 브랜치 위로 재배치(rebase)시켜 보겠다.
yegang@yegangs:~/hello-git-cli$ git checkout mybranch1
Switched to branch 'mybranch1'
# 체크아웃
yegang@yegangs:~/hello-git-cli$ git rebase master
Current branch mybranch1 is up to date.
# 리베이스
yegang@yegangs:~/hello-git-cli$ git rebase master
Current branch mybranch1 is up to date.
yegang@yegangs:~/hello-git-cli$ git log --oneline --all
db8ebff (HEAD -> mybranch1) mybranch1의 두 번째 커밋
0e4f33b mybranch1의 첫 번째 커밋
7240873 (origin/master, master) Second commit
f3d91a3 First commit리베이스를 시도하였지만 아무런 변화가 없다. 왜나하면 mybranch1 브랜치는 이미 master 브랜치 위에 있기 때문에 재배치할 커밋이 없기 때문이다.
그렇다면 master 브랜치로 체크아웃 한 뒤 반대 방향에서 리베이스해 보겠다.
yegang@yegangs:~/hello-git-cli$ cat file1.txt
hello test
second
# 두 커밋 전의 내용이 담겨 있다.
yegang@yegangs:~/hello-git-cli$ git rebase mybranch1
Successfully rebased and updated refs/heads/master.
# 리베이스
yegang@yegangs:~/hello-git-cli$ cat file1.txt
hello test
second
third - mybranch1
fourth - mybranch1
# 변경 사항 확인 결과 빨리감기 병합이 된 것을 확인하였다.
yegang@yegangs:~/hello-git-cli$ git log --oneline --decorate --all --graph
* db8ebff (HEAD -> master, origin/master, mybranch1) mybra
nch1의 두 번째 커밋
* 0e4f33b mybranch1의 첫 번째 커밋
* 7240873 Second commit
* f3d91a3 First commit
# HEAD는 master로 최신 커밋을 가리키고 있으나, 여전히 mybranch1 브랜치가 남아 있다.이제 변경된 내용을 원격저장소로 push해 보겠다.
yegang@yegangs:~/hello-git-cli$ git push
Enumerating objects: 8, done.
Counting objects: 100% (8/8), done.
Delta compression using up to 4 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (6/6), 607 bytes | 607.00 KiB/s, done.
Total 6 (delta 0), reused 0 (delta 0), pack-reused 0
To https://github.com/yeganghwang/hello-git-cli.git
7240873..db8ebff master -> master다음으로 mybranch1 브랜치를 삭제해 보겠다.
yegang@yegangs:~/hello-git-cli$ git branch -d mybranch1
Deleted branch mybranch1 (was db8ebff).
# 브랜치가 삭제되었다. 이제 git log 명령으로 로그롤 확인하면 mybranch1이 확인되지 않을 것이다.
yegang@yegangs:~/hello-git-cli$ git log --oneline --decorate --all --graph
* db8ebff (HEAD -> master, origin/master) mybranch1의 두 번째 커밋
* 0e4f33b mybranch1의 첫 번째 커밋
* 7240873 Second commit
* f3d91a3 First commit
# 정상적으로 브랜치가 삭제되어 표시되지 않는다.배포 버전에 태그 넣기
태그는 주석 있는 태그와 간단한 태그 두 종류가 있다. 일반적으로 주석 있는 태그의 사용을 권장하기 때문에 주석 있는 태그를 사용해 보겠다.
git tag -a -m <간단한 메시지> <태그 이름> [브랜치 또는 체크섬]: -a로 주석 있는 태그를 생성한다. 메시지와 태그 이름은 필수이며 브랜치 이름을 생략하면 HEAD에 태그를 생성한다.git push <원격저장소 별명> <태그 이름>: 원격 저장소에 태그를 업로드한다.
먼저 로그를 확인해 보겠다.
yegang@yegangs:~/hello-git-cli$ git log --oneline -n1
db8ebff (HEAD -> master, origin/master) mybranch1의 두 번째 커밋이제 태그를 작성해 보겠다.
yegang@yegangs:~/hello-git-cli$ git tag -a -m "첫 번째 태그 생성" v0.1git log 명령을 이용하여 태그 생성을 확인해 보겠다.
db8ebff (HEAD -> master, tag: v0.1, origin/master) mybranc
h1의 두 번째 커밋tag: v0.1이 정상적으로 표시된다. 이제 태그를 푸시할 수 있다.
yegang@yegangs:~/hello-git-cli$ git push origin v0.1
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 189 bytes | 189.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0
To https://github.com/yeganghwang/hello-git-cli.git
* [new tag] v0.1 -> v0.1태그는 차후에 커밋을 식별할 수 있는 유용한 정보이기 때문이 잘 활용하는 것이 좋다. 태그를 사용하면 GitHub의 Tags 탭에서 확인할 수 있고, Release 탭에서 다운받을 수도 있다.
댓글
댓글 쓰기