git - bỏ qua các cam kết cụ thể khi hợp nhất


200

Tôi đã sử dụng Git khoảng một năm nay và nghĩ rằng nó thật tuyệt vời, nhưng tôi mới bắt đầu phiên bản thứ hai của dự án và bắt đầu một chi nhánh mới cho nó. Tôi đang vật lộn một chút với cách tốt nhất để xử lý mọi việc trong tương lai.

Tôi có hai nhánh được gọi là master10 (cho v1) và master20 (cho v2). Tôi đã thực hiện sửa lỗi trong v1 trên nhánh master10 và phát triển công cụ mới của master20. Bất cứ khi nào tôi thực hiện sửa lỗi, tôi hợp nhất nó vào v2 bằng cách kiểm tra master20 và thực hiện git merge master10. Càng xa càng tốt.

Tuy nhiên, bây giờ, tôi đã thực hiện một thay đổi trong v1 mà tôi không muốn trong v2, nhưng tôi muốn tiếp tục hợp nhất các bản sửa lỗi khác. Làm cách nào để tôi bảo Git bỏ qua cam kết cụ thể đó (hoặc một loạt các cam kết), nhưng trong tương lai tôi vẫn muốn hợp nhất các bản sửa lỗi khác.

Tôi nghĩ git rebasecó thể là những gì tôi cần nhưng đọc tài liệu và đầu tôi gần như nổ tung.

Tôi nghĩ những gì tôi muốn là một cái gì đó giống như lệnh "git sync" nói với git rằng hai nhánh hiện không đồng bộ và trong tương lai chỉ hợp nhất các cam kết từ điểm đồng bộ hóa này.

Bất kỳ trợ giúp đánh giá cao.

Câu trả lời:


289

Ví dụ, nếu bạn muốn hợp nhất nhưng không phải tất cả các cam kết trên nhánh "duy trì" thành "chính chủ", bạn có thể thực hiện việc này. Nó đòi hỏi một số công việc ---- như đã đề cập ở trên, trường hợp sử dụng thông thường là hợp nhất mọi thứ từ một nhánh --- nhưng đôi khi điều đó xảy ra là bạn đã thay đổi thành phiên bản phát hành không nên tích hợp lại (có thể là mã đó đã được áp dụng trong chủ đã), vậy làm thế nào để bạn đại diện cho điều đó? Ở đây đi ...

Vì vậy, giả sử duy trì đã có 5 thay đổi được áp dụng và một trong những thay đổi đó sẽ không được hợp nhất trở lại thành chủ, mặc dù tất cả những thay đổi khác đều phải như vậy. Bạn làm điều này trong ba giai đoạn: thực sự hợp nhất mọi thứ trước đó, nói với git để đánh dấu duy trì ~ 3 là hợp nhất ngay cả khi không, và sau đó hợp nhất phần còn lại. Điều kỳ diệu là:

bash <master>$ git merge maint~4
bash <master>$ git merge -s ours maint~3
bash <master>$ git merge maint

Lệnh đầu tiên hợp nhất mọi thứ trước khi bạn gặp rắc rối với chủ. Thông báo nhật ký hợp nhất mặc định sẽ giải thích bạn đang hợp nhất "nhánh 'duy trì" (phần đầu) ".

Lệnh thứ hai hợp nhất các cam kết rắc rối ~ 3 cam kết, nhưng tùy chọn "-s ours" cho git sử dụng một "chiến lược hợp nhất" đặc biệt, trên thực tế, hoạt động bằng cách đơn giản là giữ cây bạn đang hợp nhất và bỏ qua các cam kết ) bạn đang hợp nhất hoàn toàn. Nhưng nó vẫn tạo ra một cam kết hợp nhất mới với HEAD và duy trì ~ 3 với tư cách là cha mẹ, vì vậy biểu đồ sửa đổi bây giờ nói rằng duy trì ~ 3 được hợp nhất. Vì vậy, trên thực tế có lẽ bạn cũng muốn sử dụng tùy chọn -m để 'git merge', để giải thích rằng việc duy trì ~ 3 cam kết thực sự bị bỏ qua!

Lệnh cuối cùng chỉ đơn giản là hợp nhất phần còn lại của duy trì (duy trì ~ 2..maint) thành chủ để tất cả các bạn được đồng bộ hóa lại.


5
Tôi nghĩ rằng nếu bạn cần hoãn việc hợp nhất cam kết đó, bạn có ít lựa chọn ngoài việc bỏ qua nó (hợp nhất -s của chúng tôi) và sau đó áp dụng nó bằng lệnh cherry-pick. Khi cam kết có thể truy cập được từ chủ, nó không thể được hợp nhất lại - tránh việc sáp nhập cùng một thay đổi hai lần là một trong những mục tiêu chính.
araqnid

3
Về ví dụ về chi nhánh phụ của bạn: Tôi nghi ngờ rằng một khi bạn đã hợp nhất chi nhánh phụ, bạn sẽ ở trong tình trạng giống hệt như bạn sau bước thứ hai của bài viết của tôi. Tạo các nhánh bổ sung làm cho không có sự khác biệt cho các mối quan hệ cam kết.
araqnid

5
Chỉ cần quan tâm, nếu bạn chỉ muốn bỏ qua một thay đổi, tại sao bạn không thực hiện một hợp nhất duy nhất và sau đó hoàn nguyên một thay đổi đó, thay vì thực hiện ba hợp nhất? Nó sẽ dẫn đến ít thay đổi hơn được cam kết với kho lưu trữ và một lịch sử rõ ràng hơn.
Đánh dấu gian hàng

3
Thường thì việc đặt tên cho các cam kết sẽ dễ dàng hơn. Vì vậy, bạn chỉ cần xem nhật ký git của nhánh sắp sáp nhập và lưu ý các giá trị băm của cam kết không được hợp nhất và trước đó - thay vì đếm cam kết
zwirbeltier

14
@MarkBooth: Cam kết bạn muốn bỏ qua có thể xảy ra xung đột lớn với chi nhánh bạn muốn hợp nhất. Dễ dàng bỏ qua thay vì sửa các xung đột sau đó hoàn nguyên thay đổi đó và sửa lại xung đột một lần nữa
SztupY

39

IMHO, điều hợp lý nhất để làm, là hợp nhất mọi thứ và sau đó sử dụng git Revert (commit_you_dont_want) để xóa nó .

Thí dụ:

git merge master
git revert 12345678

Nếu bạn có nhiều cam kết "bỏ qua" hoặc muốn chỉnh sửa thông báo hoàn nguyên:

git merge master
git revert -n 123456
git revert -n abcdef
git commit -m "... Except commits 123456 and abcdef"

Sau đó, lịch sử của bạn có thể trông như sau:

| ... Except 123456 and abcdef
|\ Merge branch 'master' into 'your_branch'

Nếu bạn có xung đột liên quan đến CHỈ những cam kết "bỏ qua" này, bạn có thể sử dụng:

git merge master -X ours

Vì vậy, phiên bản của bạn sẽ tồn tại trên các phiên bản khác. Ngay cả khi không có thông báo lỗi, bạn vẫn có thể "hoàn nguyên" những cam kết không mong muốn đó, bởi vì chúng có thể có những thay đổi khác không xung đột và bạn vẫn không muốn chúng.

Nếu bạn có xung đột hình dung KHÔNG CHỈ các cam kết "bỏ qua", bạn nên giải quyết chúng theo cách thủ công và có thể bạn sẽ phải giải quyết chúng một lần nữa trong quá trình hoàn nguyên.


2
Nếu sau đó bạn muốn hợp nhất những cam kết được hoàn nguyên đó vào nhánh thành câu hỏi, liệu Git có còn bỏ qua chúng không?
Anriëtte Myburgh

@ AnriëtteMyburgh Bạn có thể hoàn nguyên các cam kết đảo ngược để sau đó hợp nhất chúng vào - điều mà bạn thực sự không thể làm dễ dàng với chiến lược "hợp nhất - của chúng ta".
Lily Chung

Cảm ơn, đây chính xác là những gì tôi cần có một vài cam kết cũ hơn trong một nhánh tính năng mà tôi không muốn ở chủ và một bó mà tôi muốn ở chủ. Đẹp và sạch sẽ.
Vale Trujillo

17

Cam kết bao gồm tổ tiên. Bạn không thể hợp nhất một cam kết mà không hợp nhất các cam kết trước đó.

Bạn có thể chọn anh đào, tất nhiên. Đó là một dòng chảy tốt khi bạn có một chi nhánh ở chế độ bảo trì.


1
Cảm ơn, cherry hái sẽ làm công việc. Không đẹp như những gì tôi đã hy vọng nhưng nó sẽ làm được.
Brad Robinson


3

Một loại quảng cáo cho dự án của tôi về cơ bản bao gồm quá trình được mô tả bởi @araqnid.

Đó là loại trợ giúp giới thiệu dòng chảy GIT sau:

  • có thông báo hàng ngày / hàng tuần về việc sáp nhập đang chờ xử lý từ các chi nhánh bảo trì vào chi nhánh dev / master
  • người bảo trì chi nhánh kiểm tra trạng thái và quyết định xem liệu tất cả các cam kết có được yêu cầu hay không và chặn một số người trong số họ hoặc yêu cầu các nhà phát triển tự chặn. Cuối cùng, chi nhánh bảo trì được sáp nhập vào tuyến trên.

Một trích dẫn từ trang dự án:

Tùy thuộc vào quy trình công việc, có thể có các chi nhánh bảo trì hoặc dành riêng cho khách hàng cùng với chi nhánh chính. Những nhánh này còn được gọi là nhánh LTS.

Thông thường, các bản sửa lỗi nóng đi vào các nhánh nơi báo cáo lỗi và sau đó cam kết được hợp nhất trở lại vào nhánh chính.

Thực tiễn chung là để tất cả các nhánh được đồng bộ hóa hoàn hảo với chủ, tức là bạn muốn thấy một đồng bằng rõ ràng giữa một nhánh cụ thể và chủ để hiểu liệu chủ có chứa tất cả các tính năng và lỗi hay không.

Tuy nhiên, đôi khi bạn không muốn các cam kết cụ thể vì chúng là dành riêng cho khách hàng và sẽ không được hiển thị bởi những người dùng khác. Hoặc nhánh chính của bạn chuyển hướng nhiều đến mức nó đòi hỏi cách tiếp cận hoàn toàn khác để khắc phục vấn đề, hoặc thậm chí tốt hơn, vấn đề không còn tồn tại ở đó nữa.

Ngoài ra, trong trường hợp chọn cherry từ master vào nhánh bảo trì, kết quả sẽ bị chặn trong master.


0

Tạo một nhánh thứ ba cho những thay đổi bạn muốn trong master10 nhưng không phải trong master20. Luôn coi master10 là "bậc thầy" của bạn, nhánh ổn định nhất trong tất cả. Chi nhánh tất cả các chi nhánh khác muốn giữ đồng bộ mọi lúc.


Tôi đoán điều đó có thể làm việc, nhưng tôi đã rơi vào trạng thái này và một nhánh thứ ba có thể sẽ khiến tôi bối rối hơn nữa. :)
Brad Robinson

0

Thay vì reverthoặc cherry-picktrong trường hợp này, bạn cần có git để xem xét những thay đổi bạn bỏ qua là cũ hơn so với những thay đổi bạn đã thực hiện.

Vì thế:

  1. hợp nhất các cam kết cuối cùng trước khi các cam kết bạn muốn bỏ qua. Điều này, tất nhiên, sẽ hợp nhất tất cả các cam kết trước. git merge ccc
  2. hợp nhất các cam kết bạn muốn bỏ qua. git merge fff --no-commit
  3. giai đoạn bất kỳ sự hợp nhất, bỏ qua tất cả các thay đổi, hoàn tác tất cả các thay đổi. (Có lẽ có các lệnh chống lừa đảo cho việc này, nhưng tôi chỉ thực hiện phần này trong Giao diện người dùng - tuy nhiên bạn biết cách)
  4. hoàn thành hợp nhất trống git merge --continue
  5. hợp nhất các cam kết SAU khi bạn muốn bỏ qua. git merge source-branch-head

Sau Bước 4, git sẽ xem xét chi nhánh của bạn gần đây hơn cam kết đó, vì bạn đã xử lý nó (bằng cách chọn giữ các phiên bản của BẠN về mọi thứ).

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.