git에서 12 개의 라이브러리에 대해 버전 관리를 수행하는 방법은 모두 병렬로 작동했습니다.


11

우리는 프로젝트를 수행하고 있지만 프로젝트간에 많은 코드를 재사용하고 공통 코드를 포함하는 많은 라이브러리를 가지고 있습니다. 새로운 프로젝트를 구현함에 따라 일반적인 코드를 제외하고 라이브러리에 넣는 더 많은 방법을 찾습니다. 라이브러리는 서로 의존하고 프로젝트는 라이브러리에 의존합니다. 각 프로젝트 및 해당 프로젝트에 사용 된 모든 라이브러리는 참조하는 모든 라이브러리의 동일한 버전을 사용해야합니다. 소프트웨어를 출시하면 몇 년 동안, 때로는 수십 년 동안 버그를 수정하고 새로운 기능을 추가해야 할 것입니다. 우리는 약 12 ​​개의 라이브러리를 보유하고 있으며, 변경 사항은 종종 2 개 이상의 프로세스를 삭감했으며, 여러 팀이 여러 프로젝트를 동시에 진행하여 이러한 라이브러리를 모두 동시에 변경합니다.

우리는 최근에 git으로 전환하고 각 라이브러리와 각 프로젝트에 대한 리포지토리를 설정했습니다. 우리는 숨김을 공통 저장소로 사용하고, 기능 분기에서 새로운 작업을 수행 한 다음 풀 요청을 작성하고 검토 후에 만 ​​병합합니다.

프로젝트에서 다루어야 할 많은 문제는 여러 라이브러리와 프로젝트의 특정 코드를 변경해야합니다. 여기에는 종종 라이브러리 인터페이스의 변경이 포함되며 일부는 호환되지 않습니다. (이것이 비린 것처럼 들린다면 : 우리는 하드웨어와 인터페이스하고 일반 인터페이스 뒤에 특정 하드웨어를 숨 깁니다. 거의 다른 공급 업체의 하드웨어를 통합 할 때마다 현재 인터페이스가 예상하지 못한 경우가 발생하여이를 개선해야합니다.) 예, 프로젝트를 상상 P1라이브러리를 사용하여 L1, L2하고 L3. L1또한 사용 L2하고 L3, 그리고 L2용도 L3뿐만 아니라. 종속성 그래프는 다음과 같습니다.

   <-------L1<--+
P1 <----+  ^    |
   <-+  |  |    |
     |  +--L2   |
     |     ^    |
     |     |    |
     +-----L3---+

이제이 프로젝트를위한 기능의 변화를 필요로 상상 P1하고 L3있는의 인터페이스를 변경 L3. 이제 프로젝트를 추가 P2하고 P3이러한 라이브러리를 참조 믹스,에. 모든 인터페이스를 새로운 인터페이스로 전환하고 모든 테스트를 실행하고 새로운 소프트웨어를 배포 할 여유가 없습니다. 대체 대안은 무엇입니까?

  1. 새로운 인터페이스를 구현 L3
  2. 풀 요청을 L3하고 검토를 기다립니다
  3. 변경 사항을 병합
  4. 의 새로운 릴리스를 만들 L3
  5. 새 릴리스를 P1참조 하여 기능에 대한 작업을 시작한 L3다음 P1기능 분기 에 기능을 구현하십시오.
  6. 풀 요청을하고이를 검토하고 병합합니다.

(방금 전환 L1하고 L2새로운 릴리스 로 전환하는 것을 잊어 버렸습니다 .이 부분을 고수 할 곳조차 알지 못합니다. 왜냐하면 병렬로 수행해야하기 때문입니다 P1...)

이는 지루하고 오류가 발생하기 쉽고이 기능을 구현하는 데 오랜 시간이 걸리므로 독립적 인 검토가 필요하며 (검토하기가 훨씬 더 어려워 짐) 전혀 확장되지 않으며 비즈니스를 중단시킬 수 있습니다. 우리는 아무 일도하지 않습니다.

그러나 너무 많은 오버 헤드없이 새로운 프로젝트에서 새로운 기능을 구현할 수있는 프로세스를 만들기 위해 분기 및 태깅을 어떻게 사용합니까?


1
툴링을 변경해도 너무 많은 프로세스에 영향을 미치지 않아야합니다. 그래서 git으로 전환하기 전에이 문제를 어떻게 처리 했습니까?
Bart van Ingen Schenau 2016 년

너무 많은 라이브러리가 의존 할 때 기존 메소드를 중단하지 않고 인터페이스에 새로운 메소드를 추가하는 것이 가능합니까? 일반적으로 이것은 최선의 아이디어는 아니지만 최소한 새로운 기능을 구현하는 데 도움이되며 여분의 순간이있을 때마다 이전 방법을 올바르게 폐기 할 수 있습니다. 아니면 이러한 인터페이스가 "병렬 인터페이스"와 같이 작동하기에는 너무 상태가 양호합니까?
Ixrec 2016 년

1
@Ixrec : 나는 "이것은 git way가 아니다"라고 들었습니다. 모두가 개별 프로젝트에 개별 리포지토리를 사용하므로 우리도 그렇게 결정했습니다.
sbi 2016 년

2
나는 그들이 자주 변경되어야하는 경우 별도의 프로젝트가 아니라고 주장합니다. "프로젝트"사이의 경계는 항상 일종의 장기적인 하위 호환성을 보장해야합니다.
Ixrec 2016 년

1
@Ixrec : 더 많은 하드웨어를 통합하는 것은 더 많은 플랫폼으로 코드를 포팅하는 것과 유사합니다.이 작업을 많이 수행할수록 다른 하드웨어 / 플랫폼에 대한 변경이 줄어 듭니다. 따라서 장기적으로 코드가 안정화됩니다. 그러나 지금 당장 시장에 오래 머무를 수있는 프로세스를 찾아야합니다.
sbi 2016 년

답변:


5

여기에 명백한 것을 언급하지만 언급 할 가치가 있습니다.

일반적으로 git repos는 독립적 인 경향이 있기 때문에 lib / 프로젝트마다 조정됩니다. 프로젝트를 업데이트하고 나머지는 신경 쓰지 않습니다. 그것에 따라 다른 프로젝트는 적합하다고 생각 될 때마다 단순히 lib를 업데이트합니다.

그러나 사례는 상관 된 구성 요소에 따라 크게 달라 지므로 일반적으로 하나의 기능이 많은 구성 요소에 영향을줍니다. 그리고 전체는 번들로 패키지되어야합니다. 기능 / 변경 / 버그를 구현하려면 종종 여러 라이브러리 / 프로젝트를 한 번에 적용해야하므로 모두 동일한 리포지토리에 배치하는 것이 좋습니다.

이것에 대한 장점 / 단점이 있습니다.

장점 :

  • Tracability : 지점은이 기능 / 버그와 관련된 모든 프로젝트 / lib에서 변경된 모든 것을 보여줍니다.
  • 번들링 : 태그를 선택하기 만하면 모든 소스를 얻을 수 있습니다.

단점 :

  • 합병 : ... 한 번의 프로젝트로 이미 어려움을 겪는 경우가 있습니다. 서로 다른 팀이 공유 지점에서 작업하면서 영향을 미칠 준비를하십시오.
  • 위험한 "oops"요소 : 한 직원이 실수를해서 저장소를 엉망으로 만들면 모든 프로젝트와 팀에 영향을 줄 수 있습니다 .

가격이 그만한 가치가 있는지 아는 것은 당신에게 달려 있습니다.

편집하다:

다음과 같이 작동합니다.

  • 기능 X를 구현해야합니다
  • 지점 만들기 feature_x
  • 모든 개발자는이 브랜치에서 작업하고 패러렐 리 작업을 할 것입니다. 아마도 프로젝트 / lib와 관련된 전용 디렉토리에서
  • 완료되면 검토하고 테스트하고 패키지화하십시오.
  • 그것은 마스터에 다시 ... 그리고 이것은 그동안 때문에 힘든 부분 일 수있다 병합 feature_y하고 feature_z도 추가되었을 수 있습니다. "팀 간"병합이됩니다. 이것이 심각한 단점입니다.

단지 기록을 위해 : 이것은 대부분의 경우 나쁜 생각이며 병합 단점은 일반적으로 종속성 관리 / 적절한 기능 추적을 통해 얻는 것보다 높기 때문에 신중하게 수행해야한다고 생각합니다.


감사합니다, 우리는 현재 이것을보고 있습니다. 이것에 비추어 이해하지 못하는 것은 git으로 분기하는 방법입니다. SVN에서 분기는 저장소의 하위 트리를 저장소의 다른 곳에 복사하는 것을 의미합니다. 이를 통해 저장소에 하위 트리의 분기를 쉽게 만들 수 있으므로 프로젝트가 많을 경우 각 하위 트리를 개별적으로 분기 할 수 있습니다. 자식에 이와 같은 것이 있습니까, 아니면 항상 전체 저장소를 분기 할 수 있습니까?
sbi

@ sbi : 전체 저장소를 분기합니다. 다른 브랜치에서 하위 트리를 사용할 수 없으므로 사례의 요점을 이길 수 있습니다. Git은 아무 것도 "복사"하지 않고 단순히 작업중인 지점의 변경 사항을 추적합니다.
dagnelies 2016 년

따라서 병합 또는 리베이스 할 때 하나의 라이브러리에 대한 기능 분기를 작성하여 다른 라이브러리도 모두 병합해야합니다. 이것은 실제 단점입니다. (BTW, SVN은 또한 게으른 사본 만
수행합니다

@sbi : 편집 참조
dagnelies

1
글쎄, 현재 우리 대부분은 편안하지 않습니다. :-/게다가, git 로의 이동을 추진 한 사람들조차도 개발 프로세스를 git에 적합하게 만드는 방법을 모릅니다. 한숨. 일이 더 부드러워지기 시작할 때까지 몇 개월이 걸릴 것 같습니다. 어쨌든 감사합니다. 지금까지 가장 유용한 답변입니다.
sbi

4

찾고있는 솔루션은 git 서브 모듈과 함께 사용되는 종속성 관리 도구입니다.

다음과 같은 도구 :

  • 메이븐
  • 개미
  • 작곡가

이러한 도구를 사용하여 프로젝트의 종속성을 정의 할 수 있습니다.

서브 모듈이 최소 버전 > 2.xx 이상이어야 하거나 호환 가능한 버전 범위를 나타내는 = 2.2. * 또는 특정 버전 <2.2.3 미만을 나타낼 수 있습니다 .

패키지 중 하나의 새 버전을 릴리스 할 때마다 버전 번호로 태그를 지정할 수 있습니다. 이렇게하면 특정 버전의 코드를 다른 모든 프로젝트로 가져올 수 있습니다


그러나 의존성 관리는 우리의 문제가 아니며, 이것이 해결되었습니다. 현재 많은 라이브러리에서 정기적으로 변경하고 있으며 안정적인 프로젝트 릴리스를 유지하면서 새 버전 작성의 오버 헤드를 최소화해야합니다. 당신의 대답은 이것에 대한 해결책을 제공하지 않는 것 같습니다.
sbi

@sbi 새 버전을 만들고 안정적인 프로젝트 릴리스를 유지 관리하는 오버 헤드를 관리합니다. 프로젝트 x가 프로젝트 y 버전 2.1.1에 의존하도록 지시 할 수 있으므로 프로젝트 x에 영향을 미치지 않는 새 버전의 프로젝트 y를 작성할 수 있습니다.
Patrick

다시 말하지만, 의존성을 선언하는 것은 우리의 문제가 아닙니다. 우리는 이미 할 수 있습니다. 문제는 여러 프로젝트 / 라이브러리에서 효율적으로 변경 내용을 관리하는 방법입니다. 당신의 대답은 이것을 설명하지 못합니다.
sbi

@ sbi : 그렇다면 정확히 무엇이 문제입니까? 변경, 버전 충돌, 필요한 경우 종속성 업데이트 및 Voila를 수행합니다. 초기 게시물에서 설명한 것은 일반적인 maven & co입니다. 물건. 각 배포판은 명확하게 정의 된 버전 화 된 라이브러리를 기반으로합니다. 어떻게 더 명확해질 수 있습니까?
dagnelies

@arnaud : 3 개 이상의 레이어를 절단하는 (현재 다소 일반적인) 변경에 대한 프로세스의 처리 시간은 우리를 죽일 것입니다. 내 질문에 설명되어 있다고 생각했습니다.
sbi

0

서브 모듈

한 의견에서 제안한 것처럼 하위 모듈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각 프로젝트에서 사용하는 라이브러리 버전을 쉽게 확인할 수 있으며 필요에 따라 독립적으로 업데이트 할 수 있습니다. 서브 모듈은 상황에 적합하며 프로세스 속도를 늦추지 않습니다.

이 과정의 일부 를 자동화 하는 방법을 찾을 수도 있지만 위의 단계 대부분에는 인간의 두뇌가 필요합니다. 시간을 줄이는 가장 효과적인 방법은 라이브러리와 프로젝트를 쉽게 발전시키는 것입니다. 코드베이스가 새로운 요구 사항을 정상적으로 처리 할 수 ​​있다면 코드 검토가 더 간단 해지고 시간이 거의 걸리지 않습니다.

(편집) 당신을 도울 수있는 또 다른 한가지는 그룹 관련 코드 리뷰이다. 모든 변경 사항을 커밋하고 변경 사항을 사용하는 모든 라이브러리 및 프로젝트에 변경 사항을 전파 할 때까지 풀 요청을 합산하기 전에 (또는 변경하기 전에) 기다립니다. 전체 종속성 체인에 대해 더 큰 검토를 마칩니다. 각 지역 변경이 작은 경우 시간을 절약하는 데 도움이 될 수 있습니다.


당신은 의존성 문제를 해결하는 방법을 설명하고 (이전에 언급했듯이) 우리가 가지고있는 바로 그 문제를 부정합니다. 왜 귀찮게합니까? (FWIW, 우리는 발전소를 운전하는 소프트웨어를 작성합니다. 깨끗하고 안전하며 철저하게 검토 된 코드가 가장 중요한 기능입니다.)
sbi

@sbi 분기 및 태깅의 특별한 경우가 아닌 경우 서브 모듈은 무엇입니까? 당신이 생각하는 그들은 또한 의존성을 추적하기 때문에 서브 모듈은 의존성 관리에 대한 있습니다. 그러나 원하는 경우 태그가있는 하위 모듈을 다시 발명하십시오. 귀하의 문제를 이해하지 못했습니다. 검토 된 코드가 주요 기능인 경우 검토를 위해 시간을 투자해야합니다. 당신은 혼란에 빠지지 않으며, 당신은 당신에게 주어진 제약 조건으로 가능한 한 빨리갑니다.
coredump 2015 년

리뷰는 우리에게 매우 중요합니다. 이것이 여러 리포지토리의 여러 변경 사항에 대해 여러 리뷰로 분할되는 문제 (및 리뷰)에 대해 우려하는 이유 중 하나입니다. 또한 우리는 한 가지 문제로 인해 사형을 집행하는 데 어려움을 겪고 싶지 않으며 코드 작성 및 검토에 시간을 소비한다는 것입니다. 다시 서브 모듈 : 지금까지 내가 들었던 것은 "걱정하지 마라. 이것은 git way가 아니다." 음, 우리의 요구 사항이 매우 독창적 인 것처럼 보이면이 결정을 다시 검토해야 할 것입니다.
sbi

0

그래서 내가 이해하는 것은 P1의 경우 L3 인터페이스를 변경하고 싶지만 L3 인터페이스에 의존하는 다른 P2 및 P3이 즉시 변경되기를 원한다는 것입니다. 이것은 이전 버전과의 호환성의 일반적인 경우입니다. 이 이전 버전과의 호환성 유지 에 대한 좋은 기사가 있습니다.

이 문제를 해결할 수있는 몇 가지 방법이 있습니다.

  • 이전 인터페이스를 확장 할 수있을 때마다 새 인터페이스를 작성해야합니다.

또는

  • 얼마 후 이전 인터페이스를 폐기하려면 여러 버전의 인터페이스를 사용할 수 있으며 모든 종속 프로젝트가 이동하면 이전 인터페이스를 제거합니다.

1
릴리스 브랜치를 통해 이전 버전과의 호환성이 보장되며 우리의 문제는 아닙니다. 문제는 인터페이스가 여전히 자주 바뀌는 단계에 있음에도 불구하고 현재 빠르게 변화하는 코드베이스에 앉아 있다는 것입니다. 나는 SVN에서 그러한 짐승을 관리하는 방법을 알고 있지만 관리에 익사하지 않고 자식에서 어떻게 해야하는지 모르겠다.
sbi

0

내가 당신의 문제를 올바르게 받고 있다면 :

  • 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 개발자는 당신이 그렇게하면 이상하게 당신을 볼 것입니다 ...


"4 개를 모두 함께 변경해야하는 경우 프로세스 실패로 계산됩니다 . " 실제로는 그렇지 않습니다. 사실, 이것은 우리가 SVN을 사용하여 한 것입니다.
sbi

어떤 경우에는 단순히 모든 프로젝트를 저장소에 넣는 데 아무런 문제가 없다고 생각합니다.
soru

현재 라이브러리를 두 개의 저장소에만 배치하는 것을 평가하고 있습니다. 그것은 여전히 ​​하나 이상이지만 "모든 프로젝트마다 하나"보다 훨씬 적으며 라이브러리는 두 그룹으로 나눌 수 있습니다. 입력 해 주셔서 감사합니다!
sbi

PS : "언어를 바꾸고 싶지 않다고 생각합니다." 이것은 내장 된 것입니다. :)
sbi

-1

간단한 해결책이 있습니다 : 전체 저장소에서 릴리스 브랜치를 잘라 내고 모든 수정 사항을 활발하게 출시 된 모든 릴리스로 병합하십시오 (git에서 명확한 경우가 가능해야 함).

모든 대안은 시간이 지남에 따라 프로젝트가 성장함에 따라 끔찍한 혼란을 초래할 것입니다.


좀 더 자세히 설명해 주시겠습니까? 나는 당신이 무엇을 제안하는지 잘 모르겠습니다.
sbi

명확한 경우에는 분기 지점을 기본 분기 및 타임 스탬프로 정의합니다. 기본 브랜치-> 릴리스 개발 브랜치-> 개인 개발 브랜치 계층이 있습니다. 모든 개발은 개인 브랜치에서 수행 된 다음 계층 구조로 병합됩니다. 고객 릴리스 지점은 릴리스 개발 지점에서 분리됩니다. 나는 git에 익숙하지 않지만 무료 소스 제어 시스템 중 가장 명확한 사례를 보인다.
zzz777

내 질문을주의 깊게 읽으면 리포지토리 간 변경 사항 전파와 관련된 오버 헤드에 문제가 있음을 알 수 있습니다. 이것은 당신의 대답과 관련이 없습니다.
sbi

@ sbi 귀하의 질문을 오해하여 죄송합니다. 그리고 나는 당신이 조만간 끔찍한 혼란에 직면 할 것을 두려워합니다.
zzz777
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.