드디어 깃헙으로 협업하기 포스팅이다. 이전에도 말했지만, 난 협업경험이 없다. 때문에 포스팅이 잘못됐다면 지적해주면 매우 감사드리겠음.
팀프로젝트가 있는데 협업경험이 없다고? 라고 생각할 수도 있는데, 정확히는 팀프로젝트 두번 다 개발적으로 협업하는게 어려운 상황이었다.
첫번째 팀프로젝트는 네트워크인프라 교육과정에서 파이널 프로젝트였기때문에, 팀원 총 다섯분 중, 인프라팀 세분, 개발팀 두 명중에 나는 개발팀이었다. 애초에 개발팀인원자체가 적었어서 개발적으로 협업이 애매했다. 더해서 개발팀원 한분과 같이 협업을 했는데, 서로 쓰는 언어가 달랐음.. 또한 네트워크 인프라에서는 msa가 대세기때문에 우리팀도 eks쿠버네티스 환경에서 msa구조의 서비스를 만들었다. 때문에 서로 같은 레포지토리를 코드를 짤 수 있는 설계 자체가 아니었다. 이때 우리팀은 organization 으로 프로젝트 협업을 하였다. 즉 개발자별로 담당하는 레포지토리가 있었고 레포지토리당 혼자서만 건드는 협업구조라, 내가 기대한 개발팀에서의 협업이란 구조가 이루어지지 않았다.
두번째 단어장프로젝트는 팀원 세 명이서 진행한 프로젝트인데, 여기또한 팀원 두 분은 인프라 담당이었고, 개발은 전체적인 코드를 나 혼자 담당하였다. 당연히 개발자 레포지토리가 따로 있었고 난 개발 레포지토리만 손댔었다.
물론 인프라팀의 cicd파일 수정을 위해 잠깐씩 pull과 merge해야하는 경우가 있었지만 이건 뭐 너무 단순한거라..
지금까지 혼자 코딩공부를 해왔기에, 깃으로 협업할 수 있는 기회가 없었음.. 취직을 준비하는 현재 상황으로써는 협업을 알아두고 가야한다고 판단해서 깃으로 협업하기 포스팅 시리즈를 쓴거다. 혼자놀기의 진수를 볼 수 있음. (쫌 쪽팔림)
2025년의 시작을 앞서, 나는 puppy world프로젝트를 진행하기로 하였다.
강아지를 위한 어플리케이션 개발인데, 강아지 개발자인 muzzi씨와 dori씨를 팀원으로 모셨고, 내가 팀장직을 하게 되었다.
각자는 github레포지토리가 존재하는 형태에서 협업을 할 것이다.
협업 하는 방식이 여러가지가 있는데 이번 포스팅에선 fork로 협업하는 방식으로 해보겠다.
환경셋팅
일단 각기 다른 개발자가 협업을 하는 환경을 만드려고 컴퓨터를 여러대 쓰는 환경이 필요했따.
그래서 muzzi가 쓰는 컴퓨터인 우분투이미지로 만든 muzzi computer vm과, dori가 쓰는 컴퓨터인 dori computer vm을 만들었다.
각 vm ssh연결해놨음
그리고 크롬창을 서로 다른 구글계정으로 로그인하고 각 깃허브 계정을 생성하였고, muzzi worker계정으로 접속한 github, dori worker계정으로 접속한 github를 만들었다.
우분투환경인 무찌와 도리 계정에서 전부 본견의 깃허브 계정에 로그인되어 자기 레포에 push와 pull을 할 수 있는 상태임
난(nurd worker) 그냥 내 컴퓨터에서 접속한걸로 가정을 했음.
fork 협업방식?
대략적인 구성도를 보면, fork협업방식은 먼저 팀장이 puppy-project라는 깃허브 레포지토리를 본인 깃허브 계정에 만든다.
그리고 무찌랑 도리 개발자가 팀장의 fork-puppy-project레포지토리를 통째로 그대로 복사해서 본견의 각 깃허브 계정에 복사해서 가져온다.(fork하는게 깃허브 홈페이지에 따로있음)
각 개발자는 복제해온 레포지토리를 로컬로 clone후, 각각 코드를 알아서 수정하고 고친다음에, 본견 계정의 레포지토리에 push한 후, 이 레포지토리를 통쨰로 팀장의 레포지토리에 pull request를 보낸다.
그럼 팀장은 팀원들이 수정한 코드들이 잘 동작하는지 확인하고, 이 pull request로 코드의 변화를 팀장 계정레포에 merge할지 말지 결정을 하는거다.
이게 대략적인 fork협업방식의 구조임
해보자
먼저 nurdworker 내 계정에 레포지토리를 하나 만들었다. fork-puppy-project라는 레포지토리에 app.js파일을 만들고 그 안에 app.js파일이 들어있다.
로컬에 팀장님 코드를 가져왔지만, 아직 내 코드엔 반영을 못한거다. 즉 내 코드에 merge를 해야한다는거임.
git merge <팀장님레포주소>/<팀장님 브랜치명>
이렇게하면 무찌코드에 팀장님의 코드가 반영된걸 확인 할 수 있다.
다만 중요한건, fetch후에 merge를 해야한다는거다. merge명령어를 쓸때는 현재 로컬주소의 커밋정보를 가지고 merge를 하는것이기 때문.
++참고로 pull을 해봤는데 뭔가 안됐다. 왜인지는 모르겠는데.. fetch, merge조합으로 하니까 됐음. 걍 단순히 fetch로 팀장님 레포의 main브랜치의 최신상태를 로컬에 가져오고, 이 브랜치 최신상태를 현재 내 branch에 merge하면 팀장님 코드가 반영이 된다는것.
pull은 뭘까?
레포지토리의 최신상태를 현재코드에 반영할때 사용을 했었다.
pull은 정확히는 fetch와 merge를 합친거다.
테스트를 또 해보자.
팀장이 test pull이라는 코드를 추가하고 push했다.
팀장 레포지토리에 test pull커밋이 적용된걸 확인 할 수 있음.
이제 무찌 시점에서
아까 test fetch커밋상태였지만 pull명령어 한번을 쓰니 코드가 test pull로 업데이트가 잘 되었다.
다만 가끔 pull시에 이렇게 되는경우가 있더라.. 나도 잘은 모르는데 그냥 fetch + merge를 쓰는게 더 좋다고함 gpt가.
만약 그냥 이렇게 나눠쓰기 싫으면
git pull --rebase upstream main
이렇게 rebase전략으로 pull해오라고하면됨. 뭔진 나도 잘 모름
협업을 해보자!
이런식으로 전략을 짜보자.
먼저 팀장 github계정의 기준이 되는 레포지토리를 판다.
그리고 무찌랑 도리가 각 본견의 계정으로 팀장의 레포지토리를 fork해서 가져간다.
이후에 fork로 가져간 레포지토리에서 무찌랑 도리는 각각 main브랜치로 작업을한다. (기능별로 브랜치 따로 해서 해도됨. 기준은 각자 fork한 레포지토리의 main브랜치에서 작업한다는거임.)
강아지 개발자들이 본인 main브랜치를 기준으로 작업을 한 후, 코드가 맘에들면 팀장님 레포지토리의 muzzi-dev, dori-dev라는 브랜치에 pull request를 보낸다.
팀장은 해당 리퀘스트가 진심을 담아 보낸 리퀘스트인지 판단후 merge를 결정한다.
사실 팀장은 muzzi-dev브랜치와 dori-dev브랜치를 건들일이 없다. 그냥 이건 강아지 개발자들의 코드 테스트용임.
팀장은 각 muzzi-dev, dori-dev브랜치에서 코드가 정상적으로 동작하면 해당 브랜치를 main브랜치에 merge를 한다
그림에는 안그렸지만 팀장도 본인 개발용 브랜치를 따로 만들어서 main에 넣을지 말지 결정할 수 있음
왜이렇게 설계했나요? & 장점은 뭘까?
1. 위에 코드를 테스트해보면서 매번 팀장이 브랜치를 새로 만들고, pull request의 코드를 가져와서 테스트 하는게 귀찮을것 같았다. 때문에 리퀘스트를 각 강아지개발자-dev 브랜치에 그냥 받아들이고, 이 브랜치를 로컬로 가져와서 테스트 해보면 될것같았음.
2. 이렇게 설계하면 원본 브랜치인 main브랜치도 안전할거임.
3. 각 강아지 개발자들도 깃에 대해서 수준차가 있다 가정. 예를들어 무찌는 브랜치를 잘 구분 하는 강아지이고, 도리는 내 포스팅 step1처럼 main브랜치만 다루는 남자다운 스타일이라고 한다면, 어차피 지네 레포지토리의 main브랜치기준으로 최종 커밋을 하는 시스템임. 만족한다면 이걸 팀장 레포에 만들어진 지네 브랜치에 pull request를 보내면 됨.
4. 직접적으로 팀장의 main브랜치에 pull request보내는것이 아니기 때문에 팀장은 pull request를 merge하냐마냐에 따른 리스크를 줄일 수 있음. 즉 팀장은 강아지-dev브랜치는 해당 pull request코드를 테스트할때만 사용하는 용도.
5. 다만 팀장은 main브랜치가 업데이트 될때마다 팀원들에게 직접 알려줘야하고 팀원은 이런 공지가 내려올때마다 upstream에서 코드를 본인 main브랜치와 작업중인 브랜치에 merge해야함. 그냥 심심하면 팀장 main브랜치 fetch, merge하라고하면됨
private 레포지토리를 fork방식으로 협업하려면 강아지 개발자들을 collaborator로 설정하면 된다.
먼저 private레포지토리 priv-fork-puppy-project를 하나 팀장이 새로 만들자.
이제 강아지 개발자 무찌가 신나서 팀장님의 레포지토리를 fork하려고 달러감
404가 떠버림
당연한거다. private레포지토리는 아무도 들어올수 없는데 default니까..
# 해결방법
팀장은 해당 private 레포지토리의 setting에 들어가자
그리고 collaborators탭에서 add people버튼 클릭
우리 강아지 개발자들 깃허브 이름을 검색해서 collaborator로 초대
무찌랑 도리 둘다 검색해서 초대하샘
collaborator로 잘 초대하였다.
무찌의 깃허브 계정의 메세지를 확인하면
priv-fork-puppy-project레포지토리로 초대가 잘 왔다.
도리 깃허브에서도 잘 와있을거임
무찌계정에서 초대장을 승락하자.
이렇게 팀장의 사설 레포지토리에 잘 접속이 된다.
이제 fork도 걍 해오면 됨.
무찌 계정에서 fork해온 priv-fork-puppy-project도 역시 private레포지토리로 지정되어있다.
사실 collaborator로 팀원을 초대하는 방법은 다음 포스팅에서 다루려고 했다. 간단하게 미리 말하자면 fork는 레포지토리를 통째로 가져와서 pull request를 보내는 방식인 방면에, collaborator는 한 레포지토리에 collaborator를 초대해서 레포지토리의 권한을 부여하는 식이라서 바로 push를 때릴 수 있다.
지금 위에서는 사설 레포지토리를 팀원이 fork해야하기위해 초대를 한건데, 지금 상태에서 muzzi랑 dori는 팀장의 레포지토리에 fork하고 그럴것도 없이 직접적으로 push할 수 있는 막강한 상태이다.
따라서 이 권한을 조절해줘야한다.
하지만 이건 collaborator로 협업하는 방법 포스팅에서 다룰것이므로 이번 포스팅에선 적지 않겠다.
Conclusion
사실 이번 포스팅 쓰면서 rebase나 뭐 pull머시기 명령어를 많이 썼다. 최대한 단순한 방법으로 적으려고 상황을 일일히 안적었음.. 포스팅도 사진이 많다보니 너무 드러워져서..
또한 브랜치작명이라던지 이런것도 같이 포함하고싶었는데 지금도 포스팅이 난잡한데 더 이상해질까봐 생략함. fork방식만으로 하지는 않기도 한다. 이후에 적을 collaborator방법도 적절히 섞으면서 협업을 한단다. 이건 팀장의 몫임. 암튼 fork방식은 이런형식이고 오픈소스 코드 수정할때도 많이 쓰인다.