Git configuration
시작하기 전에, 자주 사용하는 커맨드를 ~/.gitconfig
파일에 설정해놓으면 사용할 때 편합니다. 제가 세팅해놓고 사용 중인 것들입니다.
[init]
defaultBranch = main
[alias]
co = checkout
st = status
br = branch
ci = commit
mt = mergetool
[core]
editor = code --wait
[merge]
tool = vscode
[mergetool "vscode"]
cmd = code --wait $MERGED
trustExitCode = true
keepBackup = false
[diff]
tool = vscode
[difftool "vscode"]
cmd = code --wait --diff $LOCAL $REMOTE
이렇게 설정을 하면 git checkout feature/my-branch
를 git co feature/my-branch
로, git commit -m "Added something cool"
를 git ci -m "Added something cool"
으로 조금이나마 짧게 사용할 수 있습니다. 이렇게 보기엔 큰 차이가 없어보여도, alias가 설정되지 않은 컴퓨터로 git을 사용하려고 하면 소소하게 불편하더라구요. 🥲
GitHub fork & git remote
GitHub repo에서 우측 상단에 Fork 버튼을 클릭해 개인 프로젝트를 생성하고 clone을 받습니다. 로컬 컴퓨터에서 클론한 프로젝트로 이동하고, git remote -v
를 입력해보면 아래와 같이 표시가 됩니다. (“hngskj” 부분에 자신의 github 아이디가 나와야 합니다.)
origin https://github.com/hngskj/react.git (fetch)
origin https://github.com/hngskj/react.git (push)
upstream https://github.com/facebook/react.git (fetch)
upstream https://github.com/facebook/react.git (push)
upstream
은 오픈소스로 열려있는 github에 올라가 있는 공용 프로젝트입니다. origin
은 내가 fork를 한 github에 올라가 있는 개인 프로젝트입니다. (둘 다 내 컴퓨터에 있지 않고 github에 있는 프로젝트라서 remote라고 부릅니다.) 그리고 clone을 받아서 local
컴퓨터에 있는 프로젝트까지 신경써야 할 프로젝트가 3개가 되었습니다. 3개 프로젝트의 상태를 잘 관리하며 개발을 하면 즐거운 협업을 할 수 있습니다! 🤩
git fetch & pull
방금 fork를 하고 clone 했기 때문에 3 프로젝트 모두 상태가 같을 것 입니다. upstream:main [hello]
, origin:main [hello]
, local:main [hello]
이때 새로운 기능을 추가하기 위해 새로운 브랜치를 만들고 기능을 추가했습니다. local:feature [hello hi]
pr을 날리기 위해 origin에 feature를 push 해줍니다. $ git push origin feature
그럼 github에 origin:feature [hello hi]
로 업데이트가 되고 pr을 날릴 수 있습니다. 아직 upstream에 다른 커밋이 추가된게 없기 때문에 conflict이 생기지 않고 merge가 잘 될 것입니다.
그런데 upstream에 새로운 커밋이 생성되었으면upstream:main [hello there]
, 내가 작업한 코드와 충돌이 안나는지 확인이 필요합니다. 이를 위해 local:main
을 업데이트 해줍니다.
$ git fetch --all # remote의 상태 확인
$ git co main # checkout
$ git pull # main 브랜치 최신화
이제 local에 main 브랜치가 upstream의 main 브랜치와 상태가 같아졌습니다. local:main [hello there]
git rebase
내가 작업한 [hello hi]
와 conflict를 해결하기 위해 merge
나 rebase
방법을 사용할 수 있습니다. 자주 사용하는 방법은 merge이지만 협업을 할 때 빛을 발하는 rebase를 사용해보도록 하겠습니다. 😙
$ git co feature
$ git rebase main # 작업한 feature를 업데이트된 main으로 rebase를 하겠다.
그럼 아래와 같은 메시지가 나옵니다. 대략 “rebase를 하려고 하는데 conflict이 났고 개발자가 해결을 해야한다” 입니다.
이때 git mt
를 입력해주면 vscode가 자동으로 열리면서 conflict를 해결해야 하는 파일이 열립니다. CLI에서 git mt
가 실행 중입니다. (만약 vscode에 새 탭이 열리지 않으면, vscode>View>Command Palette 를 열고 Shell Command: Install ~
을 실행해주세요.)
올바른 코드로 저장하고 탭을 닫습니다. 그럼 CLI에 git mt
가 종료되고, 해당 파일에 대한 conflict이 해결됩니다. 또 다른 conflict이 없어질 때까지 git rebase --continue
로 작업하다 보면 아래와 같은 탭이 생기는데, 모두 resolve해서 수정된 내용에 대한 커밋 메시지를 입력할 수 있습니다.
문제가 없으면 탭을 닫아줍니다. “Successfully rebased and updated detached HEAD.” 라는 메시지가 보이면 성공적으로 rebase를 마치게 됩니다! 🥳 local:feature [hello there! hi]
local의 feature 브랜치는 upstream의 main에 머지될 준비가 되었습니다.
git force push
이제 다시 3개의 프로젝트를 보면, 아래와 같습니다.
upstream:main [hello there]
origin:main [hello]
origin:feature [hello hi]
local:main [hello there]
local:feature [hello there! hi]
작업한 내용의 pr을 upstream의 main에 날리기 위해서는 origin:feature
도 업데이트가 되어야 합니다. 이를 위해 force push를 해줍니다.
$ git co feature
$ git push origin feature -f
force push를 하는 이유는 rebase 과정에서, feature에서 작업한 커밋들이 변경되었기 때문입니다. -f
를 붙이지 않고 push를 하면 github pr에서 동일한 커밋 메시지들이 중복되어 생기는 (커밋 번호는 다른) 당황스러운 로그를 확인하게 됩니다. 😇 force push까지 하면 origin:feature [hello there! hi]
로 업데이트가 되고, GitHub PR에서 conflict 없이 Rebase and merge를 할 수 있습니다.
upstream:main [hello there! hi]
origin:main [hello]
origin:feature [hello there! hi]
local:main [hello there]
local:feature [hello there! hi]
필수는 아니지만 나중을 위해서 origin:main
과 local:main
도 업데이트를 해줍니다.
$ git co main
$ git fetch --all
$ git pull # local:main 업데이트
$ git push origin main # origin:main 업데이트
여기까지 따라오시느라 고생하셨습니다. 🎉 GitHub repo를 fork해서 upstream과 origin을 관리하고, rebase로 conflict를 해결하는 방법을 통해 다른 개발자들과 협업하는 과정을 살펴보았습니다.
수정이 필요하거나 추가하면 좋을 내용이 있다면 언제든지 피드백 부탁드립니다! 🙏