etc./StackOverFlow

Subversion 저장소에서 "분기", "태그" 및 "트렁크"는 무엇을 의미합니까?

청렴결백한 만능 재주꾼 2023. 5. 2. 22:10
반응형

질문자 :grapefrukt


Subversion(일반 저장소) 토론에서 이 단어를 많이 보았습니다.
나는 지난 몇 년 동안 내 프로젝트에 SVN 을 사용해 왔지만 이러한 디렉토리의 완전한 개념을 이해한 적이 없습니다.

그들은 무엇을 의미합니까?



흠, Nick re 태그가 브랜치와 비슷하다는 데 동의하는지 잘 모르겠습니다. 태그는 마커일 뿐입니다.

  • Trunk 는 프로젝트 시작부터 현재까지 개발의 주체가 될 것입니다.

  • 분기 는 트렁크의 코드 무결성을 유지하면서 코드에 주요 변경 사항을 적용하는 데 사용되는 트렁크의 특정 지점에서 파생된 코드 복사본입니다. 주요 변경 사항이 계획에 따라 작동하는 경우 일반적으로 트렁크에 다시 병합됩니다.

  • 태그 는 보존하려는 줄기나 가지의 특정 시점이 됩니다. 보존에 대한 두 가지 주요 이유는 이것이 알파, 베타, RC 또는 RTM 여부와 상관없이 소프트웨어의 주요 릴리스이거나 트렁크에 대한 주요 개정이 적용되기 전 소프트웨어의 가장 안정적인 지점이기 때문입니다.

오픈 소스 프로젝트에서 프로젝트 이해 관계자가 트렁크로 받아들이지 않은 주요 브랜치는 포크 의 기반이 될 수 있습니다. 예를 들어, 다른 소스 코드와 공통 출처를 공유하는 완전히 별개의 프로젝트입니다.

분기 및 태그 하위 트리는 다음과 같은 방식으로 트렁크와 구별됩니다.

Subversion을 사용하면 시스템 관리자가 특정 이벤트가 발생할 때 실행을 위해 트리거되는 후크 스크립트를 만들 수 있습니다. 예를 들어, 저장소에 변경 사항을 커밋합니다. 일반적인 Subversion 저장소 구현에서는 "/tag/"를 포함하는 모든 경로를 생성 후 쓰기 방지되도록 처리하는 것이 매우 일반적입니다. 최종 결과는 태그가 일단 생성되면 변경할 수 없다는 것입니다(적어도 "일반" 사용자에게는). 이것은 태그 가 변경된 객체의 부모 노드인 경우 추가 변경을 방지하여 불변성을 적용하는 후크 스크립트를 통해 수행됩니다.

Subversion은 또한 버전 1.5부터 "분기 병합 추적"과 관련된 기능을 추가하여 분기에 커밋된 변경 사항을 증분 "스마트" 병합을 지원하여 트렁크로 다시 병합할 수 있습니다.


Jon Limjap

우선 @AndrewFinnell과 @KenLiu가 지적했듯이 SVN에서 디렉토리 이름 자체는 아무 의미가 없습니다. "트렁크, 분기 및 태그"는 단순히 대부분의 저장소에서 사용되는 일반적인 규칙입니다. 모든 프로젝트가 모든 디렉토리를 사용하는 것은 아니며("태그"를 전혀 사용하지 않는 것이 합리적입니다) 사실, 규칙을 어기는 것이 종종 혼동되기는 하지만 실제로 원하는 대로 호출하는 것을 막을 수 있는 것은 없습니다.

분기와 태그의 가장 일반적인 사용 시나리오를 설명하고 사용 방법에 대한 예제 시나리오를 제공하겠습니다.

  • 트렁크 : 주요 개발 영역. 이것은 코드의 다음 주요 릴리스가 있는 곳이며 일반적으로 모든 최신 기능을 포함합니다.

  • 분기 : 주 버전을 릴리스할 때마다 분기가 생성됩니다. 이를 통해 미완성 또는 테스트되지 않은 최신 기능을 릴리스하지 않고도 버그 수정을 수행하고 새 릴리스를 만들 수 있습니다.

  • 태그 : 버전(최종 릴리스, 릴리스 후보(RC) 및 베타)을 릴리스할 때마다 해당 태그를 만듭니다. 이렇게 하면 해당 상태의 코드의 특정 시점 복사본이 제공되므로 필요한 경우 과거 버전으로 돌아가서 모든 버그를 재현하거나 과거 버전을 그대로 다시 릴리스할 수 있습니다. SVN의 분기와 태그는 가볍습니다. 서버에서 파일의 전체 복사본을 만들지 않고 "이 파일은 이 개정판에서 복사되었습니다"라는 표시만 몇 바이트만 차지합니다. 이를 염두에 두고 릴리스된 코드에 대한 태그 생성에 대해 걱정해서는 안 됩니다. 앞서 말했듯이 태그가 생략되는 경우가 많으며 대신 변경 로그 또는 기타 문서에서 릴리스가 만들어지면 개정 번호를 명확히 합니다.


예를 들어 새 프로젝트를 시작한다고 가정해 보겠습니다. 결국 버전 1.0으로 출시될 "트렁크" 작업을 시작합니다.

  • trunk/ - 곧 1.0이 될 개발 버전
  • 가지/ - 비어 있음

1.0.0이 완료되면 트렁크를 새로운 "1.0" 브랜치로 분기하고 "1.0.0" 태그를 생성합니다. 이제 궁극적으로 1.1이 될 작업이 트렁크에서 계속됩니다.

  • trunk/ - 곧 1.1이 될 개발 버전
  • branch/1.0 - 1.0.0 릴리스 버전
  • tags/1.0.0 - 1.0.0 릴리스 버전

코드에서 몇 가지 버그를 발견하고 트렁크에서 수정한 다음 수정 사항을 1.0 분기에 병합합니다. 반대로 할 수도 있고 1.0 브랜치의 버그를 수정한 다음 트렁크에 다시 병합할 수도 있지만 일반적으로 프로젝트는 무언가를 놓칠 가능성을 줄이기 위해 단방향 병합을 고수합니다. 때때로 버그는 1.1에서 더 이상 사용되지 않기 때문에 1.0에서만 수정될 수 있습니다. 그것은 정말로 중요하지 않습니다. 당신은 1.0에서 수정된 것과 동일한 버그로 1.1을 릴리스하지 않기를 원할 뿐입니다.

  • trunk/ - 곧 1.1이 될 개발 버전
  • branch/1.0 - 곧 출시될 1.0.1 릴리스
  • tags/1.0.0 - 1.0.0 릴리스 버전

충분한 버그(또는 하나의 중요한 버그)를 찾으면 1.0.1 릴리스를 수행하기로 결정합니다. 따라서 1.0 분기에서 태그 "1.0.1"을 만들고 코드를 릴리스합니다. 이 시점에서 트렁크에는 1.1이 포함되고 "1.0" 분기에는 1.0.1 코드가 포함됩니다. 다음에 1.0으로 업데이트를 릴리스하면 1.0.2가 됩니다.

  • trunk/ - 곧 1.1이 될 개발 버전
  • branch/1.0 - 곧 출시될 1.0.2 릴리스
  • tags/1.0.0 - 1.0.0 릴리스 버전
  • tags/1.0.1 - 1.0.1 릴리스 버전

마침내 1.1을 출시할 준비가 거의 완료되었지만 먼저 베타를 수행하고 싶습니다. 이 경우 "1.1" 분기 및 "1.1beta1" 태그를 수행할 수 있습니다. 이제 1.2(또는 2.0)가 될 작업은 트렁크에서 계속되지만 1.1에 대한 작업은 "1.1" 분기에서 계속됩니다.

  • trunk/ - 곧 1.2가 될 개발 버전
  • branch/1.0 - 곧 출시될 1.0.2 릴리스
  • branch/1.1 - 곧 출시될 1.1.0 릴리스
  • tags/1.0.0 - 1.0.0 릴리스 버전
  • tags/1.0.1 - 1.0.1 릴리스 버전
  • tags/1.1beta1 - 1.1 베타 1 릴리스 버전

1.1 최종 버전을 릴리스하면 "1.1" 분기에서 "1.1" 태그를 수행합니다.

또한 원하는 경우 1.0을 계속 유지하여 세 가지 모든 분기(1.0, 1.1 및 트렁크) 간에 버그 수정을 이식할 수도 있습니다. 중요한 점은 유지 관리하는 소프트웨어의 모든 기본 버전에 대해 해당 버전에 대한 최신 버전의 코드가 포함된 분기가 있다는 것입니다.


분기의 또 다른 용도는 기능입니다. 여기에서 트렁크(또는 릴리스 분기 중 하나)를 분기하고 새 기능을 별도로 작업합니다. 기능이 완료되면 다시 병합하고 분기를 제거합니다.

  • trunk/ - 곧 1.2가 될 개발 버전
  • branch/1.1 - 곧 출시될 1.1.0 릴리스
  • branch/ui-rewrite - 실험 기능 분기

이것에 대한 아이디어는 방해가 되는 것(다른 사람들이 작업을 수행하는 것을 방해하거나 방해하는 것), 실험적인 것(성공하지 못할 수도 있는 것), 또는 아마도 시간이 오래 걸리는 작업을 할 때입니다. (그리고 트렁크에서 1.2를 분기할 준비가 되었을 때 1.2 릴리스를 유지하는 것이 두렵다면) 분기에서 분리하여 수행할 수 있습니다. 일반적으로 변경 사항을 항상 트렁크에 병합하여 최신 상태로 유지하므로 작업이 끝나면 다시 통합(트렁크로 다시 병합)하기가 더 쉽습니다.


또한 여기서 사용한 버전 관리 체계는 많은 것 중 하나일 뿐입니다. 일부 팀은 1.1, 1.2 등으로 버그 수정/유지 관리 릴리스를 수행하고 1.x, 2.x 등으로 주요 변경 사항을 수행합니다. 여기서 사용법은 동일하지만 분기 이름을 "1" 또는 "1"로 지정할 수 있습니다. "1.0" 또는 "1.0.x" 대신 .x". (제쳐두고, 의미론적 버전 관리 는 버전 번호를 수행하는 방법에 대한 좋은 가이드입니다).


gregmac

Nick이 말한 것 외에도 Streamed Lines: Branching Patterns for Parallel Software Development에서 자세히 알아볼 수 있습니다.

여기에 이미지 설명 입력

이 그림에서 main 은 트렁크, rel1-maint 는 분기, 1.0 은 태그입니다.


grom

일반적으로 (도구 불가지론적 관점) 분기는 병렬 개발에 사용되는 메커니즘입니다. SCM은 0에서 n개의 분기를 가질 수 있습니다. Subversion은 0입니다.

  • Trunk 는 Subversion 에서 권장 하는 주요 분기이지만 강제로 만들 필요는 없습니다. 당신은 그것을 '메인' 또는 '릴리스'라고 부를 수도 있고, 전혀 가지고 있지 않을 수도 있습니다!

  • Branch 는 개발 노력을 나타냅니다. 리소스(예: 'vonc_branch')의 이름을 따서 이름을 지정해서는 안 됩니다.

    • 목적 'myProject_dev' 또는 'myProject_Merge'
    • 릴리스 경계 'myProjetc1.0_dev'또는 myProject2.3_Merge' 또는 'myProject6..2_Patch1'...
  • 태그 는 해당 상태로 쉽게 돌아가기 위한 파일의 스냅샷입니다. 문제는 태그와 분기가 Subversion에서 동일하다는 것 입니다. 그리고 나는 확실히 편집증적 접근을 추천할 것입니다:

    Subversion과 함께 제공되는 액세스 제어 스크립트 중 하나를 사용하여 태그 영역에서 새 복사본을 만드는 것 외에는 아무 것도 하지 못하도록 할 수 있습니다.

태그는 최종입니다. 그 내용은 절대 변경되어서는 안됩니다. 절대. 항상. 릴리스 노트의 한 줄을 잊으셨습니까? 새 태그를 만듭니다. 오래된 것을 사용하지 않거나 제거하십시오.

이제 "이런 가지를 다시 병합한 다음 마침내 트렁크 분기에 병합"에 대해 많이 읽었습니다. 이를 병합 워크플로 라고 하며 여기에는 필수 항목 이 없습니다. 트렁크 브랜치가 있기 때문에 다시 병합해야 하는 것은 아닙니다.

관례에 따라 트렁크 분기는 현재 개발 상태를 나타낼 수 있지만 이는 다음을 포함하는 간단한 순차 프로젝트에 대한 것입니다.

  • '사전' 개발 없음(현재 '트렁크' 개발과 호환되지 않는 변경을 암시하는 다음 다음 버전 준비를 위해)
  • 대규모 리팩토링 없음(새로운 기술 선택 테스트용)
  • 이전 릴리스의 장기 유지 관리 없음

이러한 시나리오 중 하나(또는 모두)를 사용하면 4개의 '트렁크', 4개의 '현재 개발'을 얻게 되며 이러한 병렬 개발에서 수행하는 모든 작업이 반드시 '트렁크'에 다시 병합되어야 하는 것은 아닙니다.


Community Wiki

SVN에서 태그와 분기는 정말 유사합니다.

태그 = 일반적으로 릴리스에 사용되는 정의된 시간 조각

분기 = 또한 개발을 계속할 수 있는 정의된 시간 조각으로, 일반적으로 1.0, 1.5, 2.0 등과 같은 주요 버전에 사용되며 릴리스할 때 분기에 태그를 지정합니다. 이를 통해 트렁크의 주요 변경 사항을 계속 진행하면서 프로덕션 릴리스를 계속 지원할 수 있습니다.

트렁크 = 개발 작업 공간, 여기에서 모든 개발이 발생하고 분기 릴리스에서 변경 사항이 다시 병합됩니다.


Nick Berardi

형식적인 의미는 없습니다. 폴더는 SVN에 대한 폴더입니다. 프로젝트를 구성하는 데 일반적으로 허용되는 방법입니다.

  • 트렁크는 주요 개발 라인을 보관하는 곳입니다. 브랜치 폴더는 짧은 포스트로 설명하기 힘든 브랜치를 생성할 수 있는 곳입니다.

  • 분기는 트렁크와 별도로 작업하는 프로젝트 하위 집합의 복사본입니다. 아무데도 가지 않을 수 있는 실험을 위한 것일 수도 있고, 다음 릴리스를 위한 것일 수도 있습니다. 나중에 안정되면 트렁크로 다시 병합됩니다.

  • 그리고 tags 폴더는 일반적으로 릴리스 체크포인트에서 리포지토리의 태그가 지정된 복사본을 만들기 위한 것입니다.

하지만 내가 말했듯이 SVN에게 폴더는 폴더입니다. branch , trunk 및 tag는 단지 관례일 뿐입니다.

저는 '복사'라는 단어를 자유롭게 사용하고 있습니다. SVN은 실제로 저장소의 전체 복사본을 만들지 않습니다.


Eric Z Beard

트렁크 는 최신 소스 코드와 기능을 담고 있는 개발 라인입니다. 최신 버그 수정과 프로젝트에 추가된 최신 기능이 있어야 합니다.

분기 는 일반적으로 빌드를 중단 할 트렁크(또는 다른 개발 라인)에서 떨어진 작업을 수행하는 데 사용됩니다. 새 기능은 종종 분기에 빌드된 다음 트렁크에 다시 병합됩니다. 분기에는 분기가 시작된 개발 라인에 대해 반드시 승인되지 않은 코드가 포함되어 있는 경우가 많습니다. 예를 들어, 프로그래머는 분기에서 최적화를 시도하고 최적화가 만족스러운 경우에만 개발 라인에서 다시 병합할 수 있습니다.

태그 는 특정 시간에 저장소의 스냅샷입니다. 이들에 대한 개발이 발생해서는 안됩니다. 클라이언트가 사용 중인 항목에 쉽게 액세스할 수 있도록 클라이언트에 릴리스된 사본을 가져오는 데 가장 자주 사용됩니다.

다음은 리포지토리에 대한 매우 좋은 가이드에 대한 링크입니다.

Wikipedia의 기사도 읽을 가치가 있습니다.


mbillard

이제 그것이 소프트웨어 개발에 관한 것입니다. 어떤 것에 대해서도 일관된 지식이 없고, 모두가 나름의 방식을 가지고 있는 것 같지만, 그것은 어쨌든 상대적으로 젊은 분야이기 때문입니다.

여기 내 평범하고 간단한 방법이 있습니다.

트렁크 - 트렁크 디렉토리에는 가장 최근에 승인되고 병합된 작업 본문이 포함됩니다. 많은 사람들이 고백한 것과 달리 내 트렁크는 깨끗하고 단정하며 승인된 작업만을 위한 곳이며 개발 영역이 아니라 릴리스 영역입니다.

트렁크가 모두 해제될 준비가 된 것처럼 보이는 특정 시점에서 태그가 지정되고 해제됩니다.

지점 - 지점 디렉토리에는 실험 및 진행 중인 작업이 포함되어 있습니다. 분기 아래의 작업은 트렁크에 병합되도록 승인될 때까지 그대로 유지됩니다. 나에게 이것은 모든 작업이 수행되는 영역입니다.

예를 들면: 제품에 대한 5번째 개발 라운드를 위한 iteration-5 브랜치를 가질 수 있고, 9번째 실험 라운드를 위한 프로토타입-9 브랜치를 가질 수 있습니다.

tags - tags 디렉토리에는 승인된 분기 및 트렁크 릴리스의 스냅샷이 포함됩니다. 분기가 트렁크에 병합되도록 승인되거나 트렁크가 릴리스될 때마다 승인된 분기 또는 트렁크 릴리스의 스냅샷이 태그 아래에 만들어집니다.

나는 태그를 사용하여 시간을 앞뒤로 매우 쉽게 관심 지점으로 이동할 수 있다고 가정합니다.


BakerTheHacker

OpenCV 2 Computer Vision Application Programming Cookbook의 저자 웹사이트를 검색하다가 SVN에 관한 이 훌륭한 튜토리얼을 발견했고 공유해야 한다고 생각했습니다.

그는 SVN을 사용하는 방법과 'trunk', 'tag' 및 'branch'라는 문구가 의미하는 바에 대한 자습서를 가지고 있습니다.

그의 튜토리얼에서 직접 인용:

팀이 현재 작업하고 있는 소프트웨어 프로젝트의 현재 버전은 일반적으로 trunk 라는 디렉토리 아래에 있습니다. 프로젝트가 발전함에 따라 개발자는 해당 버전을 업데이트하여 버그를 수정하고 새로운 기능을 추가하고 해당 디렉토리 아래에 변경 사항을 제출합니다.

특정 시점에서 버전을 고정하고 현재 개발 단계에 있는 소프트웨어의 스냅샷을 캡처할 수 있습니다. 이는 일반적으로 소프트웨어의 공식 버전(예: 고객에게 제공할 버전)에 해당합니다. 이러한 스냅샷은 프로젝트의 tags 디렉토리 아래에 있습니다.

마지막으로, 어떤 시점에서 소프트웨어를 위한 새로운 개발 라인을 만드는 것이 종종 유용합니다. 예를 들어, 소프트웨어를 수정해야 하는 대체 구현을 테스트하려고 하지만 새 솔루션을 채택할지 결정할 때까지 이러한 변경 사항을 주 프로젝트에 제출하고 싶지 않은 경우에 이러한 상황이 발생합니다. 그러면 메인 팀은 다른 개발자가 프로토타입 작업을 하는 동안 프로젝트 작업을 계속할 수 있습니다. 당신은 프로젝트의 새로운 개발 라인을 branch 라는 디렉토리에 넣을 것입니다.


Vince

트렁크 디렉터리는 가장 최근의 변경 사항을 보관하는 데 사용되기 때문에 가장 익숙할 디렉터리입니다. 기본 코드베이스는 트렁크에 있어야 합니다.

branch 디렉토리는 그것이 무엇이든 상관없이 당신의 가지를 보관하기 위한 것입니다.

tags 디렉토리는 기본적으로 특정 파일 세트에 태그를 지정하기 위한 것입니다. 이 개정판에서는 "1.0"이 이러한 파일이 되고 "1.1"은 이 개정판에서 이러한 파일이 되기를 원하는 릴리스와 같은 작업에 대해 이 작업을 수행합니다. 일반적으로 태그가 만들어지면 수정하지 않습니다. 태그에 대한 자세한 내용은 4장. 분기 및 병합 ( Subversion을 사용한 버전 제어 )을 참조하십시오.


bradtgmurray

모든 사람이 약간 다른 정의를 갖는 이유 중 하나는 Subversion이 분기 및 태그에 대한 지원을 0으로 구현하기 때문입니다. Subversion은 기본적으로 다음과 같이 말합니다. 우리는 다른 시스템의 완전한 기능을 갖춘 분기와 태그를 살펴보았지만 유용하지 않았기 때문에 아무 것도 구현하지 않았습니다. 대신 이름 규칙을 사용하여 새 디렉토리에 복사본을 만드십시오 . 물론 모든 사람은 약간 다른 규칙을 가질 수 있습니다. 실제 태그와 단순한 복사 + 명명 규칙의 차이점을 이해하려면 Wikipedia 항목 Subversion 태그 및 분기를 참조하십시오.


MarcH

태그 = 일반적으로 릴리스에 사용되는 정의된 시간 조각

이것이 "태그"가 일반적으로 의미하는 것이라고 생각합니다. 그러나 Subversion에서:

형식적인 의미는 없습니다. 폴더는 SVN에 대한 폴더입니다.

나는 다소 혼란스럽다고 생각한다: 브랜치나 태그에 대해 아무것도 모르는 개정 제어 시스템. 보기의 구현 관점에서, 나는 "복사"를 만드는 서브 버전 방법은 매우 영리하다 생각하지만 난이라고 부르는 약 나를 알 필요 새는 추상화 .

아니면 제가 CVS를 너무 오래 사용해왔을 수도 있습니다.


sme

약간의 혼동은 태그의 개념과 SVN에서의 구현의 차이에서 비롯된다고 생각합니다. SVN에게 태그는 복사본인 분기입니다. 태그 수정은 잘못된 것으로 간주되며 실제로 TortoiseSVN과 같은 도구는 경로에 ../tags/..가 있는 항목을 수정하려고 하면 경고합니다.


denis phillips

'태그'가 무엇인지 잘 모르겠지만 분기는 상당히 일반적인 소스 제어 개념입니다.

기본적으로 분기는 트렁크에 영향을 주지 않고 코드 변경 작업을 수행하는 방법입니다. 상당히 복잡한 새 기능을 추가하고 싶다고 가정해 보겠습니다. 변경 사항을 체크인할 수 있기를 원하지만 기능을 완료할 때까지 트렁크에 영향을 미치고 싶지 않습니다.

먼저 분기를 만듭니다. 이것은 기본적으로 분기를 만든 시점의 트렁크 복사본입니다. 그런 다음 지점에서 모든 작업을 수행합니다. 분기에서 변경한 사항은 트렁크에 영향을 미치지 않으므로 트렁크를 계속 사용할 수 있으므로 다른 사람들이 계속해서 작업할 수 있습니다(예: 버그 수정 또는 작은 개선 작업). 기능이 완료되면 분기를 트렁크에 다시 통합합니다. 이렇게 하면 모든 변경 사항이 분기에서 트렁크로 이동됩니다.

사람들이 가지에 사용하는 많은 패턴이 있습니다. 한 번에 여러 주요 버전이 지원되는 제품이 있는 경우 일반적으로 각 버전은 분기가 됩니다. 제가 일하는 곳에 QA 지점과 Production 지점이 있습니다. 코드를 QA에 릴리스하기 전에 QA 분기에 변경 사항을 통합한 다음 거기에서 배포합니다. 프로덕션으로 릴리스할 때 QA 분기에서 프로덕션 분기로 통합하므로 프로덕션에서 실행 중인 코드가 QA에서 테스트한 것과 동일하다는 것을 알 수 있습니다.

여기 Branchs 에 대한 Wikipedia 항목이 있습니다 . 왜냐하면 내가 할 수 있는 것보다 더 잘 설명할 수 있기 때문입니다. :)


Herms

트렁크 : 애자일의 모든 스프린트가 완료된 후 부분적으로 배송 가능한 제품이 나옵니다. 이러한 릴리스는 트렁크에 보관됩니다.

분기 : 진행 중인 각 스프린트에 대한 모든 병렬 개발 코드는 분기에 보관됩니다.

태그 : 부분적으로 출하 가능한 베타 버전의 제품을 출시할 때마다 태그를 만듭니다. 이렇게 하면 해당 시점에 사용할 수 있었던 코드가 제공되어 개발 중 필요한 경우 해당 상태로 돌아갈 수 있습니다.


Ujjwal

GIT에 익숙한 사람들에게 GIT의 마스터는 SVN의 트렁크와 동일합니다.

분기와 태그는 GIT와 SVN에서 동일한 용어를 사용합니다.


Desert Rose

출처 : http:www.stackoverflow.com/questions/16142/what-do-branch-tag-and-trunk-mean-in-subversion-repositories

반응형