Hợp nhất sửa lỗi từ thân cây trong các nhánh cũ


9

Chúng tôi hiện đang trong quá trình chuyển đổi từ svn sang git (sau một năm dành cho việc thuyết phục mọi người, yay!) Trong công ty của tôi.

Cho đến nay, đây là tất cả để tốt hơn nhưng có một điều nhỏ mà chúng tôi hiện đang có trong quy trình làm việc của mình là tôi cũng không thể tìm thấy một tương đương tốt.

Hiện tại, tất cả các nhà phát triển của chúng tôi làm việc trong tổng thể. Mỗi quý một lần, chúng tôi phân nhánh chủ thành chi nhánh Xx, sau này sẽ trở thành phiên bản mới nhất của chúng tôi. Điều này có nghĩa là repo svn của chúng tôi trông như thế này:

  • Thân cây
  • chi nhánh
    • 3,8
    • 4.1
    • 4.2
    • ...

Chúng tôi không thực sự sử dụng thẻ.

Thỉnh thoảng, có một sửa lỗi khẩn cấp được phát hiện.

Cách hiện tại để chúng tôi làm điều đó là:

  • Sửa nó trong master
  • SVN hợp nhất phạm vi cam kết liên quan trở lại vào các chi nhánh có liên quan (Có thể là phiên bản mới nhất của chúng tôi, có thể nhiều hơn nữa).

Chúng tôi làm trong ngành vũ trụ, vì vậy các chi nhánh của chúng tôi tồn tại lâu và quá trình nâng cấp khách hàng khá dài, đó là lý do tại sao chúng tôi đã làm việc như vậy cho đến nay.

Bây giờ, làm thế nào sẽ là một tương đương tốt trong git?

Cho đến nay, tôi đã cố gắng sửa lỗi trong một nhánh được sinh ra từ master, và sau đó hợp nhất nhánh này trở lại trong master và trong 4.3 (ví dụ). Điều quan trọng là, nhánh hotfix chứa lịch sử chính và tất cả các cam kết giữa chủ và 4.3 cũng được hợp nhất, điều mà chúng tôi không muốn.

Những điều tôi có thể nghĩ cho đến nay:

  • Tôi đã xem xét phương pháp Git Workflow rất thành công và giải pháp của họ là sửa lỗi trong nhánh phát hành và hợp nhất lại thay vì cách khác. Điều này có thể hoạt động trong trường hợp của chúng tôi, nhưng sẽ khá cồng kềnh vì nó đòi hỏi chúng tôi phải biết chi nhánh lâu đời nhất mà chúng tôi muốn sửa lỗi trước khi thực sự sửa lỗi.
  • Một giải pháp khác là sửa lỗi trong master, và sau đó cherry chọn các xác nhận (như chúng ta làm cho svn merge ngày hôm nay). Điều khó chịu ở đây là trong trường hợp này, chúng tôi mất lịch sử về những gì đã được hợp nhất trở lại ở đâu, vì những quả anh đào trông giống như những cam kết mới và chúng tôi mất mối quan hệ.

Vì vậy, cách "tốt" để làm điều đó là gì? Chúng ta có nên sửa chữa các cam kết trong lịch sử, hoặc chọn cherry và theo dõi thủ công những gì đã được hợp nhất, hoặc thậm chí một cái gì khác không?

Nếu có ít kinh nghiệm sản xuất với git, vì vậy tôi chắc chắn rằng tôi có thể đã bỏ lỡ điều gì đó.

Câu trả lời:


9

Luồng Git giả định rằng bạn chỉ có một bản phát hành được hỗ trợ duy nhất, với masternhánh luôn luôn chỉ đến bản phát hành mới nhất. Vì bạn hỗ trợ nhiều bản phát hành cùng một lúc, bạn không thể sao chép quy trình làm việc 1: 1 đó. Nitie Git Flow là một ví dụ rất hay về chiến lược phân nhánh, nhưng bạn phải điều chỉnh nó theo nhu cầu của mình. Quan trọng nhất, bạn sẽ có nhiều nhánh phát hành hoạt động.

Khi bạn xác định một lỗi, bạn sẽ phải thực hiện một số thử nghiệm để xác định tất cả các phiên bản bị ảnh hưởng. Nó không đủ để viết bản sửa lỗi trước, sau đó hợp nhất nó trở lại vào các nhánh phát hành dưới dạng hotfix. Thông thường, bạn sẽ kết thúc với một số phiên bản bị ảnh hưởng liên tục. Các phiên bản rất cũ có thể không chứa lỗi, các phiên bản mới hơn có thể đã vô tình sửa lỗi đó. Bạn sẽ cần xác minh lỗi trên mỗi phiên bản để bạn có thể xác minh lỗi thực sự đã hết sau khi sửa. Nếu bạn có thể biểu thị lỗi dưới dạng một bản thử nghiệm tự động, thì việc tìm ra cam kết có vấn đề thông qua git bisecthoặc chạy thử nghiệm cho mỗi bản phát hành là khá đơn giản .

for release in 3.8 4.1 4.2
do
  git checkout $release
  if ./testcase >release-$release.log
  then echo "$release ok"
  else echo "$release AFFECTED"
  fi
done

Bây giờ, bạn đã sử dụng để viết sửa chữa trên trunk/ master. Đây là vấn đề vì phần lỗi có thể đã thay đổi giữa các phiên bản, do đó, một bản vá thường không áp dụng cho phiên bản cũ hơn. Cụ thể, mã trong mastercó thể phụ thuộc vào bất kỳ tính năng nào có sẵn trong bản gốc, có thể không có trong các phiên bản cũ hơn. Do đó, rất có ý nghĩa rằng một cam kết Git tham chiếu toàn bộ lịch sử của nó, không chỉ là tập thay đổi. Khi hợp nhất trở lại, nó sẽ kéo theo tất cả lịch sử mà nó phụ thuộc vào.

Sử dụng cherry-pickhoặc rebasebỏ qua lịch sử này và ghi lại một cam kết mới với cùng một thay đổi, nhưng một lịch sử khác. Như đã chỉ ra, điều này sẽ không hoạt động nếu cơ sở mã của bạn đã chuyển hướng.

Giải pháp chính xác của Cameron là viết bản sửa lỗi dưới dạng hotfix trên bản phát hành bị ảnh hưởng lâu đời nhất. Sau đó, bạn hợp nhất bản phát hành cũ nhất vào bản phát hành cũ thứ hai. Thông thường, một bản phát hành mới hơn sẽ chứa tất cả các cam kết của một bản phát hành cũ hơn, vì vậy điều này là ổn. Nếu mọi thứ đã thay đổi, bây giờ bạn có cơ hội giải quyết thủ công xung đột hợp nhất. Sau đó, bạn tiếp tục hợp nhất mỗi bản phát hành vào bản phát hành trẻ hơn cho đến khi bạn hoàn thành. Điều này duy trì lịch sử thích hợp và tránh được rất nhiều công việc không cần thiết, trong khi chỉ yêu cầu nỗ lực phải được sử dụng bằng mọi cách. Đặc biệt, sự hợp nhất gia tăng này giúp bạn tiến gần hơn đến trạng thái phát triển hiện tại theo các bước nhỏ.

Như một sơ đồ:

| o normal commit |
| x hotfix        |
| ⇘ merging       |

3.8 --o-----------------x
       \                 ⇘
4.1     o--o--o-----------x'
               \           ⇘
4.2             o--o--o-----x''
                       \     ⇘
develop                 o--o--x'''--o--o

2
Để đầy đủ, giả sử thử nghiệm có một chút sai và phiên bản 3.7 có cùng một lỗi (giả sử, nó chỉ xảy ra trên một trường hợp cạnh trong 3.7, nhưng xảy ra trong các trường hợp được kiểm tra dễ dàng hơn trong 3.8+), nhưng chỉ được phát hiện sau sửa chữa đã được hợp nhất như thế này. Bạn sẽ chỉ chọn anh đào tại thời điểm đó?
Izkata

2
@Izkata vâng, tại thời điểm đó, không còn có thể giả vờ rằng có bất kỳ loại lịch sử hợp lý nào, vì vậy, hái anh đào là một cách tốt để áp dụng các thay đổi cho bản phát hành cũ hơn. Tuy nhiên, điều này ngụ ý rằng các nhánh phát hành đã chuyển hướng và các bản phát hành mới hơn không còn chứa tất cả các cam kết của các bản phát hành cũ hơn. Do đó, chúng ta nên thực hiện lại chuỗi hợp nhất từ ​​bản phát hành mà chúng ta đã thay đổi thành nhánh phát triển. Tuy nhiên, trong lần hợp nhất đầu tiên, chúng tôi có thể loại bỏ các thay đổi được chọn bởi vì chúng tôi đã áp dụng bản sửa lỗi cho bản phát hành mới hơn.
amon

Cảm ơn bạn đã trả lời @amon. Câu trả lời của bạn rất đầy đủ, và đi theo hướng mà tôi đã xem xét, vì vậy thật tốt khi có xác nhận. Chúng tôi sẽ đảm nhận các yêu cầu riêng của ngành và điều chỉnh cách tiếp cận dòng chảy git với thứ gì đó phù hợp với chúng tôi hơn. Cảm ơn một lần nữa!
jlengrand
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.