Sử dụng GIT, làm cách nào để tôi có thể hợp nhất các thay đổi có chọn lọc từ một cam kết trên một 'ngã ba' khác?


81

Hãy xem trường hợp này:

  1. Tôi quyết định 'fork' một codebase trên github.com và bắt đầu thực hiện quy trình của mình: Chỉnh sửa - Cam kết - Đẩy; hay còn gọi là hack hack hack.
  2. Sau khi tôi thực hiện một số thay đổi, tôi thấy một số thay đổi mà một người khác đã thực hiện trên cùng một dự án và tôi thích chúng!
  3. Tôi quyết định muốn hợp nhất chúng thành của tôi. Vấn đề là, tôi chỉ muốn một 'phần' của một cam kết cụ thể, trong số nhiều cam kết mà anh ta đã thực hiện.

Phương pháp hiệu quả nhất để nhận được số lượng thay đổi đã chọn này, được hợp nhất vào 'fork' của tôi là gì?



Câu trả lời:


119

Sau khi troll làn sóng của thế giới IRC, ai đó đã đưa ra một giải pháp tuyệt vời:

git cherry-pick SHA1 --no-commit
git add --patch

Hy vọng rằng điều đó sẽ giúp bất kỳ ai khác có cùng câu hỏi!

CHỈNH SỬA: OK, có lẽ nó không đơn giản như vậy. Dưới đây là các bước đầy đủ:

  1. Trước tiên, bạn phải ở trong kho lưu trữ của mình, thực hiện cd-ing cần thiết để truy cập thư mục làm việc của bạn.

  2. Bây giờ bạn cần thêm nhánh từ xa, rồi tìm nạp nó. Làm điều này bằng cách:

    git remote add someUser git://github.com/someUser/someRepo.git

    git fetch someUser

  3. Bây giờ bạn có thể chạy các lệnh chẳng hạn như git log someUser/masterđể tìm SHA1 cam kết mà bạn muốn hợp nhất trong 'một phần'.

  4. Sau khi bạn có SHA, bây giờ bạn có thể chạy:

    git cherry-pick -n SHA1

    nơi SHA1được cam kết SHA, duh!

  5. Rất có thể sẽ có xung đột, tùy thuộc vào độ tuổi của cam kết và tần suất thay đổi khu vực cụ thể của dự án. Xin lỗi, nhưng bạn phải giải quyết những vấn đề này theo cách thủ công với trình chỉnh sửa đáng tin cậy của bạn. Vì vậy, hãy rút VIM, hoặc bất cứ thứ gì khác mà bạn sử dụng và giải quyết các xung đột cho đến khi bạn đến giai đoạn mà bạn thích những thay đổi.

  6. Bây giờ bạn phải đặt lại chỉ mục về bản sửa đổi HEAD, sau đó bạn có thể sử dụng add --patchlệnh GIT đáng tin cậy để chọn và chọn những thay đổi bạn muốn:

    git reset HEAD

    git add --patch hoặc là git add -p

  7. Yay! Thời gian cam kết:

    git commit -m "I merged a select amount of changes"

  8. Để dọn dẹp mớ hỗn độn (Những thứ bạn đã nói không git add --patch) và chỉ giữ lại những thay đổi đã chọn trong kho lưu trữ đang làm việc của bạn, hãy chạy:

    git reset --hard HEAD

    Rõ ràng git checkout -fcũng là một lựa chọn khác.


Tôi rất vui vì bạn đã tìm thấy git add -p; nó cực kỳ mạnh mẽ. Nếu bạn đã có cam kết được đề cập (ví dụ: không sử dụng --no-committrên cherry-pick hoặc đó là một trong những cam kết của bạn), bạn có thể sử dụng git reset HEAD^để tua lại chỉ mục một cam kết trở lại, sau đó thêm lại các thay đổi git add -p, cam kết trong các bước . Nếu cam kết không ở đầu nhánh, bạn có thể sử dụng git rebase -ivà chọn chỉnh sửa cam kết được đề cập.
Cascabel 10/09/09

3
đi dạo tốt. nhớ nếu bạn chỉ muốn toàn bộ cam kết, bạn chỉ cần phát ra -nở bước 4. Như thế này:git cherry-pick SHA1
Hulvej

Điểm mấu chốt ở đây là git remote add <user> <fork-url>- sau đó bạn có thể git cherry-pickbình thường.
Tom,

2

Tôi không rõ bạn muốn gì. Nếu bạn chỉ muốn mang lại một số cam kết nhất định từ các nhánh khác, bạn có thể sử dụng git cherry-pick SHA. Giải thích đầy đủ trên gitready .


Tôi chỉ sau một 'phần' / 'phần' / 'một vài dòng' của một cam kết cụ thể, được hợp nhất vào kho lưu trữ của tôi. Không đặc biệt tệp cụ thể.
Tim

Trong trường hợp đó, git định dạng bản vá SHA, Git áp dụng <vá> là một lựa chọn
hgmnz

2

Tôi thực sự thích giải pháp của Tim, tuy nhiên đôi khi tôi thích mày mò trong vimdiff. Giải pháp của tôi cho vấn đề này là thô thiển, nhưng nó phù hợp với tôi vì tôi thích vim.

Tôi đã đặt vimdiff làm bộ khuếch tán của mình, và sau đó để hợp nhất có chọn lọc, tôi khác nhánh:

git difftool <branch> <file>

Sau đó, tôi đi đến ngăn có phiên bản của nhánh hiện tại và chỉnh sửa bản gốc trong vim (đôi khi điều này không cần thiết, nhưng đôi khi vimdiff mở một phiên bản trong / tmp) và tắt chế độ chỉ đọc:

:e <file>
:set readonly!

Bây giờ tôi có thể sử dụng các công cụ vá lỗi của vim như dodpáp dụng những gì tôi muốn, và thực hiện các chỉnh sửa nhỏ khác khi tôi tiếp tục. Khi tôi hoàn tất, tôi lưu tệp, thoát khỏi vim, sau đó chuyển sang giai đoạn và cam kết tệp ở dạng git như một chỉnh sửa thông thường.

Như tôi đã nói, điều này không đặc biệt phức tạp, nhưng nó rất mạnh mẽ và vẫn hoàn toàn nằm trong dòng lệnh. Chỉ cần đảm bảo thêm thông báo cam kết rõ ràng, vì git sẽ không tự động bao gồm thông báo hợp nhất cho bạn.

ví dụ vimdiff http://j.mp/1dZVllt


Tôi không nghĩ rằng câu trả lời này hoàn toàn đủ điều kiện để trở thành một câu trả lời độc lập chính thức. Thông tin hữu ích, nhưng không liên quan đặc biệt. (tại sao điều này ở đầu câu trả lời?)
Mike Kormendy

1

Nếu bạn chỉ muốn một cổng của một cam kết, có lẽ tốt nhất bạn nên chọn cam kết mà bạn muốn và đặt lại các tệp bạn không muốn chạm vào.

git cherry-pick SHA1
git checkout HEAD file1 file2 ... fileN

Tất nhiên, nếu bạn có một số phần đã sửa đổi trong một tệp và chỉ muốn giữ một số phần trong số chúng, bạn không có lựa chọn nào khác ngoài việc chỉnh sửa tệp theo cách thủ công, cắt bỏ các thay đổi của chúng.


2
Thanh toán có cần thiết ở đây không? Lệnh cherry pick không đưa các thay đổi vào thư mục làm việc của bạn sao?
Casey Watson
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.