git: Áp dụng các thay đổi được giới thiệu bởi cam kết trong một repo này sang repo khác


115

Tôi có một repo1repo2trên máy cục bộ. Chúng rất giống nhau, nhưng sau này là một số loại nhánh khác ( repo1không được duy trì nữa).

/path/to/repo1 $ git log HEAD~5..HEAD~4
<some_sha> Add: Introduce feature X

Làm thế nào để áp dụng các thay đổi do cam kết <some_sha>trong repo1đến repo2?

Tôi có cần chuẩn bị một số bản vá hay có thể thực hiện một số bản vá cherry-pickgiữa các bản đại diện không?

Làm thế nào về việc làm tương tự nhưng đối với phạm vi cam kết?


2
Bạn không thể chỉ kéo từ repo1 sang repo2?
zwol

đối với trường hợp nhẹ cụ thể hơn nơi bạn đang tìm kiếm để áp dụng thay đổi vào một tập tin hoặc các tập tin đã được chuyển theo một trong các kho, nhìn ở đây: stackoverflow.com/questions/3491270/...
Braham Snyder

Câu trả lời:


31

Khi bị hack, bạn có thể thử sửa đổi công thức để so sánh các cam kết trong hai kho lưu trữ khác nhau trên trang GitTips , tức là:

GIT_ALTERNATE_OBJECT_DIRECTORIES=../repo/.git/objects \
git cherry-pick $(git --git-dir=../repo/.git rev-parse --verify <commit>)

đâu ../repolà đường dẫn đến kho lưu trữ khác.

Với Git hiện đại, bạn có thể sử dụng nhiều bản sửa đổi và phạm vi sửa đổi với cherry-pick .

$(git --git-dir=../repo/.git rev-parse --verify <commit>) đây là để dịch <commit>(ví dụ HEAD, hoặc v0.2, hoặc master~2, là các giá trị trong kho lưu trữ thứ hai mà bạn sao chép từ đó) sang định danh SHA-1 của cam kết. Nếu bạn biết SHA-1 của một thay đổi mà bạn muốn chọn, thì không cần thiết.

Tuy nhiên, LƯU Ý rằng Git có thể bỏ qua việc sao chép các đối tượng từ kho lưu trữ nguồn, vì nó không biết rằng kho lưu trữ đối tượng thay thế chỉ là tạm thời, cho một hoạt động. Bạn có thể cần sao chép các đối tượng từ kho thứ hai với:

GIT_ALTERNATE_OBJECT_DIRECTORIES=../repo/.git/objects git repack -a -d -f

Điều này đặt những đối tượng được mượn từ kho thứ hai vào kho lưu trữ gốc

Không được thử nghiệm.


Một giải pháp không quá hack là làm theo câu trả lời của trang :

  • Chuyển đến kho lưu trữ thứ hai mà bạn muốn sao chép các cam kết và tạo các bản vá từ các cam kết mà bạn muốn git format-patch
  • Theo tùy chọn, sao chép các bản vá (0001- *, v.v.) vào kho lưu trữ của bạn
  • Sử dụng git am --3wayđể áp dụng các bản vá lỗi

1
Hoạt động tốt. Nếu bạn gặp sự cố với commit thì hãy thực hiện 'git reset HEAD; git thêm. '.
gumik

5
điều này thật tuyệt vời - bạn sẽ thực hiện một loạt các cam kết như thế nào? chỉ sha1 ... sha2?
hvgotcodes

Tôi cũng nhận được fatal: unable to read tree ...nhưng sau khi git reset HEAD^mọi thứ hoạt động tốt
jmarceli

@hvgotcodes nó hoạt động với tôi đơn giản bằng cách chuyển phạm vi <commit>nhưng rev-parse --verifylệnh không thích nó vì nó chỉ chấp nhận các giá trị cam kết duy nhất. Nhưng khi cherry-pickchấp nhận cả giá trị cam kết đơn và phạm vi, tôi hỏi: tại sao lại rev-parsecần?
Chuim

1
@Chuim: git rev-parselà cần thiết nếu bạn muốn đề cập đến một cam kết theo tên ref của nó dựa trên trong kho lưu trữ khác, ví dụ master, HEAD^^hoặc một cái gì đó như thế; rev-parse biến nó thành mã định danh SHA-1 chung.
Jakub Narębski

207

Bạn có thể muốn sử dụng git format-patchvà sau đó git amáp dụng bản vá đó vào kho lưu trữ của mình.

/path/to/1 $ git format-patch sha1^..sha1
/path/to/1 $ cd /path/to/2
/path/to/2 $ git am -3 /path/to/1/0001-…-….patch

Hoặc, trong một dòng:

/path/to/2 $ git --git-dir=/path/to/1/.git format-patch --stdout sha1^..sha1 | git am -3

9
Giải pháp này tỏ ra đơn giản và an toàn hơn so với câu trả lời được chấp nhận là sử dụng hái cherry trực tiếp GIT_ALTERNATE_OBJECT_DIRECTORIES(giải pháp đó sẽ làm hỏng kho lưu trữ của tôi).
Chuim

2
Khi có xung đột, nó sẽ không hoạt động vì nó không tìm thấy các cam kết trên nhánh khác.
Roger Far

2
Thêm --ignore-whitespacevào git amlệnh có thể giải quyết bất kỳ xung đột nào và tránh cần phải thực hiện hợp nhất 3 chiều
Hugheth

97

Bạn có thể thực hiện cherry-picknếu bạn thêm repo thứ hai làm điều khiển từ xa vào repo đầu tiên (và sau đó fetch).


11
Đó thực sự là cách thích hợp để làm điều đó.
Wilbert

5
Đây cũng là cách phù hợp với tôi. Và tôi chỉ sử dụng nó và nó hoạt động tốt cho tôi.
Ricky Nelson,

10
Tôi thà nói: làm git fetch [remote-name]trong repo thứ hai và sau đó git cherry-pick [sha1].

5
Cách tiếp cận này hiệu quả đối với tôi, cảm ơn. Vì repo thứ hai cũng là cục bộ, chỉ cần sử dụng URI tệp khi thêm nó làm điều khiển từ xa.
palimpsestor

2
Trong trường hợp của tôi, tôi có hai bản sao của một kho lưu trữ git từ xa khổng lồ (để cho phép làm việc song song), có nghĩa là tất cả lịch sử của nó đã được tải xuống và lưu trữ hai lần trong HD của tôi. Nếu tôi cũng phải thêm từng cái làm điều khiển từ xa của cái kia, điều đó sẽ tạo thêm hai bản sao bổ sung của cùng một lịch sử và có khả năng sẽ yêu cầu đồng bộ giữa chúng trước khi tôi có thể cherry-pick. Vì vậy, mặc dù nó có thể cảm thấy là cách "đúng đắn", nó không phải lúc nào cũng thực tế nhất.
Chuim

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.