어떤 Git 브랜칭 모델이 적합합니까?


378

우리 회사는 현재 간단한 트렁크 / 릴리스 / 핫픽스 분기 모델을 사용하고 있으며 회사 또는 개발 프로세스에 가장 적합한 분기 모델에 대한 조언을 원합니다.

  1. 워크 플로우 / 분기 모델

    아래는 내가 본 세 가지 주요 설명이지만 부분적으로 서로 상충되거나 우리가 겪은 후속 문제를 분류하기에 충분히 멀지 않습니다 (아래 설명 참조). 따라서 지금까지 우리 팀은 그다지 훌륭한 솔루션이 아닙니다. 더 나은 일을하고 있습니까?

  2. 병합 대 리베이스 (얽힌 대 순차적 이력)

    해야 하나 pull --rebase또는 작업까지 메인 라인에 다시 병합와 대기가 완료? 개인적으로 나는 합병에 의지한다. 왜냐하면 이것은 어떤 작업이 시작되고 완료되었는지에 대한 시각적 설명을 유지하기 때문이며, 심지어이 merge --no-ff목적을 선호하기도한다 . 그러나 다른 단점이 있습니다. 또한 많은 병합의 유용한 특성을 실현하지 않은 - 그것은 아니라고 교환 법칙이 성립 (마스터로 주제 분기를 병합하는 주제 지점에 평균 병합 마스터를하지 않습니다).

  3. 자연스러운 워크 플로를 찾고 있습니다

    절차가 간단한 규칙으로 특정 상황을 포착하지 않기 때문에 실수가 발생하는 경우가 있습니다. 예를 들어, 이전 릴리스에 필요한 수정은 물론 모든 분기로 업스트림을 병합 할 수 있도록 충분히 다운 스트림을 기반으로해야합니다 (이 용어의 사용법이 명확합니까?). 그러나 개발자가 다운 스트림에 추가로 배치해야한다는 사실을 깨닫기 전에 수정 프로그램이 마스터에 수정되며, 이미 푸시 된 경우 (심지어 더 나쁘거나 병합되거나 그에 기반한 것) 남아있는 옵션은 다음과 같습니다. 관련된 위험. 이와 같은 간단한 규칙을 사용하십니까?또한 여기에는 반드시 하나의 토픽 브랜치가 다른 토픽 브랜치를 반드시 배제해야하는 어색함이 포함됩니다 (공통 기준선에서 분기되었다고 가정). 개발자는 방금 작성한 코드가 더 이상 존재하지 않는 것처럼 느껴지는 다른 기능을 시작하고 싶지 않습니다.

  4. 체리 픽으로 인해 병합 충돌을 피하는 방법은 무엇입니까?

    병합 충돌을 만드는 확실한 방법은 가지 간 체리 픽을 선택하는 것입니다. 다시 병합 할 수 없습니까? 어느 지점에서든 동일한 커밋을 되돌리기 (이 방법은 무엇입니까)에 적용하면이 상황을 해결할 수 있습니까? 이것이 크게 병합 기반 워크 플로를 추진하지 않는 이유 중 하나입니다.

  5. 국소 가지로 분해하는 방법?

    토픽 브랜치에서 완성 된 통합을 조립하는 것이 좋을지 모르지만 종종 개발자가 작업을 명확하게 정의하지 않았으며 (때로는 "포킹"과 같이 간단하지 않음) 일부 코드가 이미 "기타"토픽에 들어간 경우, 위의 질문에 따르면 다시 거기에서 꺼낼 수 없습니까? 토픽 브랜치를 정의 / 승인 / 졸업 / 릴리즈하는 방법은 무엇입니까?

  6. 코드 검토 및 졸업과 같은 적절한 절차 는 물론 아름답습니다.

    그러나 우리는 단순히 이것을 관리하기에 충분히 얽힌 상태를 유지할 수 없습니다-어떤 제안? 통합 지점, 일러스트레이션?

다음은 관련 질문 목록입니다.

또한 작업 중심 개발 에 Plastic SCM이 작성하는 내용을 확인하고 Plastic을 선택하지 않은 경우 nvie의 분기 모델지원 스크립트를 연구하십시오 .


2
하아, 고마워, 실제로는 ... 나는 실제로 그 대부분을 읽었습니다 ... stuff :-). 평범한 솔루션에 정착하지 않고 완벽한 검색을 계속하는 것은 내가 알고있는 것입니다. 종종 이것은 실수이지만,이 경우에는 많은 위험에 처해 있으며 현재 해결해야 할 솔루션이 너무 지저분하거나 가난합니다. 그래서 내가 가진 모든 문제를 나열하기로 결정했습니다.
HiQ CJ

: 플라스틱 SCM 블로그는 적어도 통찰력에서의 토론에 자신의 의견을 던졌다 codicesoftware.blogspot.com/2010/08/...
이 HiQ CJ

1
"merge --no-ff"를 사용할 때는주의해야합니다. sandofsky.com/blog/git-workflow.html
Doppelganger

1
@Doppelganger --no-ff가 귀하가 게시 한 링크에 설명 된 문제에 얼마나 구체적으로 기여하고 있는지에 관심이 있습니다. 나에게 설명 된 문제는 검사 점 커밋으로 bisect의 실패와 그 경우 도움이되지 않는 git blame의 실패가 있지만 "--no-ff"가 사용하지 않는 것과는 달리 어떻게 변경하는지 알 수 없습니다. 저자는 --no-ff와의 병합으로 파일을 수정하지 않는다고 불평하지만 파일이 없으면 파일도 수정되지 않으며 이전 기록에서 이전 커밋 만 볼 수 있습니다.
codeling

다른 분기 모델 : 선인장 모델 barro.github.io/2016/02/… , 메인 라인 모델 bitsnbites.eu/a-stable-mainline-branching-model-for-git . 이 두 가지 브랜칭 모델은 gitflow와 다른 접근 방식을 제공합니다.
Mathieu Momal

답변:


90

DVCS에 대한 새로운 개발자가 알아야 할 가장 어려운 기능은 게시 프로세스 에 관한 것입니다 .

  • 필요한 원격 리포지토리를 가져 오기 (페치 / 풀) 할 수 있습니다.
  • 원하는 (베어) 저장소에 게시 (푸시) 할 수 있습니다

이를 통해 몇 가지 규칙을 준수하여 질문을 쉽게 할 수 있습니다.

지금:

워크 플로우 / 분기 모델 :

각 워크 플로우는 릴리스 관리 프로세스지원하기 위해 있으며 각 프로젝트에 맞게 조정됩니다.
내가 언급 한 워크 플로에 추가 할 수있는 것은 각 개발자가 기능 분기를 만들지 말고 "현재 개발자"분기 만 만들어야한다는 것입니다. 진실은 다음과 같습니다. 기능 (여러 기능이 너무 복잡해 졌기 때문에), 없음 (해제 준비가되지 않았기 때문에), 다른 기능 (원래 기능이 "모핑"되었기 때문에), ...

"통합 자"만이 "중앙"저장소에 공식 기능 분기를 설정해야하며, 개발자는 해당 기능에 맞는 작업의 일부를 리베이스 / 병합하기 위해 가져올 수 있습니다.

병합 대 리베이스 (얽힌 대 순차적 이력) :

나는 당신이 언급 한 답변을 좋아합니다 ( " 사내 개발을위한 git 사용법에 대한 워크 플로우 설명 ")

자연스러운 워크 플로우를 찾고 있습니다 .

수정 사항의 경우, 각 수정 사항을 버그 추적의 티켓과 연관시키는 데 도움이되므로 개발자는 이러한 수정 사항을 커밋해야하는 위치 (즉, 수정 사항에 대한 전용 지점)를 기억할 수 있습니다.
그런 다음 후크를 사용하면 유효성이 검사되지 않은 버그 수정 또는 푸시하지 않아야하는 분기의 푸시로부터 중앙 저장소를 보호 할 수 있습니다. (여기에 특정 솔루션이 없으므로이 모든 것을 환경에 맞게 조정해야합니다)

체리 픽으로 인해 병합 충돌을 피하는 방법은 무엇입니까?

Jakub Narębski그의 답변 에서 언급했듯이 , 체리 피킹은 드문 상황이 필요한 경우 예약해야합니다.
설정에 많은 체리 따기 (예 : "드문 일이 아닙니다")가 포함 된 경우 무언가 꺼져있는 것입니다.

동일한 커밋을 되돌릴 때 적용합니까 (어떻게 수행합니까?)

git revert 처리해야하지만 이상적이지는 않습니다.

국소 가지로 분해하는 방법?

브랜치가 아직 어디에나 밀리지 않는 한, 개발자는 커밋 히스토리를 재구성해야합니다 (한 번은 개발이보다 결정적이고 안정적인 형태를 취함).

  • 필요한 경우 여러 지점 (명확한 식별 기능별로 하나씩)
  • 한 지점 내에서 일관된 커밋 세트 ( Git Checkins 다듬기 참조 )

코드 검토 및 졸업과 같은 적절한 절차?

통합 브랜치 (전용 통합)를 통해 개발자는 다음을 수행 할 수 있습니다.

  • 원격 통합 브랜치에서 자신의 개발을 리베이스 (풀-리베이스)
  • 현지에서 해결
  • 그 레포로 개발을 밀어
  • 엉망이되지 않는 적분기로 확인하십시오.)

@UncleCJ : 보시다시피, 이것은 "최종 질문"에 대한 최종 답변 이 아닙니다 .;)
VonC

이해하고, 아이러니 한 느낌도 있지만 괜찮습니다 ;-)
HiQ CJ

3
@ UncleCJ upstream은 모든 커밋이 끝나는 곳 (SVN 용어의 릴리스 버전 또는 트렁크)에서 정기적으로 내 게시물에서 가져옵니다. 다운 스트림은 그 아래에있는 모든 사람입니다. 업스트림으로 물건을 보내는 것은 (linux-2.6과 같은) 릴리스 저장소로 병합하는 과정이며, 다운 스트림은 외출이나 변경 사항이 관리자에게 당신의 미니언에게 말한 것처럼 저장소에서 변경됩니다. 팀을 의미합니다.

2
@UncleCJ : "엄격히 순차적 인 히스토리를 얻기 위해 체크인을 다듬기가 까다 롭습니다."Git1.7을 사용하는 것이 더 쉽고 rebase --interactive --autosquash다른 커밋 메시지의 시작과 함께 모든 커밋을 자동으로 이동합니다. 해당 커밋이 티켓 번호 (예 : 티켓 번호)를 사용하는 경우 해당 티켓과 관련된 수정 프로그램이 당시에 순차적으로 작성되지 않은 경우에도 자동 스쿼시는 해당 커밋을 빠르게 재정렬 할 수 있습니다.
VonC

1
@UncleCJ : "엄격한 순차 히스토리 (필요한가 아닌가?!)": 항상 필요한 것은 아니지만 기능적 종속성 ( stackoverflow.com/questions/881092/… )과 의미 적 충돌 ( stackoverflow.com/questions )을 추적하는 데 도움이 됩니다. / 2514502 /… )
VonC

21

git에 대해 가장 오해 된 것 중 하나는 분산 된 성격이라고 생각합니다. 이것은 원하는 경우 SVN 동작을 모방 할 수 있지만 작업 방식에 따라 서브 버전을 말하는 것은 매우 다릅니다. 문제는 거의 모든 워크 플로가 수행하는 것인데, 이는 훌륭하지만 오해의 소지가 있습니다.

커널 개발에 대해 잘 알고 있다면 (핵심에 집중할 것), 모든 사람들은 커널 개발을위한 자체 git 저장소를 가지고있다. Torvalds가 관리하는 linux-2.6.git 리포지토리가 릴리스 리포지토리 역할을합니다. "릴리스"분기에 대한 기능 개발을 시작하려는 경우 여기에서 복제합니다.

다른 저장소는 일부 개발을 수행합니다. 아이디어는 linux-2.6에서 복제하여 작동하는 "새로운"기능을 가질 때까지 원하는만큼 분기하는 것입니다. 그런 다음 준비가되면 신뢰할 수있는 사람이이 저장소를 저장소로 가져와 주류로 병합 할 수 있습니다. 리눅스 커널에서 이것은 linux-2.6.git에 도달 할 때까지 여러 레벨 (신뢰할 수있는 중위)에서 발생하며,이 시점에서 "커널"이됩니다.

이제 혼란스러워지는 부분이 있습니다. 지점 이름은 리포지토리 전체에서 일관되지 않아도됩니다. 그래서 내 저장소의 지점에있는의 마스터 git pull origin master:vanilla-code로부터 지점을 얻을 수 있습니다 . 무슨 일이 일어나고 있는지 알면 실제로 중요하지 않습니다. 모든 리포지토리가 서로 피어이며 SVN과 같은 여러 컴퓨터에서 공유되는 것이 아니라는 의미에서 배포됩니다.originvanilla-code

따라서이 모든 것을 염두에두고

  1. 나는 그들이 어떻게 브랜칭을 수행하는지 각 프로그래머에게 달려 있다고 생각합니다. 릴리스 등을 관리하기위한 중앙 저장소 만 있으면됩니다. 트렁크는 다음과 같습니다 head. 릴리스는 태그 또는 분기 일 수 있으며 핫픽스는 아마도 자체 분기 일 수 있습니다. 실제로 릴리스를 브랜치로 사용하여 패치를 계속 유지할 수 있습니다.
  2. 나는 합병하지 않을 것이다. 예를 들어 저장소를 가져 와서 복제하고 분기하고 일부 개발자를 한 다음 origin저장소에서 다른 분기를 만들고 최신 버전 master을 병합하여 yourbranch다른 사람이 적은 노력으로 변경 사항을 가져올 수 있도록하십시오. 가능한. 내 경험상 진정으로 리베이스 할 필요는 거의 없습니다.
  3. 나는 그것이 Git이 작동하는 방식과 그것이 무엇을 할 수 있는지 이해하는 경우라고 생각합니다. 시간이 많이 걸리고 많은 의사 소통이 필요합니다. 다른 개발자들과 함께 git을 사용하기 시작했을 때 무슨 일이 일어나고 있는지, 심지어 지금까지 확실하지 않은 것들을 이해하기 시작했습니다.
  4. 병합 충돌이 유용합니다. 나는 당신이 모든 것이 작동하기를 원하지만 사실은 코드 변경이며 결과를 작동하는 것으로 병합해야한다는 것을 알고 있습니다. 병합 충돌은 실제로 더 많은 프로그래밍입니다. 나는 그들에 대해 무엇을 해야하는지에 대한 쉬운 설명을 찾지 못했습니다. 여기에는 병합 충돌이있는 파일을 확인하고 파일을 원래대로 변경 git add .한 다음 git commit.
  5. 그러나 그것은 적합합니다. 내가 말했듯이, 각 사용자 git 저장소는 가지고 놀 수 있으며 지점 이름 이 같을 필요는 없습니다 . 예를 들어 준비 저장소가있는 경우 이름 지정 스키마를 적용 할 수 있지만 릴리스 저장소에서만 각 개발자에 대해 필요하지 않습니다.
  6. 이것이 병합 단계입니다. 코드를 검토하고 품질 테스트를 통과 할 것으로 판단되는 경우에만 릴리스 지점으로 병합합니다.

도움이 되길 바랍니다. VonC가 방금 비슷한 설명을 게시 한 것으로 알고 있습니다 ... 충분히 빨리 입력 할 수 없습니다!

주석에서 OP와 관련이있는 것처럼 상업적 설정에서 git을 사용하는 방법에 대한 추가 생각을 편집하십시오 .

  • 릴리스 리포지토리 (Restore Repository)는 product.git실제로 제품 자체를 돌보는 책임을 맡고있는 많은 수석 프로그래머 / 기술자가 액세스 할 수 있습니다. 이들은 OSS에서 관리자의 역할과 유사합니다.
  • 이 프로그래머들은 아마도 부분적으로 새로운 버전의 개발을 이끌 기 때문에 스스로 코드를 작성하고 다양한 저장소를 유지할 수도 있습니다. 실제로 새로운 기능에 대한 준비 리포지토리를 관리하고 자체 리포지토리가있을 수도 있습니다.
  • 그 아래에는 개별 비트를 개발하는 프로그래머가 있습니다. 예를 들어 누군가 UI 작업을 담당 할 수 있습니다. 따라서 UI.git 저장소를 관리합니다.
  • 그 아래에는 하루 종일 일하면서 기능을 개발하는 실제 프로그래머가 있습니다.

어떻게됩니까? 모든 사람들은 매일 "업스트림"소스, 즉 릴리스 저장소 (이전 개발의 최신 자료를 포함 할 것)에서 시작합니다. 모두가 직접이 작업을 수행합니다. 이것은 아마도 "마스터"또는 아마도 "최신"이라고 불리는 저장소의 지점에 있습니다. 그런 다음 프로그래머는 몇 가지 작업을 수행합니다. 이 작업은 확실하지 않은 작업 일 수 있으므로 분기를 만들고 작업을 수행합니다. 작동하지 않으면 지점을 삭제하고 되돌아 갈 수 있습니다. 그렇다면 현재 작업중인 기본 지점으로 병합해야합니다. 우리는이에서 작업하는 UI 프로그래머입니다 말할 것이다 latest-ui그가 않도록git checkout latest-ui 다음git merge abc-ui-mywhizzynewfeature. 그런 다음 기술 책임자 (UI 책임자)에게이 작업을 완료했습니다. UI 리더는 그렇게합니다 git pull user-repo lastest-ui:lastest-ui-suchafeature-abc. 그런 다음 UI 리드가 해당 지점에서이를보고 실제로는 매우 훌륭하다고합시다 ui-latest. 그런 다음 그 아래의 모든 사람에게 ui-latest지사 또는 이름을 부여 해달라고 지시 할 수 있으므로 개발자가이 기능을 탐색합니다. 팀이 만족 스러우면 UI 책임자가 테스트 책임자에게 변경을 가져 오도록 요청할 수 있습니다. 이 기능은 테스트를 수행하고 버그 보고서 등을 제출하는 모든 사람 (변경의 다운 스트림)에게 전파됩니다. 마지막으로, 기능이 테스트 등을 통과하면 최상위 기술 담당자 중 한 명이 프로그램의 현재 작업중인 사본으로 병합 할 수 있습니다. 그런 다음 모든 변경 사항이 다시 전파됩니다. 등등.

"전통적인"작업 방식이 아니며 SVN / CVS와 같은 "계층 적"보다는 "피어 기반"으로 설계되었습니다. 본질적으로 모든 사람은 액세스 권한을 갖지만 로컬에서만 액세스 할 수 있습니다. 리포지토리에 액세스하고 계층을 사용할 수있는 릴리스 저장소로 지정하는 리포지토리입니다.


광범위한 답변 (및 투표)에 감사드립니다. 유용한 정보를 제공하는 데 몇 시간 더 읽을 것입니다. 그러나 우리는 OSS 개발위원회가 아닌 회사입니다. ;-) 저는 "자신의 리포지토리에서 원하는대로 바이올린"보다 더 명확한 지침을 내 개발자에게 도와야합니다. 이 포스트가 어디로 인도하는지 보자. 나는 좋은 추진력을 느낀다.
HiQ CJ

@VonC 감사합니다. @UncleCJ는 사실이지만 릴리스 관리자 등이 있습니다. 리포지토리에 액세스 할 수있는 사람이라면 누구나이 작업을 수행 할 수 있습니다. 개발과 관련하여 개발자에게 이유 내에서 자유롭게 분기 할 수있는 자유를주는 것은 어떻습니까? 병합 동의에 대한 프로토콜을 제공하고 원하는대로 중앙 리포지토리의 이름을 지정하면 문제가 없습니다. 그러나 일반적인 명명 스키마는 나쁜 생각이 아닙니다. 개인 브랜치에는 초기 버전-기능-지점을 사용하고 브랜치에는 버전을 사용하는 경향이 있습니다.

@ UncleCJ 회사에서 어떻게 작동하는지에 대한 예를 추가했습니다. 본질적으로 OSS 역할이 관리자로 대체되었지만 아이디어를 얻었습니다. SVN에 비해 개발자가 오프라인으로 작업 할 수 있다는 이점이 있습니다 (풀 / 푸시하려면 네트 만 필요). 잘 구현하면 기능을 쉽게 테스트 할 수 있다고 생각합니다.

와우, 그것은 실제로 좋은 예입니다. 우리는 졸업식에 이와 비슷한 것을 사용할 수 있습니다. 우리가 OSS를하지 않기 때문에 모든 사람이 규제를 받아야하므로 실제로는 작고 평평한 팀이지만 빡빡한 일정으로 효율적으로 협업하고 팀으로서 배우려고 노력해야합니다. . 그렇기 때문에 나는이 어리석은 질문을하여 나중에 나머지 팀을 도울 수 있습니다. :-). 또한 #git에서 리드 타임을 단축하기위한 압력과 잘못 정의 된 기준선을 사용하면 발을 밟고 있다는 것을 깨달았습니다 ... 나중에 돌아올 것입니다.
HiQ CJ

그것은 충분히 공평합니다-나는 최근에 거기에 왔는데, 그 예제를 시도하고 많은 실패로 ... 그리고 OSS 프로젝트의 작업 방식에 적응하여 정확하게 그 예를 선택했습니다. 진짜 큰 문제는 당신이 어떻게 브랜치와 리포지토리가 어디에 있는지 중요하지 않다는 것입니다. 어쨌든 나에게 진짜 충격적인 방법으로 원하는 방식으로 정의 할 수 있습니다! 그러나 그것은 당신이 흥미로운 일을 할 수있게합니다. 어쨌든 행운을 빌어 요!

9

좋은 결과를 얻은 모델은 다음과 같습니다.

"축복 된"저장소는 모두 기본적으로 클라이언트-서버 토폴로지입니다.

마스터 브랜치가 없으므로 개발자가 코드를 "기본"으로 푸시 할 수 없습니다.

모든 개발은 토픽 브랜치에서 이루어집니다. jn / newFeature 또는 jn / issue-1234를 쉽게 식별 할 수 있도록 네임 스페이스 이름이 지정되었습니다.

또한 화이트 보드의 브랜치와 칸반 / 스크럼 카드 사이에는 일대일 매핑이 있습니다.

지점을 해제하려면 축복받은 레포로 밀고 칸반 카드를 검토 준비 상태로 옮깁니다.

그런 다음 검토에서 지사를 수락하면 릴리스 후보가됩니다.

승인 된 분기 세트가 함께 병합되고 버전 번호로 태그가 지정되면 릴리스가 발생합니다.

새로운 태그를 축복받은 저장소로 푸시하면 새로운 기능을위한 새로운 기반이 생깁니다.

병합 충돌을 피하기 위해 개발자는 릴리스되지 않은 브랜치를 최신 릴리스 태그로 업데이트 (병합)해야합니다.


2

개인적으로, 나는 마스터 지사에 릴리스 준비 코드 만 유지하려고합니다.

새로운 기능이나 버그 수정 작업을 할 때 지점에서 수행합니다. 또한 지점에서 단위 테스트를 수행합니다. 모든 것이 정상적으로 작동하면 다시 마스터로 병합 / 리베이스해야합니까?

다음과 같은 일반적인 지점 명명 규칙을 사용하려고합니다.

  • bugfix / recursive_loop
  • bugfix / sql_timeout
  • 기능 / 새로운 레이아웃
  • 기능 / 향상된 _ 검색
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.