Tôi có thể có được một đầu ra tương thích với bản vá từ git-diff không?


160

Tôi đang làm một cái gì đó rất đơn giản sai. Tôi đang cố gắng chuẩn bị một tệp vá thông thường, vì vậy tôi có thể áp dụng lại một số thay đổi:

$ git diff > before
$ git diff something_here > save.patch
$ git checkout . 
$ patch < save.patch
$ git diff > after
$ diff before after
$

Với something_here trống nó gần như hoạt động, nhưng tên tệp không đúng. Tôi nghĩ rằng tôi chỉ thiếu một số tùy chọn.

Trong cuộc sống thực, tôi sẽ thực hiện hợp nhất sau khi thanh toán, vì vậy bản vá có thể thất bại ở đó, nhưng bạn thấy những gì tôi đang làm.

Chỉnh sửa lỗi của tôi ở đây để đặt câu hỏi sai. Câu hỏi thực tế là, tôi muốn lưu các thay đổi của mình đi, thực hiện hợp nhất, sau đó áp dụng lại các thay đổi, nếu có thể? Tôi đã hỏi nó sai cách vì tôi đã quen sử dụng bản vá để giải quyết các loại vấn đề này và có git diffvẻ như đó là những gì nó muốn tôi làm.

Nhận xét của Charles Bailey đã có câu trả lời đúng. Đối với tôi, git-application là điều nên làm (git-stash trông có trọng lượng nặng hơn tôi cần và nổi loạn và các gói chắc chắn vượt quá mức kỹ năng hiện tại của tôi.) Tôi sẽ chấp nhận câu trả lời mà Charles đưa ra (vì bạn không thể chấp nhận một bình luận). Cảm ơn tất cả những lời đề nghị.

Chỉnh sửa, 6 năm sau Như bất kỳ ai quen thuộc với chủ đề này đều biết, tôi đã ước tính quá mức độ khó của git stash. Khá nhiều mỗi ngày hoặc lâu hơn, tôi sẽ sử dụng trình tự sau:

$ git stash
$ git merge
$ git stash pop

8
Có bất kỳ lý do bạn đặc biệt muốn sử dụng patchhơn là git apply?
CB Bailey

3
Và thậm chí sau đó, bạn có thực sự cần các bản vá hơn là một cái gì đó như git stashhoặc các công cụ git khác?
CB Bailey

3
Sau chỉnh sửa, tôi nghĩ đó git stashlà giải pháp dễ nhất cho những gì bạn đang cố gắng thực hiện, nhưng có rất nhiều cách tiếp cận hiệu quả.
CB Bailey

1
@Malvolio: Thật vậy, bạn thậm chí không phải nghĩ đến một tên tệp tạm thời để lưu trữ bản vá của mình.
CB Bailey

4
@Charlse, đôi khi bạn cần gửi một bản vá cho ai đó mà không có toàn bộ kho git. Ví dụ nếu sử dụng git-svn.
Elazar Leibovich

Câu trả lời:


139

Nếu bạn muốn sử dụng bản vá, bạn cần xóa các a/ b/tiền tố mà git sử dụng theo mặc định. Bạn có thể làm điều này với --no-prefixtùy chọn (bạn cũng có thể làm điều này với -ptùy chọn của patch ):

git diff --no-prefix [<other git-diff arguments>]

Thông thường, nó dễ dàng hơn để sử dụng thẳng git diffvà sau đó sử dụng đầu ra để cung cấp cho git apply.

Hầu hết thời gian tôi cố gắng tránh sử dụng các bản vá văn bản. Thông thường, một hoặc nhiều cam kết tạm thời kết hợp với rebase git stashvà các gói dễ quản lý hơn.

Đối với trường hợp sử dụng của bạn, tôi nghĩ rằng đó stashlà thích hợp nhất.

# save uncommitted changes
git stash

# do a merge or some other operation
git merge some-branch

# re-apply changes, removing stash if successful
# (you may be asked to resolve conflicts).
git stash pop

7
git diff --no-prefix master > diff.patchvà sau đógit checkout master patch -p0 < diff.patch
Natim

1
@Natim Để đảm bảo an toàn tối đa, tôi khuyên bạn nên sử dụng patch --dry-run < diff.patchtrước khi ban hành lệnh cuối cùng.
ᴠɪɴᴄᴇɴᴛ

1
@ lợi ích của việc đó là gì? Vì chúng tôi đang sử dụng git, chúng tôi không thể mất bất cứ thứ gì phải không?
Natim

1
@Natim Như tôi đã nói, chỉ cần an toàn tối đa, không cần hoàn tác bất cứ điều gì trong trường hợp có lỗi. Tôi cũng đã suy nghĩ về những người đọc nó và muốn sử dụng patchbên ngoài git (có thể sử dụng tệp vá được tạo bởi diff) trong trường hợp sử dụng chung hơn.
ᴠɪɴᴄᴇɴᴛ

Để bao gồm mới tập tin trong bản vá của bạn, bạn cần phải cũng bao gồm "git diff --no-prefix --cached" trong bản vá. Có lẽ có một cách tốt hơn?
Jamshid

219

Sử dụng chỉ -p1: bạn sẽ cần phải sử dụng -p0trong --no-prefixtrường hợp nào, vì vậy bạn chỉ có thể bỏ qua --no-prefixvà sử dụng -p1:

$ git diff > save.patch
$ patch -p1 < save.patch

$ git diff --no-prefix > save.patch
$ patch -p0 < save.patch

1
Nếu bạn đang tự hỏi tại sao, người đàn ông tài liệu tổng hợp nó một cách độc đáo - nguồn .
tutuDajuju

3
Điều này sẽ không hoạt động với đổi tên; git diffxuất ra một dòng mà patchbỏ qua. git applylà con đường để đi
hraban

17

Các khác biệt git có một phân đoạn đường dẫn bổ sung được thêm vào các đường dẫn tệp. Bạn có thể loại bỏ mục này trong đường dẫn bằng cách chỉ định -p1 bằng bản vá, như vậy:

patch -p1 < save.patch

10
  1. Tôi lưu khác biệt của thư mục hiện tại (bao gồm các tệp không được cam kết) so với CHÍNH hiện tại.
  2. Sau đó, bạn có thể vận chuyển save.patchtệp đến bất cứ nơi nào (bao gồm các tệp nhị phân).
  3. Trên máy mục tiêu của bạn, áp dụng bản vá bằng cách sử dụng git apply <file>

Lưu ý: đó là khác biệt các tập tin hiện đang dàn dựng.

$ git diff --binary --staged HEAD > save.patch
$ git reset --hard
$ <transport it>
$ git apply save.patch

Hahaha. Điều đó thật buồn cười. Tôi đã hỏi câu hỏi này gần bốn năm trước và cách tôi đã làm điều này đã phát triển nhưng nếu bạn hỏi tôi ngày hôm qua làm thế nào, tôi sẽ đưa ra câu trả lời của bạn và nói rằng tôi đã nhận được nó từ câu trả lời cho câu hỏi này. (Trên thực tế tôi có thể sẽ sử dụng trần git diff > save.patchgit checkout .thay vì thiết lập lại, nhưng vâng ...
Malvolio

Oh đã không nhận thấy 4 tuổi của nó: P. Btw, thiết lập lại chỉ để chứng minh rằng nó hoạt động .. Tôi cũng không thấy bất cứ ai sử dụng git applyhoặc làm cho khác biệt liên quan đến trạng thái của bạn và con trỏ đến cam kết cuối cùng có sẵn. Làm chỉ git diffđã không làm bất cứ điều gì ở tất cả
Matej

Vâng, bây giờ tôi tự hỏi làm thế nào tôi phát hiện ra git apply. Vấn đề với git diff(tôi nghĩ) từ việc sử dụng git reset- các mối quan hệ giữa repo, chỉ mục và khu vực làm việc là vấn đề.
Malvolio

8

Một mẹo hữu ích để tránh tạo các tệp vá tạm thời:

git diff | patch -p1 -d [dst-dir]

Chính xác những gì tôi muốn. Cũng hoạt động hoàn hảo với stash! git stash show -p stash@{3} | patch -p1 -d [dst-dir]
dtmland
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.