it-swarm-vi.com

Các nhà phát triển dày dạn vẫn phải đối phó với xung đột hợp nhất?

Tôi vẫn là một kỹ sư phần mềm trong đào tạo, nhưng tôi đã nghe câu ngạn ngữ sau nhiều lần:

Các lập trình viên giỏi không phải đối phó với các xung đột hợp nhất.

Bất cứ khi nào tôi làm việc trong một dự án với những người khác, tôi sẽ mất một lượng thời gian và nỗ lực khó chịu để giải quyết xung đột hợp nhất. Vì vậy, tôi bắt đầu tự hỏi rằng câu ngạn ngữ đó đúng như thế nào. Tôi nhận thức được các kỹ thuật như GitFlow và nhanh nhẹn có thể khiến các nhà phát triển phân chia hiệu quả công việc của họ, cam kết thường xuyên hơn và duy trì nhiều nhánh mã, do đó xung đột hợp nhất ít xảy ra hơn. Nhưng chắc chắn chúng vẫn xảy ra và có khả năng tàn phá?

Nói cách khác, các nhà phát triển dày dạn mất bao nhiêu thời gian và nỗ lực để giải quyết xung đột hợp nhất (khi họ có thể làm việc trên các dự án của họ)? Là các kỹ thuật có sẵn có thể thực sự phủ nhận bất kỳ ảnh hưởng của xung đột hợp nhất?

57
lemeneux

Tôi nghĩ rằng hơi thiếu thận trọng khi nói rằng các nhà phát triển giỏi không bao giờ có xung đột hợp nhất, nhưng họ chắc chắn có thể giảm số lần xảy ra. Điều cũng rất quan trọng cần nhớ rằng phát triển phần mềm là một hoạt động nhóm. Hành động của các thành viên khác trong các đội cũng có thể tăng hoặc giảm khả năng xảy ra xung đột hợp nhất.

Đầu tiên, điều quan trọng là phải hiểu những cách phổ biến mà hợp nhất xung đột xảy ra:

  • Hai người thực hiện các thay đổi khác nhau cho cùng một dòng mã
  • Ai đó quyết định định dạng lại toàn bộ tệp để mỗi dòng được thay đổi
  • Xóa một tập tin và sau đó thay thế nó (đó là một xung đột cây)
  • Mã được xóa và thêm cùng lúc bởi hai người khác nhau (không phổ biến với Visual Studio .vsproj các tập tin)

Phát triển các đội đã đưa ra các cách để tránh những tình huống này:

  • Đảm bảo rằng mỗi thành viên trong nhóm đang làm việc trong các phần khác nhau của mã (nghĩa là được xử lý trong phân công nhiệm vụ)
  • Các tiêu chuẩn mã ra lệnh cho dù bạn sử dụng dấu cách hay tab, đặt tên tiêu chuẩn, v.v ... để việc định dạng lại toàn bộ mã bán hàng là không cần thiết
  • GitFlow để mọi người đều làm việc trên nhánh riêng của họ và có thể giải quyết xung đột ở giai đoạn Yêu cầu kéo (tất cả các kết hợp hạ nguồn đều hoạt động tuyệt vời)
  • Cam kết thường xuyên và thường xuyên hợp nhất từ ​​phát triển để đảm bảo nhánh tính năng của bạn không bao giờ quá lỗi thời
  • Đảm bảo các tính năng của bạn đủ nhỏ, chúng có thể được thực hiện trong 1-3 ngày.

Với những thay đổi như vậy, bạn có thể giảm thiểu rất nhiều khả năng xảy ra xung đột. Bạn sẽ không bao giờ có thể loại bỏ hoàn toàn chúng.

97
Berin Loritsch

Có lẽ trích dẫn là không đầy đủ:

Các lập trình viên giỏi không phải đối phó với xung đột hợp nhất ...
[.__.] ... bởi vì các lập trình viên giỏi Lực đẩy.

Mặc dù vậy, nghiêm túc, cách duy nhất để tránh xung đột hợp nhất là làm việc một mình (và thậm chí điều đó không giúp ích gì cho tôi, đã xảy ra xung đột với chính tôi trong các dự án cá nhân). Trong một công ty tuyển dụng các nhà phát triển có kinh nghiệm, tuy nhiên có ba yếu tố làm giảm nỗi đau của xung đột hợp nhất:

  1. Giao tiếp tuyệt vời trong nhóm.

    Đó là, bạn biết những gì đồng nghiệp của bạn đang làm việc và họ biết những gì bạn làm. Do đó, khi bạn có thể sửa đổi một khu vực mà ai đó trong nhóm của bạn đang làm việc, bạn hỏi (hoặc bạn nói). Bằng cách này, bạn giảm được rất nhiều nguy cơ của một cam kết đau đớn.

    Điều này đặc biệt áp dụng cho những nhiệm vụ tái cấu trúc có thể ảnh hưởng đáng kể đến một phần lớn của cơ sở mã hoặc thực hiện các thay đổi gây khó khăn khi hợp nhất. Giả sử bạn đang thay đổi loại biến đã cho ở mọi nơi, trong khi đồng nghiệp của bạn đang triển khai một tính năng sử dụng biến này. Bạn không chỉ có nguy cơ có một cuộc xung đột hợp nhất đau đớn, mà còn phá vỡ sự xây dựng trong quá trình hợp nhất.

  2. Kiến trúc tuyệt vời.

    Nếu bạn đang làm việc trên cơ sở mã kế thừa với các tệp 4K-LOC và cần bất kỳ thay đổi cơ bản nào để sửa đổi hàng tá tệp, có thể mỗi lần thay đổi, bạn sẽ gặp xung đột hợp nhất.

    Mặt khác, khi kiến ​​trúc đủ tốt, bạn giảm nguy cơ xảy ra xung đột hợp nhất thành hai tình huống: (1) khi bạn sửa đổi giao diện hoặc (2) trong đó hai đồng nghiệp đang sửa đổi chính xác cùng một phần của ứng dụng . Trong trường hợp đầu tiên, bạn giao tiếp, giảm nhiều hơn nguy cơ hợp nhất đau đớn. Trong trường hợp thứ hai, bạn thực hiện lập trình cặp, loại bỏ hoàn toàn hợp nhất.

  3. Giao tiếp thích hợp với các đội khác.

    Đôi khi, nó xảy ra có xung đột hợp nhất giữa các đội khác nhau. Giả sử một nhóm đang sửa đổi một mô-đun, trong khi một nhóm khác đang sửa đổi mã sử dụng mô-đun này.

    Các nhà phát triển có kinh nghiệm sẽ có xu hướng áp dụng các giao diện thích hợp, chẳng hạn như SOA, điều này sẽ làm cho các phần riêng biệt của hệ thống trở nên độc lập hơn về mặt kỹ thuật. Hơn nữa, họ sẽ phụ thuộc nhiều hơn vào các thực tiễn cụ thể như các yêu cầu Đẩy để tránh sửa đổi trực tiếp mã của người khác.

    Đây thực chất là hai điểm đầu tiên, nhưng các nhóm chéo: bạn giao tiếp tốt hơn và bạn đảm bảo các phần được xen kẽ nhiều hơn.

27
Arseni Mourzenko

Một đồng nghiệp của tôi đã gặp một nhà phát triển, người không phải đối phó với xung đột hợp nhất.

Ông đã thực hiện một số thay đổi, hợp nhất chúng và một vài ngày sau đó, những thay đổi đã biến mất. Ông phát hiện ra rằng một người khác (ở một lục địa khác cũng vậy) đã thay thế các tập tin thay vì hợp nhất.

Anh ta đặt các thay đổi trở lại, hơi nhợt nhạt - và vài ngày sau những thay đổi đó lại biến mất.

Đó là khi anh ấy có một cuộc nói chuyện dài với người quản lý của mình, người đã nói chuyện rất lâu với người quản lý của đội kia, có thể có hoặc không bao gồm các mối đe dọa bạo lực thể xác, và người quản lý của đội kia dường như đã nói chuyện lâu với nhà phát triển. Câu hỏi, và hành vi dừng lại.

Điều đó nói rằng, các nhà phát triển có kinh nghiệm có thể tránh một số xung đột hợp nhất.

  1. Khi bạn đổi tên một tệp, thực hiện một hợp nhất trong đó đổi tên tệp (và rõ ràng là những thay đổi gây ra bởi điều này, như thay đổi bao gồm các câu lệnh hoặc tệp dự án) hoàn toàn là thay đổi duy nhất.

  2. Đảm bảo rằng các cài đặt trình chỉnh sửa của mọi người đều giống nhau, để bạn không tạo ra các thay đổi chỉ bằng cách xem mã.

  3. Bạn nhận được xung đột hợp nhất nếu hai người thay đổi mã ở cùng một nơi. Vì vậy, nếu bạn thêm vào một tập tin, đừng thêm vào cuối, mà hãy thêm vào vị trí chính xác. Theo cách đó, nếu một nhà phát triển khác làm điều tương tự, các xung đột hợp nhất sẽ ít xảy ra hơn.

  4. Hợp nhất cơ sở mã chung vào chi nhánh của bạn theo thời gian, để bạn không bao giờ có nhiề hợp nhất xung đột. Một xung đột là dễ dàng, 10 trong một hợp nhất là một vấn đề.

  5. Việc hợp nhất từ ​​chi nhánh của bạn vào cơ sở mã chung phải không bao giờ gây ra xung đột. Đó là bởi vì bạn đã làm (4) ngay trước khi bạn cố gắng thực hiện hợp nhất, do đó, việc hợp nhất sẽ kết thúc việc lấy mã của bạn mà không có bất kỳ thay đổi nào.

Chỉ cần lưu ý: Có, đó là sự thật, các nhà phát triển giỏi không bao giờ có xung đột hợp nhất từ ​​chi nhánh của họ vào cơ sở mã chung. Bởi vì bất kỳ xung đột hợp nhất đã được xử lý trước đó.

21
gnasher729

Như các câu trả lời khác đã mô tả, xung đột hợp nhất xảy ra bất kể kinh nghiệm hay kỹ năng, và một câu ngạn ngữ cho rằng chúng là một loại điểm yếu đến từ việc thiếu kỹ năng là vô lý.

Các câu trả lời khác đã lưu ý những cách mà các nhà phát triển lành nghề có thể học để giúp giảm bớt xung đột hợp nhất, từ việc ngăn chặn sự hỗn loạn định dạng đến việc hợp nhất thường xuyên để phối hợp nhóm tốt hơn, nhưng tôi nghĩ có một sự thật đối với khái niệm rộng hơn mà bạn nêu ra: các nhà phát triển lành nghề có thể trở nên tốt hơn đối phó với xung đột hợp nhất khi chúng xảy ra.

Giải quyết xung đột hợp nhất là khó khăn. Bạn phải tìm ra các xung đột, hiểu các dấu xung đột, tìm ra những gì đã thay đổi ở mỗi bên khi xem xét bối cảnh của mã (có thể liên quan đến các vấn đề khó phát hiện như định dạng), có thể tra cứu các cam kết riêng lẻ từ cả hai phía của hợp nhất hiểu ý định ban đầu, thực sự giải quyết xung đột, giải quyết các tác động có thể có của sự thay đổi ở nơi khác trong cơ sở mã (hoặc thậm chí trong các kho khác nếu có API hoặc giao diện), biên dịch, kiểm tra, cam kết, v.v ... Bạn phải nhớ cách có được hệ thống kiểm soát phiên bản để làm những gì bạn muốn trong quá trình này. Và sau đó là các trường hợp phức tạp hơn: xung đột liên quan đến các tập tin và thư mục bị di chuyển/xóa; xung đột liên quan đến các tệp nhị phân; xung đột liên quan đến các tệp được tạo (bao gồm cả những thứ như tệp cấu hình Visual Studio và Xcode; ngay cả khi xung đột đơn giản, bản thân tệp sẽ không quen thuộc cho đến khi bạn có một số kinh nghiệm với nó); xung đột đủ khó chịu khi bạn đi tìm người ở phía bên kia của sự hợp nhất và tìm ra nó cùng nhau; đủ thứ vui vẻ.

Đó là tất cả rất nhiều thứ để giải quyết. Nó có thể gây ra một chút hoảng loạn: bạn đang đi du lịch hào hứng để bọc thứ gì đó và đột nhiên bạn phải đối mặt với các thông báo lỗi, ">>>>>>>" thứ lạ ở giữa các tệp của bạn và một một loạt các mã không quen thuộc đột nhiên xuất hiện từ một nơi khác. Giống như bất kỳ nhiệm vụ lập trình nào khác, kinh nghiệm có thể giúp xây dựng các kỹ năng để đối phó với nó hiệu quả hơn và ít đau đớn hơn. Lần đầu tiên bạn gặp phải một cuộc xung đột hợp nhất, đó là một thử thách khó hiểu, trong khi lần thứ 500 thì thường xuyên hơn. Bởi thời điểm này:

  • Bạn có kỹ năng sử dụng hệ thống kiểm soát phiên bản để có được thông tin bạn cần và thực hiện các thay đổi bạn muốn.
  • Bạn đã quen thuộc với định dạng xung đột, đọc khác biệt và hình dung các thay đổi của hợp nhất.
  • Bạn có thể đã chọn công cụ, nguồn mở hoặc thương mại, để giúp hợp nhất và học cách sử dụng chúng một cách hiệu quả. Những công cụ này có thể giúp ích rất nhiều, đến nỗi tôi sẽ in đậm: các công cụ tốt có thể giúp làm cho xung đột hợp nhất ít đau đớn hơn .
  • Bạn biết loại xung đột nào là điển hình trong các dự án của bạn (tệp cấu hình IDE, dưới cùng của tệp chuỗi, các điểm nóng khác thay đổi thường xuyên) và điều chỉnh các quy trình để ngăn chặn chúng hoặc trở nên lão luyện trong việc giải quyết chúng thực sự nhanh chóng. Các xung đột phổ biến như "oh, cả hai chúng tôi đã thêm các chuỗi mới vào cuối tệp" trở nên dễ dàng để khắc phục.
  • Bạn có thể dự đoán các loại nhiệm vụ tái cấu trúc có khả năng gây ra xung đột với phần còn lại của nhóm và phối hợp để giảm đau.
  • Bạn biết khi nào không hợp nhất. Nếu bạn thử hợp nhất và phát hiện ra rằng bạn đã thêm một tham số cho hàm mà người khác đã xóa, có lẽ tốt hơn là dừng và suy nghĩ lại chiến lược của bạn bên ngoài phạm vi của quy trình giải quyết xung đột.
  • Bạn biết khi nào bạn đã thực hiện một mớ hỗn độn thực sự và sẽ dễ dàng hơn để bắt đầu hợp nhất lại.
  • Bạn biết khi cơ sở mã cơ sở đã thay đổi quá nhiều để tạo ra "hợp nhất" một mô tả công bằng cho những gì bạn đang làm, vì vậy bạn lưu ý những thay đổi bạn thực sự muốn thực hiện, loại bỏ các thay đổi của bạn và bắt đầu lại với một ĐẦU sạch mới. Ví dụ: nếu thay đổi của bạn chỉ là thêm một tệp hình ảnh mới và trong khi đó, một người nào đó đã xuất hiện và biến tất cả các hình ảnh của dự án thành các họa tiết, thì bạn không thực sự hợp nhất nữa khi thực hiện nhiệm vụ theo một cách khác, vì vậy hãy thổi bay nỗ lực trước đó của bạn và làm theo cách mới.

Với tất cả điều này, hầu hết các xung đột hợp nhất trở thành thói quen, do đó, tốn ít thời gian và công sức hơn để xử lý chúng. Chúng vẫn xảy ra, và đôi khi gây ra sự thất vọng đáng kể, nhưng thường tàn phá ít hơn nhiều.

6
Zach Lipton

Đó không phải là sự tồn tại của xung đột hợp nhất, mà là chúng gây ra bao nhiêu vấn đề.

"Thiệt hại" từ xung đột hợp nhất với các nhà phát triển thiếu kinh nghiệm được coi là một vấn đề lớn. Mọi người phát minh ra các kế hoạch kiểm soát nguồn điên rồ hoặc thậm chí ngừng sử dụng kiểm soát nguồn cùng nhau để tránh những vấn đề 'lớn' này.

Nhưng với một đội ngũ có kinh nghiệm, xung đột hợp nhất gây ra hầu như không có vấn đề gì và được giải quyết nhanh chóng.

Tôi nghĩ có hai sự khác biệt chính của cách tiếp cận góp phần vào điều này:

  1. Sử dụng kiểm soát nguồn đúng cách. Chi nhánh tính năng, rất nhiều cam kết nhỏ, kéo trước khi đẩy, kiểm tra trước khi đẩy, v.v.

  2. Hiểu những thay đổi của người khác. Nếu bạn hiểu các thay đổi về tính năng và mã đã mâu thuẫn với thay đổi của bạn thì việc hợp nhất hai thay đổi là đơn giản.

Hãy chú ý đến các nhiệm vụ khác khi đứng lên, nói chuyện với người khác về cách họ đang thực hiện thay đổi và nơi bạn có thể xung đột. Đồng ý về cách mọi thứ nên làm việc trước.

5
Ewan

Tích hợp liên tục .

Để hiểu lý do tại sao CI giúp xem xét rằng để trải nghiệm xung đột hợp nhất, (các) thay đổi trong nhánh đó cần phải xung đột với một hoặc nhiều thay đổi trên bản gốc:

             A  B  C
master    *--*--*--*--*
           \         /
feature-x   *--------

Chi nhánh tồn tại càng lâu đối với nhiều thay đổi sẽ được thực hiện trên chủ, và do đó, khả năng một trong những thay đổi đó sẽ gây ra xung đột (ngay cả khi thay đổi trên chi nhánh là rất nhỏ):

             A  B  C  D  E  F  G  H
master    *--*--*--*--*--*--*--*--*--*
           \                        /
feature-x   *-----------------------

Có nhiều cách khác nhau chúng ta có thể làm để giảm khả năng xảy ra bất kỳ 2 thay đổi nào xung đột (như tránh định dạng lại hoặc tổ chức công việc cẩn thận để tránh nhiều nhà phát triển làm việc trên cùng một khu vực), nhưng cách tiếp cận đơn giản nhất là hợp nhất các thay đổi nhanh hơn, giảm số lượng thay đổi được thực hiện trên bản gốc và lần lượt có khả năng xảy ra xung đột:

             A     B  C
master    *--*--*--*--*--*
           \   /    \   /
feature-x   *--      *--

Nếu bạn đang thực hành CI đúng cách thì mọi người nên cam kết với một chi nhánh được chia sẻ nhiều lần mỗi ngày , tức là cứ sau vài giờ. Điều đó đủ nhanh để nhiều thời gian sẽ không có bất kỳ thay đổi nào đối với chủ, chứ đừng nói đến những thay đổi mâu thuẫn. Điều tuyệt vời hơn nữa là ngay cả khi bạn thấy xung đột, các thay đổi của bạn sẽ rất nhỏ và vì vậy việc giải quyết xung đột sẽ tương đối đơn giản - trong trường hợp xấu nhất (khi bạn cần loại bỏ hoàn toàn và thực hiện lại thay đổi của mình), bạn đã mất hầu hết một vài giờ làm việc.


Trong các bình luận, đề xuất rằng các nhà phát triển nên thường xuyên hợp nhất từ master thay vì thành master, điều này chắc chắn có ích, nhưng không nhiều như tích hợp liên tục. Ví dụ, trong biểu đồ sau, mỗi cam kết trên bản gốc (A, B và C) có cơ hội xung đột với bất kỳ cam kết nào trên nhánh (X, Y hoặc Z), với tổng số 9 xung đột tiềm ẩn. Sáp nhập một lần vào chủ cuối cùng có nghĩa là tất cả 9 xung đột tiềm năng cần được giải quyết cùng một lúc:

             A  B  C
master    *--*--*--*--*
           \         /
feature     *--*--*--
            X  Y  Z

Nếu thay vào đó, chúng tôi hợp nhất từ ​​chủ vào nhánh tính năng của mình sau mỗi thay đổi trên chính:

             A     B     C
master    *--*-----*-----*---*
           \  \     \     \ /
feature     *--*--*--*--*--*
            X     Y     Z

Sau đó, mỗi lần chúng ta hợp nhất, chúng ta cần xử lý các xung đột sau:

  • Trong lần hợp nhất đầu tiên, chúng tôi phải giải quyết mọi xung đột giữa các lần xác nhận A và X
  • Trong lần hợp nhất thứ hai, chúng tôi giải quyết mọi xung đột giữa B và X, B và Y
  • Trong lần hợp nhất vừa qua, chúng tôi giải quyết mọi xung đột giữa C và X, C và Y, C và Z

Lưu ý rằng mặc dù chúng tôi không bao giờ cần giải quyết xung đột giữa A và Y, vì thay đổi A đã được hợp nhất vào nhánh tính năng của chúng tôi trước khi thay đổi Y được thực hiện. Tổng cộng chúng tôi đã cố gắng tránh 3 trong số 9 xung đột hợp nhất tiềm năng bằng cách thường xuyên sáp nhập từ chủ.

Cũng lưu ý rằng mỗi lần chúng tôi hợp nhất số lượng xung đột tiềm năng tăng lên - nhánh tính năng tồn tại càng nhiều thay đổi (và do đó xung đột tiềm năng) sẽ được thực hiện trên chủ, nhưng kẻ giết người thực sự ở đây là mỗi thay đổi chúng tôi thực hiện trên nhánh tính năng có tác động nhân lên số lượng xung đột tiềm năng mỗi khi chúng ta hợp nhất.

Bây giờ hãy xem xét những gì có thể xảy ra nếu chúng ta đang thực hành CI:

             A     B     C
master    *--*--*--*--*--*--*
           \   / \   / \   /
feature     *--   *--   *--
            X     Y     Z

Lần này chúng tôi đã phải đối phó với các xung đột hợp nhất sau đây:

  • Khi hợp nhất thay đổi X thành chủ, chúng tôi phải giải quyết mọi xung đột giữa A và X
  • Khi hợp nhất thay đổi Y, chúng tôi phải giải quyết mọi xung đột giữa X và V
  • Khi hợp nhất Z, chúng tôi phải giải quyết mọi xung đột giữa Z và C

Như trước đây, chúng tôi không bao giờ cần giải quyết bất kỳ xung đột nào giữa A và Y, vì thay đổi A đã được sáp nhập vào nhánh tính năng của chúng tôi trước khi chúng tôi thực hiện thay đổi Y, nhưng lần này chúng tôi cũng không cần hợp nhất các thay đổi X và B, X và C hoặc Y và C, tránh 6 trong số 9 xung đột tiềm ẩn.

Xem câu hỏi này để biết thêm thông tin/hướng dẫn về việc sáp nhập thường xuyên vào chủ:

Tốt hơn là nên hợp nhất các mối quan hệ thường xuyên hay chỉ sau khi hoàn thành một sự hợp nhất lớn của các nhánh tính năng?

1
Justin

"Lập trình viên mắc lỗi mọi lúc " --- John Carmack

Những người đưa ra khẳng định gần giống với "Tôi là nhà phát triển 'ngôi sao nhạc rock" hoặc "Các lập trình viên giỏi không phải đối phó với xung đột hợp nhất ..." thường không phải là những người đặt ra dường như dồi dào trong cộng đồng phát triển phần mềm nói chung và nên được bỏ qua như vậy.

Xây dựng phần mềm sẽ được sản xuất bởi những người thực tế ngoài bạn không phải là chuyện nhỏ. Bạn sẽ phạm sai lầm .... và những người bạn đang làm việc cùng sẽ thường mắc lỗi. Dựa trên đánh giá về năng lực kỹ thuật của bất kỳ ai về việc họ có phải đối phó với các xung đột hợp nhất hay không là vô nghĩa.

0
user405887

Bất cứ ai nói rằng có một khái niệm đặc biệt về "lập trình viên giỏi" trong tâm trí, có lẽ sẽ diễn ra như sau:

  • Good Coder hoạt động một mình trong một Chương trình tuyệt vời mà người đó thiết kế một mình.
  • Không có nhánh của chương trình, hoặc phát hành các nhánh hoặc bất cứ thứ gì thuộc loại này, và do đó không bao giờ có bất kỳ hoạt động nổi loạn nào tạo ra xung đột.
  • Khi các lỗi được tìm thấy trong các bản phát hành cũ của chương trình, người dùng sẽ nâng cấp mạnh mẽ lên đường cơ sở hiện tại hoặc các nhà bảo trì gói hạ nguồn khác cập nhật các bản sửa lỗi cần thiết từ đường cơ sở hiện tại (do đó Good Coder không bao giờ thấy các xung đột có liên quan).
  • Trong trường hợp hiếm hoi mà một số người bên ngoài cung cấp bản sửa lỗi hoặc cải tiến cho Chương trình lớn, họ phải cung cấp một bản vá áp dụng sạch cho người phát triển hiện tại, do đó, Bộ giải mã tốt được bảo vệ khỏi mọi nỗ lực chuyển tiếp liên quan đến giải quyết xung đột.
  • Cuối cùng, Good Coder không bao giờ sắp xếp lại thứ tự các cam kết của mình (chẳng hạn như với rebase tương tác của git).
0
Kaz