Skip to content

GitLab flow

Github에서 말하는 flow는 너무나도 간단하여 배포, 환경 구성, 릴리즈, 통합에 대한 이슈를 남겨둔 것이 많았다. 그것을 보안하기 위해 GitLab에서 관련 내용들을 추가적으로 덧붙여 설명한 것을 일컫는다.

About

Git은 다양한 분기 전략과 워크플로를 허용합니다. 이 때문에 많은 조직에서 워크플로가 너무 복잡하거나 명확하게 정의되지 않았거나 문제 추적 시스템과 통합되지 않았습니다. 따라서 우리는 GitLab 흐름을 명확하게 정의된 모범 사례 집합으로 제안합니다. 기능 중심 개발 (Feature-driven development; FDD)기능 분기 (Feature Branch) 를 문제 추적 과 결합 합니다.

GitLab 흐름으로 분기 릴리스

소프트웨어를 외부 세계에 릴리스해야 하는 경우에만 릴리스 분기 (Release Branch)로 작업해야 합니다.

Release_branches_with_GitLab_flow.jpg

main을 시작점으로 하여 안정적인 분기를 만들고 가능한 한 늦게 분기합니다. 이렇게 하면 여러 분기에 버그 수정을 적용해야 하는 시간을 최소화할 수 있습니다.

릴리스 분기를 발표한 후에는 분기에 심각한 버그 수정만 추가하십시오. 가능한 경우 먼저 이러한 버그 수정을 에 병합 main한 다음 릴리스 분기에 cherry-pick합니다.

릴리스 분기 (Release Branch)로 병합하여 시작하는 경우 에 cherry-pick하는 것을 잊어버릴 수 있으며 main 이후 릴리스에서 동일한 버그가 발생합니다.

릴리스에 병합한 다음 체리 선택하는 것을 "업스트림 우선 (upstream first)" 정책이라고 하며 GoogleRed Hat 에서도 시행하고 있습니다.

릴리스 분기에 버그 수정을 포함할 때마다 새 태그를 설정 하여 패치 버전을 높입니다. 이 때, Semantic Versioning을 준수합니다.

일부 프로젝트에는 최신 릴리스 분기와 동일한 커밋을 가리키는 안정적인 분기도 있습니다. 이 흐름에서는 프로덕션 분기(또는 Git 흐름 분기)가 있는 것이 일반적이지 않습니다.

GitLab 흐름으로 요청 병합/끌어오기

기능 분기에서 몇 시간 이상 작업하는 경우 중간 결과를 나머지 팀과 공유하십시오. 이렇게 하려면 아무에게도 할당하지 않고 병합 요청을 만듭니다. 대신 설명이나 댓글에서 사람들을 언급하십시오 (예: /cc @mark @susan) 이것은 병합 요청이 아직 병합할 준비가 되지 않았지만 피드백을 환영한다는 것을 나타냅니다.

팀 구성원은 일반적으로 병합 요청에 대해 또는 라인 주석이 있는 특정 라인에 주석을 달 수 있습니다. 병합 요청은 코드 검토 도구 역할을 하며 별도의 코드 검토 도구가 필요하지 않습니다. 검토 결과 단점이 드러날 경우 누구나 수정 사항을 커밋하고 푸시할 수 있습니다. 일반적으로 이 작업을 수행하는 사람은 병합 요청의 작성자입니다. 병합 요청의 diff는 새 커밋이 분기에 푸시될 때 자동으로 업데이트됩니다.

기능 분기를 병합할 준비가 되면 변경하려는 코드베이스에 대해 가장 잘 알고 있는 사람에게 병합 요청을 할당하십시오. 또한 피드백을 원하는 다른 사람을 언급하십시오. 할당된 사람이 결과에 만족하면 분기를 병합할 수 있습니다. 할당된 사람이 불편하면 추가 변경을 요청하거나 병합하지 않고 병합 요청을 닫을 수 있습니다.

GitLab에서는 분기와 같이 수명이 긴 분기를 보호하는 것이 일반적 main이므로 대부분의 개발자가 수정할 수 없습니다. 따라서 보호된 분기로 병합하려면 유지 관리자 역할을 가진 사람에게 병합 요청을 할당하십시오.

기능 분기를 병합한 후 소스 제어 소프트웨어에서 제거해야 합니다. GitLab에서는 병합할 때 이를 수행할 수 있습니다. 완료된 분기를 제거하면 분기 목록에 진행 중인 작업만 표시됩니다. 또한 누군가가 문제를 다시 열 경우 문제를 일으키지 않고 동일한 브랜치 이름을 사용할 수 있습니다.

GitLab 흐름으로 문제 추적

GitLab 흐름은 코드와 이슈 트래커 간의 관계를 보다 투명하게 만드는 방법입니다.

코드에 대한 모든 중요한 변경은 목표를 설명하는 문제로 시작해야 합니다. 모든 코드 변경에 대한 이유가 있으면 나머지 팀에 알리고 기능 분기의 범위를 작게 유지하는 데 도움이 됩니다. GitLab에서 코드베이스에 대한 각 변경 사항은 문제 추적 시스템의 문제로 시작됩니다. 아직 문제가 없으면 변경 작업에 한 시간 이상의 작업이 필요한 경우 문제를 만듭니다. 많은 조직에서 문제 제기는 스프린트 계획에 사용되기 때문에 개발 프로세스의 일부입니다.

문제 제목은 시스템의 원하는 상태를 설명해야 합니다.

예를 들어 "관리자는 사용자를 제거할 수 없음" 보다 관리자로서 오류 없이 사용자를 제거하고 싶습니다 라는 제목이 더 좋습니다. [^0]

코딩할 준비가 되면 분기에서 문제에 대한 main 분기를 만듭니다. 이 분기는 이 변경과 관련된 모든 작업의 ​​장소입니다.

지점의 이름은 조직 표준에 따라 결정될 수 있습니다. 완료했거나 코드에 대해 논의하려면 병합 요청을 엽니다. 병합 요청은 변경 사항을 논의하고 코드를 검토할 수 있는 온라인 공간입니다.

병합 요청을 열었지만 아무에게도 할당하지 않으면 임시 병합 요청 (Draft) 입니다. 이들은 제안된 구현을 논의하는 데 사용되지만 아직 main 분기에 포함할 준비가 되지 않았습니다.

병합 요청의 제목을 [Draft] 또는 Draft: 또는 (Draft) 로 시작하여 준비되기 전에 병합되지 않도록 합니다.

코드가 준비되었다고 생각되면 병합 요청을 검토자에게 할당합니다.

검토자는 코드가 분기 에 포함될 준비가 되었다고 생각되면 변경 사항을 병합할 수 있습니다. 병합 버튼을 누르면 GitLab이 코드를 병합하고 나중에 이 이벤트를 볼 수 있도록 병합 커밋을 생성합니다. 병합 요청은 분기가 없이 병합될 수 있는 경우에도 항상 병합 커밋을 생성합니다. 이 병합 전략을 Git에서는 "빨리 감기 없음 (no fast-forward)"이라고 합니다. 병합 후 더 이상 필요하지 않은 기능 분기를 삭제합니다. GitLab에서 이 삭제는 병합 시 옵션입니다.

분기가 병합되었지만 문제가 발생하여 문제가 다시 열렸다고 가정합니다. 이 경우 첫 번째 분기가 병합될 때 삭제되었으므로 동일한 분기 이름을 다시 사용하는 데 문제가 없습니다. 언제든지 모든 문제에 대해 최대 하나의 분기가 있습니다. 하나의 기능 분기가 둘 이상의 문제를 해결할 수 있습니다.

병합 요청의 문제 연결 및 닫기

커밋 메시지 또는 병합 요청에 대한 설명에서 문제를 언급하여 문제에 연결합니다. (예: "Fixes #16" 또는 “Duck typing is preferred. See #12.”)

그런 다음 GitLab은 언급된 문제에 대한 링크를 만들고 병합 요청에 다시 연결되는 문제에 주석을 만듭니다.

연결된 문제를 자동으로 닫으려면 "수정 (fixes)" 또는 "닫기 (closes,)" - 콤마(, 까지 포함 이다! - 라는 단어를 사용하여 언급하세요. (for example, “fixes #14” or “closes #67.”). GitLab은 코드가 기본 분기에 병합될 때 이러한 문제를 닫습니다.

여러 저장소에 걸쳐 있는 문제가 있는 경우 각 저장소에 대한 문제를 만들고 모든 문제를 상위 문제에 연결합니다.

rebase 로 커밋 스쿼시

Git을 사용하면 대화형 리베이스(rebase -i)를 사용하여 여러 커밋을 하나로 묶거나 재정렬할 수 있습니다. 이 기능은 몇 개의 작은 커밋을 단일 커밋으로 바꾸거나 순서를 보다 논리적으로 만들려는 경우에 도움이 됩니다.

pick c6ee4d3 add a new file to the repo
pick c3c130b change readme

# Rebase 168afa0..c3c130b onto 168afa0
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out
~
~
~
"~/demo/gitlab-ce/.git/rebase-merge/git-rebase-todo" 20L, 673C

그러나 동일한 분기에 다른 활성 기여자가 있는 경우 원격 서버에 푸시한 커밋을 리베이스하지 않아야 합니다. 리베이스는 모든 변경 사항에 대해 새 커밋을 생성하기 때문에 동일한 변경 사항에 여러 식별자가 있기 때문에 혼동을 일으킬 수 있습니다. 동일한 브랜치에서 작업하는 모든 사람의 기록이 귀하의 기록과 일치하지 않기 때문에 병합 오류가 발생할 수 있습니다. 작성자나 다른 기여자에게 정말 골칫거리가 될 수 있습니다. 또한 누군가가 이미 코드를 검토한 경우 리베이스하면 마지막 검토 후 변경된 내용을 말하기가 어렵습니다.

달리 동의하지 않는 한 다른 사람이 작성한 커밋을 절대 리베이스해서는 안됩니다. 이것은 기록을 다시 쓸 뿐만 아니라 저자 정보도 잃게 됩니다. Rebase는 다른 작성자가 의 일부로 귀속되고 공유되지 않도록 합니다 git blame.

병합에 많은 커밋이 포함되는 경우 실행 취소가 더 어려워 보일 수 있습니다. GitLab Squash-and-Merge 기능 을 사용하여 병합하기 직전에 모든 변경 사항을 하나의 커밋으로 스쿼시하여 이 문제를 해결할 수 있습니다. 다행히도 모든 커밋으로 병합을 취소할 수 있습니다. 이를 수행하는 방법은 병합 커밋을 되돌리는 것입니다. 병합을 되돌리는 이 기능을 유지하는 것은 수동으로 병합할 때 항상 "no fast-forward" (--no-ff) 전략을 사용하는 좋은 이유입니다.

기능 분기에서 병합 커밋 줄이기

병합 커밋이 많으면 저장소 기록이 지저분해질 수 있습니다. 따라서 기능 분기에서 병합 커밋을 피해야 합니다. 종종 사람들은 브랜치 에서 커밋한 후 커밋을 재정렬하기 위해 rebase를 사용하여 병합 커밋을 피합니다. rebase를 사용하면 기능 브랜치에 병합할 때 병합 커밋을 방지하고 main깔끔한 선형 기록을 만듭니다.

리베이스할 때마다 동일한 충돌을 해결해야 할 수 있으므로 리베이스하면 더 많은 작업이 생성될 수 있습니다. 때때로 기록된 해상도( rerere)를 재사용할 수 있지만 충돌을 한 번만 해결하면 되므로 병합하는 것이 더 좋습니다. Atlassian은 블로그에서 병합과 리베이스 간의 절충점에 대해 더 철저하게 설명합니다.

많은 병합 커밋이 생성되는 것을 방지하는 좋은 방법은 main을 기능 분기에 자주 병합하지 않는 것입니다.

main을 병합해야 하는 세 가지 이유는 다음과 같다.

  • 새 코드 활용 (utilizing new code)
  • 병합 충돌 해결 (resolving merge conflicts)
  • 오랫동안 진행되고 있는 브랜치의 업데이트 (updating long-running branches)

기능 브랜치를 생성한 후 도입된 일부 코드를 사용해야 하는 main경우 커밋을 선택하여 문제를 해결할 수 있습니다.

기능 분기에 병합 충돌이 있는 경우 병합 커밋을 만드는 것이 이를 해결하는 표준 방법입니다.

.gitattributes를때로는 병합 충돌을 줄이는 데 사용할 수 있습니다. 예를 들어, 여러 새 항목이 서로 충돌하지 않도록union merge driver를 사용하도록 변경 로그 파일을 설정할 수 있습니다.

병합 커밋을 생성하는 마지막 이유는 장기 실행 기능 분기를 프로젝트의 최신 상태로 최신 상태로 유지하기 위한 것입니다. 여기서 해결책은 기능 분기를 짧게 유지하는 것입니다. 대부분의 기능 분기는 하루 미만의 작업 시간이 소요됩니다.

기능 분기 작업이 하루 이상 걸리는 경우가 많으면 기능을 더 작은 작업 단위로 분할하십시오.

기능 분기를 하루 이상 열어 두어야 하는 경우 최신 상태로 유지하기 위한 몇 가지 전략이 있습니다.

  • 한 가지 옵션은 CI(지속적 통합)를 사용 하여 하루를 시작할 때 main을 병합하는 것입니다.
  • 또 다른 옵션은 태그가 지정된 릴리스와 같이 잘 정의된 시점에서만 병합하는 것입니다.
  • Feature Toggle을 사용 하여 불완전한 기능을 숨겨서 main매일 다시 병합할 수도 있습니다.

자동 분기 테스트와 지속적인 통합을 혼동하지 마십시오. Martin Fowler는기능 분기에 대한 기사에서 다음과 같이 구분합니다. “[사람들]은 커밋할 때마다 모든 분기에서 CI 서버를 사용하여 빌드를 실행하고 있기 때문에 CI를 수행한다고 말합니다. 그것은 지속적인 구축이고 좋은 일이지만 통합이 없으므로 CI가 아닙니다.”

결론적으로, 병합 커밋을 방지하려고 노력해야 하지만 제거해서는 안 됩니다. 코드베이스는 깨끗해야 하지만 기록은 실제로 일어난 일을 나타내야 합니다. 소프트웨어 개발은 ​​작고 지저분한 단계로 이루어지며 기록에 이를 반영하는 것이 좋습니다. 도구를 사용하여 커밋의 네트워크 그래프를 보고 코드를 생성한 지저분한 기록을 이해할 수 있습니다. 코드를 리베이스하면 기록이 올바르지 않으며 도구가 커밋 식별자 변경을 처리할 수 없기 때문에 이를 수정할 방법이 없습니다.

자주 커밋하고 자주 푸시

개발 작업을 더 쉽게 만드는 또 다른 방법은 자주 커밋하는 것입니다. 테스트 및 코드 작업 세트가 있을 때마다 커밋해야 합니다. 작업을 개별 커밋으로 분할하면 나중에 코드를 살펴보는 개발자에게 컨텍스트를 제공합니다. 더 작은 커밋은 기능이 개발된 방법을 명확하게 합니다. 특정 시점으로 롤백하거나 관련 없는 여러 변경 사항을 되돌리지 않고 하나의 코드 변경 사항을 되돌리는 데 도움이 됩니다.

자주 커밋하면 작업을 공유하는 데 도움이 되며, 이는 모든 사람이 작업 중인 내용을 알 수 있도록 하는 데 중요합니다. 아직 검토할 준비가 되지 않은 경우에도 기능 분기를 자주 푸시해야 합니다. 기능 분기 또는 병합 요청 에서 작업을 공유 하면 팀 구성원이 작업을 복제하는 것을 방지할 수 있습니다. 완료되기 전에 작업을 공유하면 변경 사항에 대한 토론과 피드백도 가능합니다. 이 피드백은 검토되기 전에 코드를 개선하는 데 도움이 될 수 있습니다.

좋은 커밋 메시지를 작성하는 방법

커밋 메시지는 커밋 내용뿐만 아니라 의도를 반영해야 합니다. 커밋에서 변경 사항을 볼 수 있으므로 커밋 메시지에서 변경한 이유를 설명해야 합니다.

좋은 커밋 메시지의 예는 "템플릿을 결합하여 사용자 보기에서 중복 코드를 줄입니다."입니다. "변경", "개선", "수정" 및 "리팩토링"이라는 단어는 커밋 메시지에 많은 정보를 추가하지 않습니다. 자세한 내용은 커밋 메시지 형식 지정에 대한 Tim Pope의 노트 를 참조하세요.

커밋 메시지에 더 많은 컨텍스트를 추가하려면 변경 출처에 대한 정보를 추가하는 것이 좋습니다. 예를 들어 GitLab 문제의 URL 또는 Jira 문제 번호에는 변경 사항에 대한 심층적인 컨텍스트가 필요한 사용자를 위한 추가 정보가 포함됩니다.

Properly escape special characters in XML generation.

Issue: gitlab.com/gitlab-org/gitlab/-/issues/1

병합 전 테스트

이전 워크플로에서 CI(지속적 통합) 서버는 일반적으로 main분기에서만 테스트를 실행했습니다. main개발자는 코드가 분기 를 손상시키지 않도록 해야 했습니다 . GitLab 흐름을 사용할 때 개발자는 이 main분기에서 분기를 생성하므로 절대 끊어지지 않는 것이 중요합니다. 따라서 각 병합 요청은 수락되기 전에 테스트해야 합니다. Travis CI 및 GitLab CI/CD와 같은 CI 소프트웨어는 프로세스를 단순화하기 위해 병합 요청 자체에 빌드 결과를 표시합니다.

병합 요청 테스트에는 한 가지 단점이 있습니다. CI 서버는 병합된 결과가 아니라 기능 분기 자체만 테스트합니다. main이상적으로는 서버가 각 변경 후에 분기를 테스트할 수도 있습니다. 그러나 커밋할 때마다 다시 테스트하는 main것은 계산 비용이 많이 들고 테스트 결과를 더 자주 기다리는 것을 의미합니다. 기능 분기는 수명이 짧아야 하므로 분기만 테스트하는 것은 허용되는 위험입니다. 새 커밋 main이 기능 분기와 병합 충돌을 일으키는 경우 main분기로 다시 병합하여 CI 서버가 테스트를 다시 실행하도록 합니다. 이전에 말했듯이 며칠 이상 지속되는 기능 분기가 자주 있는 경우 문제를 더 작게 만들어야 합니다.

기능 분기 작업

기능 분기를 만들 때 항상 최신 버전에서 분기하십시오 main. 작업이 다른 브랜치에 의존한다는 것을 시작하기 전에 알고 있다면 거기에서 브랜치를 할 수도 있습니다. 시작 후 다른 브랜치에서 merge해야 한다면 merge commit에 그 이유를 설명한다. 아직 공유 위치에 커밋을 푸시하지 않은 경우 main또는 다른 기능 분기를 기반으로 변경 사항을 통합할 수도 있습니다. 코드가 작동할 수 있고 그렇게 하지 않고도 깔끔하게 병합할 수 있는 경우 업스트림에서 다시 병합하지 마십시오. 필요할 때만 병합하면 나중에 main기록을 엉망으로 만드는 기능 분기에 병합 커밋이 생성되는 것을 방지할 수 있습니다.

브랜치 설명

feature
모든 기능 구현은 feature 브랜치에서 시작합니다. feature 브랜치는 master 브랜치에서 분기되고 머지됩니다.
master
gitlab flow의 master 브랜치 역할은 git flow의 develop 브랜치와 동일합니다. master 브랜치는 feature 브랜치에서 병합된 기능에 대해 test를 진행합니다. 전체적인 테스트가 진행되어 기능에 대한 보장이 되었다면 production 브랜치로 머지합니다.
만약 staging 단계를 원한다면 pre-production 브랜치로 머지를 진행합니다.
production
gitlab flow의 production 브랜치 역할은 git flow의 master 브랜치와 동일합니다. 테스트가 끝난 기능에 대해 배포를 하기 위한 브랜치입니다.
pre-production
master → production 브랜치 사이에 pre-production 브랜치를 두어 변경 사항을 바로 production에 배포하지 않고 test server에 배포하여 통합 테스트를 진행하거나 시간을 두고 반영하는 브랜치입니다.

Flows

Favorite site