2010-11-11 32 views
8

Tôi có tình huống sau: Tôi đã thực hiện một số cam kết với kho lưu trữ cục bộ của mình, và sau đó hợp nhất rất lớn một nhánh khác (~ 150 commit) vào master - nó có rất nhiều xung đột trong đó.Làm thế nào để sử dụng git rebase -i sau khi git merge mà không làm rối tung mọi thứ?

Bây giờ, tôi muốn di chuyển một cam kết tôi đã thực hiện trước khi hợp nhất để được sau khi nó trước khi đẩy.

Thông thường, tôi sẽ sử dụng "rebase -i" cho nó. Thật không may, hành vi mặc định là phá vỡ cam kết hợp nhất tôi đã thực sự thêm 150 cam kết để làm chủ vào các cam kết riêng biệt (tôi hiểu nó giống như tôi sẽ sử dụng rebase thay vì hợp nhất để bắt đầu) - mà là hành vi xấu đối với tôi vì nhiều lý do.

Tôi đã phát hiện ra cờ '-p' để rebase, giữ lại các hợp nhất và rất hài lòng về nó. Thật không may, điều này thực sự áp dụng cùng một hợp nhất một lần nữa, và quên tất cả về công việc khó khăn của tôi trong việc giải quyết xung đột. Một lần nữa - hành vi xấu!

Có giải pháp cho những gì tôi muốn không? Sử dụng rebase -i sau khi hợp nhất để sắp xếp lại hoặc chỉnh sửa các cam kết cụ thể mà không phải lặp lại các hoạt động sau hợp nhất của tôi?

Cảm ơn!

+2

Bạn đã xem [git rerere] (http://www.kernel.org/pub/software/scm/git/docs/git-rerere.html) chưa? –

+2

'git rerere' không thể giúp bạn ngay bây giờ, vì nó ghi lại độ phân giải xung đột khi bạn cam kết hợp nhất ... ngoại trừ có một tập lệnh gọi là [rerere-train.sh] (http://git.kernel.org/? p = git/git.git; a = blob; f = contrib/rerere-train.sh; hb = HEAD) trong thư mục contrib của git mà "primes" cơ sở dữ liệu định tuyến lại từ các cam kết hợp nhất mà bạn đã thực hiện. – Cascabel

Trả lời

13

Đây là đoạn mã rerere-train.sh Tôi đã đề cập trong nhận xét của mình - về cơ bản nó làm lại quá trình hợp nhất, sử dụng độ phân giải của bạn và chỉ cho phép đọc lại nó. Bạn có thể làm điều này bằng tay chỉ dành riêng cho duy nhất của bạn cam kết nếu bạn thích:

git checkout <parent of merge commit> 
git merge <merged commit>   # if this goes cleanly, we're done 
git rerere      # done automatically if rerere.enabled is true 
git checkout <merge commit> -- . # check out the files from the result of the merge 
git rerere      # done automatically if rerere.enabled is true 
git reset --hard     # wipe away the merge 

# and you'd want to follow with git checkout <branch> to return to where you were 

Nhưng bạn cũng có thể chỉ cần đặt rerere.enabled true, và làm những bước trừ các cuộc gọi trực tiếp đến git rerere - và bạn muốn được thiết lập trong trong tương lai, với định tuyến lại tự động được chạy bất cứ khi nào bạn giải quyết xung đột. Đây là những gì tôi làm - thật tuyệt vời.

Nếu bạn muốn chạy tập lệnh trực tiếp, có thể bạn sẽ muốn chạy tập lệnh với các đối số như rerere-train.sh ^<commit before the merge> <current branch>. (Ký hiệu ^commit có nghĩa là "không đi ngang qua đây vào lịch sử", vì vậy nó sẽ không bận tâm làm điều này cho tất cả hợp nhất cam kết trong repo của bạn.)

Tuy nhiên bạn sẽ có được rerere để làm điều này, bạn nên kết thúc với độ phân giải mong muốn được ghi lại. Điều đó có nghĩa là bạn có thể tiếp tục và thực hiện rebase -i của mình, và khi bạn gặp phải xung đột, thì rerere sẽ sử dụng RESolution. Chỉ cần một head-up: nó vẫn còn để lại các tập tin đánh dấu là mâu thuẫn trong chỉ mục, để bạn có thể kiểm tra chúng, và chắc chắn rằng những gì nó đã làm cho tinh thần. Khi bạn đã thực hiện xong, hãy sử dụng git add để kiểm tra xem liệu bạn có tự giải quyết xung đột hay không và tiếp tục như bình thường!

git-rerere manpage chứa một mô tả rất đẹp, dài về sử dụng bình thường của định tuyến lại, không bao giờ thực sự liên quan đến việc gọi lại - tất cả được thực hiện tự động. Và một lưu ý rằng nó không nhấn mạnh: tất cả đều dựa trên những mâu thuẫn xung đột, vì vậy nó có thể tái sử dụng độ phân giải ngay cả khi xung đột kết thúc ở một nơi hoàn toàn khác, miễn là nó vẫn xung đột văn bản.

+0

Chà, điều này trông giống như git-fu nghiêm túc! – Benjol

+0

@Benjol: Giải quyết xung đột là hoạt động kinh doanh nghiêm túc! (Nhưng nó không thực sự đáng sợ - chỉ cần kích hoạt lại trong cấu hình và để cho phép thuật xảy ra.) – Cascabel

+0

Trang quản lý git-rerere được liên kết hiện không tìm thấy 404. – Jez

1

Tôi đã tạo một tập lệnh để thực hiện việc này here. Xem open issues để biết các giới hạn đã biết.

Trước tiên, bạn cần cài đặt rerere-train.sh vào PATH của mình.Trên Fedora, điều này có thể được thực hiện với:

install "$(rpm -ql git|grep '/rerere-train.sh$')" ~/bin 
0

Tôi đã sử dụng rerere-train.sh từ câu trả lời của người dùng @ Jefromi. Tuy nhiên tôi có lỗi này:

$ ../rerere-train.sh HEAD 
C:\Program Files\Git\mingw64/libexec/git-core/git-sh-setup: line 6: .: git-sh-i18n: file not found 

Từ http://kernel.opensuse.org/cgit/kernel-source/commit/?h=linux-next&id=d52b9f00588bb18d7f7a0e043eea15e6c27ec40c này, tôi thấy điều này:

Michal Marek

The git-sh-setup helper has apparently never been meant to be used by scripts outside of git. This became apparent with git 2.10:

Sau downloading an older version - 2.3.4 xách tay - Tôi quản lý để làm rerere-train.sh làm việc.

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