Tạo một bản vá git từ những thay đổi trong thư mục làm việc hiện tại


879

Nói rằng tôi có những thay đổi không được cam kết trong thư mục làm việc của tôi. Làm thế nào tôi có thể tạo một bản vá từ những người mà không phải tạo một cam kết?


29
Câu trả lời được chấp nhận có lẽ nên được thay đổi, với câu trả lời thứ hai phổ biến hơn gần bốn lần.
Tim Ogilvy

5
@TimOgilvy đồng ý. OP nên làm điều đó. Câu trả lời thứ hai phổ biến hơn nhiều và cung cấp thêm thông tin
John Demetriou

1
Tôi nghĩ rằng đáng để đề cập đến bạn cần bản vá từ những thay đổi không được cam kết trong tiêu đề.
2i3r

Câu trả lời:


401

git diffcho những thay đổi không có căn cứ. git diff --cachedcho các thay đổi theo giai đoạn.


12
yup, git diff là nghịch đảo của git áp dụng
Spike Gronim

33
git format-patchcũng bao gồm khác biệt nhị phân và một số thông tin meta. Trên thực tế đó sẽ là đặt cược tốt nhất để tạo một bản vá, nhưng afaik điều này chỉ hoạt động đối với các nguồn / thay đổi được kiểm tra, phải không?
Eric

20
Đôi khi nó có thể hữu ích để tạo một bản vá liên quan đến thư mục hiện tại. Để đạt được điều này, hãy sử dụnggit diff --relative
ejboy

30
git diff> a.patch để ghi nó vào một tệp
qasimzee

139
Terse giáp với mỉa mai, câu trả lời dưới đây là hữu ích hơn.
Không khí

1865

Nếu bạn chưa cam kết thay đổi, thì:

git diff > mypatch.patch

Nhưng đôi khi điều đó xảy ra là một phần của những thứ bạn đang làm là các tệp mới không bị theo dõi và sẽ không nằm trong git diffđầu ra của bạn . Vì vậy, một cách để thực hiện một bản vá là tạo mọi thứ cho một cam kết mới ( git addmỗi tệp hoặc chỉ git add .) nhưng không thực hiện cam kết, và sau đó:

git diff --cached > mypatch.patch

Thêm tùy chọn 'nhị phân' nếu bạn muốn thêm tệp nhị phân vào bản vá (ví dụ: tệp mp3):

git diff --cached --binary > mypatch.patch

Sau này bạn có thể áp dụng bản vá:

git apply mypatch.patch

Lưu ý: Bạn cũng có thể sử dụng --stagednhư một từ đồng nghĩa của --cached.


128
Cảm ơn bạn rất nhiều cho ví dụ. Trái ngược với câu trả lời được chấp nhận, bạn chỉ ra các lệnh làm thế nào và không chỉ nói. Rất hữu ích và làm việc hoàn hảo đối với tôi :)
Nuala

4
Tôi đã làm chính xác điều đó và nhận được "fatal: không nhận dạng được đầu vào" khi thực hiện git áp dụng. Bất kỳ ý tưởng những gì có thể gây ra điều này và làm thế nào để khắc phục nó?
Vitaly

6
@Vitaly: bản vá của bạn có thể đọc được nếu bạn mở nó bằng trình soạn thảo văn bản không? nó phải sạch sẽ không có ký tự lạ, ví dụ: nếu cài đặt color.diff được đặt, bản vá của bạn sẽ có một số 'ký tự màu' có thể khiến 'git áp dụng' thất bại, trong trường hợp đó hãy thử git diff --no-color. Nếu không, nó trông giống như một vấn đề mã hóa.
jcarballo

3
Liên quan đến "các tệp mới không bị theo dõi": "git diff" và "git diff --cached" chỉ hoạt động nếu "git add <file>" được gọi đầu tiên. (Tôi mới sử dụng git và tự hỏi tại sao tôi luôn có một bản vá trống)
Ẩn danh

5
Điều này đã đưa tôi ra khỏi một địa ngục hợp nhất / nổi loạn khá dễ dàng, cảm ơn :)
John Hunt

86

git diffgit applysẽ làm việc cho các tệp văn bản, nhưng sẽ không hoạt động đối với các tệp nhị phân.

Bạn có thể dễ dàng tạo một bản vá nhị phân đầy đủ, nhưng bạn sẽ phải tạo một cam kết tạm thời. Khi bạn đã thực hiện (các) cam kết tạm thời của mình, bạn có thể tạo bản vá với:

git format-patch <options...>

Sau khi bạn thực hiện bản vá, hãy chạy lệnh này:

git reset --mixed <SHA of commit *before* your working-changes commit(s)>

Điều này sẽ khôi phục (các) cam kết tạm thời của bạn. Kết quả cuối cùng khiến bản sao làm việc của bạn (cố ý) bị bẩn với cùng những thay đổi ban đầu bạn có.

Về phía nhận, bạn có thể sử dụng thủ thuật tương tự để áp dụng các thay đổi cho bản sao làm việc mà không cần có lịch sử cam kết. Đơn giản chỉ cần áp dụng các bản vá, và git reset --mixed <SHA of commit *before* the patches>.

Lưu ý rằng bạn có thể phải được đồng bộ hóa tốt để toàn bộ tùy chọn này hoạt động. Tôi đã thấy một số lỗi khi áp dụng các bản vá khi người thực hiện chúng không kéo theo nhiều thay đổi như tôi có. Có lẽ có nhiều cách để làm cho nó hoạt động, nhưng tôi đã không nhìn sâu vào nó.


Đây là cách tạo các bản vá tương tự trong Rùa Git (không phải tôi khuyên bạn nên sử dụng công cụ đó):

  1. Cam kết thay đổi công việc của bạn
  2. Nhấp chuột phải vào thư mục gốc và nhấp Tortoise Git->Create Patch Serial
    1. Chọn bất kỳ phạm vi nào có ý nghĩa ( Since: FETCH_HEADsẽ hoạt động nếu bạn được đồng bộ hóa tốt)
    2. Tạo các bản vá
  3. Nhấp chuột phải vào thư mục gốc và nhấp Tortise Git->Show Log
  4. Nhấp chuột phải vào cam kết trước (các) cam kết tạm thời của bạn và nhấpreset "<branch>" to this...
  5. Chọn Mixedtùy chọn

Và làm thế nào để áp dụng chúng:

  1. Nhấp chuột phải vào thư mục gốc và nhấp Tortoise Git->Apply Patch Serial
  2. Chọn (các) bản vá chính xác và áp dụng chúng
  3. Nhấp chuột phải vào thư mục gốc và nhấp Tortise Git->Show Log
  4. Nhấp chuột phải vào cam kết trước khi (các) cam kết của bản vá và nhấp vàoreset "<branch>" to this...
  5. Chọn Mixedtùy chọn

5
Về mặt kỹ thuật, điều này không yêu cầu tạo ra một cam kết mà OP yêu cầu tránh, nhưng đó là một cam kết tạm thời và câu trả lời là hữu ích bất kể.
davenpcj

33

Để tạo một bản vá với cả tệp sửa đổi và tệp mới (dàn dựng), bạn có thể chạy:

git diff HEAD > file_name.patch

Cảm ơn, trong trường hợp của tôi, câu trả lời này hoạt động, nhưng git diff --cached > mypatch.patchkhông hoạt động.
khai thác

Tôi có một câu hỏi: có thể file_name.patchđược sử dụng bởi patchlệnh? Chúng có tương thích với nhau không?
Rakshith Ravi

git diff + git diff --cached / staged == git diff HEAD (hiển thị tất cả các thay đổi kể từ lần cam kết cuối cùng)
K. Biểu tượng

20

Tôi thích:

git format-patch HEAD~<N>

trong đó <N>số lần cam kết cuối cùng để lưu dưới dạng các bản vá.

Các chi tiết về cách sử dụng lệnh có trong DOC

CẬP NHẬT
Ở đây bạn có thể tìm thấy làm thế nào để áp dụng chúng sau đó.

CẬP NHẬT Đối với những người không có ý tưởng về format-patch
Thêm bí danh:

git config --global alias.make-patch '!bash -c "cd ${GIT_PREFIX};git add .;git commit -m ''uncommited''; git format-patch HEAD~1; git reset HEAD~1"'

Sau đó, tại bất kỳ thư mục của kho dự án của bạn chạy:

git make-patch

Lệnh này sẽ tạo 0001-uncommited.patchtại thư mục hiện tại của bạn. Bản vá sẽ chứa tất cả các thay đổi và các tệp chưa được theo dõi hiển thị cho lệnh tiếp theo:

git status .

@jcarballo: Tôi đã cập nhật câu trả lời. Hãy thả tôi bất kỳ thông báo nào bạn có.
Eugen Konkov

2
Có một cách đơn giản hơn là tạo ra một cam kết và không phổ biến. git diff --cached --binary
Gaurav Agarwal

9

Nếu bạn muốn làm nhị phân, đưa ra một --binarytùy chọn khi bạn chạy git diff.


0

Chúng tôi cũng có thể chỉ định các tệp, chỉ bao gồm các tệp có thay đổi tương đối, đặc biệt khi chúng mở rộng nhiều thư mục cũ

git diff ~/path1/file1.ext ~/path2/file2.ext...fileN.ext > ~/whatever_path/whatever_name.patch

Tôi thấy điều này không được chỉ định trong các câu trả lời hoặc nhận xét, tất cả đều có liên quan và chính xác, vì vậy đã chọn để thêm nó. Rõ ràng là tốt hơn so với ngầm!

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.