클라이언트와 서버를 갖춘 응용 프로그램이 있다고 가정합니다 (간단하게). 두 저장소 또는 한 쌍의 개별 저장소에 하나의 저장소를 사용하는 것이 더 좋은 아이디어입니까?
그것들을 혼합하면 상관 변경 사항을 추적하고 관련 분기 (예 : 프로토콜 진화)를 유지하기가 쉽지만 다른 한편으로는 개별 개발이 더 복잡해집니다 ...
클라이언트와 서버를 갖춘 응용 프로그램이 있다고 가정합니다 (간단하게). 두 저장소 또는 한 쌍의 개별 저장소에 하나의 저장소를 사용하는 것이 더 좋은 아이디어입니까?
그것들을 혼합하면 상관 변경 사항을 추적하고 관련 분기 (예 : 프로토콜 진화)를 유지하기가 쉽지만 다른 한편으로는 개별 개발이 더 복잡해집니다 ...
답변:
git 또는 mercurial을 사용하는 경우 하위 모듈 이나 하위 리포지토리 를 살펴볼 수 있습니다 .
클라이언트, 서버 및 인터페이스 파일 은 자체 리포지토리에 있지만 수퍼 리포지토리 수준 에서 함께 연결됩니다 . 이를 통해 최상위 레벨에서 한 번의 체크 아웃을 수행 git하거나 hg각 서브 모듈 / 하위 리포지토리의 적절한 커밋을 확인할 수 있습니다.
클라이언트와 서버가 서로 적절한 경우에만 수퍼 리포지토리에 커밋하면 수퍼 리포지토리는 작동 시스템을 체크 아웃하는 옵션 만 제공하므로 이전 클라이언트에 대해 새 클라이언트를 실행하려고 시도하지 않습니다. 서버 또는 그 반대.
하위 모듈 / 하위 저장소는 약간의 추가 복잡성으로 인해 단일 모 놀리 식 저장소의 장점과 함께 별도의 저장소를 사용하는 모든 이점을 제공합니다.
이 답변은 다른 SCM 을 옹호 git하거나 이의를 제기 하기위한 것이 아니며 hg, 이 옵션이 존재 함을 알 수있을만큼 이러한 SCM 만 잘 알고 있다는 것입니다. svn예를 들어 외부의 작동 방식을 이해하지 못합니다 .
갈라진!
사실, 아마도 클라이언트와 해당 클라이언트 전용 라이브러리, 서버 (및 해당 라이브러리) 및 공유 라이브러리 (두 인터페이스 사이의 기능을 노출하는 API 인터페이스 포함)를위한 세 개의 저장소가있을 것입니다. , 다른 모든 공유 코드). 이것이 핵심이라고 생각합니다. 공유 코드는 별도의 저장소에 있어야합니다. 이렇게하면 클라이언트와 서버 간의 상호 운용성이 항상 동일한 버전이고 각 소비자의 디자인과 분리되도록 할 수 있습니다.
분명히 이것은 사용중인 특정 통신 프레임 워크에 따라 항상 가능하지는 않지만 데이터 전송 객체의 형식 또는 사용자 지정 프로토콜의 핸드 셰이크 단계 (또는 다른 예)를 지시하는 공유 코드가있을 수 있습니다 .
상당히 괜찮은 Continuous Integration 및 QA 설정 (내 경험상 상당히 큰 가정이지만 그럼에도 불구하고 만들 것입니다. QA 부서가 없으면 최소한 CI를 가져와야 함)을 가정해야합니다. 가능한 코드 불일치를 방지하기 위해 단일 리포지토리 패턴을 사용할 필요가 없습니다. CI 서버가 라이브러리 상호 운용성을 플래그 지정하거나 QA 팀이 런타임 오류를 포착합니다 (또는 더 나은 단위 테스트).
분할 리포지토리의 이점은 시스템의 개별 부분을 개별적으로 버전 화하는 기능에 있습니다. 지난 주 서버의 사본을 가져와 이번 주 클라이언트와 함께 실행하여 성능 문제의 근본 원인을 파악하고 싶습니까? 걱정 마.
에 의욕 이 방식은 사용하여, 사용할 수 있습니다 ->나타낸다 subrepo의 관계 :
product -> client -|-> (many components)
|-> shared component A
-> server -|-> (many components)
|-> shared component A
제품에 하위 저장소 클라이언트, 서버가 있습니다. 이들 각각의 구성 요소는 하위 리포지토리로 구성 될 수 있으며, 둘 중 하나 이상이 공유 될 수 있습니다.
태깅은 아마도 그 아래가 아닌 처음 두 레벨에서 수행되어야합니다.
커미트는 구성 요소 레벨에서 수행되며, superrepos는 이름 지정된 분기 및 제품 버전을 효과적으로 추적합니다. 명명 된 브랜치 / 북마크는 일반적으로 유용성 (예 : 교육 성) 및 하위 리포지토리와의 호환성을 위해 복제 브랜치보다 낫습니다.
hg는 superrepos 가 제품 이라고 가정 하고 커밋은 최상위 수준에서 수행되지만 여러 제품이 동일한 구성 요소를 사용하는 경우 특히 잘 작동하지 않습니다. :-)
git으로 전환하면이 체계가 많이 바뀌지 않을 것이라고 생각하지만 아직 git에서 시도하지 않았습니다.
가장 간단한 방법은 단일 저장소를 사용하므로하지 않는 복잡성을 위하여 복잡성처럼, 그 그렇지 않으면 강력한 인수가없는 경우 기본 선택해야한다.
클라이언트와 서버 개발이 다른 조직에 의해 수행됩니까? 클라이언트 (또는 서버)의 여러 구현이 있습니까? 클라이언트 오픈 소스와 서버 구현은 비밀입니까? 이러한 모든 질문에 대한 대답이 "아니오"인 경우 단일 저장소보다 복잡한 것이 있으면 불편을 겪지 않을 것입니다.
별도의 코드베이스를 유지하기로 선택한 경우 비 호환성 및 종속성 문제를 피하기 위해이를 관리하는 방법에 대한 명확한 정책이 필요합니다. 처음 몇 개의 딸꾹질을 마친 후에는 가장 안전한 것은 항상 두 저장소를 함께 체크 아웃하고 함께 빌드하고 함께 배포하는 것입니다.
모듈성은 좋은 속성이지만 리포지토리를 분할하는 것은이를 달성하기위한 도구가 아닙니다. 이전 단락에서 알 수 있듯이 여러 코드베이스로 분할되는 결합 된 구성 요소를 가질 수 있으며 (바람직하지 않음), 동일한 코드베이스 내에 원하는 모듈 식 구성 요소를 가질 수 있습니다 (바람직 함).
여러 번, 개발 및 배포를 단순화했기 때문에 팀이 기존 git 리포지토리를 병합하도록 옹호했습니다.
잠시 동안 저장소를 잊어 버리십시오. 다른 사람과 공유하지 않은 경우 컴퓨터에서 두 프로젝트를 어떻게 구성 하시겠습니까? 나머지 팀은 어떻게할까요? 당신은 ...
클라이언트와 서버 모두에 대한 모든 소스 파일을 동일한 디렉토리에 두시겠습니까?
클라이언트와 서버에 대한 서브 디렉토리를 포함하는 기본 프로젝트 디렉토리를 작성 하시겠습니까?
두 프로젝트를 완전히 분리하여 유지합니까?
일단 팀으로서 그것에 대한 합의에 도달하면 코드 저장소에서 프로젝트를 확인할 준비가 된 것입니다. 내가 생각할 수있는 모든 개정 제어 도구는 원하는 디렉토리 구조를 기꺼이 재현합니다. 어떤 파일이 어떤 프로젝트에 속하는지는 신경 쓰지 않습니다. 그리고 하나의 저장소 또는 두 개 (또는 여섯 개)를 갖는 것의 차이점은 약간의 관리상의 차이를 제외하고는 그리 크지 않습니다.
예를 들어 Subversion을 사용하면 클라이언트와 서버에 대한 개별 리포지토리와 단일 결합 리포지토리의 가장 큰 차이점은 개정 번호가 변경되는 방식에 있습니다. 단일 저장소를 사용하면 클라이언트 또는 서버에 코드를 커밋 할 때마다 버전 번호가 증가합니다. 별도의 리포지토리를 사용하면 서버 프로젝트에 대한 커밋은 클라이언트의 헤드 개정 번호를 변경하지 않습니다.