마스터 브랜치에서 수백 개의 맞춤형 브랜치 유지


140

현재 공유 저장소에 PHP 애플리케이션을위한 하나의 마스터 브랜치가 있습니다. 우리는 소프트웨어 가입자 인 500 명 이상의 고객을 보유하고 있으며, 대부분의 고객은 각각 별도의 지점에있는 서로 다른 목적을 위해 약간의 사용자 정의를 가지고 있습니다. 사용자 정의는 다른 텍스트 필드 이름, 완전히 새로운 기능 또는 모듈 또는 데이터베이스의 새 테이블 / 열일 수 있습니다.

우리가 직면 한 문제는 수백 가지의 맞춤형 분기를 유지 관리하고 고객에게 배포 할 때마다 새로운 기능을 제공하고 마스터 분기를 업데이트하며 업데이트하기 위해 마스터 분기 변경 사항을 사용자 지정 분기로 푸시하려는 것입니다. 최신 버전으로

불행히도 이로 인해 종종 사용자 정의 코드에서 많은 충돌이 발생하며 모든 충돌을 해결하기 위해 모든 단일 브랜치를 통해 많은 시간을 소비합니다. 이는 매우 비효율적이며 이러한 충돌을 해결할 때 실수가 드물지 않은 것으로 나타났습니다.

병합하는 동안 노력이 덜 드는 마스터 브랜치로 클라이언트 릴리스 브랜치를 최신 상태로 유지하는보다 효율적인 방법을 찾고 있습니다.


11
"X 도구를 사용할 수 있습니다"라는 대답을하지 말아 죄송합니다.
궤도에서 가벼움 경주

3
또는 빌드 중에 (아마도 더 일반적 임) 그냥 .. 완전히 별도의 코드베이스가 아닙니다.
궤도에서 가벼움 레이스

15
@FernandoTan-눈에 보이는 증상은 코드 일 수 있지만 질병의 근본 원인은 제품 단편화입니다. 치료는 코드 정리가 아니라 제품 포커스 / 제품 기능 매핑에서 가져와야합니다. 결국에는 일어날 것입니다. 나는 더 내 대답에 설명 된 한 - programmers.stackexchange.com/a/302193/78582
알렉스 S

8
이것은 또한 경제적 인 문제 일 수 있습니다. 당신은 정말로 그 500 명의 고객 모두에게서 돈을 벌고 있습니까? 그렇지 않은 경우 고객이 추가 요금을 지불하지 않으면 가격 책정 모델을 지나치게 생각하고 변경 요청을 거부해야합니다.
Christian Strempfer

13
이로 인해 내 마음이 아프게되었습니다. 다행히도 다른 사람들이 이미 정답을 외치고 있습니다. 추가 권장 사항은 이것을 작성하여 TheDailyWTF에 제출하는 것입니다.
zxq9

답변:


314

당신은 완전히 지점을 학대하고 있습니다! 버전 관리의 유연성이 아니라 응용 프로그램의 유연성을 통해 사용자 지정 기능을 제공해야합니다 (발견 한 바와 같이 이러한 종류의 용도로는 설계되지 않았습니다).

예를 들어, 텍스트 필드 레이블을 응용 프로그램에 하드 코딩하지 않고 텍스트 파일에서 가져 오도록합니다 (국제화 방식). 일부 고객의 기능이 다른 경우 엄격하고 안정적인 API에 의해 엄격한 내부 경계를 적용 하여 애플리케이션을 모듈 식 으로 만들어 필요에 따라 기능을 플러그인 할 수 있습니다.

핵심 인프라 및 모든 공유 기능은 한 번만 저장, 유지 관리 및 테스트 하면 됩니다.

처음부터이 작업을 수행해야합니다. 이미 500 개의 변형 제품 (!)이있는 경우이를 수정하는 것은 일 이 될 것 입니다.


142
"처음부터이 작업을 수행해야합니다"에 대해 +1입니다. 이 수준의 기술 부채는 회사를 파괴 할 수 있습니다.
데니스

31
@Daenyth : 솔직히 500 개의 커스텀 브랜치가 있었지만 아직은 놀랍습니다 . 누가 상황을 악화시킬 수 있습니까? lol
궤도에서 가벼움

73
@FernandoTan 너무 너무 너무 너무 너무 너무 죄송합니다.
enderland

20
@ 페르난도 탄 : 나도. :( 어쩌면 인터뷰에서 더 많은 질문을해야했을까요?;) 분명히, 내 대답에서 "당신"은 조직입니다. 추상화입니다. 나는 개인에게 책임을 부여하려고하지 않습니다.
궤도에서 가벼움 경주

58
먼저 더 많은 통찰력을 얻으십시오 : 개발자가 현재 버전과 사용자 정의 된 브랜치간에 차이를 만들도록하십시오. 따라서 적어도 차이점이 무엇인지 알 것입니다. 이 목록을 통해 분기를 가장 빠르게 줄일 수있는 위치를 확인할 수 있습니다. 50에 사용자 정의 필드 이름이 있으면 그에 초점을 맞추면 50 가지가 절약됩니다. 다음을 찾으십시오. 복원 할 수없는 일부가있을 수도 있지만 최소한 금액이 줄어들고 더 많은 고객을 확보하면 더 이상 증가하지 않습니다.
Luc Franken

93

500 명의 고객을 확보하는 것은 좋은 문제입니다. 지점에서이 문제를 피하기 위해 시간을 앞당기면 고객을 확보하기에 충분한 시간 동안 거래를 지속 할 수 없었을 것입니다.

먼저, 고객이 자신의 커스텀 버전을 유지하는 데 드는 모든 비용 을 충당하기에 충분한 비용을 청구하기를 바랍니다 . 나는 고객이 자신의 커스터마이즈를 다시 수행하기 위해 비용을 지불하지 않고 새로운 버전을 얻을 것으로 기대한다고 가정합니다. 나는 지점의 95 %에서 동일한 모든 파일을 찾는 것으로 시작합니다. 95 %는 응용 프로그램의 안정적인 부분입니다.

그런 다음 분기간에 몇 줄만 다른 모든 파일을 찾으십시오. 이러한 차이를 제거 할 수 있도록 구성 시스템을 도입하십시오. 예를 들어, 텍스트 필드 레이블이 다른 수백 개의 파일을 갖는 대신 텍스트 레이블을 대체 할 수있는 구성 파일이 하나 있습니다. (이 작업은 한 번에 수행 할 필요는 없습니다. 고객이 처음 텍스트 필드 레이블을 변경하려고 할 때 텍스트 필드 레이블을 구성 할 수있게하십시오.)

그런 다음 전략 패턴, 의존성 주입 등을 사용하여 어려운 문제로 넘어갑니다.

클라이언트 자신의 필드에 대한 열을 추가하지 않고 데이터베이스에 json을 저장하는 것을 고려하십시오. 이는 SQL로 이러한 필드를 검색 할 필요가없는 경우 유용합니다.

파일을 브랜치에 체크인 할 때마다 반드시 메인 파일과 비교하여 공백을 포함하여 모든 단일 변경을 정당화해야합니다. 많은 변경이 필요하지 않으며 체크인 전에 제거 할 수 있습니다. 코드 포맷에 대한 편집기 설정이 다른 개발자 한 명일 수 있습니다.

먼저 파일 수가 많은 500 개의 지점에서 다른 파일이 거의없는 대부분의 지점으로 이동하려고합니다. 여전히 살 돈이 충분합니다.

수년 동안 500 개의 지점을 보유하고있을 수 있지만 관리하기가 훨씬 쉬운 경우에는 이겼습니다.


br3w5의 의견에 따라 :

  • 클라이언트마다 다른 수업을 수강 할 수 있습니다
  • 클래스 외부에서 호출 된 모든 메소드를 정의하는 "xxx_baseclass"를 작성하십시오.
  • xxx가 xxx_clientName (xxx_baseclass의 하위 클래스)이되도록 클래스 이름을 바꾸십시오.
  • 각 클라이언트에 올바른 버전의 클래스가 사용되도록 종속성 주입을 사용하십시오.
  • 그리고 이제 똑똑한 통찰력을 위해 br3w5가 등장했습니다! 정적 코드 분석 도구를 사용하여 이제 복제 된 코드를 찾아 기본 클래스 등으로 이동하십시오.

쉬운 곡식을 얻은 후에 만 ​​위의 작업을 수행하고 먼저 몇 개의 수업으로 추적하십시오.


28
실제 문제에 대한 접근을 시도한 +1
Ian

35
나는 당신이 대답을 쓴 동일한 @Ian이 아니라는 것을 깨달을 때까지 당신이 당신의 대답에 대해 자신을 축하하고 있다는 것을 정말로 걱정했습니다.
Theron Luhn

2
어쩌면 정적 코드 분석 도구를 사용하여 코드의 어떤 부분이 복제되는지 좁혀 야합니다 (동일한 모든 파일을 식별 한 후)
br3w5

1
또한 클라이언트 코드의 버전을 가지고 팀을 추적하기 위해 버전 패키지를 만드는
br3w5

1
"단순히 코드를 리팩터링"하는 바람이 많이
Roland Tepp

40

앞으로 인터뷰에서 Joel 테스트 질문을하십시오. 난파선에 들어 가지 않을 가능성이 더 높습니다.


이것은, 아, 우리가 어떻게 말할 것인가 ... 정말로, 정말로 나쁜 문제입니다. 이 기술 부채에 대한 "이자율"은 매우 높을 것입니다. 복구 할 수 없습니다 ...

이러한 사용자 지정 변경 사항은 "핵심"과 어떻게 통합됩니까? 그들 만의 라이브러리를 만들고 하나의 "핵심"과 각각의 특정 고객에게 고유 한 "애드온"을 가질 수 있습니까?

아니면 이것들이 모두 아주 작은 구성입니까?

솔루션이 다음과 같은 조합이라고 생각합니다.

  • 하드 코드 된 모든 변경 사항을 구성 기반 항목으로 변경합니다. 이 경우 모든 사람이 동일한 핵심 응용 프로그램을 갖지만 사용자 (또는 사용자)는 필요에 따라 기능을 설정 / 해제하고 이름 지정 등을 설정합니다.
  • "클라이언트 별"기능 / 모듈을 별도의 프로젝트로 옮기기 때문에 하나의 "프로젝트"를 갖지 않고 쉽게 추가 / 제거 할 수있는 모듈이있는 하나의 "핵심 프로젝트"가 있습니다. 또는 이러한 구성 옵션을 만들 수도 있습니다.

마치 500 명 이상의 고객을 보유한 것처럼 사소한 것도 아닙니다. 이 분리에 대한 변경 사항이 시간이 많이 걸리는 작업이 될 것으로 기대합니다.

또한 모든 고객 별 코드를 쉽게 분리하고 분류하는 데 심각한 문제가 있다고 생각합니다.

변경 사항의 대부분은 특히 표현의 차이가 있다면, 내가 좋아하는 독서 질문에 제안 언어 현지화에 대한합니다. 여러 언어를 완전히 수행하든 아니면 일부만 수행하든 솔루션은 동일합니다. 이것은 구체적으로 PHP와 현지화입니다.


1
또한이 작업은 (최소한의) 큰 과제이므로 관리자에게이 문제에 대해 많은 시간과 돈을 투자하도록 설득하는 것은 큰 도전이 될 것입니다. @FernandoTan이 사이트에는이 특정 문제를 해결하는 데 도움이되는 질문과 답변이있을 수 있습니다.
Radu Murzea

10
joel 테스트의 어떤 질문에서 회사가 지점을 남용하고 있다고 말했습니까?
SpaceTrucker

2
@SpaceTrucker : 음, "매일 빌드합니까?" 도움이 될 수 있습니다. 500 개의 지점이 있으면 아마도 해당 지점이 없거나 일부 지점에 대해서만 수행한다고 언급했을 수 있습니다.
sleske

17

이것은 VCS로 칠 수있는 최악의 안티 패턴 중 하나입니다.

여기서 올바른 접근 방식은 사용자 지정 코드를 구성으로 구동되는 것으로 바꾸는 것입니다. 그런 다음 각 고객은 구성 파일이나 데이터베이스 또는 다른 위치에 하드 코딩 된 자체 구성을 가질 수 있습니다. 전체 기능을 활성화 또는 비활성화하고 응답 모양을 사용자 정의하는 등의 작업을 수행 할 수 있습니다.

이를 통해 생산 코드를 사용하여 하나의 마스터 분기를 유지할 수 있습니다.


3
이렇게하면 자신에게 유리한 자세를 취하고 가능한 한 전략 패턴 을 사용하십시오 . 이렇게하면 단순히 if(getFeature(FEATURE_X).isEnabled())전체적으로 흩어져있는 것보다 코드를 유지 관리하기가 훨씬 쉬워집니다 .
TMN

13

지점의 목적은 주요 지점의 안정성을 훼손 할 위험없이 가능한 개발 방법을 모색하는 것입니다. 그것들은 결국 적절한 시간에 다시 합쳐 지거나 막 다른 길로 이어지는 경우 폐기되어야합니다. 당신이 가진 것은 많은 가지가 아니라 같은 프로젝트의 500 가지가 넘는 포크 이며 중요한 변경 세트를 모든 것에 적용하려고 시도하는 것은 사이프시 작업입니다.

대신해야 할 일은 구성을 통해 동작을 수정하고 거꾸로 된 종속성에 의해 허용되는 동작을 주입하는 데 필요한 진입 점이있는 핵심 코드를 자체 저장소에 배치 하는 것 입니다.

그런 다음 클라이언트에 대해 다른 설정을 사용하면 외부에서 구성한 상태 (예 : 데이터베이스)로 서로를 구별하거나 필요한 경우 별도의 리포지토리로 라이브를 수행하여 코어를 하위 모듈로 추가 할 수 있습니다.


6
유지 보수 분기를 잊어 버렸습니다. 이는 기본적으로 답변에서 설명한 분기와 반대입니다. :)
궤도에서 가벼움 경주

7

모든 중요한 것들이 여기에 좋은 대답으로 제안되었습니다. 프로세스 제안으로 5 펜스를 추가하고 싶습니다.

이 문제를 장기 또는 중급 범위에서 해결하고 코드 개발 방법에 대한 정책을 채택하고 싶습니다. 유연한 학습 팀이 되십시오. 누군가가 소프트웨어를 구성 할 수있게 만드는 대신 500 개의 저장소를 가질 수 있다면 지금까지의 작업 방식을 스스로에게 물어볼 차례입니다.

다음을 의미합니다.

  1. 변경 관리 책임을 명확히 : 고객이 어떤 adaptions, 필요로하는 경우 를 판매하고, 이를 허용하고을하고 있는 사람은 코드가 변경되는 방식을 결정 하는가? 일부 사항을 변경해야 할 경우 나사를 어디로 돌리겠습니까?
  2. 역할, 팀에서 누가 새로운 레포지토리를 만들 수 있는지, 누가 아닌지 역할을 명확히하십시오 .
  3. 팀의 모든 사람이 소프트웨어 유연성을 허용하는 패턴의 필요성을 확인하도록하십시오.
  4. 관리 도구를 명확하게 설명하십시오. 어떤 고객이 어떤 코드를 채택했는지 신속하게 알 수 있습니다. 나는 "500 개의 목록"이 성가신 것처럼 들리지만, 원한다면 여기에 "정서적 경제"가있다. 빠른 시간 내에 고객의 변경 사항을 알 수 없으면 목록을 시작해야하는 것처럼 더 많은 손실을 당하게됩니다. 그런 다음이 목록을 사용하여 다른 사람들의 답변이 표시 한 방식으로 기능을 그룹화하십시오.
    • 사소한 / 주요 변경으로 고객 그룹화
    • 주제 관련 변경 사항별로 그룹화
    • 병합하기 쉬운 변경 및 병합하기 어려운 변경으로 그룹화
    • 여러 저장소에 대해 동일한 변경 사항이있는 그룹을 찾으십시오 (예, 일부는있을 것입니다).
    • 아마도 관리자 / 투자자와 대화하기 위해 가장 중요한 것 : 비싼 변화와 저렴한 변화로 그룹화하십시오 .

이것은 팀에서 나쁜 압력 분위기를 조성하는 것은 아닙니다. 차라리 여러분이 먼저 이러한 요점을 명확히하고, 지원이 있다고 생각 될 때마다 팀과 함께 구성하십시오. 모든 경험을 향상시키기 위해 테이블에 친숙한 사람들을 초대하십시오.

그런 다음 작은 불꽃 에서이 물건을 요리하는 장기 시간 창을 설정하십시오. 제안 : 매주 적어도 두 개의 저장소를 병합하여 하나 이상 제거하십시오 . 일상과 감독을 받으면 종종 두 개 이상의 지점을 병합 할 수 있다는 것을 알게 될 것입니다. 이렇게하면 1 년 안에 최악의 (가장 비싼) 지점을 처리 할 수 ​​있으며 2 년 안에이 문제를 줄여서 더 나은 소프트웨어를 만들 수 있습니다. 그러나 결국 아무도 "시간"을 가지지 않기 때문에 더 이상 기대하지 마십시오. 그러나 소프트웨어 아키텍트로서 더 이상 이것을 허용하지 않는 사람입니다.

이것이 내가 당신의 입장에 있다면 그것을 처리하려고 시도하는 방법입니다. 그러나 나는 당신 팀이 어떻게 그런 것들을 받아 들일 것인지, 소프트웨어가 실제로 이것을 어떻게 허용하는지, 어떻게 당신을 지원하는지, 그리고 아직도 배워야 할 것을 모릅니다. 당신은 소프트웨어 아키텍트입니다-그냥 가십시오 :-)


2
기술적 문제 뒤에 숨어있는 사회적 / 조직적 문제를 해결하는 데 대한 좋은 점. 이것은 종종 간과됩니다.
sleske

5

모든 혐오 자들과 달리 실제 비즈니스 요구를 가정 해 봅시다.

(예를 들어, 인도 물은 소스 코드이며, 고객은 동일한 비즈니스 라인에서 서로 경쟁자이므로 서로 비밀을 유지하겠다는 비즈니스 모델을 약속합니다)

또한,의 기업은 모든 지점을 유지하기 위해 도구를 가지고 있다고 가정하자, 즉 하나 인력 (의 말을하자 100 개발자 병합에 전념, 5 일 출시 지연을 가정 또는 10 DEVS 가정 50 일 출시 지연을 확인한다), 또는 자동화 된 머지 (Merge)가 모든 지점에서 핵심 스펙확장 스펙 으로 모두 테스트되는 놀라운 자동화 테스트는 "정확하게 "병합되지 않은 변경 사항에만 사람의 개입이 필요합니다. 고객이 사용자 지정뿐만 아니라 유지 관리 비용을 지불하는 경우 이는 유효한 비즈니스 모델 일 수 있습니다.

내 (그리고 나쁜 사람들) 질문, 당신은 각 고객에게 배달을 담당 하는 전담 직원이 있습니까? 예를 들어 10,000 명 규모의 회사라면 그럴 수 있습니다.

이는 경우에 따라 플러그인 아키텍처 로 처리 될 수 있습니다. 코어가 트렁크이고 플러그인이 트렁크 또는 분기에있을 수 있으며 각 고객에 대한 구성이 고유 한 이름의 파일이거나 고객 지사에 있다고 가정 해 봅시다.

플러그인은 런타임에로드되거나 컴파일시 내장 될 수 있습니다.

근본적으로 동일한 문제가 여전히 적용되는 근본적으로 동일한 프로젝트가 실제로 많은 프로젝트를 수행합니다. 간단한 핵심 변경 사항은 통합하기가 쉽지 않으며 충돌 변경 사항을 롤백하거나 많은 플러그인에 변경 사항이 필요합니다.

플러그인이 충분하지 않은 경우가 있습니다. 플러그인 인터페이스 수가 처리하기에 너무 많은 코어 내부를 조정해야하는 경우가 있습니다.

이상적으로 는 트렁크가 핵심 코드이고 분기가 측면 (여분의 코드와 추가를 코어에 연결하는 방법) 인 측면 지향 프로그래밍에 의해 처리됩니다.

간단한 예를 들어, 사용자 지정 foo이 코어 이전 또는 이후에 실행 klass.foo되거나이를 대체하거나이를 감싸서 입력 또는 출력을 변경할 수 있도록 지정할 수 있습니다.

이를위한 수많은 라이브러리가 있지만 병합 충돌 문제는 사라지지 않습니다. 깔끔한 병합은 AOP에 의해 처리되며 여전히 사람의 개입이 필요합니다.

마지막으로 이러한 비즈니스는 실제로 지점 유지 관리 와 관련 이 있습니다. 즉, 고객 별 기능 X가 너무 일반적이기 때문에 모든 고객이 비용을 지불하지는 않지만 코어로 이전하는 것이 더 저렴합니까?


3

증상을보고 질병의 근본 원인을 해결하지 못하고 있습니다. '코드 관리'접근 방식을 사용하는 것은 증상이 있지만 장기적으로 해결되지는 않습니다. 근본 원인은 '잘 관리 된'제품 기능, 기능 및 확장 및 변형이 부족하기 때문입니다.

귀하의 '사용자 정의'코드의 확장에 불과 대표하지 않습니다 제품의 특징 및 기능데이터 필드 등의 변경.

사용자 정의 기능이 얼마나 광범위하고, 얼마나 다른지, 문맥 상 유사하거나 그렇지 않은 경우 제품의 코드베이스를 '위생'하는 데 많은 영향을 미칩니다.

코딩 및 버전 관리 방법 외에도 제품 관리, 제품 아키텍처 및 데이터 아키텍처 가 작동하는 곳 입니다. 진심으로.

결국,이 코드는 고객에게 비즈니스 및 제품 기능 / 서비스 를 제공하는 것에 지나지 않습니다 . 그것이 회사가 지불하는 것입니다.

이에 대한 더 나은 처리는 코드 관점이 아닌 '기능'관점에서 이루어져야합니다.

귀하, 회사 및 제품이 모든 사람에게 모든 것이 될 수는 없습니다. 이제 500 명의 고객으로 이루어진 적절한 수익 기반을 확보 했으므로 이제 원하는대로 제품화해야합니다.

그리고 여러 가지를 제공하는 경우 제품 기능을 체계적으로 모듈화하는 것이 좋습니다.

당신의 제품은 얼마나 넓고 깊어 질까요? 그렇지 않으면 줄을 따라 가면서 '서비스 품질'문제 및 '제품 희석 및 조각화'로 이어질 것입니다.

당신은있을 것인가 CRM 이나 ERP 또는 주문 처리 / 파견 또는 Microsoft Excel?

기존 확장 프로그램은 대규모 소프트웨어 전공 이 스타트 업에서 얻은 제품을 가져 오고 병합 하는 방식으로 롤업하고 조화를 이루어야합니다 .

강력한 제품 관리 및 데이터 아키텍처 담당자가 다음을 매핑해야합니다.

  • 마스터 브랜치, 제품 기능 및 기능 기반
  • 맞춤 확장 기능, 유형 및 변형
  • '맞춤 필드'의 의미와 변형

핵심 응용 프로그램의 전체 맥락에서 이러한 느슨한 제품 스레드 / 지점의 동화 및 조화에 대한 로드맵을 작성합니다.

추신 : 나와 연결하십시오.이 문제를 해결하는 데 도움을 줄 수있는 사람을 알고 있습니다 :)


-5

나는 이것에 관련 될 수있다. 많은 프로젝트를 진행했습니다. 실제로 개발 작업의 90 %가 이러한 문제를 해결하고 있습니다. 모든 사람이 완벽하지는 않으므로 올바른 방법으로 현재 위치에 버전 관리를 사용하는 것이 좋습니다. 가능하면 다음을 수행 할 수 있습니다.

  • 이제부터 고객이 업데이트를 요청하면 새 분기 저장소로 옮깁니다.
  • 마스터로 병합하려면 첫 번째로 수행하고 충돌을 해결하십시오.
  • 그런 다음 리포지토리를 사용하여 문제와 스프린트를 관리하고 마스터에서 시작하려는 문제를 마스터로 유지하십시오. 이로 인해 릴리스주기에 더 많은 부담이 가해 지지만 시간이 지남에 따라 비용이 절약됩니다.
  • 신규 고객을위한 기본 리포지토리의 마스터 지점을 유지 관리하고 기본 리포지토리에는 향후 작업을 위해 작업중인 지점 만 있어야합니다. 레거시 브랜치는 고객 리포지토리로 마이그레이션되면 삭제할 수 있습니다.

40 개의 지점이있는 GitHub 에서 저장소 를 Bitbucket으로 직접 가져 와서 40 개의 저장소를 작성했습니다. 4 시간 밖에 걸리지 않았습니다. 이것은 WordPress 테마 변형이므로 밀어 넣기가 빠릅니다.

"처음으로 제대로하지 않는 것"에는 여러 가지 이유가 있으며, 빨리 받아들이고 "이번에 올바르게해라"는 사람들은 항상 성공할 것이라고 생각합니다.


16
여러 리포지토리가 유지 관리를 더 쉽게 만드는 방법은 무엇입니까?
Mathletics

우리와 같은 일부 고객은 맞춤형 솔루션이 될 때 각 리포지토리에 액세스하고 자체 문제를 관리해야하므로 자체 리포지토리가있어 관리하기가 쉽고 워드 프레스 테마 변형이라고 말했듯이 잘 작동했습니다. 많은 경우에 작동하지 않을 수 있습니다.
Farrukh Subhani
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.