우리는 프로젝트를 수행하고 있지만 프로젝트간에 많은 코드를 재사용하고 공통 코드를 포함하는 많은 라이브러리를 가지고 있습니다. 새로운 프로젝트를 구현함에 따라 일반적인 코드를 제외하고 라이브러리에 넣는 더 많은 방법을 찾습니다. 라이브러리는 서로 의존하고 프로젝트는 라이브러리에 의존합니다. 각 프로젝트 및 해당 프로젝트에 사용 된 모든 라이브러리는 참조하는 모든 라이브러리의 동일한 버전을 사용해야합니다. 소프트웨어를 출시하면 몇 년 동안, 때로는 수십 년 동안 버그를 수정하고 새로운 기능을 추가해야 할 것입니다. 우리는 약 12 개의 라이브러리를 보유하고 있으며, 변경 사항은 종종 2 개 이상의 프로세스를 삭감했으며, 여러 팀이 여러 프로젝트를 동시에 진행하여 이러한 라이브러리를 모두 동시에 변경합니다.
우리는 최근에 git으로 전환하고 각 라이브러리와 각 프로젝트에 대한 리포지토리를 설정했습니다. 우리는 숨김을 공통 저장소로 사용하고, 기능 분기에서 새로운 작업을 수행 한 다음 풀 요청을 작성하고 검토 후에 만 병합합니다.
프로젝트에서 다루어야 할 많은 문제는 여러 라이브러리와 프로젝트의 특정 코드를 변경해야합니다. 여기에는 종종 라이브러리 인터페이스의 변경이 포함되며 일부는 호환되지 않습니다. (이것이 비린 것처럼 들린다면 : 우리는 하드웨어와 인터페이스하고 일반 인터페이스 뒤에 특정 하드웨어를 숨 깁니다. 거의 다른 공급 업체의 하드웨어를 통합 할 때마다 현재 인터페이스가 예상하지 못한 경우가 발생하여이를 개선해야합니다.) 예, 프로젝트를 상상 P1
라이브러리를 사용하여 L1
, L2
하고 L3
. L1
또한 사용 L2
하고 L3
, 그리고 L2
용도 L3
뿐만 아니라. 종속성 그래프는 다음과 같습니다.
<-------L1<--+
P1 <----+ ^ |
<-+ | | |
| +--L2 |
| ^ |
| | |
+-----L3---+
이제이 프로젝트를위한 기능의 변화를 필요로 상상 P1
하고 L3
있는의 인터페이스를 변경 L3
. 이제 프로젝트를 추가 P2
하고 P3
이러한 라이브러리를 참조 믹스,에. 모든 인터페이스를 새로운 인터페이스로 전환하고 모든 테스트를 실행하고 새로운 소프트웨어를 배포 할 여유가 없습니다. 대체 대안은 무엇입니까?
- 새로운 인터페이스를 구현
L3
- 풀 요청을
L3
하고 검토를 기다립니다 - 변경 사항을 병합
- 의 새로운 릴리스를 만들
L3
- 새 릴리스를
P1
참조 하여 기능에 대한 작업을 시작한L3
다음P1
기능 분기 에 기능을 구현하십시오. - 풀 요청을하고이를 검토하고 병합합니다.
(방금 전환 L1
하고 L2
새로운 릴리스 로 전환하는 것을 잊어 버렸습니다 .이 부분을 고수 할 곳조차 알지 못합니다. 왜냐하면 병렬로 수행해야하기 때문입니다 P1
…)
이는 지루하고 오류가 발생하기 쉽고이 기능을 구현하는 데 오랜 시간이 걸리므로 독립적 인 검토가 필요하며 (검토하기가 훨씬 더 어려워 짐) 전혀 확장되지 않으며 비즈니스를 중단시킬 수 있습니다. 우리는 아무 일도하지 않습니다.
그러나 너무 많은 오버 헤드없이 새로운 프로젝트에서 새로운 기능을 구현할 수있는 프로세스를 만들기 위해 분기 및 태깅을 어떻게 사용합니까?
답변
여기에 명백한 것을 언급하지만 언급 할 가치가 있습니다.
일반적으로 git repos는 독립적 인 경향이 있기 때문에 lib / 프로젝트마다 조정됩니다. 프로젝트를 업데이트하고 나머지는 신경 쓰지 않습니다. 그것에 따라 다른 프로젝트는 적합하다고 생각 될 때마다 단순히 lib를 업데이트합니다.
그러나 사례는 상관 된 구성 요소에 따라 크게 달라 지므로 일반적으로 하나의 기능이 많은 구성 요소에 영향을줍니다. 그리고 전체는 번들로 패키지되어야합니다. 기능 / 변경 / 버그를 구현하려면 종종 여러 라이브러리 / 프로젝트를 한 번에 적용해야하므로 모두 동일한 리포지토리에 배치하는 것이 좋습니다.
이것에 대한 장점 / 단점이 있습니다.
장점 :
- Tracability : 지점은이 기능 / 버그와 관련된 모든 프로젝트 / lib에서 변경된 모든 것을 보여줍니다.
- 번들링 : 태그를 선택하기 만하면 모든 소스를 얻을 수 있습니다.
단점 :
- 합병 : … 한 번의 프로젝트로 이미 어려움을 겪는 경우가 있습니다. 서로 다른 팀이 공유 지점에서 작업하면서 영향을 미칠 준비를하십시오.
- 위험한 “oops”요소 : 한 직원이 실수를해서 저장소를 엉망으로 만들면 모든 프로젝트와 팀에 영향을 줄 수 있습니다 .
가격이 그만한 가치가 있는지 아는 것은 당신에게 달려 있습니다.
편집하다:
다음과 같이 작동합니다.
- 기능 X를 구현해야합니다
- 지점 만들기
feature_x
- 모든 개발자는이 브랜치에서 작업하고 패러렐 리 작업을 할 것입니다. 아마도 프로젝트 / lib와 관련된 전용 디렉토리에서
- 완료되면 검토하고 테스트하고 패키지화하십시오.
- 그것은 마스터에 다시 … 그리고 이것은 그동안 때문에 힘든 부분 일 수있다 병합
feature_y
하고feature_z
도 추가되었을 수 있습니다. “팀 간”병합이됩니다. 이것이 심각한 단점입니다.
단지 기록을 위해 : 이것은 대부분의 경우 나쁜 생각이며 병합 단점은 일반적으로 종속성 관리 / 적절한 기능 추적을 통해 얻는 것보다 높기 때문에 신중하게 수행해야한다고 생각합니다.
답변
찾고있는 솔루션은 git 서브 모듈과 함께 사용되는 종속성 관리 도구입니다.
다음과 같은 도구 :
- 메이븐
- 개미
- 작곡가
이러한 도구를 사용하여 프로젝트의 종속성을 정의 할 수 있습니다.
서브 모듈이 최소 버전 > 2.xx 이상이어야 하거나 호환 가능한 버전 범위를 나타내는 = 2.2. * 또는 특정 버전 <2.2.3 미만을 나타낼 수 있습니다 .
패키지 중 하나의 새 버전을 릴리스 할 때마다 버전 번호로 태그를 지정할 수 있습니다. 이렇게하면 특정 버전의 코드를 다른 모든 프로젝트로 가져올 수 있습니다
답변
서브 모듈
한 의견에서 제안한 것처럼 하위 모듈 을 git 시도해보십시오 .
프로젝트를 할 때 P1
세 가지 서브 모듈을 의미 L1
, L2
그리고 L3
, 실제로 세 저장소에서 특정 커밋에 대한 참조를 저장 : 사람들이있는 작업 각 라이브러리의 버전 이 프로젝트 .
따라서 여러 프로젝트가 여러 하위 모듈과 함께 작동 할 수 있습니다 . 프로젝트 가 새 버전을 사용하는 동안 P1
이전 버전의 라이브러리 L1
를 참조 할 수 있습니다 P2
.
새 버전을 제공하면 어떻게됩니까 L3
?
- 새로운 인터페이스를 구현
L3
- 커밋, 테스트 , 풀 요청, 검토, 병합, … (이를 피할 수 없음)
- 보장
L2
과 함께 작품을L3
커밋, … L1
새로운 작업을 보장L2
…P1
모든 라이브러리의 새 버전에서 작동 하는지 확인 하십시오.- 내부
P1
의의 로컬 작업 복사본L1
,L2
그리고L3
, 당신이 관심있는 변화를 fetche. git add L1 L2 L3
모듈에 대한 새로운 참조를 커밋하기 위해 커밋 변경- 에 대한 풀 요청
P1
, 테스트, 검토, 풀 요청, 병합 …
- 내부
방법론
이는 지루하고 오류가 발생하기 쉽고이 기능을 구현하는 데 오랜 시간이 걸리므로 독립적 인 검토가 필요하며 (검토하기가 훨씬 더 어려워 짐) 전혀 확장되지 않으며 비즈니스를 중단시킬 수 있습니다. 우리는 아무 일도하지 않습니다.
예, 다음을 변경하기 때문에 독립적 인 검토 가 필요합니다 .
- 도서관
- 그것에 의존하는 라이브러리
- 여러 라이브러리에 의존하는 프로젝트
당신은 쓰레기를 제공하기 때문에 사업을 중단 하시겠습니까? (실제로는 아닐 수도 있습니다). 그렇다면 테스트를 수행하고 변경 사항을 검토해야합니다.
적절한 git 툴을 사용하면 gitk
각 프로젝트에서 사용하는 라이브러리 버전을 쉽게 확인할 수 있으며 필요에 따라 독립적으로 업데이트 할 수 있습니다. 서브 모듈은 상황에 적합하며 프로세스 속도를 늦추지 않습니다.
이 과정의 일부 를 자동화 하는 방법을 찾을 수도 있지만 위의 단계 대부분에는 인간의 두뇌가 필요합니다. 시간을 줄이는 가장 효과적인 방법은 라이브러리와 프로젝트를 쉽게 발전시키는 것입니다. 코드베이스가 새로운 요구 사항을 정상적으로 처리 할 수 있다면 코드 검토가 더 간단 해지고 시간이 거의 걸리지 않습니다.
(편집)
당신을 도울 수있는 또 다른 한가지는 그룹 관련 코드 리뷰이다. 모든 변경 사항을 커밋하고 변경 사항을 사용하는 모든 라이브러리 및 프로젝트에 변경 사항을 전파 할 때까지 풀 요청을 합산하기 전에 (또는 변경하기 전에) 기다립니다. 전체 종속성 체인에 대해 더 큰 검토를 마칩니다. 각 지역 변경이 작은 경우 시간을 절약하는 데 도움이 될 수 있습니다.
답변
그래서 내가 이해하는 것은 P1의 경우 L3 인터페이스를 변경하고 싶지만 L3 인터페이스에 의존하는 다른 P2 및 P3이 즉시 변경되기를 원한다는 것입니다. 이것은 이전 버전과의 호환성의 일반적인 경우입니다. 이 이전 버전과의 호환성 유지 에 대한 좋은 기사가 있습니다.
이 문제를 해결할 수있는 몇 가지 방법이 있습니다.
- 이전 인터페이스를 확장 할 수있을 때마다 새 인터페이스를 작성해야합니다.
또는
- 얼마 후 이전 인터페이스를 폐기하려면 여러 버전의 인터페이스를 사용할 수 있으며 모든 종속 프로젝트가 이동하면 이전 인터페이스를 제거합니다.
답변
내가 당신의 문제를 올바르게 받고 있다면 :
- 4 개의 상호 관련 모듈 (P1 및 L1 ~ L3)이 있습니다.
- L1에서 L3에 영향을 미치는 P1을 변경해야합니다.
- 4 개를 모두 함께 변경해야하는 경우 프로세스 실패로 계산됩니다.
- 1 씩 1 씩 변경해야하는 경우 프로세스 실패로 계산됩니다.
- 변경해야하는 청크를 미리 식별해야하는 경우 프로세스 실패로 계산됩니다.
따라서 목표는 P1과 L1을 한 번에 수행 한 다음 한 달 후에 L2와 L3을 다른 곳에서 수행하는 것입니다.
자바 세계에서 이것은 사소한 것이며 아마도 작동하는 기본 방법입니다.
- 분기를 적절하게 사용하지 않고 모든 것이 하나의 저장소에 들어갑니다.
- 모듈은 모두 동일한 디렉토리 트리에 있다는 사실이 아니라 버전 번호를 기반으로 maven에 의해 컴파일되고 서로 링크됩니다.
따라서 디스크의 다른 디렉토리에있는 P1의 사본에 대해 컴파일하는 경우 컴파일되지 않는 L3 용 로컬 디스크의 코드를 컴파일 할 수 있습니다. 운 좋게도 그렇게하지 않습니다. 소스 코드가 아닌 컴파일 된 jar 파일에 대해 이야기를 컴파일 / 링크하기 때문에 Java가이를 간단하게 수행 할 수 있습니다.
C / C ++ 세계 에서이 문제에 대한 기존의 널리 사용되는 솔루션을 알지 못하며 언어를 바꾸고 싶지 않다고 생각합니다. 그러나 동등한 일을하는 파일을 만들면 쉽게 해킹 될 수 있습니다.
- 버전 번호가 포함 된 알려진 디렉토리에 설치된 라이브러리 + 헤더
- 적절한 버전 번호를 위해 모듈 당 디렉토리로의 컴파일러 경로 변경
maven에서 C / C ++ 지원을 사용할 수도 있지만 대부분의 C 개발자는 당신이 그렇게하면 이상하게 당신을 볼 것입니다 …
답변
간단한 해결책이 있습니다 : 전체 저장소에서 릴리스 브랜치를 잘라 내고 모든 수정 사항을 활발하게 출시 된 모든 릴리스로 병합하십시오 (git에서 명확한 경우가 가능해야 함).
모든 대안은 시간이 지남에 따라 프로젝트가 성장함에 따라 끔찍한 혼란을 초래할 것입니다.