2010-02-19 28 views
9

Tôi muốn chia nhỏ các mô-đun được phân phối với ứng dụng lớn hơn thành các mô-đun con riêng biệt và giữ khả năng kéo từ phía trên.Lặp lại sử dụng git-filter-branch để ghi lại các cam kết mới

Vì vậy, điều này phức tạp hơn Detach subdirectory into separate Git repository. Tôi không chỉ sử dụng git-filter-branch một lần mà còn muốn giữ khả năng kéo các thay đổi ngược dòng sau khi đã thực hiện (và ngược dòng thì không).

Đơn giản chỉ cần chạy lại git-filter-branch trên toàn bộ lịch sử từ thượng nguồn, bao gồm các cam kết mới không tìm thấy trong lịch sử viết lại của tôi không phải là một tùy chọn vì có hàng trăm mô-đun mà tôi phải làm điều này và số lần commit nhận được gần 100.000. Tôi đoán điều này liên quan đến việc hạn chế lịch sử chỉ với các cam kết mới, viết lại chúng và sau đó thêm chúng sau khi cam kết viết lại trước đó, nhưng tôi không chắc chắn làm thế nào để làm điều này - và có thể có một cách tiếp cận tốt hơn.

Sẽ rất tuyệt nếu các chi nhánh và thẻ có thể được giữ nguyên nhưng điều này không thực sự cần thiết và nếu nó làm phức tạp những điều tôi thực sự muốn mất chúng.

+0

Tôi cũng muốn biết về việc này. Mỗi khi tôi kéo repo phụ thuộc, tôi phải chạy lại nhánh lọc để đưa các bản cập nhật vào dự án của tôi (tôi không muốn hợp nhất toàn bộ repo). –

+0

Tôi đã rất ngạc nhiên khi không có ai đưa ra câu trả lời, sau khi tất cả mọi chuyện diễn ra như một thử thách thú vị. Vâng, tôi đã tự mình hack một thứ gì đó nhưng quên đăng nó ở đây. Sở thích của bạn đã nhắc tôi - dưới đây là giải pháp của tôi. – tarsius

+2

Bạn đã từng xem [* git subtree *] chưa (http://github.com/apenwarr/git-subtree/blob/master/git-subtree.txt)? Nó có thể tách ra một cây con thành một nhánh mới và, với tùy chọn '--rejoin', làm điều đó theo kiểu tăng dần. –

Trả lời

8

Đối rebase đầu tiên làm điều này:

git checkout -b rebased master 
git filter-branch --some-filter 
git tag rebased-done master 

Và để "hợp nhất" sau cam kết:

# Create a tempory branch and rebase it's tail use 'rebase-done~' 
# and not 'rebase-done' because some filters (like --index-filter) 
# require this, others might not. 
git checkout -b rebased-tail master 
git filter-branch -f --some-filter -- rebased-done~..HEAD 

# Get the commit in branch 'rebased' corresponding to tag 'rebase-done' 
# (which tags a commit in 'master' not 'rebased'). Depending on your 
# situation you might have to determine this commit differently (in my 
# use case I am absolutely sure that there is never a commit with the 
# same author date - if that doesn't work you might want to compare 
# commit messages). 
start_time=$(git show --quiet --pretty=%at rebased-done) 
start_hash=$(
git log --reverse --pretty="%H %at" rebased_tail | 
while read hash time 
do 
    [ "$time" = "$start_time" ] && echo $hash && break 
done 
) 

# Finally apply the rebased commits. 
git checkout rebased 
git format-patch -k --stdout $start_hash..rebased-tail | git am -k 
git branch -D rebased-tail 
git tag -f rebased-done master 
Các vấn đề liên quan