2010-09-12 27 views
310

Trong Git, có cách nào hợp nhất tất cả các thay đổi từ một chi nhánh này sang nhánh khác, nhưng bí danh với một lần commit duy nhất cùng một lúc?Hợp nhất tất cả các thay đổi từ một nhánh khác dưới dạng một cam kết đơn

Tôi thường làm việc trên một tính năng mới trong một chi nhánh riêng và thường xuyên cam kết/đẩy - chủ yếu để sao lưu hoặc chuyển những gì tôi đang làm việc cho một máy khác. Chủ yếu là những cam kết nói "Tính năng xxx WIP" hoặc một cái gì đó dư thừa.

Khi công việc đã hoàn tất và tôi muốn hợp nhất chi nhánh WIP thành chính, tôi muốn loại bỏ tất cả các cam kết trung gian đó, và chỉ có một cam kết sạch duy nhất.

Có cách nào dễ dàng để thực hiện việc này không?

Cách khác, làm thế nào về lệnh làm đổ tất cả các cam kết trên một nhánh kể từ điểm được phân nhánh?

Trả lời

403

Một tùy chọn khác là git merge --squash <feature branch> sau đó cuối cùng cũng làm git commit.

Từ Git merge

--squash

--no-squash

Sản xuất cây và chỉ số trạng thái làm việc như thể một merge thực xảy ra (trừ trường hợp hợp nhất thông tin), nhưng không thực sự làm cam kết hoặc di chuyển HEAD, cũng không ghi lại $GIT_DIR/MERGE_HEAD để gây ra anh ấy tiếp theo git commit lệnh để tạo hợp nhất cam kết. Điều này cho phép bạn tạo một cam kết đơn trên đầu trang của chi nhánh hiện tại có hiệu lực giống như sáp nhập một chi nhánh khác (hoặc nhiều hơn trong trường hợp trường hợp bạch tuộc).

+0

Tính năng tuyệt vời! Tôi yêu git. Trong khi tôi ' chắc chắn sẽ sử dụng điều này trong tương lai, tôi vẫn khuyên bạn nên biết cách của bạn xung quanh rebase -i Đó là một kỹ năng tốt để có, chỉ trong trường hợp bạn thực sự muốn làm cho họ nhiều hơn chỉ là một cam kết –

+2

A Vấn đề là nó trông giống như định dạng mà bạn thường thấy khi toàn bộ văn bản được hiển thị không thực sự trở thành một phần của thông báo cam kết, nhưng trong Vì vậy, nếu bạn không muốn tất cả những điều đó, bạn cần tự xóa tất cả thông tin đó khỏi thư cam kết của bạn. Tôi nên thử nghiệm điều này trước khi sử dụng nó ... –

+5

Điều đó, và, được cảnh báo rằng chi nhánh sẽ không được xem là đã hợp nhất. ttp: //stackoverflow.com/questions/19308790/git-branch-merged-no-merged-and-squash-option – rxgx

-5

Bạn có thể thực hiện việc này bằng lệnh "rebase". Hãy gọi các ngành "chính" và "tính năng":

git checkout feature 
git rebase main 

Lệnh rebase sẽ phát lại tất cả các cam kết về "tính năng" là một cam kết với cha mẹ bằng "chính".

Bạn có thể muốn chạy git merge main trước git rebase main nếu "chính" đã thay đổi vì "đối tượng địa lý" đã được tạo (hoặc từ lần hợp nhất gần đây nhất). Bằng cách đó, bạn vẫn có lịch sử đầy đủ của mình trong trường hợp bạn có xung đột hợp nhất.

Sau rebase, bạn có thể hợp nhất chi nhánh của bạn to main, mà nên kết quả trong việc kết hợp với nhanh về phía trước:

git checkout main 
git merge feature 

Xem rebase trang của Understanding Git Conceptually cho một cái nhìn tổng quan tốt

+0

Điều này không hiệu quả đối với tôi. Tôi vừa tạo ra một repo thử nghiệm đơn giản, với một nhánh WIP và đã thử các bên trên và có các xung đột hợp nhất (mặc dù tôi đã không thực hiện bất kỳ thay đổi nào trên master). –

+0

Nếu tính năng được tạo từ chính (git checkout -b tính năng chính) và bạn đã có một hợp nhất gần đây từ chính, bạn không nên nhận được xung đột từ rebase – NamshubWriter

+0

OK, đã thử lại. Không có xung đột lần này, nhưng lịch sử không bị đè bẹp. –

19

Hãy thử git rebase -i master trên chi nhánh tính năng của bạn. Sau đó bạn có thể thay đổi tất cả, nhưng một 'chọn' thành 'bíp' để kết hợp các cam kết. Xem squashing commits with rebase

Cuối cùng, bạn có thể thực hiện hợp nhất từ ​​nhánh chính.

+5

Có hoạt động, nhưng tôi không muốn gặp rắc rối khi khởi động lại tương tác. Tôi chỉ muốn tất cả mọi thứ kể từ khi chi nhánh phẳng. –

+2

+1 Điều này làm cho một lịch sử sạch sẽ. Việc xác định và quản lý các cam kết dễ dàng hơn như các bản vá lỗi, thẻ, câu chuyện, v.v. – rxgx

165

Tìm thấy nó! Lệnh hợp nhất có một tùy chọn --squash

git checkout master 
git merge --squash WIP 

tại thời điểm này mọi thứ được hợp nhất, có thể xung đột nhưng không được cam kết. Vì vậy, tôi có thể bây giờ:

git add . 
git commit -m "Merged WIP" 
+0

'git add'' làm gì? –

+0

@MichaelPotter Nó thêm tất cả các tệp và thay đổi –

+0

'git add .' thêm tất cả các tệp không bị bỏ qua trong thư mục hiện tại, tôi sẽ cảnh giác với việc chọn các tệp không mong muốn theo cách này. –

-1

git merge --squash <feature branch> là một tùy chọn tốt. "Git commit" cho bạn biết tất cả thông báo chi tiết về tính năng chi nhánh với lựa chọn của bạn để giữ nó.

Đối với ít cam kết hợp nhất.

git hợp nhất làm x lần - mặc định đặt lại HEAD^--soft rồi git commit.

Rủi ro - các tệp đã xóa có thể quay lại.

0

Tôi muốn đè bẹp tất cả các cam kết trong tổng thể của tôi thành một. Tôi cố gắng này không thành công:

$ git checkout --orphan new_master 
$ git merge --squash master 
fatal: Squash commit into empty head not supported yet 

Vì vậy, tôi đã làm điều này:

$ tar cf /tmp/git.tar --exclude .git . 
$ git checkout --orphan new_master 
$ tar xf /tmp/git.tar 
$ git commit -m "Initial commit" 

mà làm việc độc đáo.

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