Kéo tất cả các cam kết từ một nhánh, đẩy các cam kết đã chỉ định sang một nhánh khác


102

Tôi có các nhánh sau:

  • master
  • production

và các chi nhánh từ xa sau:

  • origin/master
  • origin/production

Tôi có một tập lệnh tìm nạp origin/masternhánh và nhận được sự khác biệt của những gì đã thay đổi từ lần tìm nạp cuối cùng của tôi ( log -p master..origin/master). Sau đó, tôi hợp nhất origin/master.

Các cam kết được tìm thấy được chuyển đến một công cụ xem xét mã.

Tôi muốn đẩy các cam kết thành công - và chỉ chúng - đến chi nhánh sản xuất, và sau đó là tất nhiên origin/production.

Làm thế nào tôi có thể làm như vậy?

Ngoài ra, tôi có 2 tập lệnh đang chạy: một tập lệnh tìm nạp từ origin/master, đẩy chi tiết cam kết vào cơ sở dữ liệu và hợp nhất, và tập lệnh khác mà tôi hiện đang viết sẽ phải đẩy các cam kết thành công.

Tôi muốn có 2 tập lệnh đó chạy trong khi tránh điều kiện cuộc đua / xung đột hợp nhất. Vì tôi chỉ muốn làm việc với các cam kết được chỉ định, có thể có cách để loại bỏ các cam kết mà tôi không muốn?


Ý bạn là gì khi 'cam kết thành công'?
bdonlan

một trong những đã được xem xét và đánh dấu là thành công. nó không thực sự quan trọng ở đây, quan trọng là có những cam kết tôi muốn giữ lại và đẩy sang một nhánh khác, và những cam kết khác tôi muốn loại bỏ / bỏ qua.
Sylvain

Câu trả lời:


312

Thuật ngữ mà tôi nghĩ bạn đang tìm là 'hái anh đào'. Đó là, lấy một cam kết duy nhất từ ​​giữa một nhánh và thêm nó vào nhánh khác:

A-----B------C
 \
  \
   D

trở thành

A-----B------C
 \
  \
   D-----C'

Tất nhiên, điều này có thể được thực hiện bằng lệnh git cherry-pick.

Vấn đề với cam kết này là git coi các cam kết bao gồm tất cả lịch sử trước chúng - do đó, nếu bạn có ba cam kết như vậy:

A-----B-----C

Và cố gắng loại bỏ B, bạn phải tạo một cam kết hoàn toàn mới như sau:

A-----------C'

Trong đó C 'có ID SHA-1 khác. Tương tự như vậy, anh đào chọn một cam kết từ chi nhánh này sang chi nhánh khác về cơ bản liên quan đến việc tạo ra một bản vá, sau đó áp dụng nó, do đó mất lịch sử theo cách đó.

Việc thay đổi các ID cam kết này phá vỡ chức năng hợp nhất của git giữa những thứ khác (mặc dù nếu được sử dụng ít, sẽ có những khám phá về điều này). Tuy nhiên, quan trọng hơn, nó bỏ qua các phụ thuộc hàm - nếu C thực sự sử dụng một hàm được định nghĩa trong B, bạn sẽ không bao giờ biết.

Có lẽ cách tốt hơn để xử lý điều này là có nhiều nhánh hạt mịn hơn. Nghĩa là, thay vì chỉ có 'master', hãy có 'featureA', 'bugfixB', v.v. Thực hiện xem xét mã trên toàn bộ chi nhánh tại một thời điểm - trong đó mỗi chi nhánh chỉ tập trung vào làm một việc - và sau đó hợp nhất một nhánh khi bạn hoàn thành. Đây là quy trình làm việc mà git được thiết kế cho và những gì nó tốt ở :)

Nếu bạn nhấn mạnh vào việc giải quyết mọi thứ ở cấp độ các bản vá, bạn có thể muốn xem xét darcs - nó coi một kho lưu trữ là một tập hợp các bản vá, và do đó, hái cherry trở thành thao tác cơ bản. Tuy nhiên, điều này có một loạt vấn đề riêng, chẳng hạn như rất chậm :)

Chỉnh sửa: Ngoài ra, tôi không chắc mình hiểu câu hỏi thứ hai của bạn, về hai tập lệnh. Có thể bạn có thể mô tả nó chi tiết hơn, có thể là một câu hỏi riêng để mọi thứ không trở nên khó hiểu?


Về câu hỏi thứ hai của tôi, tôi chỉ muốn đảm bảo rằng các quy trình tìm nạp thay đổi (tập lệnh thứ nhất) và đẩy các cam kết đã cho đến một vị trí khác (tập lệnh thứ hai) có thể hoạt động mà không có điều kiện chủng tộc / xung đột hợp nhất, trong khi làm việc với các nhánh khác nhau. Nhưng cuối cùng thì tôi đoán điều đó không thành vấn đề vì tôi có thể hợp nhất 2 tập lệnh thành một để 2 tập lệnh không hoạt động đồng thời :)
Sylvain

9
"Việc thay đổi ID cam kết này phá vỡ chức năng hợp nhất của git trong số những thứ khác" @bdonlan vui lòng giải thích cách chức năng hợp nhất được phanh. Nó có nghĩa là gì?
Narek

5
@Narek Anh ấy có thể có nghĩa là những thay đổi trong cam kết C 'sẽ xung đột với những thay đổi tương tự trong cam kết C khi bạn sẽ hợp nhất nhánh thứ hai. Đó là hậu quả của việc mất lịch sử đằng sau cam kết C.
bytefu.

1
"Và cố gắng thoát khỏi B" - tại sao bạn lại cố gắng loại bỏ B?
d512

3
@ user1334007, ý anh ấy là trước đây nó từng là ABC. Bây giờ, do bạn chọn C, nhánh của bạn là AD-C ', không còn chứa' B 'nữa.
AnneTheAgile,

1

Tôi nhận ra đây là một câu hỏi cũ, nhưng được tham chiếu ở đây: Cách hợp nhất một cam kết cụ thể trong Git

Do đó, một câu trả lời mới hơn: Sử dụng các nhánh tính năng và yêu cầu kéo.

Điều này trông như thế nào, trong đó fA là một cam kết với tính năng A và fB là một cam kết với tính năng B:

            fA   fC (bad commit, don't merge)
           /  \ /
master ----A----B----C
                \  /
                 fB

Các yêu cầu kéo được liên kết với chức năng của GitHub, nhưng thực sự ý tôi là ai đó có trách nhiệm hợp nhất các nhánh tính năng thành tổng 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.