ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 깃허브 오픈소스 프로젝트에 참여하기
    소프트웨어 개발 툴 2019. 1. 27. 19:01

    오늘은 이 포스트를 통해 깃허브에서 오픈소스 프로젝트 참여하는 법을 설명하고자 한다. 깃허브의 사용법을 알고 있어도 오픈소스 프로젝트에 참여하는 것은 굉장히 어렵게 다가 올 때가 많다. 또 어떤 오픈소스 프로젝트에 참여하려고 할 때 어디서부터 시작해야 할 지 모르겠다고 생각하는 사람들도 많을 것이다. 그 이유는 오픈소스 프로젝트에 참여할 때 어떤 룰을 따라야 하기 때문이다. 그 룰을 따르지 않으면 내가 커밋한 코드는 거부되고 말 것이다. 그런 불상사가 없도록 지금부터 오픈소스 프로젝트에 참여 시 지켜야 할 것들과 참여하는 방법을 소개하고자 한다.


    깃허브 오픈소스에 참여하기

     시작하기에 앞서 git이나 Github에 대해 잘 알지 못하는 독자들은 git과 github튜토리얼을 먼저 진행하길 바란다.

    깃허브 Fork

    원하는 오픈소스 프로젝트를 Fork한다. 예를들어 https://github.com/fsoftwareengineer/githubtutorial 이 프로젝트에 참여하고 싶다면 오른쪽 상단에 보이는 Fork버튼을 눌러 이 리파지토리를 본인의 리파지토리로 복사한다. 

    Fork를 하는 것은 본인 버전의 리파지토리를 생성하는 것과 같다. Fork를 누르면 다음과 같이 자신의 리파지토리로 넘어간다.

    상단의 리파지토리 이름이 <아이디>/<포크 한 리파지토리 이름>으로 설정되어 있을 것이다. 이렇게 해서 본인 버전의 리파지토리를 가지게 되었다. 본인 버전의 리파지토리라 함은 당신이 이제 이  Fork된 버전의 리파지토리를 Clone 및 Commit 할 수 있는 권한이 생겼다는 것이다.

    깃허브 Clone

    리모트(remote) 환경에 있는 리파지토리를 로컬(local) 환경(컴퓨터)로 다운로드 하는 것을 Clone이라고 부른다. 클론을 하기 위해서는 리파지토리의 주소가 필요한데 주소는 본인이 포크란 리파지토리에 "Clone or download"에서 찾을 수 있다.

    클론 할 주소를 복사했다면 커맨드라인을 이용해 원하는 디렉토리로 클론한다. 클론이 완료됐다면 현재 디렉토리에 githubtutorial이라는 프로젝트가 생겼을 것이다. 

    $git clone https://github.com/<본인 아이디>/githubtutorial.git
    Cloning into 'githubtutorial'...
    remote: Enumerating objects: 18, done.
    remote: Counting objects: 100% (18/18), done.
    remote: Compressing objects: 100% (15/15), done.
    remote: Total 18 (delta 0), reused 18 (delta 0), pack-reused 0
    Unpacking objects: 100% (18/18), done.


    깃허브 Issue

    오픈소스에 참여하기로 결정 했을 때 가장 먼저 드는 생각이 무엇인가? 각자 다른 생각을 하겠지만 많은 사람들이 '어디서부터 뭘 어떻게 해야하나?'하는 생각을 할 것이다. 특히 오픈소스의 규모가 크고 컨트리뷰터(당신 처럼 오픈소스에 참여하는 사람)가 많을수록 고민은 더 커질 것이다. 게다가 대부분의 규모 있는 오픈소스 프로젝트들은 이슈 트래킹 시스템을 사용한다. 그래서 뭘 고쳐서 커밋해야 할 지 모르겠다면 해당 오픈소스의 Issue트래킹 보드을 확인 해 보는 것이 현명하다. 여기 또는 여기에서 Issue탭을 누르면 githubtutorial의 이슈 보드로 들어 갈 수 있다. 글 작성 당시 데모를 위해 미리 2개의 이슈를 만들어 놓았다.

     

    보통 이슈는 다음과 같이 [프로젝트이름]-[이슈번호] <이슈 제목> 으로 구성된다. 깃허브의 경우 몇가지 태그가 있는데 good for first는 처음 컨트리뷰션을 하는 개발자들이 하기 좋다는 뜻이다. 이렇게 해서 본인이 할 수 있을 것 같은 이슈 중의 하나를 선택한다. 여기서는 데모를 위해 가장 첫번째 이슈를 선택하도록 하겠다. 

    이 이슈가 본인이 하기 가장 적당하다고 생각한다면 오른쪽 Assignees를 통해 자기 자신에게 어사인 하도록하자. 이제부터 이 이슈는 당신의 이슈이다. 


    깃허브 Branch

    이제 git의 branch개념에 대해서 짚고 넘어가도록 하자. 현재 master 브랜치가 존재한다. master브랜치는 팀 마다 다르게 사용되긴 하지만 보통 프로덕션 release 브랜치인 경우가 많다. 무슨 뜻이냐 하면 master브랜치에 있는 코드가 서버에서 돌고있는 코드인 경우가 많다는 뜻이다. 따라서 마스터 브랜치의 코드에 자신이 개발하던 것을 그대로 커밋 하는 경우는 흔치 않다. 일단 아래의 마스터 브랜치를 보자.

    <git directed acyclic graph - 색이 있는 동그라미는 commit, 회색 동그라미은 branch off 또는 merge in을 의미한다.>


    이 그림은 마스터 브랜치의 타임라인이다. 마스터 브랜치를 release브랜치로 사용 하는 경우 대부분 develop브랜치를 따로 둔다. develop브랜치란 개발자들이 checkout하고, 자신의 브랜치를 만들고 개발을 진행하는 브랜치를 의미한다. 예를들어서 위의 스크린샷을 보면  master브랜치 위에 feature/develop이라는 브랜치가 있는 것을 확인 할 수 있다. 앞으로는 feature/develop 브랜치에서부터 브랜치 오프(branch off)를 하면 된다는 뜻이다.


    현재 이 리파지토리의 타임라인은 다음과 같다. 마스터 브랜치가 존재하고 그 이후에 branch off된 feature/develop브랜치가 존재한다. 브랜치의 이름은 오픈소스마다 다르고 어떻게 브랜치를 이용하는지도 오픈소스마다 다르다. 따라서 어떤 오픈소스에 참여 한다면 그 오픈소스의 문서를 반드시 읽어보기 바란다. 대부분의 오픈소스는 컨트리뷰터들을 위한 가이드가 준비되어있다.


    자, 다시 터미널로 돌아가서 클론한 프로젝트의 내부로 들어간다.

    $cd githubtutorial
    $git branch

    feature/develop
    * master

    (END)

    git branch명령어를 통해 어느 브랜치의 코드를 가지고 있는지 확인 할 수 있다. ( ":q"를 누르면 빠져나갈 수 있다. ) 또는 대부분의 자바 IDE의 경우 Version Control을 지원하므로 IDE를 통해 확인 할 수 있다.


    이제 가장 활동적으로 개발중인 브랜치인 feature/develop브랜치를 체크아웃한다.

    git checkout feature/develop
    Switched to branch 'feature/develop'
    Your branch is up to date with 'origin/feature/develop'.

    이제 당신은 feature/develop 브랜치 위에 있다. 그렇다면 여기에서 이제 개발을 하면 되는 것인가? 내가 commit하고 push할 코드는 나의 개발이 끝날 때 까지 다른 사람들의 코드와 분리되어 있어야 한다. 그렇지 않으면 동작하지 않는 코드를 commit/push하고 다른 사람들의 코드까지 엉망진창으로 만들어 버릴 수 있다. 그런 상황을 막기 위해 "내가 개발할 이슈" 브랜치를 만들도록 하자. 위에서 봤듯이 내가 개발할 이슈 브랜치는 보통 해당 브랜치의 <상위 브랜치>/<프로젝트>-<이슈넘버>로 구성된다. 이 포스트에서는 tutorial-1을 개발 할 것이므로 브랜치는 feature/tutorial-1이 된다. 이 글을 보는 삐멜 독자들 중에서 위 과정을 전부 실습 하고 싶다면 https://github.com/fsoftwareengineer/githubtutorial/issues 의 목록중에서 하나 골라서 실습 해 보도록 해라. 만약 이슈가 없는 경우 실습 하고 싶으니 이슈를 만들어달라고 댓글로 남기면 이슈를 만들고, 끝까지 실습을 진행 할 수 있도록 최대한 돕도록 하겠다. 이제 예제를 보자.


    git checkout -b feature/tutorial-1
    Switched to a new branch 'feature/tutorial-1'

    아까와 같이 git branch를 통해 자신이 어느 브랜치에 있는지 확인해도 좋다. 지금 브랜치 타임라인은 다음과 같다.


    git checkout -b feature/tutorial-1을 했을 당시의 브랜치가 feature/develop이었기 때문에 현재 우리는 feature/develop에서 복사된 복사본을 갖고 있다고 생각하면 쉽다. 이제 이 브랜치에서 개발을 하면 된다. 이슈 설명에서 말했듯이 이 브랜치에서는 Main클래스 내부에 있는 Contact클래스를 바깥으로 옮기도록 하겠다. 수정 완료 시 git add를 통해 파일을 스테이징 시키고, git commit을 이용해 커밋한다. 커밋 시 메시지를 "이슈제목"으로 하라. 오픈소스마다 커밋 메시지를 작성하는 방법이 다르니 참여하는 오픈소스의 문서나 다른 사람들이 어떻게 커밋 메시지를 작성했나 확인하고 커밋하기 바란다.

    :githubtutorial feature/tutorial-1 4d △ ✓ ◒ ➜ git add src/Contact.java
    :githubtutorial feature/tutorial-1 4d △ ✓ ➜ git add src/Main.java

    커밋 시 다음 처럼 커밋 메시지를 이슈제목으로 한다. 다시 말하지만 커밋을 어떻게 하느냐는 오픈소스마다 다르다. 

    ➜ git commit -m "tutorial-1:separate Contact from Main class"
    [feature/tutorial-1 8aeb5b7] tutorial-1:separate Contact from Main class
    3 files changed, 14 insertions(+), 6 deletions(-)
    create mode 100644 .gitignore
    create mode 100644 src/Contact.java

    커밋 했다면 이제 push하도록 한다. push를 하는 순간 본인이 만든 브랜치가 깃허브의 브랜치 목록에 뜰 것이다. 본인의 커밋 해시(예: 8aeb5b7)를 기억해라.

    ➜ git push --set-upstream origin feature/tutorial-1
    Counting objects: 6, done.
    Delta compression using up to 4 threads.
    Compressing objects: 100% (6/6), done.
    Writing objects: 100% (6/6), 582 bytes | 582.00 KiB/s, done.
    Total 6 (delta 2), reused 0 (delta 0)
    remote: Resolving deltas: 100% (2/2), completed with 2 local objects.
    remote:
    remote: Create a pull request for 'feature/tutorial-1' on GitHub by visiting:
    remote: https://github.com/fsoftwareengineer/githubtutorial/pull/new/feature/tutorial-1
    remote:
    To https://github.com/fsoftwareengineer/githubtutorial.git

    * [new branch] feature/tutorial-1 -> feature/tutorial-1
    Branch 'feature/tutorial-1' set up to track remote branch 'feature/tutorial-1' from 'origin'.

    깃허브 Pull Request 

    자 이제 깃허브로 돌아가면 다음과 같은 화면을 볼 수 있을 것이다.


    지금까지 당신은 개발 브랜치에서 당신의 "이슈" 브랜치를 따와 그 브랜치에서 개발을 했고, 개발이 완료되어 해당 브랜치를 remote리파지토리에 push했다. 따라서 새로 만들어진 브랜치가 깃허브에 반영된 것이다. 하지만 당신의 브랜치는 여전히 다른 브랜치들과 분리된 상태로, 당신은 자신의 브랜치가 개발브랜치인 "feature/develop"로 합쳐 질 수 있도록(merge라고 한다.) 이 프로젝트의 관리자 또는 리드 개발자에게 요청해야 한다. 그 요청을 바로 "Pull Request"라고 한다. "Compare & pull request"를 눌러보자.



    가장 처음으로 어느 브랜치로 자신의 브랜치를 머지시킬 것인지 확인해라(빨간 박스). 보통 "base"브랜치는 본인이 branch off 했던 브랜치이다. 우리는 feature/develop에서 branch off했으므로 feature/develop를 base로 한다. 상단에 Pull Request제목을 적고 Write란에 해당 풀 리퀘스트의 목적을 적는다. 다시 한번 말하지만 풀 리퀘스트를 작성하는 방법은 오픈소스 마다 다르므로 꼭 확인하고 진행하기 바란다. 스크롤바를 내려 혹시 잘못된 파일이 커밋 됐는지 다시 한번 확인해라. 

    다 확인이 되었고 자신의 코드에 만족한다면 "Create pull request"를 눌러라.

    이 화면이 보인다면 당신은 성공적으로  Pull Request를 한 것이다. 이제 당신은 프로젝트 관리자들 중 한명이 당신의 풀 리퀘스트를 리뷰하길 기다리면 된다. 마스터 브랜치의 타임라인에서 당신의 상태는 Pending review상태이다. 

    깃허브 Review

     리뷰 상태에 들어가면 당신이 할 수 있는 일은 거의 없다. 당신의 코드에 버그가 있거나 어떤 이유로 리젝을 당한다 해도 너무 걱정하지 마라. 리젝 당하는 일을 비일비재하고 당신 자체를 거부하는 것이 아니라 현재 코드가 머지 될 수 없음을 의미할 뿐이다. 이유 없이 풀 리퀘스트를 리젝하는 경우는 없으며, 거부 사유를 명시하면 그에 따라 코드를 수정하고 리뷰를 다시 요청하면 된다. 리뷰 과정이 끝나면 프로젝트 관리자가 당신의 코드를 base브랜치로 머지하고, 풀 리퀘스트를 닫을 것이다. 그렇게 되면 당신의 코드는 다음 릴리즈에 함께 출시되는 것이다!

    위 처럼 당신의 코드가 머지되고,

    이슈가 닫히는 순간 이 이슈는 끝이다! 마스터 브랜치의 타임라인은 다음과 같다.


    마지막으로 짚고 넘어갈 점

    • 다시한번 말하지만 리파지토리와 프로젝트를 운영하는 방식은 각 오픈소스마다 다르다. 따라서 참여하고자 하는 오픈소스의 프로젝트 문서를 잘 읽어보길 바란다.

    • 오픈소스를 참여하는 방식은 다양하다. 코드 컨트리뷰션은 그 중 하나일 뿐인다. 코딩이 별로 하고 싶지 않다면 문서를 통한 컨트리뷰션도 고려해 볼 수 있다.

    • 리뷰어의 풀리퀘스트 거부를 개인적으로 받아들이지 말아라. 그 사람은 당신이 누군지 모른다. 그저 코드에 문제가 있거나 양식에 맞지 않는 경우 코드를 머지 할 수 없을 뿐이다.

    • 인내심을 가져라. 코드 리뷰어는 매우 바쁘다. 나도 처음 오픈 소스 프로젝트를 했을 때 두 달 넘게 리뷰를 받지 못했다.

    • 커밋 하기 전에 반드시 빌드 및 테스트를 해라. 자칫 잘못하면 돌아가지도 않는 코드를 올릴 수도 있다.


     이 포스트를 읽어 보고 바로 오픈 소스를 시작 하는 것도 좋지만 먼저 실습을 해 보는 것이 가장 도움이 될 것이다. 자신의 리파지토리에서 실습 하고 싶다면 그래도 좋지만 혹시 모든 과정을 실습 해 보고 싶다면 https://github.com/fsoftwareengineer 를 이용해 실습 하길 바란다. 이슈는 다양하게 만들 수 있으니 혹시 이슈가 떨어지면 댓글로 실습 요청한다고 달아주면 된다. 실습 관련 하여 https://github.com/fsoftwareengineer/githubtutorial/blob/master/README.md 다음 글을 참고한다.




    '소프트웨어 개발 툴' 카테고리의 다른 글

    맥북 Homebrew 설치하기  (2) 2019.02.03
    git 명령어: git branch  (1) 2019.02.01
    git 명령어 : git cherry-pick  (3) 2019.01.30
    JMap, JHat으로 Heap Dump 분석  (0) 2019.01.27
    깃과 깃허브 사용법  (5) 2019.01.23

    댓글

f.software engineer @ All Right Reserved