2009-03-05 18 views
144

Tôi đã có tám cam kết trên một chi nhánh mà tôi muốn gửi email cho một số người chưa git giác ngộ, được nêu ra. Cho đến nay, mọi thứ tôi làm hoặc là cung cấp cho tôi 8 tệp vá, hoặc bắt đầu cho tôi các tệp vá cho mọi cam kết trong lịch sử của chi nhánh, kể từ khi bắt đầu. Tôi đã sử dụng git rebase --interactive để đè bẹp các cam kết, nhưng bây giờ mọi thứ tôi cố gắng mang lại cho tôi hàng tỷ bản vá lỗi từ đầu. Tôi đang làm gì sai?Làm thế nào để bạn squash cam kết thành một bản vá với git định dạng-patch?

git format-patch master HEAD # yields zillions of patches, even though there's 
          # only one commit since master 
+0

Tôi tò mò về phương pháp bạn sẽ sử dụng trong số các mệnh đề bên dưới. Hãy cho chúng tôi biết;) – VonC

+3

Tôi sẽ sử dụng git diff theo đề xuất của Rob Di Marco. Nhưng tôi nghỉ việc trong hai tuần, vừa mới chứng kiến ​​sự ra đời của bé gái thứ hai của tôi tối qua, vì vậy nó sẽ được một thời gian trước khi tôi sử dụng nó! :) – skiphoppy

+2

Tôi rất thích xem git format-patch --squash master HEAD – schoetbi

Trả lời

168

Tôi khuyên bạn nên thực hiện điều này trên một nhánh chi nhánh như sau. Nếu các cam kết của bạn nằm trong nhánh "dòng mới" và bạn đã chuyển trở lại nhánh "chính" của mình, bạn nên thực hiện thủ thuật:

[[email protected] example (master)]$ git checkout -b tmpsquash 
Switched to a new branch "tmpsquash" 

[[email protected] example (tmpsquash)]$ git merge --squash newlines 
Updating 4d2de39..b6768b2 
Fast forward 
Squash commit -- not updating HEAD 
test.txt | 2 ++ 
1 files changed, 2 insertions(+), 0 deletions(-) 

[[email protected] example (tmpsquash)]$ git commit -a -m "My squashed commits" 
[tmpsquash]: created 75b0a89: "My squashed commits" 
1 files changed, 2 insertions(+), 0 deletions(-) 

[[email protected] example (tmpsquash)]$ git format-patch master 
0001-My-squashed-commits.patch 

Hy vọng điều này sẽ hữu ích!

+2

Đây là những gì tôi sử dụng khi tôi muốn giữ lịch sử cục bộ (trong trường hợp tôi cần chỉnh sửa bản vá). Nếu không, tôi chỉ sử dụng rebase -i và squash các cam kết. – sebnow

+1

giải pháp tốt nhất! cảm ơn :) – kkudi

+5

đối với tôi, nó hoạt động đáng tin cậy hơn với 'git comit -m" Các cam kết bị đè bẹp của tôi "" nếu không nó sẽ thêm các tập tin không được trả lời khác – Sebastian

18

Như bạn đã biết, git format-patch -8 HEAD sẽ cung cấp cho bạn 8 bản vá.

Nếu bạn muốn 8 cam kết của bạn xuất hiện như là một, và không nhớ viết lại lịch sử của chi nhánh của bạn (o-o-X-A-B-C-D-E-F-G-H), bạn có thể:

git rebase -i 
// squash A, B, C, D, E ,F, G into H 

hay, và nó sẽ là một giải pháp tốt hơn, replay tất cả 8 cam kết của bạn từ X (cam kết trước 8 cam kết của bạn) trên một chi nhánh mới

git branch delivery X 
git checkout delivery 
git merge --squash master 
git format-patch HEAD 

Bằng cách đó, bạn chỉ có một cam kết trên "giao hàng" chi nhánh, và nó đại diện cho tất cả 8 c cuối cùng của bạn ommits

+0

'git merge master' chỉ đơn giản là tiến nhanh về phía trước và không đè nén cam kết thành một. Thay đổi thành 'git merge --squash master' để nhận tất cả các commit bị đè bẹp và hiển thị trong vùng được tổ chức. Luồng của bạn sẽ hoạt động với thay đổi này. (Tôi đang sử dụng phiên bản git 2.1.0.) – Stunner

+0

@Stunner điểm tốt. Tôi đã chỉnh sửa câu trả lời. – VonC

21

tôi luôn luôn sử dụng git diff như vậy trong ví dụ của bạn, một cái gì đó giống như

git diff master > patch.txt 
+14

Trừ khi bạn mất tất cả thông báo cam kết và siêu dữ liệu. Vẻ đẹp của git định dạng-vá là nó có thể tái tạo lại toàn bộ chi nhánh từ một tập hợp các bản vá lỗi. – mcepl

+0

phương thức create-branch-and-squash có lợi ích khi kết hợp tất cả các thông điệp cam kết thành một, nhưng phương thức này nhanh hơn nhiều nếu bạn muốn viết thông điệp cam kết của riêng bạn – woojoo666

+0

thực sự, một thông điệp kết hợp có thể được thực hiện bằng cách sử dụng 'git log ', xem [câu trả lời của tôi] (http://stackoverflow.com/a/32373193/1852456) cho một ví dụ – woojoo666

120

Chỉ cần thêm giải pháp một hơn để nồi: Nếu bạn sử dụng này để thay thế:

git format-patch master --stdout > my_new_patch.diff 

Sau đó, nó sẽ vẫn còn 8 bản vá lỗi ... nhưng tất cả chúng sẽ nằm trong một bản vá duy nhất và sẽ áp dụng như một bản vá với:

git am < my_new_patch.diff 
+13

Tôi thích giải pháp này. Nó là giá trị thông báo rằng nó có thể tạo ra đôi khi một bản vá lớn hơn nhiều so với phương pháp được mô tả bởi @ Adam Alexander. Điều này là do một số tệp có thể được chỉnh sửa nhiều lần thông qua các cam kết. Phương pháp này xử lý riêng từng cam kết, ngay cả khi một số tệp đã được hoàn nguyên. Nhưng hầu hết thời gian này không phải là một vấn đề. – gumik

+1

Tùy chọn này rất tuyệt nếu bạn đang cố gắng tránh hợp nhất! (ví dụ: bạn muốn bỏ qua một số cam kết). Bạn vẫn có thể 'git rebase -i ...' và đè bẹp tất cả chúng xuống một. –

17

Đây là một sự thích ứng của Adam Alexander, trong trường hợp thay đổi của bạn nằm trong nhánh chính. Đây làm như sau:.

  • Tạo mới throwaway nhánh "tmpsquash" theo quan điểm chúng tôi muốn (tìm kiếm chìa khóa SHA chạy "git --log" hoặc với gitg Chọn cam bạn muốn trở thành người đứng đầu tmpsquash , các cam kết mà sau đó trong tổng thể sẽ là cam kết đè bẹp).
  • Hợp nhất các thay đổi từ chính thành tmpsquash.
  • Cam kết các thay đổi bị đè bẹp thành tmpsquash.
  • Tạo bản vá với các cam kết bị đè bẹp.
  • Goes trở lại chi nhánh chủ

[email protected]:~/example (master)$ git branch tmpsquash ba3c498878054e25afc5e22e207d62eb40ff1f38 
[email protected]:~/example (master)$ git checkout tmpsquash 
Switched to branch 'tmpsquash' 
[email protected]:~/example (tmpsquash)$ git merge --squash master 
Updating ba3c498..40386b8 
Fast-forward 
Squash commit -- not updating HEAD 

[snip, changed files] 

11 files changed, 212 insertions(+), 59 deletions(-) 
[email protected]:~/example (tmpsquash)$ git commit -a -m "My squashed commits" 
[test2 6127e5c] My squashed commits 
11 files changed, 212 insertions(+), 59 deletions(-) 
[email protected]:~/example (tmpsquash)$ git format-patch master 
0001-My-squashed-commits.patch 
[email protected]:~/example (tmpsquash)$ git checkout master 
Switched to branch 'master' 
[email protected]:~/example (master)$ 
+0

Thực hiện các thay đổi trong chế độ chính là chống mẫu nếu bạn không tự đẩy chúng vào điều khiển từ xa. Và nếu bạn muốn, bạn có thể không cần phải tạo ra các tập tin vá lỗi cho họ. –

0

Dựa trên Adam Alexander trả lời:

git checkout newlines 
## must be rebased to master 
git checkout -b temporary 
# squash the commits 
git rebase -i master 
git format-patch master 
4

Format-vá giữa hai thẻ:

git checkout <source-tag> 
git checkout -b <tmpsquash> 
git merge --squash <target-tag> 
git commit -a -m "<message>" 
git format-patch <source-tag> 
4

Cách dễ nhất là để sử dụng git diff, một nd thêm vào git log nếu bạn muốn thông báo cam kết kết hợp rằng phương thức squash sẽ xuất ra. Ví dụ, để tạo ra các bản vá giữa cam kết abcd1234:

git diff abcd..1234 > patch.diff 
git log abcd..1234 > patchmsg.txt 

Sau đó, khi áp dụng các bản vá:

git apply patch.diff 
git add -A 
git reset patch.diff patchmsg.txt 
git commit -F patchmsg.txt 

Đừng quên --binary lập luận để git diff khi giao dịch với các tập tin phi văn bản, ví dụ hình ảnh hoặc video.

Các vấn đề liên quan