향상된 Git 흐름 설명
게시 됨: 2022-03-11실수로 Git으로 손상을 입히는 것은 너무 쉽습니다. 그러나 Git을 사용하는 가장 좋은 방법은 항상 논란의 여지가 있습니다.
Git 자체는 기본 분기 작업만 자세히 설명하므로 사용 패턴(예: 분기 모델)은 사용자 의견의 문제로 남게 됩니다. Git 분기 모델은 소프트웨어 개발자가 코드베이스를 변경할 때 필연적으로 발생하는 혼란을 조직화하여 고통을 덜어줍니다.
많은 개발자와 마찬가지로 실제 소프트웨어 개발을 계속할 수 있도록 "그냥 작동하는" 무언가를 원했습니다. 그래서 Git 사용자에게 자주 권장되는 분기 모델인 Git flow 를 선택했습니다. 처음에는 Git 흐름의 논리를 사용하고 있었지만 실제로 문제가 발생할 때까지는 그럴 수 있습니다. 또는 Git 흐름이 채택하기에 적합하지 않은 것 같습니다. 결국 수많은 변수가 작용하고 모든 상황에서 단일 분기 모델이 잘 작동하지는 않습니다.
좋은 소식! 기존 Git 흐름 모델의 변형인 향상된 Git 흐름 은 주요 이점을 유지하면서 Git 흐름 워크플로의 보다 일반적인 조작을 단순화합니다.
고전적인 Git Flow 모델의 화려함과 불행
나는 상당한 가치 증가 (즉, 릴리스 )로 발전하는 제품을 개발할 때 Git 흐름이 얼마나 뛰어난지를 발견한 이래로 Git 흐름을 강력하게 옹호해 왔습니다.
스크럼 기반 개발에서 일반적으로 사용되는 2주 이상의 스프린트와 같이 상당한 가치 증가는 완료하는 데 상당한 시간이 필요합니다. 개발 팀이 이미 프로덕션에 배포한 경우 프로덕션 코드가 있는 동일한 위치(예: 사용하는 Git 리포지토리의 기본 분기)에 다음 릴리스의 범위가 누적되면 문제가 발생할 수 있습니다.
제품이 아직 초기 개발 단계에 있는 동안(즉, 프로덕션도 없고 제품의 실제 사용자도 없음) 팀이 모든 것을 메인 브랜치에 보관하는 것은 괜찮습니다. 사실, 그것은 괜찮은 것 이상입니다. 이 전략은 많은 의식 없이 가장 빠른 개발 속도를 허용합니다. 그러나 프로덕션 환경에서는 상황이 바뀝니다. 그러면 실제 사람들은 안정적인 제품에 의존하기 시작합니다.
예를 들어 프로덕션에 즉시 수정해야 하는 치명적인 버그가 있는 경우 수정 사항을 배포하기 위해 지금까지 메인 브랜치에서 누적된 모든 작업을 롤백해야 하는 개발 팀은 큰 재앙이 될 것입니다. 그리고 적절한 테스트 없이 코드를 배포하는 것(코드가 반쯤 구워진 것으로 간주되든 잘 개발된 것으로 간주되든)은 분명히 선택 사항이 아닙니다.
이것이 Git 흐름을 포함하여 분기 모델이 빛나는 곳입니다. 정교한 분기 모델은 현재 사람들이 사용하는 시스템 버전에서 다음 릴리스를 분리 하는 방법, 해당 버전을 다음 릴리스로 업데이트 하는 방법, 중요한 버그의 핫픽스를 현재 버전에 도입 하는 방법에 대한 질문에 답해야 합니다.
Git 흐름 프로세스는 "main"(프로덕션 또는 "현재 버전" 분기)과 "develop"(개발 또는 "다음 릴리스" 분기)을 분리하고 기능/릴리스/핫픽스 분기 사용에 대한 모든 규칙을 제공하여 이러한 기본 시나리오를 해결합니다. . 릴리스 기반 제품의 개발 워크플로에서 발생하는 많은 골칫거리를 효과적으로 해결합니다.
그러나 고전적인 Git 흐름 모델에 잘 맞는 프로젝트를 사용하더라도 다음과 같은 일반적인 문제를 겪었습니다.
- Git 흐름은 두 개의 수명이 긴 분기, 세 가지 유형의 임시 분기 및 분기가 서로를 처리하는 방식에 대한 엄격한 규칙으로 복잡합니다. 이러한 복잡성은 실수를 더 쉽게 만들고 수정하는 데 필요한 노력을 증가시킵니다.
- 릴리스 및 핫픽스 분기에는 "이중 병합"이 필요합니다. 때때로 당신은 둘 다 하는 것을 잊을 수 있습니다. 스크립트 또는 VCS GUI 클라이언트 플러그인을 사용하여 Git 흐름 분기를 더 쉽게 만들 수 있지만 주어진 프로젝트에 관련된 모든 개발자의 모든 시스템에 대해 먼저 설정해야 합니다.
- CI/CD 워크플로에서는 일반적으로 릴리스 브랜치 자체의 최신 커밋과 메인에 대한 병합 커밋의 두 가지 최종 빌드로 끝납니다. 엄밀히 말하면, 메인에서 하나를 사용해야 하지만 둘은 일반적으로 동일하므로 혼동을 일으킬 수 있습니다.
"향상된 Git 흐름" 입력
내가 처음으로 향상된 Git 흐름을 사용한 것은 비공개 소스 프로젝트의 미개발 지역이었습니다. 나는 다른 개발자와 함께 일하고 있었고 우리는 메인 브랜치에 직접 커밋하여 프로젝트를 진행하고 있었습니다.
참고: 제품의 첫 번째 공개 릴리스까지는 개발 워크플로의 속도와 단순성을 위해 모든 변경 사항을 메인 브랜치에 직접 커밋하는 것이 절대적으로 합리적입니다. 아직 프로덕션이 없기 때문에 팀이 최대한 빨리 수정해야 하는 프로덕션 버그의 가능성은 없습니다. 따라서 고전적인 Git 흐름이 의미하는 모든 분기 마법을 수행하는 것은 이 단계에서 과도합니다.
그런 다음 우리는 초기 릴리스에 가까워졌고 그 시점을 넘어서면 메인 브랜치에 직접 커밋하는 것이 더 이상 편하지 않을 것이라는 데 동의했습니다. 우리는 꽤 빠르게 움직였고, 비즈니스 우선 순위는 견고한 개발 프로세스를 확립할 여지를 많이 남기지 않았습니다.
고전적인 Git 흐름 모델에 대한 유효한 사례인 것 같습니다. 별도의 메인 브랜치와 개발 브랜치, 그리고 상당한 가치 증가 사이에 충분한 시간이 있기 때문에 대부분 수동 QA로 충분한 결과를 얻을 수 있다는 확신이 있었습니다. 내가 Git 흐름을 옹호할 때 내 동료가 비슷한 것을 제안했지만 몇 가지 중요한 차이점이 있습니다.
처음에는 뒤로 밀었습니다. 고전적인 Git 흐름에 대해 제안된 "패치" 중 일부는 너무 혁명적인 것 같았습니다. 나는 그들이 주요 아이디어를 깨뜨릴 수 있다고 생각했고 전체 접근 방식이 실패할 것이라고 생각했습니다. 그러나 더 깊이 생각해 보니 이러한 조정이 실제로 Git 흐름을 방해하지 않는다는 것을 깨달았습니다. 한편, 위에서 언급한 모든 문제점을 해결하여 더 나은 Git 분기 모델로 만듭니다.
그 프로젝트에서 수정된 접근 방식으로 성공을 거둔 후, 저는 영구적인 코드베이스 소유자이자 아웃소싱 개발자 한두 명이 때때로 도움을 줬던 소규모 팀이 있는 다른 비공개 소스 프로젝트에서 이 방법을 사용했습니다. 이 프로젝트에서 우리는 6개월 만에 프로덕션에 들어갔고, 그 이후로 1년 넘게 CI 및 E2E 테스트를 사용해 왔으며 매달 릴리스가 있습니다.
이 새로운 분기 접근 방식에 대한 전반적인 경험은 매우 긍정적이어서 동료 개발자와 공유하여 기존 Git 흐름의 단점을 해결하는 데 도움을 주고 싶었습니다.
Classic Git Flow의 유사점: 개발 격리
향상된 Git 흐름에서 작업 격리를 위해 여전히 두 개의 수명이 긴 분기(main 및 Development)가 있습니다. (사용자는 더 이상 분기가 아니기 때문에 "기능"에 중점을 둔 핫픽스 및 릴리스 기능을 계속 가지고 있습니다. 차이점 섹션에서 자세히 설명하겠습니다.)
고전적인 Git 흐름 기능 분기에 대한 공식적인 명명 체계는 없습니다. 기능이 준비되면 개발에서 분기하고 다시 병합하여 개발하기만 하면 됩니다. 팀은 원하는 명명 규칙을 사용하거나 단순히 개발자가 "my-branch"보다 더 설명적인 이름을 사용하기를 바랄 수 있습니다. 향상된 Git 흐름도 마찬가지입니다.
일부 컷오프 지점까지 개발 분기에 축적된 모든 기능이 새 릴리스를 형성합니다.
스쿼시 병합
대부분의 시간 동안 히스토리를 훌륭하고 선형으로 유지하기 위해 기능 분기에 스쿼시 병합을 사용하는 것이 좋습니다. 이것이 없으면 팀이 몇 가지 기능 분기를 저글링할 때 커밋 그래프(GUI 도구 또는 git log --graph
)가 엉성해 보이기 시작합니다.
그러나 이 시나리오의 시각적 개체에 문제가 없더라도 스쿼시해야 하는 또 다른 이유가 있습니다. 스쿼싱 없이 커밋 히스토리 보기(일반 git log
( --graph
)와 GitHub 모두 포함)는 가장 단순한 병합 시나리오에서도 다소 일관성 없는 이야기를 제공합니다.
스쿼시 병합을 사용할 때 주의할 점은 원래 기능 분기 기록이 손실된다는 것입니다. 그러나 예를 들어 기능 분기 자체가 삭제된 후에도 스쿼시 병합된 풀 요청을 통해 기능 분기의 전체 원본 기록을 노출하는 GitHub를 사용하는 경우 이 경고가 적용되지 않습니다.
Classic Git Flow와의 차이점: 릴리스 및 핫픽스
릴리스 주기를 살펴보겠습니다. 릴리스 주기가 가장 중요한 작업이기 때문입니다. 개발에 축적된 것을 공개하려는 지점에 도달하면 엄격하게는 main의 상위 집합입니다. 그런 다음 클래식 및 향상된 Git 흐름 간의 가장 큰 차이점이 시작됩니다.

향상된 Git 흐름의 릴리스
향상된 Git 흐름으로 릴리스를 만드는 모든 단계는 기존 Git 흐름 프로세스와 다릅니다.
- 릴리스는 개발보다는 메인을 기반으로 합니다. 메인 브랜치의 현재 팁에 의미 있는 태그를 지정하세요 . "v"가 접두사로 붙는 ISO 8601 형식의 현재 날짜를 기반으로 하는 태그를 채택했습니다(예: v2020-09-09 ).
- 하루에 여러 릴리스가 있는 경우(예: 핫픽스) 필요에 따라 형식에 순차 번호나 문자가 붙을 수 있습니다.
- 태그는 일반적으로 출시 날짜와 일치하지 않습니다. 다음 릴리스 프로세스가 시작될 때 기본 분기가 어떻게 보였는지에 대한 참조를 Git이 유지하도록 하기 위한 것입니다.
-
git push origin <the new tag name>
을 사용 하여 태그를 푸시합니다 . - 그 후 약간의 놀라움이 있습니다. 로컬 메인 브랜치를 삭제합니다 . 곧 복원할 예정이므로 걱정하지 마십시오.
- main에 대한 모든 커밋은 여전히 안전합니다. 이전 단계에서 main에 태그를 지정하여 가비지 수집으로부터 보호했습니다. 이러한 모든 커밋(곧 다루게 될 핫픽스 포함)도 개발의 일부입니다.
- 주어진 릴리스에 대해 팀의 한 사람만 이 작업을 수행하는지 확인하십시오. 이른바 "릴리스 매니저" 역할입니다. 릴리스 관리자는 일반적으로 가장 경험이 많거나 가장 선임된 팀 구성원이지만 특정 팀 구성원이 이 역할을 영구적으로 맡는 것을 피하는 것이 좋습니다. 악명 높은 버스 요인을 높이기 위해 팀 간에 지식을 전파하는 것이 더 합리적입니다.
- 개발 브랜치의 팁 커밋에서 새로운 로컬 메인 브랜치를 생성합니다 .
-
git push --force
를 사용하여 이 새로운 구조를 푸시 하십시오. 원격 저장소가 그러한 "급격한 변경"을 그렇게 쉽게 받아들이지 않을 것이기 때문입니다. 다시 말하지만 다음과 같은 이유로 이 컨텍스트에서 보이는 것처럼 안전하지 않습니다.- 우리는 단지 메인 브랜치 포인터를 한 커밋에서 다른 커밋으로 옮기고 있을 뿐입니다.
- 한 번에 한 명의 특정 팀 구성원만 이 변경 작업을 수행합니다.
- 매일의 개발 작업은 개발 브랜치에서 이루어지므로 메인을 이렇게 옮겨서 다른 사람의 작업을 방해하지 않습니다.
- 당신은 당신의 새로운 릴리스가 있습니다! 스테이징 환경에 배포 하고 테스트합니다. (아래에서 편리한 CI/CD 패턴에 대해 논의할 것입니다.) 모든 수정 사항은 기본 브랜치로 직접 이동하고 그 때문에 개발 브랜치에서 분기되기 시작할 것입니다.
- 동시에 개발 분기에서 새 릴리스 작업을 시작할 수 있습니다. 이는 고전적인 Git 흐름에서 볼 수 있는 것과 동일한 이점입니다.
- 이 시점에서 현재 프로덕션(준비 중인 릴리스가 아님)에 핫픽스가 필요한 불행한 경우 아래의 "활성 릴리스 중 핫픽스 다루기..."에 이 시나리오에 대한 자세한 내용이 있습니다.
- 새 릴리스가 충분히 안정적인 것으로 간주 되면 최종 버전을 프로덕션 환경에 배포하고 모든 수정 사항을 선택하기 위해 개발을 위해 단일 스쿼시 병합을 수행합니다 .
향상된 Git 흐름의 핫픽스
핫픽스 사례는 두 가지입니다. 활성 릴리스가 없을 때 핫픽스를 수행하는 경우(즉, 팀이 개발 분기에서 새 릴리스를 준비하는 중) 간단합니다. 메인에 커밋하고 준비가 될 때까지 스테이징에서 변경 사항을 배포하고 테스트한 다음 프로덕션에 배포합니다.
마지막 단계로 다음 릴리스에 모든 수정 사항이 포함되도록 개발할 커밋을 선택합니다. 여러 핫픽스 커밋으로 끝나는 경우 여러 번 체리 선택하는 대신 패치를 만들고 적용하여 특히 IDE 또는 기타 Git 도구가 이를 용이하게 할 수 있는 경우 노력을 절약할 수 있습니다. 초기 릴리스 이후에 merge main to development를 스쿼시하려고 하면 개발 브랜치에서 수행한 독립적인 진행과 충돌이 발생할 가능성이 있으므로 권장하지 않습니다.
활성 릴리스 중 핫픽스를 처리하는 것(즉, 강제로 메인을 푸시하고 여전히 새 릴리스를 준비하는 경우)은 향상된 Git 흐름의 가장 약한 부분입니다. 릴리스 주기의 길이와 해결해야 하는 문제의 심각도에 따라 항상 새 릴리스 자체에 수정 사항을 포함하는 것을 목표로 하십시오. 이것이 가장 쉬운 방법이며 전체 워크플로를 전혀 방해하지 않습니다.
그것이 불가능할 경우(즉, 수정 사항을 빠르게 도입해야 하고 새 릴리스가 준비될 때까지 기다릴 수 없습니다.) 그런 다음 다소 복잡한 Git 절차를 준비하십시오.
- 브랜치를 생성합니다. 이를 "new-release"라고 부르지만 팀은 현재 main의 팁과 동일한 커밋에서 모든 명명 규칙을 채택할 수 있습니다. 신제품 출시를 푸시합니다.
- 현재 활성 릴리스에 대해 이전에 생성한 태그 커밋 시 로컬 메인 브랜치를 삭제하고 다시 생성합니다. 강제 푸시 메인.
- 기본에 필요한 수정 사항을 도입하고 스테이징 환경에 배포하고 테스트합니다. 준비가 되면 프로덕션에 배포하세요.
- 체리 따기 또는 패치를 통해 현재 메인에서 새 릴리스로 변경 사항을 전파하십시오.
- 그 후, 릴리스 절차를 다시 실행하십시오. 현재 메인의 팁에 태그를 지정하고 태그를 푸시하고, 새 릴리스 분기의 팁에서 로컬 메인을 삭제 및 재생성하고, 푸시 메인을 강제 실행합니다.
- 이전 태그가 필요하지 않을 수 있으므로 제거할 수 있습니다.
- 새 릴리스 분기는 이제 중복되므로 제거할 수도 있습니다.
- 이제 새 릴리스와 함께 평소와 같이 가시면 됩니다. 체리 따기 또는 패치를 통해 개발하기 위해 메인에서 긴급 핫픽스를 전파하여 마무리하십시오.
적절한 계획, 충분히 높은 코드 품질, 건전한 개발 및 QA 문화가 있다면 팀에서 이 방법을 사용해야 할 것 같지 않습니다. 만일의 경우를 대비하여 강화된 Git 흐름을 위해 이러한 재난 계획을 개발하고 테스트하는 것이 현명했지만 실제로 사용할 필요는 없었습니다.
향상된 Git 흐름을 기반으로 하는 CI/CD 설정
모든 프로젝트에 전용 개발 환경이 필요한 것은 아닙니다. 각 개발자 시스템에 정교한 로컬 개발 환경을 설정하는 것은 충분히 쉬울 수 있습니다.
그러나 전용 개발 환경은 보다 건강한 개발 문화에 기여할 수 있습니다. 개발 브랜치에서 테스트를 실행하고 테스트 범위를 측정하고 복잡성 메트릭을 계산하면 스테이징으로 끝나기 훨씬 전에 실수를 포착하여 실수 비용을 줄이는 경우가 많습니다.
향상된 Git 흐름과 결합할 때 특히 유용한 몇 가지 CI/CD 패턴을 발견했습니다.
- 개발 환경이 필요한 경우 개발 분기에 커밋할 때마다 빌드, 테스트 및 배포하도록 CI를 설정합니다. E2E 테스트에 적합하고 귀하의 경우에 의미가 있는 경우 여기에도 적합합니다.
- 기본 분기에 커밋할 때마다 스테이징 환경에 빌드, 테스트 및 배포하도록 CI를 설정합니다. E2E 테스트는 이 시점에서도 매우 유용합니다.
- 두 곳 모두에서 E2E 테스트를 사용하는 것이 중복되는 것처럼 보일 수 있지만 핫픽스는 개발 단계에서 발생하지 않는다는 점을 기억하십시오. 메인에 대한 커밋에서 E2E를 트리거하면 핫픽스 와 일상적인 변경 사항을 테스트하기 전에 테스트하지만 개발 커밋을 트리거하면 버그를 더 일찍 잡을 수 있습니다.
- 팀이 수동 요청 시 기본 환경에서 프로덕션 환경으로 빌드를 배포할 수 있도록 CI를 구성합니다.
이러한 패턴은 비교적 단순하지만 일상적인 개발 작업을 지원하는 강력한 기계를 제공합니다.
향상된 Git 흐름 모델: 개선 사항 및 가능한 제한 사항
향상된 Git 흐름은 모든 사람을 위한 것은 아닙니다. 그것은 주요 지점을 밀어내는 논란의 여지가 있는 전술을 활용하므로 순수주의자들은 그것을 분개할 수 있습니다. 하지만 실용적인 관점에서 보면 아무 문제가 없습니다.
언급했듯이 핫픽스는 릴리스 중에 더 까다롭지만 여전히 가능합니다. QA, 테스트 커버리지 등에 대한 적절한 주의를 기울이면 너무 자주 발생해서는 안 됩니다. 따라서 제 관점에서는 기존 Git 흐름과 비교하여 향상된 Git 흐름의 전반적인 이점에 대해 유효한 절충안입니다. 핫픽스가 더 자주 발생할 수 있는 더 큰 팀과 더 복잡한 프로젝트에서 향상된 Git 흐름이 얼마나 좋은지 듣고 싶습니다.
향상된 Git 흐름 모델에 대한 나의 긍정적인 경험은 또한 주로 비공개 소스 상용 프로젝트와 관련이 있습니다. 풀 요청이 종종 소스 트리의 이전 릴리스 파생을 기반으로 하는 오픈 소스 프로젝트의 경우 문제가 될 수 있습니다. 이를 해결하기 위한 기술적 장애물은 없습니다. 예상보다 더 많은 노력이 필요할 수 있습니다. 이러한 경우에 향상된 Git 흐름의 적용 가능성에 대해 오픈 소스 공간에서 많은 경험을 가진 독자의 피드백을 환영합니다.
향상된 Git 흐름에 대한 아이디어를 개발하는 데 중요한 역할을 한 Toptal 동료 Antoine Pham에게 특별한 감사를 드립니다.
Toptal 엔지니어링 블로그에 대한 추가 정보:
- 트렁크 기반 개발과 Git Flow
- 전문가를 위한 Git 워크플로: 좋은 Git 가이드
Microsoft 골드 파트너인 Toptal은 Microsoft 전문가로 구성된 엘리트 네트워크입니다. 언제 어디서나 필요한 전문가와 함께 고성능 팀을 구성하세요!