주말을 맞아 인프런 Github 강의를 달리고 있다. 2시간 23분밖에 안되는 데다가 이미 아는 부분들도 있어서 후딱 끝낼 수 있을 것 같다. 이 포스팅은 소스트리로 깃허브를 사용하는 법에 강한 강의를 듣고 내용을 정리한 글이다.
▶ 인프런 git과 github 강의 - by 코드스쿼드 정호영님
https://www.inflearn.com/course/git-and-github#
▶ 강의 자료 :
https://nextstep.camp/courses/-L6-ES5-WFWp9mKmOhE-/-L6-Em9DxKW0ylqc_PuX/lessons/-L6-Ep2TpwnVg2Qwtx_c
Ⅰ. 병합(merge)
1. 브랜치 변경하기
- 브랜치란 : 기존 내용을 유지한 채 새로운 내용을 추가하고 싶을 때 사용한다.
- 체크아웃 : 특정 브랜치로 돌아가고 싶을 때 사용한다. '이 브랜치에서 작업할게요' 같은 느낌.
- 소스트리의 체크아웃 : 브랜치 이름을 더블클릭하면 된다.
- 브랜치 : 아래와 같이 master에 6개의 커밋이 있다고 치자. 6번째 커밋이 뭔가가 맘에 안들거나 기타 등의 이유로 5번째 커밋까지만 작업한 상태로 돌아가서 다른 작업을 하고 싶다면, 브랜치를 만들면 된다. 소스트리에서 5번째 커밋을 선택한 후 '브랜치' 누르면 된다. 예를 들어 5번째 커밋 선택 후 '브랜치' 눌러서 'version2'라는 브랜치를 생성했다고 치자. 소스트리에서 'version2'를 더블클릭하고 VSCode에서 파일을 확인하면 파일이 5번째 커밋까지만 반영된 상태로 되어 있는 것을 볼 수 있다. 이렇게 다른 브랜치에서 작업을 하는 것을 checkout이라고 한다.
- HEAD 브랜치 : '현재 작업중인 브랜치'를 말한다.
ex) 예를 들어 원래 master 브랜치에서 작업하고 있다가 testing이라는 브랜치로 checkout하면 head 브랜치는 testing이 된다.
$ git checkout testing
- 브랜치가 생성되고 브랜치에서 다른 작업을 하면 위와 같이 핑크색의 분기된 아이(브랜치)를 볼 수 있다. 정말 가지친 것 같이 생겨서 브랜치라고 부르는 것....
- master : 최종본.
- 브랜치에서 작업하고 master는 최종본.
- 브랜치와 master의 내용을 합치는 것을 merge라고 한다.
2. Git 브랜치 병합(merge)하기
1) 병합(merge)이란?
- 하나의 브랜치를 현재 브랜치와 합치는 것.
- ex) 헤드 브랜치(현재 브랜치)가 master이고 여기에 version2 브랜치를 병합
==> version2의 내용이 master에 반영됨.
- https://learngitbranching.js.org/에 들어가면 브랜치들을 머지하는 것을 시각화해서 볼 수 있다.
(아래 이미지들은 저 싸이트 캡쳐한 것.)
1-1) fastforward
- master와 브랜치에서 충돌나는 부분 없이 단순히 하나가 더 앞서있는(몇 개의 커밋이 더 있는) 경우.
- 아무 문제 없이 머지된다.
1-2) fastforward 아닌 경우
- 문제없이 머지되는 경우도 있으나, 충돌날 때도 있다.
<충돌 원인>
- 과거의 커밋에서 브랜치 생성해서 작업했을 때
- 새로운 브랜치 작업 이후에 헤드에 다른 새로운 커밋이 있을 때
- 여러 브랜치를 동시에 작업하면서 머지하려고 할 때.. 등등
<충돌했을 때>
- 소스트리에서 master 더블클릭해서 체크아웃 > branch 우클릭해서 '병합' 선택 > 아래와 같이 충돌났다는 창이 뜨고,충돌난 파일이 '스테이지에 올라간 파일' 영역에도 있고 '스테이지에 올라가지 않은 파일' 영역에도 동시에 존재하며 파일명 좌측에 느낌표가 뜬다.
- 이럴 경우 수동으로 충돌난 부분 수정해줘야한다. ㅠㅠ
- VSCode에서 'Accept Current Change', 'Accept Incoming Change' 등등 원하는 옵션 선택해서 해결하면 된다.
- 아니면 VSCode에 옵션 선택 안 하고 그냥 수동으로 파일 수정해줘도 된다.
- 충돌난 파일을 수정한 후, 소스트리로 돌아와서 위의 그림의 '모두 스테이지 올리기' 클릭 > 커밋한다.
- 잘 병합(merge)되었음을 확인할 수 있다.
Ⅱ. pull
1. Pull
- pull = fetch + merge
<pull과 fetch의 차이점?>
1) pull
- 원격 저장소로부터 필요한 파일을 다운 + 병합
- 지역 브랜치와, 원격 저장소 origin/master 가 같은 위치를 가리킨다.
2) fetch
- 원격 저장소로부터 필요한 파일을 다운 (병합은 따로 해야 함)
==> 단순히 원격 저장소의 내용을 확인만 하고 로컬 데이터와 병합은 하고 싶지 않은 경우
- 지역 브랜치는 원래 가지고 있던 지역 저장소의 최근 커밋 위치를 가리키고, 원격 저장소 origin/master는 가져온 최신 커밋을 가리킨다.
- 신중할 때 사용한다.
3) fetch를 사용하는 이유?
- 원래 내용과 바뀐 내용과의 차이를 알 수 있다 (git diff HEAD origin/master)
- commit이 얼마나 됐는지 알 수 있다 (git log --decorate --all --oneline)
- 이런 세부 내용 확인 후 git merge origin/master 하면 git pull 상태와 같아진다. (병합까지 완료)
Ⅲ. reset을 이용한 커밋 되돌리기
- reset을 이용해서 커밋을 되돌리면, 쉽지만 커밋이 날아간다. (취소한 커밋을 다시 가져올 수는 있으나 번거롭다.)
- 또한, 강제 푸시가 필요하다.
- reset은 권장하지 않는 방법이다.
<SourceTree에서 reset 을 이용해서 커밋 되돌리는 법>
- 되돌리고 싶은 지점을 클릭 > 우클릭 > '이 커밋까지 현재 브랜치를 초기화' > '커밋 초기화' 창이 뜨면 'Hard - 모든 작업 상태 내 변경사항을 버림' 선택, 확인 버튼 클릭 > 경고창 Yes 선택 > 터미널 열어서 강제푸시 해줘야함ㅋ (git push --force) (아래 이미지 참고)
(아마도 터미널에 익숙하지 않은 분들이 SourceTree를 쓰실텐데... 터미널로 강제푸시 해줘야만 하면 SourceTree를 쓰는 의미가 없는 것 같다.)
<충돌 해결 방법>
- '스테이지에 올라가지 않은 파일' 선택 > 우클릭 > 충돌해결 > '내것'을 이용해 해결 또는 '저장소' 것을 사용하여 해결 버튼 두 개 중, 원하는 것을 선택하여 클릭 (아래 이미지 참고)
<Reset의 종류>
Mode | HEAD의 위치 | Index | Working Tree (작업트리) |
Soft | 변경O | 변경X | 변경X |
Mixed | 변경O | 변경O | 변경X |
Hard | 변경O | 변경O | 변경O |
- 1) Soft : 커밋만 되돌리고 싶을 때
- 2) Mixed : 변경한 인덱스의 상태를 원래대로 돌리고 싶을 때
- 3) Hard : 최근 커밋을 완전히 버리고 이전의 상태로 되돌리고 싶을 때
Ⅳ. 브랜치를 만들어서 커밋 되돌리기
- 장점 : 쉽다. reset과 다르게 내용이 사라지지 않는다.
- 단점 : 트리가 지저분해진다. (큰 단점은 아님)
Ⅴ. Revert 를 이용해서 커밋 되돌리기
- Revert : 선택한 커밋 하나의 변경사항을 되돌리는 새로운 커밋을 생성하는 것
- Revert로 여러개의 커밋을 되돌리고 싶으면 최신 커밋부터 순서대로 revert를 반복하면 됨.
- 장점 : 가장 정석적이다. 되돌리기 이전의 내용을 볼 수 있다.
- 단점 : 충돌이 날 수 있다.
<소스트리에서 revert 하는 법>
- 커밋 선택 > 우클릭 > 커밋 되돌리기
<터미널로 revert 하는 법>
- git revert HEAD : 최신 커밋을 되돌려라
- git revert HEAD HEAD ~ : 헤드와 헤드아빠를 두 개의 커밋을 되돌려라
Ⅵ. Stash
- stash : 다른 브랜치로 체크아웃하기 전에 현재 작업내용을 저장하는 임시 저장소
<작업 중인 내용을 임시 저장하는 법>
1. 브랜치1에서 임시로 커밋을 한다.
2. 브랜치2로 checkout하고 할 일 한다
3. 다시 브랜치1로 되돌아 온다
4. 1의 작업을 이어서 마무리 짓는다.
5. 커밋 덮어쓰기 (commit --amend) 한다.
6. (옵션) 필요하다면 강제 푸시(push --force)한다.
<Stash를 이용해서 같은 작업 하기>
1. Stash를 만든다.
2. 새로운 파일이 있었다면 일단 인덱스에 추가한다.
3. 체크아웃
4. 되돌아온다
5. Stash를 pop 한다.
6. 보통 커밋을 새로 생성한다.
Ⅶ. Rebase
- Rebase : merge처럼 두 브랜치를 합칠 때 사용.
- 현재 브랜치가 대상 브랜치 위로 올라간다.
- 위험하니 조심해서 사용해야함.
- Rebase > 충돌 남 > 충돌 해결 > add 후 git rebase --continue 해야함
- Rebase 취소하려면 git rebase --abort
기타
1. 로컬 저장소 깃허브 연동 해제
- 파일 탐색기 > 보기 탭 > '숨긴 항목'을 체크하면 숨겨져있는 파일들이 보이게 된다.
- 깃으로 관리되고 있는 폴더에는 숨겨진 '.git' 폴더가 있는데, 이 폴더를 삭제하면 더 이상 해당 폴더는 깃허브로 관리되지 않는다.
2. 기타 주의사항
- 코드를 남기려고 주석을 달지 마라.
- 커밋 메시지를 잘 써라.
- 한가지 구현이 완료될 때마다 커밋하자. (자주 하자)
- 첫 줄에 요약
- 한 줄 띄우고 자세하게 내용을 적자.
3. 머지 실패
- 에러메시지
hint : Updates were rejected because the tip of your current branch is behind
hint : its remote counterpart. Integrate the remote changes before pushing again.
- https://codewithhugo.com/fix-git-failed-to-push-updates-were-rejected/
- master가 브랜치에서 push/pull 둘 다 해야할때 발생하는듯...
- 조금 더 자세하게 쓰고 싶은데 새벽이라 너무 졸려서 못 쓰겠다. 내일 자고 일어나서 다시 써야겠다.
4. 내가 놓치고 있었던 개념들
- origin은 '리모트 저장소'를 말한다.
- 프로젝트를 clone한 뒤, github 싸이트에서 브랜치(리모트 브랜치)를 만든 후에 로컬에서 작업을 해왔었기에, 내 로컬에만 생성되고 리모트에는 생성되지 않은 브랜치가 있을 수도 있다는 걸 생각도 못했었다. 5번을 알아보다가 알게 되었는데, 왜 이걸 생각을 못했지 하고 신기했다.
5. 소스트리에서 원격 브랜치 만드는 방법
- 내가 본 인강에서 알려준대로 소스트리에서 브랜치를 만들었더니 Github 웹사이트에서는 새로 만든 브랜치가 안 나와서 너무 궁금했다. 너무 궁금해서 잠이 안 와서 뒤적거리다가 왜 그런지 알아냈다.
- 소스트리에서 아래와 같이 진행해서 브랜치를 생성하면 내 로컬에 브랜치가 생성된다. 즉, 리모트 브랜치는 또 따로 생성해주어야 한다는 것. 아래와 같이 좌측메뉴에서 origin 우클릭 > 'origin으로 푸시' 해서 리모트 브랜치를 생성하면 된다. 자세한 방법은 아래 이미지와 같다.
- 예를 들어 아래와 같이 SourceTree에서 '브랜치' 버튼을 눌러서 'test' 브랜치를 만들었다. 이 'test' 브랜치는 '로컬'에 만들어진다.
- 소스트리 브랜치 목록에서도 'test' 브랜치가 '로컬' 브랜치로 나오고, 당연히 Github 싸이트에도 브랜치가 나타나지 않는다.
- 소스트리 좌측의 '원격' 아래에 있는 'origin'을 우클릭 > 'origin으로 푸시' 선택 > 푸시할 브랜치에서 'test'를 선택해준다. 만약 우측의 '리모트 브랜치'라고 되어 있는 텍스트필드가 비어있다면 로컬 브랜치명과 동일하게 적어준다. (이 경우에는 'test') > push 버튼 클릭
- 이제 SourceTree에서도 Github에서도 원격저장소 test가 생성된 것을 확인할 수 있다.
결론
<SourceTree의 장점>
- Git에 처음 입문할 때 브랜치가 어떻게 나오는지 직관적으로 쉽게 이해할 수 있어 보인다.
- 커맨드창이 아니므로 입문자에게 부담이 덜하다.
<SourceTree의 단점>
- 변경사항이 발생 후 화면에 반영되지 않아서 (새로고침이 안 된다고 해야하나) 창 X 누르고 새 창을 켜야 하는 경우가 있다. 번거로웠다.
- SourceTree만 써서 해결할 수 없는 상황이 있다. (ex. reset 후 강제푸시 불가)
- 그냥 커맨드 쓰는게 더 좋아보인다.
Github/SourceTree 사용법을 공부하게 된 이유?
1) 여러 명이 협업해야 하는 상황
학원에서 첫 프로젝트로 자바로 게임을 만들기로 했다. 나 포함 팀원 총 6명이 협업을 해야 한다. 협업을 위해 깃허브를 사용하자고 팀원들에게 제안했고, 다들 흔쾌히 승낙해 주셨다.
2) 다른 사람에게 가르쳐줘야 함
다른 팀원분들이 깃헙을 처음 쓰시다 보니 내가 가르쳐드리고 있다. 그런데 나는 VSCode + 맥에서는 터미널/윈도우에서는 GitBash로 깃헙을 사용해왔어서 다른분들께도 GitBash로 하는 방법을 가르쳐드렸더니 초심자분들이 너무 어려워하셨다. 그래서 주말을 맞아 내 깃허브 실력도 늘리고, GitBash가 아닌 좀 더 쉬운 방법으로 깃헙을 사용하는 방법을 알아가서 다른 팀원분들께 알려드리고자 강의를 보고 있다.
3) 깃을 쓰면서도 깊게 모른다는 아쉬움
깃허브를 쓴지 1년 반쯤 되었는데 그동안 사실 pull, add, commit, push, 그리고 해봤자 config, status, checkout, merge 외에는 딱히 쓸 일이 없었다. 그러다 보니 rebase, reset 같은 기능을 써 본 적이 없어서 아쉬웠다. 나도 이김에 Github에 대해 더 깊게 알고자 공부하게 되었다.
느낀점
- 이때까지 한 커밋이 200개가 넘는데도 Head, origin 같은 기본적인 용어조차 모르고 썼다는게 당황스럽다. 이렇게 알고 있는듯했던 것들도 대충 알았던 거인게 많았겠지. 남은 5개월간 정말 제대로 공부하자.
- 주말에 하나의 테마를 잡고 쭉 달리는 게 좋은 것 같다. 저번 주말+연휴에는 Java 리듬게임 강의 16강을 완강해서 리듬게임 하나를 만들었고, 이번 주말에는 Git에 대해 더 잘 알게 되었다. 강의를 완강하고 나면 드는 뿌듯함과 뭔가 하나를 만들어냈다는 성취감이 공부를 더 열심히 하게 하는 원동력으로 작용하는 것 같다.
- SourceTree를 써보고는 별로라고 생각했는데 많은 강의들에서 (패캠 진유림님 깃 강의, 인프런 강의, 생활코딩 강의) 다뤄서 신기했다. 계속 CLI로 Git을 쓸 것 같지만 뭐든 알아두는 것이 좋은 것 같다.
- 배우고 있는 거 블로그에 포스팅 하려고 해놓고서는 12월에 2개밖에 못 했다. 열심히 하자. 1월에는 좀 더 포스팅을 많이 해야겠다.
'Programming > Git' 카테고리의 다른 글
[Git] CRLF, .gitattributes, 새로운 branch 가져오기, 원격 branch 삭제 (0) | 2020.06.05 |
---|---|
[Git] Please commit your changes or stash them before you merge. 해결방법 (0) | 2020.04.18 |
[Git] gitignore가 제대로 적용되지 않을 때 + rm 옵션 (0) | 2020.04.18 |
[Git] 로컬 폴더를 원격 저장소와 연결하기 (0) | 2020.03.04 |
[Git] 깃허브 마크다운 문법 (0) | 2020.01.24 |
[Github] 1. Git 기초개념 (0) | 2020.01.05 |