Làm thế nào và / hoặc tại sao hợp nhất trong Git tốt hơn trong SVN?


400

Tôi đã nghe nói ở một vài nơi rằng một trong những lý do chính khiến các hệ thống kiểm soát phiên bản phân tán tỏa sáng, là sự hợp nhất tốt hơn nhiều so với các công cụ truyền thống như SVN. Đây thực sự là do sự khác biệt vốn có trong cách hai hệ thống hoạt động, hoặc thực hiện DVCS cụ thể như Git / Mercurial chỉ có thuật toán hợp nhất thông minh hơn SVN?


Tôi vẫn chưa nhận được câu trả lời đầy đủ từ việc đọc những câu trả lời tuyệt vời ở đây. Đăng lại - stackoverflow.com/questions/6172037/ Cách
ripper234


nó phụ thuộc vào mô hình của bạn. trong các trường hợp đơn giản hơn, svn thường tốt hơn vì nó không vô tình gọi sáp nhập 2 chiều hợp nhất 3 chiều như git có thể làm nếu bạn đẩy / hợp nhất / kéo / đẩy trên một nhánh phát triển. xem: svnvsgit.com
Erik Aronesty

Câu trả lời:


556

Yêu cầu về lý do hợp nhất trong DVCS tốt hơn trong Subversion chủ yếu dựa trên cách phân nhánh và hợp nhất hoạt động trong Subversion trước đây. Subversion trước 1.5.0 không lưu trữ bất kỳ thông tin nào về thời điểm các chi nhánh được hợp nhất, do đó, khi bạn muốn hợp nhất, bạn phải chỉ định phạm vi sửa đổi nào phải được hợp nhất.

Vậy tại sao Subversion sáp nhập hút ?

Suy ngẫm ví dụ này:

      1   2   4     6     8
trunk o-->o-->o---->o---->o
       \
        \   3     5     7
b1       +->o---->o---->o

Khi chúng tôi muốn hợp nhất các thay đổi của b1 vào trung kế, chúng tôi sẽ đưa ra lệnh sau, trong khi đang đứng trên một thư mục có kiểm tra thân cây:

svn merge -r 2:7 {link to branch b1}

Sẽ cố gắng hợp nhất các thay đổi từ b1vào thư mục làm việc cục bộ của bạn. Và sau đó bạn cam kết thay đổi sau khi bạn giải quyết bất kỳ xung đột nào và kiểm tra kết quả. Khi bạn cam kết cây sửa đổi sẽ trông như thế này:

      1   2   4     6     8   9
trunk o-->o-->o---->o---->o-->o      "the merge commit is at r9"
       \
        \   3     5     7
b1       +->o---->o---->o

Tuy nhiên, cách xác định phạm vi sửa đổi này nhanh chóng vượt khỏi tầm kiểm soát khi cây phiên bản phát triển khi lật đổ không có bất kỳ dữ liệu meta nào về thời điểm và những sửa đổi được hợp nhất với nhau. Suy ngẫm về những gì xảy ra sau này:

           12        14
trunk  …-->o-------->o
                                     "Okay, so when did we merge last time?"
              13        15
b1     …----->o-------->o

Đây phần lớn là một vấn đề của thiết kế kho lưu trữ mà Subversion có, để tạo một nhánh bạn cần tạo một thư mục ảo mới trong kho lưu trữ một bản sao của thân cây nhưng nó không lưu trữ bất kỳ thông tin nào về thời điểm và cái gì đôi khi mọi thứ trở lại. Điều đó sẽ dẫn đến xung đột hợp nhất khó chịu. Điều thậm chí còn tồi tệ hơn là Subversion được sử dụng hợp nhất hai chiều theo mặc định, có một số hạn chế làm tê liệt trong việc hợp nhất tự động khi hai đầu chi nhánh không được so sánh với tổ tiên chung của chúng.

Để giảm thiểu Subversion này hiện lưu trữ dữ liệu meta cho chi nhánh và hợp nhất. Điều đó sẽ giải quyết mọi vấn đề phải không?

Và ồ, nhân tiện, Subversion vẫn hút

Trên một hệ thống tập trung, như lật đổ, thư mục ảo hút. Tại sao? Bởi vì mọi người đều có quyền truy cập để xem họ ngay cả những người thử nghiệm rác. Sự phân nhánh là tốt nếu bạn muốn thử nghiệm nhưng bạn không muốn xem thử nghiệm của mọi người và dì của họ . Đây là tiếng ồn nhận thức nghiêm trọng. Bạn càng thêm nhiều chi nhánh, bạn sẽ càng thấy nhiều thứ tào lao.

Càng có nhiều nhánh công khai trong kho lưu trữ, bạn càng khó theo dõi tất cả các nhánh khác nhau. Vì vậy, câu hỏi bạn sẽ có là nếu chi nhánh vẫn đang được phát triển hoặc nếu nó thực sự chết, điều khó có thể nói trong bất kỳ hệ thống kiểm soát phiên bản tập trung nào.

Hầu hết thời gian, từ những gì tôi đã thấy, một tổ chức sẽ mặc định sử dụng một chi nhánh lớn. Đó là một sự xấu hổ vì điều đó sẽ khó theo dõi các phiên bản thử nghiệm và phát hành, và bất cứ điều gì tốt khác đến từ việc phân nhánh.

Vậy tại sao DVCS, chẳng hạn như Git, Mercurial và Bazaar, tốt hơn Subversion trong việc phân nhánh và sáp nhập?

Có một lý do rất đơn giản tại sao: phân nhánh là một khái niệm hạng nhất . Không có thư mục ảo theo thiết kế và các nhánh là các đối tượng cứng trong DVCS mà nó cần phải như vậy để hoạt động đơn giản với việc đồng bộ hóa các kho lưu trữ (tức là đẩykéo ).

Điều đầu tiên bạn làm khi bạn làm việc với DVCS là sao chép các kho lưu trữ (git's clone, hg's clonevà bzr's branch). Nhân bản về mặt khái niệm giống như việc tạo một nhánh trong kiểm soát phiên bản. Một số người gọi việc này là rẽ nhánh hoặc phân nhánh (mặc dù sau này thường được sử dụng để chỉ các nhánh cùng vị trí), nhưng đó chỉ là điều tương tự. Mỗi người dùng chạy kho lưu trữ của riêng họ, điều đó có nghĩa là bạn có một nhánh cho mỗi người dùng đang diễn ra.

Cấu trúc phiên bản không phải là một cái cây , mà thay vào đó là một biểu đồ . Cụ thể hơn là một biểu đồ chu kỳ có hướng (DAG, nghĩa là một biểu đồ không có bất kỳ chu kỳ nào). Bạn thực sự không cần phải chú ý đến các chi tiết cụ thể của DAG ngoài mỗi cam kết có một hoặc nhiều tài liệu tham khảo chính (mà cam kết dựa trên). Vì vậy, các biểu đồ sau đây sẽ hiển thị các mũi tên giữa các phiên bản ngược lại vì điều này.

Một ví dụ rất đơn giản về việc sáp nhập sẽ là điều này; hãy tưởng tượng một kho lưu trữ trung tâm được gọi originvà một người dùng, Alice, nhân bản kho lưu trữ vào máy của cô ấy.

         a…   b…   c…
origin   o<---o<---o
                   ^master
         |
         | clone
         v

         a…   b…   c…
alice    o<---o<---o
                   ^master
                   ^origin/master

Điều xảy ra trong một bản sao là mọi sửa đổi được sao chép vào Alice chính xác như bản gốc (được xác thực bởi mã băm nhận dạng duy nhất) và đánh dấu nơi các nhánh của nguồn gốc đang ở.

Alice sau đó làm việc trên repo của mình, cam kết trong kho lưu trữ của riêng mình và quyết định thúc đẩy các thay đổi của mình:

         a…   b…   c…
origin   o<---o<---o
                   ^ master

              "what'll happen after a push?"


         a…   b…   c…   d…   e…
alice    o<---o<---o<---o<---o
                             ^master
                   ^origin/master

Giải pháp khá đơn giản, điều duy nhất mà originkho lưu trữ cần làm là thực hiện tất cả các phiên bản mới và chuyển chi nhánh của nó sang phiên bản mới nhất (mà git gọi là "chuyển tiếp nhanh"):

         a…   b…   c…   d…   e…
origin   o<---o<---o<---o<---o
                             ^ master

         a…   b…   c…   d…   e…
alice    o<---o<---o<---o<---o
                             ^master
                             ^origin/master

Trường hợp sử dụng, mà tôi đã minh họa ở trên, thậm chí không cần hợp nhất bất cứ điều gì . Vì vậy, vấn đề thực sự không phải là với các thuật toán hợp nhất vì thuật toán hợp nhất ba chiều khá giống nhau giữa tất cả các hệ thống kiểm soát phiên bản. Vấn đề là về cấu trúc nhiều hơn bất cứ điều gì .

Vì vậy, làm thế nào về bạn cho tôi thấy một ví dụ có một sự hợp nhất thực sự ?

Phải thừa nhận ví dụ trên là một trường hợp sử dụng rất đơn giản, vì vậy hãy thực hiện một thao tác xoắn hơn nhiều mặc dù là trường hợp phổ biến hơn. Hãy nhớ rằng originbắt đầu với ba phiên bản? Chà, anh chàng đã làm chúng, hãy gọi anh ta là Bob , đã tự mình làm việc và thực hiện một cam kết trên kho lưu trữ của riêng mình:

         a…   b…   c…   f…
bob      o<---o<---o<---o
                        ^ master
                   ^ origin/master

                   "can Bob push his changes?" 

         a…   b…   c…   d…   e…
origin   o<---o<---o<---o<---o
                             ^ master

Bây giờ Bob không thể đẩy các thay đổi của mình trực tiếp vào originkho lưu trữ. Làm thế nào hệ thống phát hiện ra điều này bằng cách kiểm tra xem các bản sửa đổi của Bob có trực tiếp giải thích từ originkhông, trong trường hợp này thì không. Bất kỳ nỗ lực thúc đẩy nào cũng sẽ dẫn đến hệ thống nói điều gì đó giống như " Uh ... tôi sợ không thể để bạn làm điều đó Bob ."

Vì vậy, Bob phải đăng nhập và sau đó hợp nhất các thay đổi (với git's pull; hoặc hg's pullmerge; hoặc bzr's merge). Đây là một quy trình gồm hai bước. Đầu tiên Bob phải tìm nạp các bản sửa đổi mới, bản sao này sẽ sao chép chúng khi chúng từ originkho lưu trữ. Bây giờ chúng ta có thể thấy rằng biểu đồ phân kỳ:

                        v master
         a…   b…   c…   f…
bob      o<---o<---o<---o
                   ^
                   |    d…   e…
                   +----o<---o
                             ^ origin/master

         a…   b…   c…   d…   e…
origin   o<---o<---o<---o<---o
                             ^ master

Bước thứ hai của quy trình kéo là hợp nhất các mẹo phân kỳ và đưa ra kết quả:

                                 v master
         a…   b…   c…   f…       1…
bob      o<---o<---o<---o<-------o
                   ^             |
                   |    d…   e…  |
                   +----o<---o<--+
                             ^ origin/master

Hy vọng việc hợp nhất sẽ không xảy ra xung đột (nếu bạn dự đoán chúng, bạn có thể thực hiện hai bước thủ công trong git với fetchmerge). Những gì sau này cần phải được thực hiện là đẩy các thay đổi đó trở lại origin, điều này sẽ dẫn đến một sự hợp nhất chuyển tiếp nhanh vì cam kết hợp nhất là hậu duệ trực tiếp của originkho lưu trữ mới nhất :

                                 v origin/master
                                 v master
         a…   b…   c…   f…       1…
bob      o<---o<---o<---o<-------o
                   ^             |
                   |    d…   e…  |
                   +----o<---o<--+

                                 v master
         a…   b…   c…   f…       1…
origin   o<---o<---o<---o<-------o
                   ^             |
                   |    d…   e…  |
                   +----o<---o<--+

Có một tùy chọn khác để hợp nhất trong git và hg, được gọi là rebase , sẽ chuyển các thay đổi của Bob sang sau các thay đổi mới nhất. Vì tôi không muốn câu trả lời này dài dòng hơn nữa nên tôi sẽ cho phép bạn đọc các tài liệu git , mercurial hoặc bazaar về điều đó thay vào đó.

Như một bài tập cho người đọc, hãy thử tìm hiểu xem nó sẽ hoạt động như thế nào với một người dùng khác có liên quan. Nó được thực hiện tương tự như ví dụ trên với Bob. Hợp nhất giữa các kho lưu trữ dễ dàng hơn những gì bạn nghĩ bởi vì tất cả các sửa đổi / cam kết đều có thể nhận dạng duy nhất.

Ngoài ra còn có vấn đề gửi các bản vá giữa mỗi nhà phát triển, đó là một vấn đề lớn trong Subversion được giảm nhẹ trong git, hg và bzr bằng các bản sửa đổi có thể nhận dạng duy nhất. Khi ai đó đã hợp nhất các thay đổi của anh ấy (nghĩa là thực hiện một cam kết hợp nhất) và gửi nó cho mọi người khác trong nhóm để tiêu thụ bằng cách đẩy vào kho lưu trữ trung tâm hoặc gửi các bản vá thì họ không phải lo lắng về việc hợp nhất, vì nó đã xảy ra . Martin Fowler gọi đây là cách làm việc tích hợp bừa bãi .

Bởi vì cấu trúc khác với Subversion, thay vì sử dụng DAG, nó cho phép phân nhánh và hợp nhất được thực hiện một cách dễ dàng hơn không chỉ cho hệ thống mà còn cho cả người dùng.


6
Tôi không đồng ý với các chi nhánh của bạn == đối số tiếng ồn. Rất nhiều chi nhánh không gây nhầm lẫn cho mọi người vì nhà phát triển chính nên nói cho mọi người biết nên sử dụng chi nhánh nào cho các tính năng lớn ... vì vậy hai nhà phát triển có thể làm việc trên chi nhánh X để thêm "khủng long bay", 3 có thể hoạt động trên Y để "cho phép bạn ném xe hơi vào người "
Ông Boy

16
John: Vâng, đối với số lượng nhỏ các chi nhánh có rất ít tiếng ồn và có thể quản lý được. Nhưng hãy quay lại sau khi bạn chứng kiến ​​hơn 50 chi nhánh và thẻ hoặc trong trường hợp lật đổ hoặc trường hợp rõ ràng trong đó hầu hết chúng không thể biết chúng có hoạt động hay không. Vấn đề sử dụng từ các công cụ sang một bên; Tại sao có tất cả những thứ đó trong kho của bạn? Ít nhất là trong p4 (vì "không gian làm việc" của người dùng về cơ bản là một nhánh cho mỗi người dùng), git hoặc hg bạn có tùy chọn không cho mọi người biết về những thay đổi bạn làm cho đến khi bạn đẩy chúng ngược dòng, đây là một cách an toàn bảo vệ khi những thay đổi có liên quan đến người khác.
Spoike

24
Tôi cũng không nhận được "quá nhiều nhánh thử nghiệm của bạn là đối số tiếng ồn, @Spoike. Chúng tôi có thư mục" Người dùng "trong đó mọi người dùng đều có thư mục riêng của mình. Ở đó, anh ta có thể phân nhánh thường xuyên như anh ta muốn. nếu bạn bỏ qua các thư mục của những người dùng khác (tại sao bạn vẫn quan tâm đến họ), thì bạn sẽ không thấy tiếng ồn. Nhưng đối với tôi, việc hợp nhất trong SVN không hút (và tôi làm điều đó thường xuyên, và không, nó không phải là nhỏ dự án). Vì vậy, có lẽ tôi đã làm gì đó sai;) Tuy nhiên, sự hợp nhất của Git và Mercurial là vượt trội và bạn đã chỉ ra điều đó một cách độc đáo.
John Smithers 21/03

11
Trong svn thật dễ dàng để tiêu diệt các nhánh không hoạt động, bạn chỉ cần xóa chúng. Thực tế là mọi người không loại bỏ các nhánh không sử dụng do đó tạo ra sự lộn xộn chỉ là vấn đề vệ sinh. Bạn cũng có thể dễ dàng kết thúc với rất nhiều chi nhánh tạm thời trong Git. Ở nơi làm việc của tôi, chúng tôi sử dụng một thư mục cấp cao nhất "temp-cành" ngoài các thư mục tiêu chuẩn - các nhánh cá nhân và các nhánh thử nghiệm đi vào đó thay vì làm lộn xộn thư mục nhánh nơi lưu giữ các dòng mã "chính thức" (chúng tôi không sử dụng các nhánh tính năng).
Ken Liu

10
Điều này có nghĩa là sau đó, từ lật đổ v1.5 ít nhất có thể hợp nhất cũng như git có thể?
Sam

29

Trong lịch sử, Subversion chỉ có thể thực hiện hợp nhất hai chiều vì nó không lưu trữ bất kỳ thông tin hợp nhất nào. Điều này liên quan đến việc lấy một tập hợp các thay đổi và áp dụng chúng cho một cái cây. Ngay cả với thông tin hợp nhất, đây vẫn là chiến lược hợp nhất được sử dụng phổ biến nhất.

Git sử dụng thuật toán hợp nhất 3 chiều theo mặc định, bao gồm việc tìm một tổ tiên chung cho các đầu được hợp nhất và sử dụng kiến ​​thức tồn tại trên cả hai mặt của hợp nhất. Điều này cho phép Git thông minh hơn trong việc tránh xung đột.

Git cũng có một số mã đổi tên tinh vi tìm kiếm, cũng giúp. Nó không lưu trữ thay đổi hoặc lưu trữ bất kỳ thông tin theo dõi nào - nó chỉ lưu trữ trạng thái của các tệp tại mỗi lần xác nhận và sử dụng phương pháp phỏng đoán để xác định tên và chuyển động mã theo yêu cầu (lưu trữ trên đĩa phức tạp hơn thế này, nhưng giao diện nó trình bày cho lớp logic hiển thị không theo dõi).


4
Bạn có một ví dụ rằng svn có xung đột hợp nhất nhưng git không?
Gqqnbig

17

Nói một cách đơn giản, việc thực hiện hợp nhất được thực hiện tốt hơn trong Git so với SVN . Trước 1.5 SVN không ghi lại hành động hợp nhất, do đó không thể thực hiện việc hợp nhất trong tương lai mà không có sự trợ giúp của người dùng cần cung cấp thông tin mà SVN không ghi lại. Với 1,5, nó trở nên tốt hơn và thực sự mô hình lưu trữ SVN có khả năng cao hơn một chút so với DAG của Git. Nhưng SVN đã lưu trữ thông tin hợp nhất ở dạng khá phức tạp, cho phép việc hợp nhất mất nhiều thời gian hơn so với Git - Tôi đã quan sát thấy các yếu tố 300 trong thời gian thực hiện.

Ngoài ra, SVN tuyên bố theo dõi đổi tên để hỗ trợ hợp nhất các tệp đã di chuyển. Nhưng thực tế nó vẫn lưu trữ chúng dưới dạng một bản sao và một hành động xóa riêng biệt và thuật toán hợp nhất vẫn vấp phải chúng trong các tình huống sửa đổi / đổi tên, nghĩa là, một tệp được sửa đổi trên một nhánh và đổi tên ở nhánh kia và các nhánh đó được sáp nhập. Những tình huống như vậy vẫn sẽ tạo ra xung đột hợp nhất giả, và trong trường hợp thư mục đổi tên, nó thậm chí còn dẫn đến việc mất các sửa đổi trong im lặng. (Người SVN sau đó có xu hướng chỉ ra rằng các sửa đổi vẫn còn trong lịch sử, nhưng điều đó không giúp ích nhiều khi chúng không xuất hiện trong kết quả hợp nhất nơi chúng sẽ xuất hiện.

Git, mặt khác, thậm chí không theo dõi các đổi tên mà chỉ ra chúng sau khi thực tế (tại thời điểm hợp nhất), và làm điều đó khá kỳ diệu.

Đại diện hợp nhất SVN cũng có vấn đề; trong 1.5 / 1.6, bạn có thể hợp nhất từ ​​thân cây sang nhánh thường xuyên như chỉ thích, tự động, nhưng hợp nhất theo hướng khác cần được thông báo ( --reintegrate) và để nhánh ở trạng thái không sử dụng được. Sau đó, họ phát hiện ra rằng đây thực sự không phải là trường hợp và a) --reintegrate thể tự động tìm ra và b) sự hợp nhất lặp đi lặp lại theo cả hai hướng là có thể.

Nhưng sau tất cả những điều này (mà IMHO cho thấy sự thiếu hiểu biết về những gì họ đang làm), tôi sẽ (OK, tôi) rất thận trọng khi sử dụng SVN trong bất kỳ kịch bản phân nhánh không cần thiết nào, và lý tưởng nhất là thử xem Git nghĩ gì kết quả hợp nhất.

Các điểm khác được đưa ra trong các câu trả lời, như khả năng hiển thị toàn cầu của các chi nhánh trong SVN, không liên quan đến khả năng hợp nhất (nhưng về khả năng sử dụng). Ngoài ra, 'Cửa hàng Git thay đổi trong khi các cửa hàng SVN (một cái gì đó khác biệt)' hầu hết không chính xác. Về mặt khái niệm, Git lưu trữ mỗi cam kết dưới dạng một cây riêng biệt (như tệp tar ), và sau đó sử dụng khá nhiều phương pháp phỏng đoán để lưu trữ hiệu quả. Việc tính toán các thay đổi giữa hai lần xác nhận tách biệt với việc thực hiện lưu trữ. Điều đúng là Git lưu trữ DAG lịch sử ở dạng đơn giản hơn nhiều mà SVN thực hiện mergeinfo của nó. Bất cứ ai cố gắng để hiểu sau này sẽ biết ý của tôi.

Tóm lại: Git sử dụng mô hình dữ liệu đơn giản hơn nhiều để lưu trữ các bản sửa đổi so với SVN, và do đó nó có thể đặt nhiều năng lượng vào các thuật toán hợp nhất thực tế thay vì cố gắng đối phó với biểu diễn => thực sự hợp nhất tốt hơn.


11

Một điều chưa được đề cập trong các câu trả lời khác và đó thực sự là một lợi thế lớn của DVCS, đó là bạn có thể cam kết cục bộ trước khi bạn thay đổi. Ở SVN, khi tôi có một số thay đổi tôi muốn đăng ký và ai đó đã thực hiện một cam kết trên cùng một chi nhánh trong thời gian đó, điều này có nghĩa là tôi phải thực hiện svn updatetrước khi tôi có thể cam kết. Điều này có nghĩa là những thay đổi của tôi và những thay đổi từ người khác hiện được trộn lẫn với nhau và không có cách nào để hủy bỏ hợp nhất (như với git resethoặc hg update -C), vì không có cam kết quay lại. Nếu việc hợp nhất là không tầm thường, điều này có nghĩa là bạn không thể tiếp tục làm việc trên tính năng của mình trước khi bạn xóa sạch kết quả hợp nhất.

Nhưng sau đó, có lẽ đó chỉ là một lợi thế cho những người quá ngu ngốc khi sử dụng các chi nhánh riêng biệt (nếu tôi nhớ chính xác, chúng tôi chỉ có một chi nhánh được sử dụng để phát triển trở lại trong công ty nơi tôi đã sử dụng SVN).


10

EDIT: Điều này chủ yếu giải quyết phần này của câu hỏi:
Đây thực sự là do sự khác biệt vốn có trong cách hai hệ thống hoạt động, hoặc thực hiện DVCS cụ thể như Git / Mercurial chỉ có thuật toán hợp nhất thông minh hơn SVN?
TL; DR - Những công cụ cụ thể đó có thuật toán tốt hơn. Được phân phối có một số lợi ích của quy trình làm việc, nhưng trực giao với các lợi thế hợp nhất.
EDIT KẾT THÚC

Tôi đọc câu trả lời được chấp nhận. Nó hoàn toàn sai.

SVN sáp nhập có thể là một nỗi đau, và nó cũng có thể là cồng kềnh. Nhưng, bỏ qua cách nó thực sự hoạt động trong một phút. Không có thông tin nào cho thấy Git giữ hoặc có thể rút ra rằng SVN không giữ hoặc có thể lấy được. Quan trọng hơn, không có lý do tại sao việc giữ các bản sao riêng biệt (đôi khi một phần) của hệ thống kiểm soát phiên bản sẽ cung cấp cho bạn thông tin thực tế hơn. Hai cấu trúc hoàn toàn tương đương.

Giả sử bạn muốn làm "một số điều thông minh" Git là "tốt hơn". Và bạn là thứ được kiểm tra vào SVN.

Chuyển đổi SVN của bạn thành dạng Git tương đương, thực hiện trong Git và sau đó kiểm tra kết quả, có thể sử dụng nhiều cam kết, một số nhánh bổ sung. Nếu bạn có thể tưởng tượng một cách tự động để biến vấn đề SVN thành vấn đề Git, thì Git không có lợi thế cơ bản.

Vào cuối ngày, bất kỳ hệ thống kiểm soát phiên bản nào cũng sẽ cho phép tôi

1. Generate a set of objects at a given branch/revision.
2. Provide the difference between a parent child branch/revisions.

Ngoài ra, để hợp nhất, nó cũng hữu ích (hoặc quan trọng) để biết

3. The set of changes have been merged into a given branch/revision.

Mercurial , Git và Subversion (hiện tại, trước đây, sử dụng svnmerge.py) đều có thể cung cấp tất cả ba thông tin. Để chứng minh điều gì đó cơ bản tốt hơn với DVC, vui lòng chỉ ra một số thông tin thứ tư có sẵn trong Git / Mercurial / DVC không có sẵn trong SVN / VC tập trung.

Điều đó không có nghĩa là chúng không phải là công cụ tốt hơn!


1
Vâng, tôi đã trả lời câu hỏi trong chi tiết, không phải tiêu đề. svn và git có quyền truy cập vào cùng một thông tin (thực ra thông thường svn có nhiều hơn), vì vậy svn có thể làm bất cứ điều gì git làm. Nhưng, họ đã đưa ra các quyết định thiết kế khác nhau, và vì vậy nó thực sự không. Bằng chứng về DVC / tập trung là bạn có thể chạy git như một VC tập trung (có thể áp dụng một số quy tắc) và bạn có thể chạy svn phân tán (nhưng nó hoàn toàn hút). Tuy nhiên, đây là tất cả quá hàn lâm đối với hầu hết mọi người - git và hg thực hiện phân nhánh và hợp nhất tốt hơn svn. Đó thực sự là điều quan trọng khi chọn một công cụ :-).
Peter

5
Cho đến phiên bản 1.5 Subversion không lưu trữ tất cả thông tin cần thiết. Đã có với SVN sau 1.5, thông tin được lưu trữ là khác nhau: Git lưu trữ tất cả các cha mẹ của một cam kết hợp nhất, trong khi Subversion lưu trữ những sửa đổi đã được hợp nhất vào chi nhánh.
Jakub Narębski

4
Một công cụ khó thực hiện lại trên kho svn là git merge-base. Với git, bạn có thể nói "chia nhánh a và b khi sửa đổi x". Nhưng svn lưu trữ "các tệp đã được sao chép từ foo sang bar", vì vậy bạn cần sử dụng phương pháp phỏng đoán để tìm ra rằng bản sao vào thanh đang tạo một nhánh mới thay vì sao chép các tệp trong một dự án. Thủ thuật là một sửa đổi trong svn được xác định bởi số sửa đổi đường dẫn cơ sở. Mặc dù có thể giả định "thân cây" hầu hết thời gian, nó cắn nếu thực sự có các nhánh.
Douglas

2
Re: "Không có thông tin mà git giữ hoặc có thể rút ra rằng svn không giữ hoặc có thể lấy được." - Tôi thấy rằng SVN không nhớ khi mọi thứ đã được hợp nhất. Nếu bạn muốn kéo công việc từ thân cây vào chi nhánh của mình và qua lại thì việc hợp nhất có thể trở nên khó khăn. Trong Git, mỗi nút trong biểu đồ sửa đổi của nó biết nó đến từ đâu. Nó có tới hai phụ huynh và một số thay đổi địa phương. Tôi tin tưởng Git để có thể hợp nhất nhiều hơn SVN. Nếu bạn hợp nhất trong SVN và xóa chi nhánh thì lịch sử chi nhánh sẽ bị mất. Nếu bạn hợp nhất trong GIT và xóa nhánh, biểu đồ vẫn còn và với nó là plugin "đổ lỗi".
Richard Corfield

1
Tuy nhiên, đó không phải là trường hợp mà git và mercurial có tất cả các thông tin cần thiết tại địa phương, trong khi svn cần xem xét cả dữ liệu cục bộ và trung tâm để lấy thông tin?
Warren Dew

8

SVN theo dõi các tệp trong khi Git theo dõi thay đổi nội dung . Nó đủ thông minh để theo dõi một khối mã được tái cấu trúc từ lớp này sang tệp khác. Họ sử dụng hai cách tiếp cận hoàn toàn khác nhau để theo dõi nguồn của bạn.

Tôi vẫn sử dụng SVN rất nhiều, nhưng tôi rất hài lòng với vài lần tôi đã sử dụng Git.

Một cuốn sách hay nếu bạn có thời gian: Tại sao tôi chọn Git


Đó cũng là những gì tôi đã đọc, và đó là những gì tôi đang tính, nhưng thực tế nó không hoạt động.
Rolf

Git theo dõi nội dung của các tập tin, nó chỉ hiển thị nội dung dưới dạng thay đổi
Ferrybig

6

Chỉ cần đọc một bài viết trên blog của Joel (đáng buồn là bài cuối cùng của anh ấy). Đây là về Mercurial, nhưng nó thực sự nói về những lợi thế của các hệ thống VC phân tán như Git.

Với kiểm soát phiên bản phân tán, phần phân tán thực sự không phải là phần thú vị nhất. Phần thú vị là các hệ thống này nghĩ về các thay đổi, không phải về các phiên bản.

Đọc bài viết ở đây .


5
Đó là một trong những bài viết tôi đã suy nghĩ trước khi đăng ở đây. Nhưng "nghĩ về các thay đổi" là một thuật ngữ nghe có vẻ rất mơ hồ (hãy nhớ rằng công ty của Joel bán DVCS ngay bây giờ)
Ông Boy

2
Tôi nghĩ điều đó cũng mơ hồ ... Tôi luôn nghĩ rằng các bộ thay đổi là một phần không thể thiếu đối với các phiên bản (hoặc sửa đổi), điều này làm tôi ngạc nhiên khi một số lập trình viên không nghĩ về các thay đổi.
Spoike

Đối với một hệ thống thực sự "nghĩ về các thay đổi", hãy xem Darcs
Max

@Max: chắc chắn, nhưng khi gặp khó khăn, Git cung cấp nơi Darcs về cơ bản cũng đau đớn như Subversion khi thực sự hợp nhất.
tripleee

Ba nhược điểm của Git là a) không tốt cho các nhị phân như quản lý tài liệu, nơi mọi người rất khó có thể muốn phân nhánh và hợp nhất b) nó giả định rằng bạn muốn sao chép MỌI THỨ c) nó lưu trữ lịch sử của mọi thứ trong bản sao cho thường xuyên thay đổi nhị phân gây ra sự phình to. Tôi nghĩ rằng một VCS tập trung tốt hơn nhiều cho những trường hợp sử dụng. Git tốt hơn nhiều cho sự phát triển thường xuyên đặc biệt là cho việc sáp nhập và phân nhánh.
locka
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.