Working w/ git

hngskj
aaant
Published in
8 min readSep 14, 2021
Git branches
Gitflow Workflow

여러 개발자들과 협업을 하면서 빼놓을 수 없는게 소스 코드의 버전 관리입니다. 이번 아티클에서는 공용 프로젝트를 fork하고 작업을 마쳐서 pr을 날리고 merge까지 하는 과정을 git-flow 전략으로 따라가보고자 합니다. 🧐

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-branchgit 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를 해결하기 위해 mergerebase 방법을 사용할 수 있습니다. 자주 사용하는 방법은 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:mainlocal:main 도 업데이트를 해줍니다.

$ git co main
$ git fetch --all
$ git pull # local:main 업데이트
$ git push origin main # origin:main 업데이트

여기까지 따라오시느라 고생하셨습니다. 🎉 GitHub repo를 fork해서 upstream과 origin을 관리하고, rebase로 conflict를 해결하는 방법을 통해 다른 개발자들과 협업하는 과정을 살펴보았습니다.

수정이 필요하거나 추가하면 좋을 내용이 있다면 언제든지 피드백 부탁드립니다! 🙏

Reference

--

--