Là sử dụng Git Stash như một quy trình công việc một antipotype?


25

Gần đây tôi đã xem xét cách tôi và nhóm của tôi sử dụng Git và cách thức hoạt động của chúng tôi. Chúng tôi hiện đang sử dụng quy trình làm việc theo nhánh tính năng có vẻ hoạt động tốt.

Tôi cũng đã thấy một số cá nhân trong nhóm của chúng tôi sử dụng quy trình làm việc dựa trên git stash . Quy trình làm việc giống như thế này:

  • Làm việc trên một nhánh chính (như master)
  • Hãy cam kết khi bạn đi
  • Nếu bạn cần nhận thay đổi hoặc chuyển đổi chi nhánh, hãy đẩy các thay đổi không được cam kết của bạn vào stash
  • Sau khi cập nhật xong, hãy tắt các thay đổi.

Tôi nên đề cập rằng quy trình công việc này được sử dụng thay vì quy trình công việc nhánh tính năng. Thay vì lấy một nhánh và làm việc trên nó, các nhà phát triển ở đây chỉ làm việc trên một nhánh duy nhất và đẩy / bật ra khỏi ngăn xếp khi họ thấy phù hợp.

Tôi thực sự không nghĩ rằng đây là một quy trình công việc tuyệt vời và việc phân nhánh sẽ phù hợp hơn là sử dụng git stash theo cách này. Tôi có thể thấy giá trị của git stash là một hoạt động khẩn cấp, nhưng không phải để sử dụng nó trong quy trình làm việc thường xuyên hàng ngày.

Sử dụng git stash thường xuyên có được coi là một mô hình chống? Nếu vậy, một số vấn đề cụ thể có thể phát sinh là gì? Nếu không, những lợi ích là gì?


2
Bạn có thể thử hỏi đồng nghiệp xem họ có vấn đề gì với quy trình làm việc không. Nếu họ không thì tôi sẽ không coi nó có hại.
AlexFoxGill

@AlexG Đó là một điểm hợp lệ. Tôi đang đặt câu hỏi ở đây để xem có người "gotchas" nào đã tìm thấy không.
joshin4colours

3
Nếu tôi hiểu chính xác ... If you need to get changes or switch branches, push your uncommitted changes onto the stash- đó chính xác là những gì mà stash dành cho.

3
@MichaelT Chi nhánh địa phương của tôi cho phép mọi thứ. Vô điều kiện.
maaartinus

2
Mẫu của tôi là: -> không sử dụng git stash -> sử dụng các nhánh tính năng -> lưu tiến trình công việc với thông báo cam kết 'wip'. -> rebase tương tác trên nhánh để nén các wip thành một cam kết có ý nghĩa nhưng đối với các thay đổi cục bộ của bạn , chỉ thay đổi. -> đẩy vào điều khiển từ xa -> hợp nhất thành chủ (và đẩy) khi thích hợp cho quy trình công việc git của bạn.
Michael Durrant

Câu trả lời:


31

Từ sách GCM SCM :

Thông thường, khi bạn đang làm việc trên một phần của dự án, mọi thứ ở trong tình trạng lộn xộn và bạn muốn chuyển đổi chi nhánh một chút để làm việc khác. Vấn đề là, bạn không muốn thực hiện một công việc nửa vời chỉ để bạn có thể quay lại điểm này sau. Câu trả lời cho vấn đề này là lệnh git stash.

Stashing có trạng thái bẩn trong thư mục làm việc của bạn - nghĩa là, các tệp được theo dõi đã sửa đổi của bạn và thay đổi theo giai đoạn - và lưu nó vào một đống các thay đổi chưa hoàn thành mà bạn có thể áp dụng lại bất cứ lúc nào.

Đưa ra mô tả này, tôi sẽ nói đây là một mô hình chống. Một lời giải thích quá đơn giản về Git Stash sẽ là "Cắt và Dán" kiểm soát nguồn. Bạn lấy một loạt các tệp đã thay đổi, "bỏ" chúng trong một cây bút bên ngoài quy trình phân nhánh thông thường của Git, và sau đó áp dụng lại những thay đổi đó cho một nhánh khác vào một ngày sau đó.

Quay trở lại xa hơn một chút, cam kết làm chủ là mô hình chống ở đây. Sử dụng cành cây. Đó là những gì họ được thiết kế cho.

Nó thực sự nắm bắt được điều này:

Bạn có thể đóng đinh vít vào tường và nó sẽ giữ một bức tranh, nhưng sử dụng tuốc nơ vít là điều bạn nên làm. Đừng dùng búa khi tuốc nơ vít ngồi ngay bên cạnh bạn.

Về việc cam kết mã "bị hỏng"

Trong khi sau đây là ý kiến, tôi đã đến ý kiến ​​này từ kinh nghiệm.

Cam kết sớm, và cam kết thường xuyên. Cam kết nhiều mã bị hỏng như bạn muốn. Xem lịch sử cam kết địa phương của bạn dưới dạng "lưu điểm" trong khi bạn hack đi thứ gì đó. Khi bạn đã hoàn thành công việc hợp lý, hãy cam kết. Chắc chắn nó có thể phá vỡ mọi thứ, nhưng điều đó không quan trọng miễn là bạn không thúc đẩy những cam kết đó. Trước khi đẩy, rebase và đè bẹp cam kết của bạn.

  1. Tạo chi nhánh mới
  2. Hack hack hack
  3. Cam kết mã bị hỏng
  4. Đánh bóng mã và làm cho nó hoạt động
  5. Cam kết mã làm việc
  6. Rebase và Squash
  7. Kiểm tra
  8. Đẩy khi các bài kiểm tra đang trôi qua

Đối với OP, chuỗi thông điệp hạt nhân Linux này có thể được quan tâm, bởi vì nó nghe có vẻ giống như một số thành viên trong nhóm của OP đang sử dụng Git theo cách tương tự.

@RibaldEddie nói trong một bình luận dưới đây:

Trước hết, một stash không nằm ngoài "quy trình phân nhánh" vì dưới mui xe, stash chỉ là một nhánh khác.

(có nguy cơ phát sinh cơn thịnh nộ của nhiều người)

Linus nói:

Với "git stash", bạn cũng có thể có nhiều thứ được sắp xếp khác nhau, nhưng chúng không xếp hàng với nhau - chúng chỉ là các bản vá độc lập ngẫu nhiên mà bạn đã bỏ đi vì đôi khi chúng bất tiện.

Điều tôi nghĩ @RibaldEddie đang cố gắng nói là bạn có thể sử dụng git stashtrong quy trình làm việc của nhánh tính năng - và điều này là đúng. Đó không phải git stashlà vấn đề. Nó là sự kết hợp của cam kết để làm chủ và sử dụng git stash. Đây là một mô hình chống.

Làm rõ git rebase

Từ bình luận của @ RibaldEddie:

Rebasing giống như dán sao chép và thậm chí tệ hơn sửa đổi lịch sử đã cam kết.

(Nhấn mạnh của tôi)

Sửa đổi lịch sử cam kết không phải là một điều xấu, miễn là lịch sử cam kết cục bộ . Nếu bạn rebase cam kết rằng bạn đã đẩy, về cơ bản bạn sẽ mồ côi bất cứ ai khác sử dụng chi nhánh của bạn. Điều này tệ đây.

Bây giờ, giả sử bạn đã thực hiện một số cam kết trong suốt một ngày. Một số cam kết là tốt. Một số ... không tốt lắm. Các git rebaselệnh kết hợp với cán nát cam kết của bạn là một cách tốt để làm sạch cam kết lịch sử địa phương của bạn. Thật tuyệt khi hợp nhất trong một cam kết với các chi nhánh công cộng vì nó giữ cho lịch sử cam kết của các chi nhánh được chia sẻ của nhóm của bạn sạch sẽ. Sau khi khởi động lại, bạn sẽ muốn kiểm tra lại, nhưng nếu các bài kiểm tra vượt qua thì bạn có thể đẩy một cam kết sạch thay vì một vài lần bẩn.

Có một luồng Linux Kernel thú vị khác về lịch sử cam kết sạch .

Một lần nữa, từ Linus:

Tôi muốn lịch sử sạch, nhưng điều đó thực sự có nghĩa là (a) sạch và (b) lịch sử.

Mọi người có thể (và có lẽ nên) rebase họ tin cây (công việc của mình). Đó là một sự dọn dẹp . Nhưng không bao giờ mã người khác. Đó là một "lịch sử hủy diệt"

Vì vậy, phần lịch sử là khá dễ dàng. Chỉ có một quy tắc chính và một quy định nhỏ:

  • Bạn không bao giờ phải phá hủy lịch sử các dân tộc khác. Bạn không được phản đối cam kết người khác đã làm. Về cơ bản, nếu nó không có dấu hiệu của bạn trên đó, thì đó là giới hạn: bạn không thể từ chối nó, bởi vì nó không phải là của bạn.

    Lưu ý rằng đây thực sự là về lịch sử của những người khác , không phải về mã của những người khác . Nếu họ gửi công cụ cho bạn dưới dạng bản vá được gửi qua email và bạn đã áp dụng nó với "git am -s", thì đó là mã của họ, nhưng đó là lịch sử của bạn .

    Vì vậy, bạn có thể phát cuồng với điều "git rebase" trên đó, mặc dù bạn không viết mã, miễn là bản thân cam kết là quyền riêng tư của bạn.

  • Làm rõ quy tắc nhỏ: một khi bạn đã xuất bản lịch sử của mình trên một số trang web công cộng, những người khác có thể đang sử dụng nó, và vì vậy bây giờ rõ ràng đó không phải là lịch sử riêng tư của bạn nữa.

    Vì vậy, một sự làm rõ nhỏ thực sự là nó không chỉ là về "cam kết của bạn", mà còn về việc nó là riêng tư đối với cây của bạn và bạn chưa đẩy nó ra và công bố nó.

...

Bây giờ phần "sạch" tinh tế hơn một chút, mặc dù các quy tắc đầu tiên khá rõ ràng và dễ dàng:

  • Giữ lịch sử của riêng bạn có thể đọc được

    Một số người làm điều này bằng cách chỉ làm việc trong đầu trước, và không phạm sai lầm. nhưng điều đó rất hiếm, và đối với phần còn lại của chúng tôi, chúng tôi sử dụng "git rebase", vv trong khi chúng tôi làm việc với các vấn đề của mình.

    Vì vậy, "git rebase" không sai. Nhưng nó chỉ đúng nếu đó là cây git RIÊNG RIÊNG CỦA BẠN.

  • Đừng phơi bày chuyện tào lao của bạn.

    Điều này có nghĩa là: nếu bạn vẫn đang trong giai đoạn "git rebase", bạn không đẩy nó ra. Nếu nó chưa sẵn sàng, bạn gửi các bản vá xung quanh hoặc sử dụng các cây git riêng (giống như "thay thế loạt bản vá") mà bạn không nói với công chúng nói chung.

(nhấn mạnh của tôi)

Phần kết luận

Cuối cùng, OP có một số nhà phát triển làm điều này:

git checkout master
(edit files)
git commit -am "..."
(edit files)
git stash
git pull
git stash (pop|apply)

Có hai vấn đề ở đây:

  1. Các nhà phát triển đang cam kết làm chủ. Khóa cái này lại ngay lập tức. Thực sự, đây là vấn đề lớn nhất .
  2. Các nhà phát triển liên tục sử dụng git stashgit pulllàm chủ khi họ nên sử dụng các nhánh tính năng.

Không có gì sai khi sử dụng git stash- đặc biệt là trước khi kéo - nhưng sử dụng git stashtheo cách này là một kiểu chống khi có quy trình công việc tốt hơn trong Git.

Họ sử dụng git stashcá trích đỏ. Nó không phải là vấn đề. Cam kết làm chủ là vấn đề.


4
Wow, điều này không đúng. Trước hết, một stash không nằm ngoài "quy trình phân nhánh" vì dưới mui xe, stash chỉ là một nhánh khác. Ý tưởng rằng đó là một quy trình sao chép-dán không có ý nghĩa. Rebasing giống như dán sao chép và thậm chí tệ hơn sửa đổi lịch sử đã cam kết. Cuối cùng, quy trình làm việc của bạn hoàn toàn vô dụng ngay khi bạn cần chia sẻ tiến độ công việc với đồng nghiệp vì nó sụp đổ ngay khi bạn thúc đẩy thay đổi. Làm thế nào điều này có sáu phiếu bầu lên là tâm trí boggling.
RibaldEddie

8
@RibaldEddie: Không có gì sai khi nổi loạn và viết lại lịch sử cam kết miễn là đó là lịch sử cam kết cục bộ. Khi bạn đẩy những cam kết đó, nhận xét của bạn sẽ chính xác, nhưng đọc lại câu trả lời của tôi. Nó nói: "Trước khi đẩy, rebase và squash cam kết của bạn." Đó là lịch sử cam kết địa phương , hoàn toàn dưới sự kiểm soát của bạn.
Greg Burghardt

1
@RibaldEddie: Tôi đã làm rõ câu trả lời của mình. Nó cần một số dọn dẹp.
Greg Burghardt

Tôi sẽ cung cấp thêm một số bối cảnh trong câu trả lời của riêng tôi.
RibaldEddie

Xem câu trả lời của tôi dưới đây-- trong khi cam kết làm chủ là một mô hình chống đối, đó không phải là vấn đề thực sự.
RibaldEddie

7

Cá nhân tôi chỉ sử dụng stashcho những gián đoạn ngắn, bất ngờ, như ai đó hỏi một câu hỏi yêu cầu thay đổi sang một nhánh khác. Tôi làm điều này bởi vì tôi đã quên về stash trước đó, sau đó họ sẽ không áp dụng sạch sẽ. Các cam kết thông thường trên các nhánh tính năng khó quên hơn nhiều và dễ hợp nhất hơn, vì vậy bây giờ tôi có xu hướng chỉ thực hiện một cam kết bị hỏng, sau đó thực hiện một git reset HEAD~1hoặc một cuộc nổi loạn nếu tôi không muốn giữ lại sau này.

Tuy nhiên, điều tuyệt vời về kiểm soát phiên bản phân tán là mọi người có thể sử dụng quy trình làm việc ưa thích của họ trong kho lưu trữ của riêng họ, miễn là các kho lưu trữ được chia sẻ đáp ứng các tiêu chuẩn. Tôi sẽ đảm bảo mọi người không chỉ sử dụng stashquy trình công việc vì họ không được đào tạo hoặc nhận thức về các lựa chọn thay thế, nhưng nếu họ vẫn chọn quy trình công việc mà bạn thấy không tối ưu, tôi sẽ bỏ qua.


1

Tôi nghĩ rằng một phần của câu hỏi của bạn là một mô hình chống là việc sử dụng một nhánh chủ chung được chia sẻ . Tuy nhiên, nếu bạn bao gồm một nhánh phát triển ngoài nhánh chính và sau đó sử dụng stash để xử lý các chuyển đổi ngữ cảnh của riêng bạn trong nhánh phát triển, thì đó sẽ không phải là một mô hình chống và nó phản ánh rất chặt chẽ một số quy trình công việc mô tả bởi các tổ chức như Etsy và Facebook.

Điều đó đã được nói, câu trả lời của @Greg Burghardt ở trên là một chút quá thuận lợi cho cái gọi là luồng công việc git-Flow hoặc nhánh tính năng. Tôi đã từng ủng hộ cho một chiến lược tương tự nhưng sau khi nhận ra rằng nó làm tăng thêm sự phức tạp không cần thiết và tạo ra cảm giác an toàn sai lầm, tôi không còn làm nữa. Nó cũng là một sự tiếp quản từ thời của các hệ thống kiểm soát phiên bản phi tập trung như lật đổ.

Đầu tiên, vì Git là một hệ thống kiểm soát phiên bản phi tập trung không giống như lật đổ, kho lưu trữ cục bộ của nhà phát triển về cơ bản là một nhánh khổng lồ của mã. Những gì một cá nhân phát triển làm cục bộ không và không nên có tác động đến các thành viên khác trong nhóm trừ khi mã bị hỏng hoặc lỗi được đẩy lên bất kỳ nhánh chia sẻ nào trong kho lưu trữ được chia sẻ.

Tuy nhiên, lệnh rebase có thể làm hỏng lịch sử của chi nhánh khi có xung đột hợp nhất tại một trong các cam kết được phát lại. Từ http://ryantablada.com/post/the-dangers-of-rebasing-a-branch

Phần còn lại của cuộc nổi loạn diễn ra suôn sẻ, tất cả các bài kiểm tra dường như đều vượt qua. Một PR được thực hiện.

Và sau đó, một số mã nữa được viết dựa trên thuộc tính bình luậnForAllPosts và mọi thứ đều bị hỏng. Nhưng chúng ta đi ai và nhờ giúp đỡ? git đổ lỗi cho thấy rằng dòng mã chỉ được viết bởi kỹ sư phía máy chủ và anh ta giơ tay.

Bây giờ kỹ sư đầu cuối của bạn đã nghỉ phép, nghỉ ốm, hoặc ai biết. Không ai có thể tìm ra mã đó sẽ trông như thế nào!

Rebase đã giết chết khả năng của nhóm để nhìn vào lịch sử để tìm ra lỗi sai vì bất kỳ xung đột hợp nhất nào trên nhánh con đều bị giết và mã gốc bị mất vĩnh viễn.

Nếu xung đột hợp nhất này xuất hiện và hợp nhất được sử dụng, thì lỗi sẽ cho thấy rằng dòng mã đó đã được chạm vào trong quy trình hợp nhất, cam kết trên nhánh cha và cam kết trên nhánh con. Một số trò chơi xung quanh với ba hoán vị và bạn có thể lấy lại ý định ban đầu vào cơ sở mã và làm việc mà không cần một đầu gãi đầu chỉ tay. Và tất cả những gì bạn thực sự có là một cam kết khác

Hơn nữa, một mô hình nhiều nhánh giả định rằng không có hai nhánh nào có thể chứa các thay đổi mã phụ thuộc lẫn nhau. Khi điều đó chắc chắn xảy ra, nhà phát triển bây giờ phải tung ra nhiều chi nhánh hơn để hoạt động hiệu quả.

Mô hình chống cơ bản mà tôi thấy không liên quan đến các nhánh so với stash, mà là về các loại vấn đề mà một số người rất thông minh đã nói đến bây giờ: bạn có tự tin vào mã của mình thông qua việc sử dụng kiểm tra đơn vị và một kiến ​​trúc tốt? Bạn có thể thực hiện các thay đổi gia tăng cho mã của mình để các nhà phát triển của bạn có thể lý giải về các thay đổi một cách dễ dàng và hiểu những thay đổi sẽ làm gì không? Các nhà phát triển của bạn thậm chí có chạy qua mã mới một lần để xem nó có thực sự hoạt động không? (Có, tôi đã thấy điều này trước đây).

Nếu câu trả lời cho những câu hỏi đó là không, thì thực sự bạn có bao nhiêu chi nhánh - các nhà phát triển sẽ nói rằng mã đã sẵn sàng, hoạt động và phù hợp với sản xuất khi thực sự không có, và sẽ không có số chi nhánh nào Giúp bạn khi mã đó đi lên sản xuất nào.


2
Nhận xét của bạn về việc nổi loạn có vấn đề với độ phân giải hợp nhất là không đúng sự thật. Rebase là loại hợp nhất giống như hợp nhất thực tế. Git chỉ là hợp nhất cam kết dưới mui xe. Nổi loạn và giải quyết xung đột hợp nhất không làm hỏng lịch sử cam kết. Nổi loạn và giải quyết không đúng cách một cuộc xung đột hợp nhất sẽ làm hỏng mọi thứ, điều này cũng giống như với một sự hợp nhất thông thường. Tôi phải đồng ý rằng các nhánh tính năng tăng thêm độ phức tạp, nhưng điều này có thể phức tạp cần thiết nếu các nhà phát triển phải xử lý nhiều thay đổi không liên quan.
Greg Burghardt

Vì vậy, bạn đang nói rằng sáp nhập có thể phá hủy lịch sử?! Có vẻ như đó là lý do chính đáng hơn để tránh có quá nhiều chi nhánh!
RibaldEddie

1
Sáp nhập không thể phá hủy lịch sử. Tôi nghĩ rằng bạn có thể đang hiểu sai về cách thức nổi loạn và sáp nhập hoạt động. Khi một xung đột hợp nhất được kích hoạt, tùy thuộc vào con người để giải quyết nó. Nếu con người giải quyết nó không chính xác, bạn không thể đổ lỗi cho Git (hoặc SVN hoặc CVS ​​hoặc {chèn điều khiển nguồn ở đây}).
Greg Burghardt

Bây giờ những gì bạn đang nói là xung đột với những gì bạn nói trước đây. Bạn đã đọc bài viết tôi trích dẫn từ? Bạn có hiểu bối cảnh trong đó một cuộc nổi loạn sẽ mất lịch sử?
RibaldEddie

1
Tôi đọc bài viết. "Tại Keen, chúng tôi cố gắng đẩy mã của mình sau gần như mỗi lần cam kết." Điều đó nghe thật điên rồ với tôi. Hoặc là họ đang thực hiện các cam kết quá lớn hoặc họ đang đẩy ra mã chưa sẵn sàng. Nếu bạn thực hiện tất cả các cam kết của mình ngay lập tức, thì ừ, việc nổi loạn sẽ gây ra vấn đề. Đó là nguyên tắc "Bác sĩ, bác sĩ, thật đau lòng khi tôi làm điều này".
Kyralessa

1

git stashlà một công cụ. Bản thân nó không phải là một mô hình, cũng không phải là một mô hình chống. Nó là một công cụ, giống như một cái búa là một công cụ. Sử dụng búa để lái đinh là một mô hình và sử dụng búa để lái vít là một mô hình chống. Tương tự như vậy, có các quy trình công việc và môi trường git stashlà công cụ chính xác để sử dụng, và quy trình công việc và môi trường sai.

Quy trình 'mọi người cam kết và đẩy lên tuyến chính' là một công việc hoạt động khá hợp lý khi không có thay đổi rủi ro cao. Nó thường được sử dụng trong các môi trường svn nơi có một máy chủ trung tâm có thẩm quyền có mã.

Git, tuy nhiên, mối quan hệ để loại bỏ với một máy chủ trung tâm. Có tất cả các nhà phát triển đang làm commit, pull(hoặc rebasenếu bạn thích điều đó), pushmọi lúc có thể tạo ra một mớ hỗn độn lớn.

Những vấn đề lớn nhất xảy ra là bạn đã có một cái gì đó trong tiến trình bị hỏng và bạn cần phải xử lý một lỗi ưu tiên. Điều này có nghĩa là bạn cần đặt công việc đó sang một bên, lấy bản mới nhất, làm việc đó mà không có công việc trước đó đang tiến hành gây ra sự cố với bản dựng mà bạn đang cố gắng thực hiện.

Đối với điều này, git stashsẽ là công cụ thích hợp để sử dụng.

Tuy nhiên, có một vấn đề lớn hơn ẩn giấu trong cốt lõi của quy trình làm việc này. Có phải là tất cả các vai trò của các nhánh kiểm soát phiên bản nằm trên một nhánh duy nhất. Dòng chính, phát triển, bảo trì, tích lũy và đóng gói đều có trên Master. Đây là một vấn đề. (Xem Chiến lược phân nhánh SCM nâng cao để biết thêm về cách tiếp cận này với các chi nhánh)

Và vâng, bạn đã gọi rằng đó không phải là một quy trình công việc tuyệt vời và có vấn đề với nó. Tuy nhiên, vấn đề không nằm ở công cụ git stash. Vấn đề là thiếu sự phân nhánh rõ rệt cho các vai trò hoặc cho các chính sách không tương thích .

git stashtuy nhiên, là thứ mà tôi đã sử dụng khi gặp tình huống tôi đã xây dựng được một chút, rơi vào trạng thái dính mà tôi không chắc liệu đó có phải là một tình huống đúng không ... vì vậy tôi đã khắc phục những thay đổi của mình và sau đó khám phá một cách tiếp cận khác để giải quyết vấn đề. Nếu điều đó đã làm việc - tuyệt vời, hãy loại bỏ những thứ trên stash và tiếp tục. Nếu thăm dò khác có stickier, sau đó đặt lại về thay đổi trước đó và áp dụng lại stash để làm việc đó. Thay thế sẽ là cam kết, kiểm tra, chi nhánh và sau đó tiếp tục trên chi nhánh mới này hoặc quay lại và đặt lại nó. Câu hỏi đặt ra là nó có thực sự đáng để đưa nó vào lịch sử hay không khi nó chỉ là thứ tôi muốn khám phá một chút?

git stashkhông phải là một mô hình chống. Sử dụng git stashnhư một cách thay thế để phân nhánh trong khi mọi người cam kết với Master là một kiểu chống - nhưng không phải vì git stash.

Nếu bạn chưa nhấn nó, chỉ cần đợi cho đến khi bạn gặp sự cố với bản dựng , khi ai đó cần thực hiện thay đổi kiến ​​trúc quan trọng đối với nhiều tệp (và xung đột hợp nhất) hoặc một số công việc chưa được kiểm tra trong mã tiến trình bị rò rỉ để sản xuất cho việc này chống mẫu để bắt kịp với bạn.

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.