Làm thế nào để tạo một bản vá git cho một cam kết cụ thể?


1233

Tôi cần phải viết một tập lệnh tạo các bản vá cho danh sách các số cam kết SHA1.

Tôi đã thử sử dụng git format-patch <the SHA1>, nhưng điều đó đã tạo ra một bản vá cho mỗi lần xác nhận kể từ SHA1 đó. Sau khi một vài trăm bản vá được tạo ra, tôi đã phải giết quá trình.

Có cách nào để tạo một bản vá chỉ cho SHA1 cụ thể không?

Câu trả lời:


1990

Thử:

git format-patch -1 <sha>

hoặc là

git format-patch -1 HEAD

Theo liên kết tài liệu ở trên, -1cờ cho git biết bao nhiêu cam kết nên được bao gồm trong bản vá;

- <n>

     Chuẩn bị các bản vá từ các cam kết cao nhất.


Áp dụng bản vá với lệnh:

git am < file.patch

211
Áp dụng bản vá: git apply --stat file.patch# hiển thị số liệu thống kê. git apply --check file.patch# kiểm tra lỗi trước khi áp dụng. git am < file.patch# áp dụng bản vá cuối cùng.
Adrian

3
Nó dường như không hoạt động nếu cam kết cuối cùng là hợp nhất từ ​​một chi nhánh khác.
Lex Li

2
Để áp dụng bản vá trên các tệp bằng cách sử dụng kết thúc dòng CRLF:git am --keep-cr < mypatch.patch
Michael Schmeißer

40
Sử dụng git am -3 < file.patchđể áp dụng bằng cách hợp nhất ba chiều sẽ cho phép bạn giải quyết xung đột bằng cách sử dụng git mergetoolsau đó (hoặc chỉnh sửa thủ công) được tìm thấy ở đây .
Matt

6
Lệnh này cũng chỉ hoạt động đối với một (các) tệp cụ thể từ cam kết: git format-patch -1 <sha> path/to/file.jsĐiều này sẽ tạo ra một bản vá chỉ chứa các khác biệt cho
tệp.js

281

Để tạo các bản vá từ các cam kết cao nhất từ ​​hàm băm sha1 cụ thể:

git format-patch -<n> <SHA1>

10 bản vá cuối cùng từ đầu trong một tệp vá duy nhất:

git format-patch -10 HEAD --stdout > 0001-last-10-commits.patch

2
bạn có thể vui lòng tử tế để cung cấp một ví dụ cho lệnh đầu tiên
Kasun Siyambalapitiya

1
git format-patch -1 HEADsẽ tạo bản vá cho cam kết gần đây nhất
Sriram Murali

1
Xin lỗi vì đã hỏi tôi điều này, vì vậy khi nó -2tạo ra các bản vá cho 2 lần cam kết gần đây nhất, và một điều nữa để làm rõ là lệnh got format-patch -2 HEADnày giống như dònggit format-patch HEAD~2
Kasun Siyambalapitiya

85

Giả sử bạn có id id 2 sau khi xác nhận 1, bạn sẽ có thể chạy:

git diff 2 1 > mypatch.diff

trong đó 2 và 1 là băm SHA.


Cảm ơn bạn đã trả lời. Điều đó có nghĩa là tôi cần kịch bản để tìm các cam kết đi trước những người tôi quan tâm. Tôi đã hy vọng rằng tôi có thể tránh điều đó.
elle

11
@elle, không, bạn không - git diff hash^ hash. "băm ^" đưa ra cam kết đi trước. (nhưng, tất nhiên, câu trả lời của manojlds tốt hơn)
J-16 SDiZ

2
git show HEAD > mypatch.difftrong khi bạn đang cam kết nên làm như vậy.
andho

1
@dookehester là chính xác hay là cách khác,git diff 1 2
Kasun Siyambalapitiya

1
Điều này sẽ không bao gồm bất kỳ tập tin nhị phân trong diff.
mắc kẹt

55

Lệnh này (như đã được đề xuất bởi @ Naftuli Tzvi Kay ):

git format-patch -1 HEAD

Thay thế HEAD bằng hàm băm hoặc phạm vi cụ thể.

sẽ tạo tệp vá cho cam kết mới nhất được định dạng để giống với định dạng hộp thư UNIX.

-<n> - Chuẩn bị các bản vá từ các cam kết cao nhất.

Sau đó, bạn có thể áp dụng lại tệp vá theo định dạng hộp thư bằng cách:

git am -3k 001*.patch

Xem : man git-format-patch.


Cảm ơn! Tôi nghĩ rằng đáng chú ý rằng việc áp dụng bản vá sẽ tạo ra một cam kết với thông điệp cam kết có tiền tố [PATCH]. Điều đó rất dễ khắc phục
Mike S

2
Hiện tượng. OP, bạn đã không chấp nhận điều này, bởi vì ...? @MikeS Không, nó không còn nữa so với bất kỳ gitbản vá có định dạng nào khác, ít nhất là nếu người dùng áp dụng nó đúng cách.
gạch dưới

2
@MikeS Tôi không thực sự điều tra lý do tại sao, nhưng bỏ -kcờ ( git am -3) đã sửa mẫu này cho tôi (không PATCH[0/10]có tin nhắn cam kết). Phiên bản Git 2.20.1.windows.1
jannis

31
git format-patch commit_Id~1..commit_Id  
git apply patch-file-name

Giải pháp nhanh chóng và đơn giản.


5
Cũng đừng quên gọi git apply --check patch-file-nametrước khi áp dụng một bản vá. Điều này sẽ giúp tránh các vấn đề.
iamantony

16

Nếu bạn muốn chắc chắn bản vá (cam kết đơn) sẽ được áp dụng trên đầu trang của một cam kết cụ thể, bạn có thể sử dụng tùy chọn git 2.9 mới (tháng 6 năm 2016) git format-patch --base

git format-patch --base=COMMIT_VALUE~ -M -C COMMIT_VALUE~..COMMIT_VALUE

# or
git format-patch --base=auto -M -C COMMIT_VALUE~..COMMIT_VALUE

# or
git config format.useAutoBase true
git format-patch -M -C COMMIT_VALUE~..COMMIT_VALUE

Xem cam kết bb52995 , cam kết 3de6651 , cam kết fa2ab86 , cam kết dep2c09 (ngày 26 tháng 4 năm 2016) của Xiaolong Ye (``) .
(Được hợp nhất bởi Junio ​​C Hamano - gitster- trong cam kết 72ce3ff , ngày 23 tháng 5 năm 2016)

format-patch: thêm --basetùy chọn '' để ghi thông tin cây cơ sở

Người bảo trì hoặc người kiểm tra bên thứ ba có thể muốn biết chính xác cây cơ sở mà loạt bản vá áp dụng. Dạy định dạng git-patch a '--base tùy chọn '' để ghi thông tin cây cơ sở và nối nó vào cuối tin nhắn đầu tiên (có thể là thư xin việc hoặc bản vá đầu tiên trong chuỗi).

Thông tin cây cơ sở bao gồm "cam kết cơ sở", là một cam kết nổi tiếng là một phần của phần ổn định của lịch sử dự án mà mọi người khác làm việc và không có hoặc nhiều "bản vá tiên quyết", nổi tiếng các bản vá trong chuyến bay chưa phải là một phần của "cam kết cơ sở" cần được áp dụng trên đầu trang của "cam kết cơ sở" theo thứ tự tôpô trước khi các bản vá có thể được áp dụng.

"Cam kết cơ sở" được hiển thị là " base-commit:" theo sau là 40-hex của tên đối tượng cam kết.
Một "bản vá tiên quyết" được hiển thị là " prerequisite-patch-id:" theo sau là "id patch" 40-hex, có thể thu được bằng cách chuyển bản vá thông qua git patch-id --stablelệnh "".


Git 2.23 (Q3 2019) sẽ cải thiện điều đó, bởi vì --basetùy chọn "" của " format-patch" đã tính toán các patch-idsbản vá tiên quyết theo cách không ổn định, đã được cập nhật để tính toán theo cách tương thích với " git patch-id --stable".

Xem cam kết a8f6855 , cam kết 6f93d26 (26 tháng 4 năm 2019) của Stephen Boyd ( akshayka) .
(Được hợp nhất bởi Junio ​​C Hamano - gitster- trong cam kết 8202d12 , ngày 13 tháng 6 năm 2019)

format-patch: làm cho --base patch-idđầu ra ổn định

Chúng tôi không xóa bối cảnh mỗi khi chúng tôi xử lý một patch-idđoạn mã trong mã thế hệ diff.c, nhưng chúng tôi đã làm điều đó khi chúng tôi tạo ra các bản vá lỗi "ổn định" bằng patch-idcông cụ ''.

Chúng ta hãy chuyển logic tương tự từ đó patch-id.csang diff.cđể chúng ta có thể có cùng hàm băm khi chúng ta tạo id-patch cho format-patch --base=các loại lệnh ''.


Trước Git 2.24 (Q4 2019), " git format-patch -o <outdir>" đã làm tương đương với " mkdir <outdir>" không " mkdir -p <outdir>", điều này đang được sửa chữa.

Xem cam kết edefc31 (ngày 11 tháng 10 năm 2019) của Bert Wesarg ( bertwesarg) .
(Được hợp nhất bởi Junio ​​C Hamano - gitster- trong cam kết F1afbb0 , ngày 18 tháng 10 năm 2019)

format-patch: tạo các thành phần hàng đầu của thư mục đầu ra

Đã ký tắt: Bert Wesarg

'git format-patch -o' đã tương đương với 'mkdir' chứ không phải 'mkdir -p', đang được sửa.

Tránh sử dụng ' adjust_shared_perm' trên các thư mục hàng đầu có thể có ý nghĩa bảo mật. Đạt được bằng cách tạm thời vô hiệu hóa ' config.sharedRepository' like ' git init'.


Với Git 2.25 (Q1 2020), " git rebase" không hoạt động tốt khi format.useAutoBasebiến cấu hình được đặt, đã được sửa.

Xem cam kết cae0bc0 , cam kết 945dc55 , cam kết 700e006 , cam kết a749d01 , cam kết 0c47e06 (04 tháng 12 năm 2019) của Denton Liu ( Denton-L) .
(Được hợp nhất bởi Junio ​​C Hamano - gitster- trong cam kết 71a7de7 , ngày 16 tháng 12 năm 2019)

rebase: Sửa chữa format.useAutoBasevỡ

Báo cáo: Christian Biesinger
Đã ký: Denton Liu

Với format.useAutoBase = true, chạy rebase dẫn đến một lỗi:

fatal: failed to get upstream, if you want to record base commit automatically,
please use git branch --set-upstream-to to track a remote branch.
Or you could specify base commit by --base=<base-commit-id> manually
error:
git encountered an error while preparing the patches to replay
these revisions:

ede2467cdedc63784887b587a61c36b7850ebfac..d8f581194799ae29bf5fa72a98cbae98a1198b12

As a result, git cannot rebase them.

Khắc phục sự cố này bằng cách luôn chuyển --no-basesang bản vá định dạng từ rebase để hiệu ứng format.useAutoBasebị phủ nhận.


8

Để tạo đường dẫn từ một cam kết cụ thể (không phải là cam kết cuối cùng):

git format-patch -M -C COMMIT_VALUE~1..COMMIT_VALUE

5

nếu bạn chỉ muốn tìm khác biệt tệp đã chỉ định, bạn có thể:

git diff master 766eceb - các kết nối /> 000-mysql-Connector.patch


0

Với nền tảng đồng bóng của tôi, tôi sẽ sử dụng:

git log --patch -1 $ID > $file

Nhưng tôi đang xem xét sử dụng git format-patch -1 $IDngay bây giờ.


-5

Cách để tạo một bản vá chỉ cho SHA1 cụ thể là gì?

Nó khá đơn giản:

Lựa chọn 1. git show commitID > myFile.patch

Lựa chọn 2. git commitID~1..commitID > myFile.patch

Lưu ý: Thay thế commitIDbằng id cam kết thực tế (mã xác nhận SHA1).


3
Phương án 1 hoàn toàn sai và không liên quan đến câu hỏi.
Anshuman Manral

3
Tùy chọn 2 cũng là một lệnh không hợp lệ. Bạn sẽ nhận được các lỗi như: git a5f4bcab7fa7de27ae79 Xem 'git - trợ giúp'. Kiểm tra lời cầu xin trước khi đăng câu trả lời
Anshuman Manral
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.