SVN 병합에있어 어려운 점은 무엇입니까? 사용자가 아니라 DVCS 옹호자가 주장한다는 주장을

가능한 중복 :
나는 Subversion 괴짜입니다. 왜 Mercurial이나 Git 또는 다른 DVCS를 고려해야합니까?

SVN에서는 병합이 어렵고 고통스럽기 때문에 분산 버전 제어 (Git, HG)가 SVN과 같은 중앙 집중식 버전 제어보다 본질적으로 우수하다고 말하는 사람이 가끔 있습니다. 문제는 SVN에서 병합하는 데 아무런 문제가 없었으며 실제 SVN 사용자가 아니라 DVCS 옹호자가 주장한다는 주장을 듣지 않았기 때문에 TV 에서 그 독창적 인 광고 를 상기시키는 곳입니다. 울퉁불퉁 한 배우들이 당신이 이미 가지고 있고 잘 작동하는 것이 매우 사용하기 어렵다고 가장하여 당신에게 필요없는 것을 팔아보십시오.

그리고 항상 제기 된 유스 케이스는 브랜치를 다시 합병 시키는데,이 밀짚 맨 제품 광고를 다시 상기시켜줍니다. 무엇을하고 있는지 아는 경우, 처음에 지점을 다시 병합하지 않아야합니다. (물론 근본적으로 잘못되고 어리석은 일을 할 때는 어렵습니다!)

따라서 어리석은 strawman 유스 케이스를 할인하면 DVCS 시스템에서 병합하는 것보다 본질적으로 어려운 SVN 병합에는 무엇이 있습니까?



답변

svn에는 두 가지의 최신 공통 조상을 정확하게 결정하기위한 적절한 데이터 구조가 없기 때문입니다. 한 번만 병합되는 브랜치에는 큰 영향을 미치지 않지만 여러 브랜치가 여러 번 병합되는 상황에서 많은 잘못된 병합 충돌이 발생할 수 있습니다.

나는 svn을 매우 밀접하게 따르지 않지만 특정 기술 문제가 최근 버전에서 수정되었다는 것을 이해합니다. 그러나 신화를 풀기에는 아직 초기에 고쳐지지 않았으며, 합병을 위해 DVCS를 시도한 사람들은 다른 이유로 그것을 고수했습니다.


답변

무엇을하고 있는지 아는 경우, 처음에 지점을 다시 병합하지 않아야합니다. (물론 근본적으로 잘못되고 어리석은 일을 할 때는 어렵습니다!)

그리고 그 안에 당신의 혼란의 근원과 전반적인 문제가 있습니다.

브랜치 병합은 “기본적으로 잘못되고 어리 석다”고 말합니다. 글쎄요, 그것은 정확히 문제입니다. 당신은 브랜치를 병합 해서는 안되는 것으로 생각하고 있습니다. 왜? 당신은 브랜치 병합이 어렵다는 것을 알고있는 SVN 사용자이기 때문 입니다. 그러므로, 당신은 결코 그것을하지 않으며, 다른 사람들도 그렇게하지 말 것을 권장합니다. 병합을 피 하도록 훈련받았습니다 . 병합 을 피하기 위해 사용하는 기술을 개발했습니다 .

나는 Mercurial 사용자입니다. 내가 유일한 개발자 인 내 자신의 프로젝트에서도 항상 브랜치를 병합 합니다 . 릴리스 브랜치를 가지고 있는데,이를 수정했습니다. 글쎄, 나는 그것을 다시 메인 라인으로 병합하여 수정 사항이 적용되도록합니다.

SVN을 사용하는 경우 완전히 다른 코드베이스 구조를 채택합니다. 왜? SVN은 병합을 어렵게 만들기 때문에 복잡한 병합 을 피하는 관용구와 기술을 개발 합니다.

DVCS를 사용하면 복잡한 병합이 기본 상태 이므로 쉽게 병합 할 수 있습니다 . DVCS에서 모든 것은 어느 정도 분기입니다. 따라서 이들의 전체 구조는 처음부터 쉽게 통합 할 수 있도록 만들어졌습니다. 이를 통해 병합을 사용하지 않는 SVN 워크 플로 대신 매일 병합을 사용하는 워크 플로를 개발할 수 있습니다.

간단한 사실은 이것입니다. SVN과는 다른 방식으로 DVCS에 접근해야합니다. 매우 다양한 종류의 버전 제어 시스템에 적절한 관용구를 사용해야합니다. SVN에서는 병합이 어렵 기 때문에 병합하지 않는 관용구를 채택합니다. DVCS에서는 병합이 많이 사용되지 않으므로 자주 병합을 사용하는 관용구를 채택합니다.

올바른 작업을위한 올바른 도구.

문제는 병합 중심 워크 플로가 병합하지 않는 SVN 스타일 워크 플로보다 훨씬 훌륭하고 사용하기 쉽다는 것입니다. 릴리스 브랜치의 무언가가 dev 브랜치로 언제 가져 왔는지 쉽게 알 수 있습니다. 지점 간의 다양한 상호 작용을보다 쉽게 ​​볼 수 있습니다. 사물에 대한 테스트 분기를 쉽게 만든 다음 테스트가 작동하지 않으면 잘라냅니다. 등등.

실제로 Joel은 이것을 할 수있는 것보다 훨씬 잘 설명합니다 . 잘 읽어야합니다.


답변

SVN 병합에 대해 너무 어려운 것은 없습니다 … 더 이상 … 올바른 철학을 따르면

내가 대부분의 다른 답변에서 볼 수있는 것은 한동안 SVN을 사용하지 않은 사람들로부터 온 것 같습니다. 누군가가 정확하게 언급했듯이 : “신화를 풀기에는 초기에 고쳐지지 않았다”.

최근에 상속받은 레거시 프로젝트에서 SVN 1.6을 사용한 경험에서 SVN은 훨씬 쉽게 병합 할 수있게되었습니다. 그럼에도 불구하고, 나는 그것이 의도 된 용도에서 벗어나는 사용자를 쉽게 겪지 않는다고 생각 합니다.

나는 SVN을 잘 알고 있었고 그 동안 개인 프로젝트를 위해 Mercurial을 시도했지만이 프로젝트 전에 SVN에서 많은 분기를 한 적이 없었습니다. 약간의 시행 착오가 있었고 시작했을 때 예기치 않은 병합 충돌 이 많이 발생했습니다.

궁극적으로, 나는 하나 (또는 ​​다른 문제)를 얻을 때마다 내가 제대로 수행하지 않았기 때문입니다 (일명 “SVN 방식”-아마도 적절한 버전 제어 방식). 나는 이것이 어려움이 있다고 믿는다. 당신은 당신이 원하는 모든 것을 조직화되지 않은 방식으로 할 수 없으며 SVN이 특히 병합에서 완벽하게 작동 할 것으로 기대한다. 합병은 사용자가 진정한 힘을 발휘하기 전에 엄격한 훈련을 받아야합니다.

병합을 깨끗하게 사용하기위한 요구 사항은 아니지만 강력하게 권장되는 사항은 다음과 같습니다.

  • SVN의 최신 버전을 사용하십시오 (제 의견으로는 1.6 이상). 점점 더 많은 자동화 및 검사가 수행됩니다.
  • 기본 “트렁크, 분기, 태그”구조를 사용하고 철학을 적용하십시오 (태그에 커밋하지 마십시오). SVN은 당신을 위해 아무것도 확인하지 않습니다. 태그를 브랜치 (프로젝트 리포지토리에서 찾은 상태)로 사용하면 여전히 작동 할 수 있지만 일관성이 있어야합니다.
  • 가지가 무엇인지, 언제 만들 수 있는지 알아야합니다. 태그와 동일합니다.
  • 소스 브랜치 (보통 트렁크이지만 기술적으로 모든 브랜치에서 브랜치 할 수 있음)를 사용하여 사이드 브랜치를 최신 상태로 유지하십시오. 이다 필수 당신이 SVN 자동 병합을 수행합니다. SVN 1.8은 실제로 최신 상태가 아니며 작업 복사본에 보류중인 수정 사항이있는 경우 자동 병합을 방지합니다 (이 동작은 1.8.5에서 다시 사라진 것 같습니다).
  • “적절한”커밋을 수행하십시오. 그것들은 매우 특정한 개념에 대한 수정만을 포함해야합니다. 가능한 한 적은 변화를 포함해야합니다. 당신은 할 수 없습니다 하나의 예를 들어 두 개의 독립적 인 버그에 대한 수정을 포함 커밋 갖고 싶어. 당신은 이미 모두 해결 한 그들은 같은 파일에 있다면 당신은 커밋 할 수 있도록 하나의 버그의 변화를 멀리 저장해야합니다 단지 , 먼저 상대방의 변화를 다음 변화의 두 번째 세트를 커밋합니다. TortoiseSVN은 “커밋 후 복원”을 통해이를 쉽게 수행 할 수 있습니다.
    • 그렇게하면 특정 독립 변경 집합을 되돌릴 수 있으며 그러한 집합을 다른 분기로 병합하는 것만 가능합니다. 예, SVN을 사용하면 체리로 선택한 개정판을 병합 할 수 있습니다.
  • 하위 분기를 사용하는 경우 (트렁크에서 분기 한 다음 새 분기에서 분기) 계층 구조를 존중하십시오. 트렁크로 하위 분기를 업데이트하거나 그 반대로 업데이트하면 약간의 어려움이 있습니다. 병합은 계층 구조로 계단식 또는 계단식으로 이루어져야합니다.
    • 몇 달 동안 실험을 한 후 이것이 가장 중요한 부분임을 보증 할 수 있습니다. 동일한 트렁크에서 두 개의 하위 브랜치를 생성 한 다음 하위 브랜치 간 또는 때때로 하위 서브 브랜치 간 비트를 병합하려고 시도했습니다. 이것은 SVN (또는 사용자)을 트립시킬 수 있습니다. 특정 개정판을 병합하면 정상적으로 작동합니다. 자동 병합에 문제가있을 수 있습니다.
    • 하위 분기 A를 트렁크와 동기화 한 다음 하위 분기 A에서 하위 분기 B로 무언가를 병합하려고 할 때 특히 문제가있었습니다. SVN은 “트렁크에서 동기화”개정이 하위 분기로 합법적으로 병합되어야한다고 생각하는 것 같습니다 B와 이것은 많은 갈등을 초래합니다.
  • 가능한 한 지점의 루트에서 병합하십시오. 그렇지 않으면, SVN은 하위 폴더에 대해 수행 된 병합을 추적하고 당신이 때 루트에서 자동 병합을 시도, 당신은 병합 개정 누락에 대해 경고를받을 수 있습니다. 단순히 루트에서 이것들을 병합함으로써 고칠 수 있지만 혼란을 피하는 것이 가장 좋습니다.
  • 당신이 저지른 지점을 조심하십시오. Switch를 사용하여 작업 복사본이 시간이 지남에 따라 다양한 지점을 가리 키도록하려면 커밋 할 위치를 확인하십시오.
    • 해당 지점 에서 변경을 원하지 않으면 특히 나쁩니다 . 나는 아직도 그 점을 잘 모르겠지만, 그것을 제거 / 올바른 지점으로 옮기는 방법 (리버 팅, 병합)에 따라 지저분한 것을 얻을 수 있습니다. 수정이 가능하지만 잠재적 충돌을 피하거나 즉시 해결하려면 수정본을 수정하여 수정해야합니다. 또는 자동 병합 후 더 복잡한 충돌을 수정해야합니다.
  • 가지를 너무 오래 만지지 마십시오. 실제로, 그것은 시간 문제가 아니라 지점과 트렁크에 얼마나 많은 수정이 이루어졌으며 얼마나 많은 변경이 있 었는가에 달려 있습니다. 두 가지 분기 간 병합 (3 방향 병합)은 항상 분기 간 가장 최근의 일반 개정과 비교됩니다. 그 사이에 더 많은 변경이있을수록 자동 병합이 더 많이 변경되지 않습니다. 물론 코드 구조 (이동 또는 이름이 바뀐 파일)를 변경 한 경우에는 훨씬 더 나쁩니다.

위의 내용을 따르지 않으면 충돌이 발생할 가능성이 큽니다. 그들은 항상 해결할 수 있지만 시간을 보내는 것이 굉장히 재미 있지는 않습니다.

오, SVN은 내가 읽고 시도한 모든 것에서 삭제 / 이동 / 이름이 바뀐 파일 / 폴더를 병합하는 것에 대해 한 가지 더 있습니다. 분명히 SVN은 여전히 ​​하나의 브랜치에서 이름이 바뀌거나 삭제되거나 이동 된 파일과 다른 브랜치에서 원래 버전이 수정 된 파일을 처리 할 수 ​​없습니다. 파일이 한 방향으로 어디로 갔는지 알지 못하고 다른 방법으로 변경 사항을 “잊어 버립니다”. 한 가지 변경 사항은 분명히 해결할 수 없지만 (파일을 삭제하거나 변경하거나 둘 다 수행 할 수는 없습니다) 이동 되거나 이름이 바뀐 파일에 변경 사항을 적용 하면 작동하지 않습니다. 잘만되면 이것은 곧 고쳐질 것이다.

SVN은 쉽게 병합 할 수 있습니까? 아닌 것 같아 평온한 방식은 아닙니다. 그것은인가 나쁜 ? 나는 그렇게 생각하지 않습니다. 그것은 당신이 그것을 잘못 사용했을 때만 얼굴에 침을 뱉고 당신이하는 일에 대해 충분히 생각하지 않습니다.

이를 바탕으로 사람들이 Mercurial을 선호하는 이유를 알 수 있습니다. 예를 들어 경험상 이러한 것들에 대해 조금 더 관대하고 모든 것이 시작부터 자동화되었습니다 (최소한 초기 버전에서). SVN은 꽤 많은 것을 따라 잡았으므로 더 이상 많은 것을 강타 할 가치가 없습니다.


답변

내부 데이터 모델은 근본적으로 다릅니다.

기본적으로 SVN에서는 지점의 내역을 볼 때 해당 지점에서 발생한 일만 볼 수 있습니다. 따라서 브랜치에서 브랜치 B로 병합 할 때 브랜치 A히스토리에는 브랜치 이후 A명시 적으로 작성된 모든 변경 사항이 포함 된 하나의 큰 커밋이 포함됩니다 B.

SVN의 첫 번째 버전에서 분기 B를 분기로 A다시 B병합해야하는 경우 동일한 개정을 두 번 병합하지 않도록 병합하려는 분기의 개정 범위를 수동으로 지정해야 했습니다. 영리한 개발자는 물론 ‘Merged in B : 1234’와 같은 커밋 메시지를 사용합니다.

SVN 1.5는 “고정”되었습니다. 그러나 병합이 기본적으로 적용되는 방식은 변경되지 않았습니다. ASVN에 1234 개정판이 병합되었음을 알리고 SVN이 올바른 개정판 범위를 자동으로 선택할 수 있도록 일부 메타 데이터를 추가했습니다 .

그러나이 솔루션은 기본적으로 병합 된 내용 추적을 기본적으로 지원하지 않는 데이터 모델에 대한 해결 방법입니다.

두 가지를 병합하는 것은 비교적 간단한 예입니다. 그러나 이보다 복잡한 시나리오를 이미징

  1. A에서 분기 를 trunk만들고 여기에 몇 가지 커밋을 만듭니다.
  2. 여기 B에서 브랜치 를 A만들고 커밋을 몇 개 만듭니다.
  3. 몇 가지 커밋을 trunk만들고A
  4. 병합 Btrunk
  5. 병합 AB
  6. 병합 Atrunk
  7. 병합 Btrunk(이 실제로 아무것도 안)

메타 데이터 모델을 사용하여 올바르게 처리하는 것은 매우 복잡합니다 (SVN이 실제로이 시나리오를 올바르게 처리하는지 여부를 알지 못하므로 테스트하려는 경향이 없습니다).

자식 에서이 시나리오를 처리하는 것은 매우 간단합니다.

git에서는 커밋 할 때마다 해당 커밋을 나타내는 내부 객체에 이전 헤드에 대한 참조가 포함됩니다. 브랜치를 병합하면 커밋에 병합되는 모든 브랜치의 이전 헤드에 대한 참조가 포함됩니다 (git에서 한 번에 여러 브랜치를 병합 할 수 있습니다)

따라서 git에서 단일 커밋의 히스토리를 검사하면 모든 히스토리를 볼 수 있고 분기 된 시점, 병합 된 시점 및 분기와 병합 사이의 분기 히스토리를 볼 수 있습니다.

따라서 부분적으로 병합 된 지점에서 병합 할 때 이미 병합 된 항목과 그렇지 않은 항목을 결정하는 것은 매우 간단합니다.

Mercurial에 대한 경험이 없지만 내부 작업이 git과 유사하다고 생각합니다.

기본적으로 SVN의 경우 분기를 저렴하게 만드는 것이 디자인 목표였습니다. 그러나 git에서는 병합을 저렴하게 만드는 것이 디자인 목표였습니다.

마지막으로 SVN을 마지막으로 사용했을 때 병합을 처리 할 수 ​​없었습니다. 병합은 한 지점에서 파일 이름이 바뀌고 다른 지점에서 수정되었습니다.


답변

오랜 개발 및 릴리스 브랜치를 포함하여 SVN 병합을 상당히 수행했습니다. 대체로 나는 살아 남았습니다. 병합은 항상 까다 롭지 만 DCVS의 단점은 그리 나쁘지 않습니다. 모든 것이 로컬이므로 알려진 올바른 개정으로 업데이트하고 계속 진행하십시오. SVN이 많으면 서버 측에서 발생했기 때문에 복구가 어려웠습니다. 일반적으로 로컬 복사본을 지우고 새로운 깨끗한 분기를 다시 시도하여 복구했습니다. 제 경우에는 나쁘지 않았습니다 .SVN 박스에 기가비트 연결이 도움이됩니다. 그러나 연결이 느릴 때 문제가 많은 계약자도 있었으므로 병합을 포함하여 모든 것이 영원히 처리되었습니다.


답변

그래, 나도 그래 나는 현재 내가 일하고있는 프로젝트의 다른 버전 (분기)에 대해 12 개의 VM을 가지고 있습니다. 이전 버전의 버그를 수정해야하는 경우 버그를 수정 한 다음 해당 커밋을 최신 버전의 분기로 병합합니다. 그러나 그것은 이제 전체 지점을 다시 합치고 있습니다. 이것이 제가 여기서 말하는 것입니다.

여기 git에 관한 아주 좋은 것들 중 하나가 있습니다. 그것은 DVCS에 대해 상속받지 않고 단지 git가 능숙한 것입니다. 모든 브랜치에서 다른 브랜치로 특정 개정 을 병합 할 수 있습니다 . 기본적으로 diff를 가져 와서 다른 지점에 적용하지만 추적을 수행하고 훨씬 자동적입니다.

따라서 분기 2.0과 분기 3.0이 있고 2.0에서 버그를 발견 한 경우 2.0에서 버그를 수정하고 수정 세트를 가져 와서 해결하고 해당 개정 3.0 분기로 병합 할 있습니다. SVN이 각 수정본에 대해 수동으로 차이를 가져 와서 적용하는 것 외에 다른 방법으로 믿지 않습니다.

물론, 자동 병합 알고리즘은 훨씬 더 부드럽게 작동하는 것으로 보이며 git은 “모든 것을위한 분기 만들기”모델을 기반으로 구축되었으므로 분기는 실제로 매우 부드럽고 쉽습니다. 가지가 얼마나 가벼운 지 자주 자주 분기하는 것 같습니다.


답변