이전 포스팅에서 gitlab에서 clone, checkout, commit, push 등 소스 코드 관련 작업 방법을 다뤘다.
간략하게 정리하면 다음과 같다.
- clone - git 기반 형상 관리 시스템에서 로컬 개발 환경으로 소스 코드 내려 받기
- checkout - 작업하려는 branch로 로컬의 소스 코드 작업 공간 변경
- commit - 작업한 소스 코드를 로컬의 git 기반 형상 관리 시스템의 해당 branch에 저장
- push - 로컬의 git에 제출한 해당 branch의 소스 코드를 원격 git으로 저장
보통 기능 구현을 위한 branch에서의 작업은 로컬에 소스코드를 내려 받은 이후, 소스코드 작성과 테스트, commit, push, 개발버전 빌드 순으로 반복 진행된다.
branch에서 목표한 기능 구현이 모두 완료되면 master (main) 브랜치에 코드를 병합 (Merge) 해야 한다.
코드를 병합하기 전에 병합할 코드를 검토하는 코드 리뷰 (Code Reivew)를 진행한다.
코드 리뷰가 완료되면 코드를 병합 (Merge)한다.
SVN과 git의 차이
SVN 기반의 형상 관리와 git 기반의 형상 관리는 코드 리뷰를 요청하고 병합하는 과정이 조금 다르다.
개발 부서에서 SVN과 git을 모두 사용했는데, 아래와 같은 프로세스 차이가 있었다.
- SVN - 코드 리뷰 요청 → (코드 리뷰 → 수정) 반복 → 코드 병합 요청 → 코드 병합
- git - 코드 병합 요청 → (코드 리뷰 → 수정) 반복 → 코드 병합
일반적으로 기능을 구현하는 개발자에게 코드 병합 권한이 없기 때문에, 프로젝트 관리자에게 요청해야 한다.
프로젝트 관리자는 병합을 요청 받은 브랜치의 코드를 검토 (Code Review)하고 수정 사항을 도출한다.
일반적으로 다음 사항들을 검토한다.
- 목표 한 기능이 적절하게 구현되었는가? (코드 작성의 핵심 목적이다.)
- 불필요하거나 이상한 코드가 존재하는가? (권장 사항을 벗어나는 패턴은 수정해야 한다.)
- 가독성이 좋은가? (보기 어려운 코드는 이해하기도 어렵다.)
- 코드의 구성과 전개 과정에 대한 의도가 이해되는가? (코드 흐름을 쉽게 파악할 수 있어야 한다.)
위의 검토 사항을 벗어나는 사항들을 수정 사항으로 도출하고, 개발자에게 코드 수정을 요청한다. (반복)
모든 검토와 수정을 마치면 프로젝트 관리자가 코드를 병합한다. (Merge)
병합 된 코드는 빌드 (Build)하고 배포 (Release)하는데, 개발자 또는 프로젝트 관리자가 수행한다.
SVN 기반
SVN은 디렉토리 기반의 형상 관리 시스템으로, git과는 조금 다른 형태로 운영된다.
- trunk - 프로젝트에서 가장 중심이 되는 디렉토리 (git의 master 또는 main 브랜치와 동일)
- branches - 기능 추가, 수정을 위한 작업 디렉토리 (git의 일반적인 브랜치와 동일)
- tags - 공식 배포가 된 경우 배포 버전 별로 소스 코드 저장 공간 (git의 tags와 동일)
git은 master나 tag를 각 커밋에 대해 tagging 해서 구분하지만, svn은 각 폴더에 소스 코드 전체를 복사하는 개념이다.
SVN은 형상 관리 시스템에 코드 리뷰 기능이 없어 별도의 코드 리뷰 시스템을 사용한다.
개발 부서에 있을 때에는 Atlassian의 FishEye를 사용했다.
보통 다음 과정으로 진행한다.
- 작업한 branch에 대한 코드 리뷰를 코드 리뷰 시스템에서 생성 - 개발자
- 프로젝트 관리자(또는 리뷰어)에게 이메일로 생성한 코드 리뷰에 대한 검토 요청 - 개발자
- 코드 리뷰 시스템에서 해당 리비전의 코드 검토 (trunk와 diff) - 프로젝트 관리자 또는 리뷰어
- 검토 기준에 부합하지 않는 사항에 대한 수정 사항 도출 - 프로젝트 관리자 또는 리뷰어
- 수정 사항에 대한 코드 수정 - 개발자
- 코드 수정과 리뷰가 완료되면 프로젝트 관리자에게 코드 병합 (merge) 요청 - 개발자
- 코드 병합 - 프로젝트 관리자
- 병합 된 코드에 대한 빌드 및 배포 (Release) 수행 - 개발자 또는 프로젝트 관리자
git 기반
git은 branch 기반의 형상 관리 시스템이라 SVN보다 훨씬 편리하다.
- 모든 코드는 branch로 관리된다.
- 특정 branch를 master (또는 main) branch로 지정하여 SVN의 trunk 처럼 운영한다.
- 각 branch는 코드를 push한 commit 단위로 구성되며, 최종 commit이 해당 branch의 최종 상태이다.
- main (master)과 tag는 특정 branch 또는 commit에 tagging 하는 방식을 사용한다.
개인적으로 git에 대한 이해를 위해 다음 도서를 참고했다.
github, gitlab, bitbucket 등 git 기반의 형상 관리 시스템은 코드 리뷰 기능이 있어 별도의 코드 리뷰 시스템이 없어도 된다.
- 개발자가 작업을 마치면 프로젝트 관리자에게 merge 요청 (Pull Request)
- 요청 받은 프로젝트 관리자는 코드 리뷰 (Code Review) 진행
- 검토 기준에 부합하지 않는 사항에 대한 수정 사항 도출 및 코드 수정
- 수정이 완료되면 프로젝트 관리자는 코드 병합 (Merge)
즉, git이 훨씬 간단하다.
다음은 예제 프로젝트를 사용해서 gitlab에서 코드 리뷰와 코드 병합을 진행하는 방법에 대해 살펴본다.
Pull Request (Merge Request)
github에서는 Pull Request라는 표현을 사용하지만, gitlab에서는 Merge Request라는 표현을 사용한다.
그 외에는 github과 거의 동일하다.
예제 프로젝트에서는 main (master) 브랜치가 있고, 작업을 진행한 env19-modify-dockerfile 브랜치가 있다.
env19-modify-dockerfile을 main (master) 브랜치에 병합하는 것이 목표다.
좌측의 Merge requests를 클릭한다.
우측 상단의 New merge request를 클릭한다.
작업한 브랜치와 병합할 브랜치를 선택한다.
- Source branch - 개발 작업을 진행한 브랜치를 선택한다. env19-modify-dockerfile을 선택했다.
- Target branch - main (master) 브랜치에 병합할 것이므로 기본 설정을 그대로 둔다.
Compare branches and continue 버튼을 클릭한다.
Title과 Description을 작성한다.
- Title - App 이름과 간략한 요약을 작성한다. (ex. [Jenkins Agent Python] Jenkins SSH Agent 빌드 이미지 생성)
- Description - 구현한 기능에 대한 간략한 설명을 작성한다. Markdown 포맷을 지원한다.
개발 부서에 있을 때 Description에는 주로 다음과 같은 항목을 기입했다. 예시이므로 적절하게 활용하면 된다.
- 개요 - 구현한 기능에 대한 간략한 설명
- 구현 내용 - 작성한 코드에 대한 간략한 요약
- 테스트 - 테스트 진행한 범위 (ex. 개발자 테스트, 통합 테스트 등)
- 참고 문서 - 해당 기능과 관련한 이슈 (이슈 관리 시스템), 개발 문서 등
아래 부분에 코드 리뷰 관련 사항을 선택하고 Create merge request를 클릭한다.
- Assignee - 코드를 병합할 사람을 지정한다. 여러명 지정은 Premium (유료) 버전에서 가능하다.
- Reviewer - 코드를 리뷰(검토)할 사람을 지정한다. 여러명 지정은 Premium (유료) 버전에서 가능하다.
- Milestone과 Label은 GitLab에 설정한 경우 사용한다. 사용하지 않았다.
- Merge option - Delete source branch when merge request is accepted. 를 사용한다. Merge 되면 작업한 branch가 자동 삭제된다.
- Commits - 제일 하단에 Commit한 이력이 표시된다.
'Squash commits when merge request is accepted.' 옵션은 Merge 할때 브랜치에서 커밋한 내역을 유지할 것인지 결정하는 부분이다.
체크하면 기존 브랜치에서 작업한 내역은 하나의 커밋으로 통합되고, main (master) 브랜치에는 하나의 커밋 분기 이력만 남는다.
그림으로 설명하면 좀 더 이해하기 쉽다.
- A에서 master는 1번 커밋이고, 브랜치에서 작업한 최종 결과가 2번 커밋이다.
- 1번과 2번을 병합 (Merge) 해서 3번 커밋을 새로운 master로 생성하는 것이 목적이다.
- Squash commits ~~~ 옵션을 사용하지 않으면 B와 같이 이력이 남는다.
- Squash commits ~~~ 옵션을 사용하면 C와 같이 이력이 남는다.
C와 같이 되면 버그가 발생했을 경우 어느 커밋부터 발생했는지 찾기 어려운 부분이 있어 사용하지 않았다.
- 작업 브랜치 하위에 브랜치를 추가 생성하여 작업한 것을 기존 작업 브랜치에 합칠 때에는 유용하다.
- 작업 브랜치를 main (master)에 합칠 때에는 이력 관리를 위해 가급적 사용하지 않는 것이 좋은 것 같다.
아래 사이트에서 정리한 내용을 참고한다.
Pull Request (Merge Request) 생성이 완료되었다.
코드 리뷰
상세 페이지의 Changes 탭을 클릭하면 코드 변경 사항을 확인할 수 있다.
코드에 마우스를 올리면 왼쪽에 말풍선이 표시되는데 확인이 필요한 사항에 대해 코멘트 할 수 있다.
코멘트를 작성하고 Start a review나 Add commnet now를 클릭한다.
- Start a review는 리뷰를 시작했다는 알림이 발생한다.
- Add comment now는 리뷰 시작은 하지 않았지만 코멘트만 남길때 사용한다.
리뷰 요청자는 해당 코멘트에 대한 답변을 기록한다.
- Resolve thread를 클릭하면 해당 사항에 대한 완료 여부를 표시한다.
- 코드를 수정해서 커밋했거나, 답변만으로 종료할 수 있는 경우 클릭한다.
- 우측 상단에 해결되지 않은 코멘트 개수가 표시된다. 모두 해결하는게 좋다.
- 코드를 수정한 경우 커밋하고 수정했다는 코멘트를 남겨주는게 리뷰어에 대한 예의이다.
이런 식으로 코드 리뷰를 진행하고, 더 이상 검토할 항목이 없으면 Overview 탭으로 이동하여 Approve를 클릭한다.
검토가 완료되었다는 의미이다.
Merge
모든 검토 사항에 대한 조치가 완료되면 코드 병합 (Merge)를 진행한다.
Approve 버튼 아래에 있는 Merge 버튼을 클릭한다.
Delete source branch는 Merge 이후 기존의 작업 브랜치를 삭제할 것인지 결정하는 부분이다.
Pull Requset 생성할 때 Merge option의 Delete source branch when merge request is accepted. 항목 체크 여부에 따라 기본 값이 설정된다.
예제 프로젝트에서는 Merge 버튼을 누르면 추가 작업 없이 Merge가 완료되었다.
브랜치 목록에서도 기존에 생성했던 작업 브랜치가 삭제 된 것을 확인할 수 있다.
Merge 버튼을 눌렀을 때 추가 작업 없이 Merge가 완료된 것은 추가 설명이 필요하다.
git은 기본적으로 Fast Forward Merge와 3-way Merge 두 가지를 지원한다.
SVN에 없는 Fast Forward Merge가 정말 좋은 기능이다.
Fast Forward Merge
git 기반 형상 관리 시스템에서 master (main)와 tag는 각 커밋에 tagging 하는 형태로 관리한다.
이 부분이 Fast Forward Merge를 가능하게 하는 가장 대표적인 특징이다.
용어 그대로 빨리 감기하는 것과 동일한 개념으로 Merge를 수행한다.
아래 그림을 보면 이해하기 쉽다.
현재 1번 커밋이 Master 브랜치이고, 1번 커밋을 기준으로 작업 브랜치를 작업해서 2번 커밋까지 진행했다.
작업 브랜치를 생성할때의 기준인 Master 브랜치가 2번 커밋을 병합할때와 동일하다.
- SVN은 1번과 2번을 병합해서 3번을 생성하여 Trunk에 커밋한다. (3-way Merge)
- git에서는 Master 브랜치의 Tagging을 1번에서 2번으로 변경한다. (Fast Forward Merge)
얼마나 간단한가!!
작업 브랜치를 생성할때의 기준인 Master 브랜치와 2번 커밋을 병합할때의 Master 브랜치가 동일해야 한다.
작업 브랜치를 생성한 이후 Master 브랜치에 변경 사항이 발생한 경우 Fast Forward Merge를 사용할 수 없다.
이러한 경우에는 3-way Merge를 진행해야 한다.
3-way Merge
3-way Merge는 전통적인 코드 Merge 방식이다.
SVN에서는 3-way Merge가 기본이고, git에서는 Fast Forward Merge가 불가능하면 3-way Merge를 진행해야 한다.
아래 그림을 보면 이해가 쉽다.
현재 1번 커밋이 Master 브랜치이고, 1번 커밋을 기준으로 작업 브랜치를 작업해서 3번 커밋까지 진행했다. (그림 A)
3번을 커밋까지 진행하는 도중에 1번 커밋이 다른 브랜치와 병합되었고, 새로 생성 된 2번 커밋이 새로운 Master 브랜치가 되었다. (그림 B)
이러한 경우 2번 커밋과 3번 커밋을 병합해야 하는데, 3번 커밋의 브랜치는 1번 커밋을 기준으로 생성했으므로 2번 커밋과 차이가 존재한다.
1번에서 2번으로 변경 된 사항을 포함하면서, 3번의 코드 내용까지 반영해야 하므로 3-way Merge를 수행하고 4번 커밋을 생성한다. (그림 C)
3-way Merge는 눕혀놓은 Y자를 생각하면 이해하기 쉽다.
- 코드 병합 과정을 기준으로 기존 코드와 변경 된 코드가 필요하다. (입력 2개)
- 코드 병합을 하면 하나의 병합 된 코드가 생성된다. (출력 1개)
그림으로 표현하면 다음과 같다.
실제로 3-way Merge를 진행하면 다음과 같은 화면 구성으로 진행된다.
- 좌측에는 기존 코드, 우측에는 변경된 코드가 나온다.
- 가운데는 병합 코드를 작업하는 부분으로, 좌측과 우측에서 필요한 부분을 넣는다.
- 기존 코드, 병합 코드, 변경 코드 영역의 중간에는 화살표가 있다. (IDE마다 다를 수 있음)
- 병합 코드에 넣을 부분을 선택하고 화살표를 누르면 해당 코드가 병합 코드에 입력 된다.
3-way Merge는 코드 작업을 하면서 피할 수 없는 과정이므로 익혀두는 것이 굉장히 유용하다.
- 여러 명이 함께 코드 작업을 하는 경우
- 작업 중인 특정 부분을 이전 커밋으로 되돌리고자 하는 경우
git 관련 자세한 사항은 다음 도서를 참고하면 도움이 된다.
'::: IT인터넷 :::' 카테고리의 다른 글
우분투 환경에 Chrome 브라우저 설치하기 (0) | 2021.12.02 |
---|---|
Jenkins에서 파이썬 빌드 구성하기 (0) | 2021.09.09 |
윈도우 10에서 Docker Desktop 없이 Docker 사용하기 (3) | 2021.09.03 |
파이썬 프로젝트 폴더 구성하기 (0) | 2021.09.02 |
Jenkins 빌드에서 Git 경로로 릴리즈와 개발중 배포 구분하여 설정하기 (0) | 2021.08.30 |