이 글은 충북대학교 SW중심사업단의 "Git/GitHub 기초/고급 특강" 강의와 backlog에서 제공하는 "누구나 쉽게 이해할 수 있는 Git 입문"을 바탕으로 작성되었습니다. https://backlog.com/git-tutorial/kr/
포스팅에 사용된 Git 연습 툴 : https://git-school.github.io/visualizing-git
썸네일 이미지 출처 : www.freecodecamp.org - https://www.freecodecamp.org/news/an-introduction-to-git-for-absolute-beginners-86fa1d32ff71/
2021년 3월 25일
지금까지는 로컬 환경에서 Git을 사용하는 방법에 대해 알아보았는데요, 오늘은 GitHub에서 원격 저장소를 만들고 원격 저장소로 커밋을 보내는 방법에 대해 포스팅하겠습니다.
우선 GitHub 사이트에서 새 원격 저장소를 만들어줍니다. GitHub 계정이 필요합니다. GitHub에 로그인 한 후에 메인 페이지 우측 상단에 있는 +버튼을 누르고 New repository
버튼을 누릅니다.
그리고 나면 다음과 같은 간단한 입력창이 뜨는데요, 차례대로 정보를 입력하면 됩니다.
마지막으로 가장 밑에 Initialize this repository with: 이라고 적혀있는 부분에서는 레포지토리에 유용한 파일을 추가해줍니다.
해당하는 부분을 전부 입력하고 Create repository 버튼을 누르면 새 원격 저장소가 만들어집니다. 이제 이 원격 저장소를 로컬 저장소와 연결하는 방법에 대해 알아보겠습니다.
원격저장소 URL을 복사합니다.
자신의 프로젝트 폴더에서 $ git init
을 실행합니다.
$ git remote add origin <URL>
을 입력합니다. 일반적으로 저장소별명은 origin이라는 이름을 사용합니다.
$ git remote -v
명령어로 원격 저장소가 잘 연결되었는지 확인합니다. 아래와 같이 fetch와 push의 주소가 출력된다면 연결이 잘 된 것입니다.
$ git remote -v
origin https://github.com/soonitoon/test_repo (fetch)
origin https://github.com/soonitoon/test_repo (push)
혹은, 단순히 $ git clone <저장소 URL>
명령어를 실행해서 위의 과정을 모두 생략할 수도 있습니다.
로컬 저장소는 혼자 사용하지만, 원격 저장소는 프로젝트 구성원 모두의 변경 사항을 관리하게 됩니다. 따라서 개발을 진행하다가 원격 저장소와 로컬 저장소를 주기적으로 동기화해야 합니다. 동기화 과정은 크게 두 가지 상황으로 나눌 수 있습니다.
첫 번째 상황에서는 pull
, 두 번째 상황은 push
명령어를 사용하게 됩니다. 이제부터 두 명령어의 기본적인 사용법과 소스 코드 병합과 관련된 심화적인 상황에 대해 알아보겠습니다.
왼쪽에 있는 것이 로컬 저장소, 오른쪽에 있는 것이 원격 저장소입니다. 현재 상황을 정리해보자면 다음과 같습니다.
즉, 그저 원격 저장소에서 최신 변경 사항을 가져와 병합시켜주기만 하면 됩니다. 병합은 fast-forward로 진행될 것입니다.
로컬 환경에서 $ git pull origin master
명령어를 입력합니다.
pull
명령어를 통해 원격 저장소의 커밋을 받아와 병합한 모습입니다. 이번에는 원격 저장소와 로컬 저장소에서 각각 변경 사항이 발생한 경우에 대해 알아보겠습니다.
처음 세 커밋까지는 원격 저장소와 로컬 저장소의 커밋이 동일합니다. 이후 로컬과 원격에서 새로운 커밋이 각각 두 개씩 만들어진 모습입니다. 이렇게 변경 사항이 겹칠 경우 앞에서와 같은 fast-forward 병합은 불가능합니다. 여기서 pull
명령어를 입력하면 리모트 브랜치와 master 브랜치의 병합 커밋이 생성됩니다. 만약 충돌이 생긴다면 충돌이 발생한 부분을 수정하고 커밋을 진행해야 합니다.
pull
명령어를 입력한 결과 master 브랜치와 리모트 브랜치가 병합된 커밋이 생겼습니다.
지금까지 pull을 설명할 때 받아오기라는 말과 병합이라는 말을 같이 사용했습니다. 그 이유는 pull 명령어가 최신 코드를 받아오고 그것을 로컬 브랜치에 병합하는 두 가지 일을 하기 때문입니다. 이 명령어가 작업하는 두 가지 일을 분리해서 시킬 수도 있습니다. 바로 fetch
와 merge
를 사용하는 방법입니다.
이 두 가지 명령어를 합친 것이 pull
이라고 할 수 있습니다.
이번에는 pull
대신 fetch
+ merge
로 원격 저장소에서 최신 커밋을 받아오고 병합하는 과정을 진행해보겠습니다.
전과 같은 상황입니다. push
후에 로컬에서 새로운 커밋 두 개가 생겼고, 원격에서도 로컬에 반영되지 않은 새 커밋 두 개가 생겼습니다. 여기서 $ git fetch origin master
명령어를 입력합니다.
실행 결과입니다. 다음과 같이 원격 저장소의 새로운 커밋을 리모트 브랜치에 받아오기만 할 뿐 아직 병합은 이루어지지 않았습니다.
여기서 $ git merge origin/master
명령어를 입력하면 pull
명령어를 입력했을 때와 같은 결과가 나오게 됩니다. 물론 rebase
를 사용할 수도 있습니다. $ git rebase origin/master
명령어로 원격 저장소의 최신 커밋을 master 브랜치에 적용할 수 있습니다.
rebase를 시각화한 모습입니다. 이렇게 하면 원격 저장소의 최신 커밋을 로컬에서 작업한 내용에 적용할 수 있습니다. 지금까지 원격 저장소의 코드를 끌어오는 pull
과 fetch
에 대해 알아보았는데요, 이젠 로컬에서 작업한 내용을 원격 저장소에 보내는 push
에 대해 알아보겠습니다.
$ git push origin <브랜치 이름>
명령어로 원격 저장소의 해당 브랜치에 로컬에서 작업한 커밋을 업로드할 수 있습니다. 이때 마지막으로 clone
이나 pull
을 받은 이후에 추가적인 변경 사항이 원격 저장소의 해당 브랜치에 생겼다면 내 커밋을 push할 수 없습니다. 이럴 때는 반드시 로컬 저장소를 최신화 한 다음 push
를 진행해야 합니다.
로컬에서 push
가 reject되는 상황을 가정해보겠습니다.
push
하기 전에 다른 누군가가 원격 저장소의 master 브랜치에 push
를 날렸습니다.push
를 해보지만 reject됩니다.이런 경우에는 먼저 로컬 저장소에 원격 저장소의 최신 커밋을 받아와야 합니다.
$ git pull origin master
명령어로 원격 저장소의 최신 커밋을 당겨와 병합합니다.병합 시 충돌이 발생한다면 충돌이 발생한 줄을 적절히 수정하고 머지 커밋을 이어서 진행합니다.
$ git push origin master
로 push를 다시 진행합니다.
push 결과입니다. 로컬에서 만들었던 새 커밋과 머지 커밋 모두 원격 저장소에 반영되었습니다. 물론 fetch
+ rebase
조합을 이용해 reject 상황을 해결할 수도 있습니다. 리베이스를 사용할 경우 마치 모든 커밋이 시간 순서대로 일어난 것처럼 깔끔하게 커밋 이력을 정리할 수 있게 됩니다. 아까의 reject 상황으로 다시 돌아갑니다.
$ git fetch origin master
명령어로 원격 저장소의 새 커밋을 '끌어오기만' 합니다.$ git rebase origin/master
명령어로 로컬에서 만들었던 새 커밋을 원격 저장소의 최신 커밋 뒤에 '이어붙입니다.'이렇게 하면 내가 만든 커밋이 원격 저장소의 변경 이력을 모두 반영한 것이 됩니다.
$ git push origin master
로 push를 다시 진행합니다.아까 merge
를 사용했을 때보다 커밋 이력이 훨씬 깔끔해진 것을 볼 수 있습니다. 마치 모든 커밋이 차례대로 일어난 것처럼 보입니다.
지금까지 pull
이나 push
를 할 때 인자로 <원격저장소 별명> <원격 저장소 브랜치 이름>
을 주었는데요, 보통은 원격 저장소와 로컬 저장소의 브랜치명이 같기 때문에 설정을 통해 인자를 생략할 수 있습니다.
$ git push -u origin master
처럼 -u
옵션을 주게 되면 브랜치를 바꾸기 전까지는 $ git push
이후의 인자를 생략할 수 있습니다.
원격 저장소와 로컬 저장소의 모든 브랜치명이 동일하다면
$ git config --global push.default current
명령어를 입력해 push
, pull
을 할 때 인자 없이 같은 이름의 브랜치라는 것을 알려줄 수 있습니다.
오늘은 로컬 저장소와 원격 저장소 간 push
와 pull
을 통해 변경 이력을 주고 받는 방법에 대해 알아보았는데요, 다음 포스팅에서는 fork와 Pull request, 오픈소스 기여에 대해 작성하겠습니다.
<참고 문서>
안녕하세요. 강사로 참여했던 개발자입니다 :) 정말 정리를 잘해놓으셔서 몇군데에도 공유해봅니다. 현업에서 뵙게되면 인사 나눠요~