2013-01-24 38 views
8

Giả sử tôi có các tình huống sau:Git rebase subtree

o (master) 
/  o--o (WIP1) 
/ /
o--o--o--o--o--o (WIP2) 
(X)  \ 
      o--o (WIP3) 

Có một câu lệnh git mà tạo ra một chi nhánh mới để nó có chứa các cây con sau khi chi nhánh X? Tôi muốn thực hiện một "rebase lớn", tôi muốn ba nhánh WIP được rebased trên master.

Tôi biết tôi có thể làm điều đó với một số tập lệnh Bash nhưng tôi muốn biết cách thực hiện điều đó bằng lệnh git.

+1

thể trùng lặp của [rebasing một chi nhánh bao gồm tất cả các con của nó] (http://stackoverflow.com/questions/5600659/rebasing-a-branch -including-all-its-children) –

+1

Có thể trùng lặp của [Rebasing a tree (một cam kết/chi nhánh và tất cả các con của nó)] (https://stackoverflow.com/questions/17315285/rebasing-a-tree-a-commit -branch-and-all-its-children) – carnicer

Trả lời

2
o (master) 
/  o--o (WIP1) 
/ /
o--p--p--o--o--o (WIP2) 
(X)  (Y) 
      \ 
      o--o (WIP3) 

này phải là một rebase --onto (bạn có thể thấy một ví dụ trong "How to move certain commits to another branch in git?"):

git rebase --onto master X WIP1 
git rebase --onto master X WIP2 
git rebase --onto master X WIP3 

Từ Chronial 's test, mà sẽ cung cấp cho:

  p'--p'--o--o (WIP2) 
     /
o-----o-----p--p--o--o--o (WIP1) 
(X) (master) (Y') 
     \ 
     p''--p''--o--o (WIP3) 

Vì vậy, các rebase đầu tiên là ok, nhưng bạn cần có Y SHA và:

git rebase --onto Y' Y WIP2 
git rebase --onto Y' Y WIP3 
+0

Điều này sẽ tạo ra ba nhánh tách ra khỏi chủ, phải không? Hay điều này sẽ di chuyển cấu trúc đằng sau X trên đỉnh của cái chủ (để các nhánh chuyển hướng sau này)? – Chronial

+0

@Chronial yes, có nguy cơ đó, đặc biệt là xem xét việc rebase sẽ không phát lại một cam kết nếu cùng một nội dung được phát hiện trên nhánh đích. Tôi sẽ phải thử nghiệm nó. – VonC

+0

vừa thử nghiệm và phân tách:/ – Chronial

0

Nếu bạn muốn có kết quả này

o (oldmaster)--o--o--B--o--o(WIP1)--o--o(WIP2)--o--o(WIP3)(master) 
/  
/  
X 

Bạn nên làm điều này:

git rebase --onto master X WIP1   /* move WIP1 on master */ 
git rebase --onto WIP1 WIP2~3 WIP2  /* move WIP2 on WIP1 */ 
git rebase --onto WIP2 WIP3~3 WIP3  /* move WIP3 on WIP2 */ 
git reset --hard WIP3     /* move master index to WIP3 */ 
11

Không có lệnh git đơn cho điều đó. Bạn sẽ phải làm một số công việc thủ công. Trong trường hợp của bạn:

o (master) 
/  o--o (WIP1) 
/ /
X--o--o--B--o--o (WIP2) 
      \ 
      o--o (WIP3) 

Trước tiên, bạn rebase WIP1 lên thạc sĩ:

git rebase --onto master X WIP1 

đó sẽ dẫn đến điều này:

   o--o (WIP1) 
(master) /
    o--o--o--B’ 
/ 
/  
X--o--o--B--o--o (WIP2) 
      \ 
      o--o (WIP3) 

Nếu bây giờ bạn chạy git rebase --onto master X WIP2, bạn sẽ có được cấu trúc này:

   o--o (WIP1) 
(master) /
    o--o--o--B’ 
    /\ 
/ o--o--B’’--o--o (WIP2) 
/  
X--o--o--B--o--o (WIP3) 

Đây có lẽ không phải những gì bạn muốn, vì vậy bây giờ bạn nên rebase WIP2 và WIP3 trên B’:

git rebase --onto B’ B WIP2 
git rebase --onto B’ B WIP3 

đó sẽ dẫn đến điều này:

    o--o (WIP1) 
(master)  /
    o--X--o--o--B’--o--o (WIP2) 
       \ 
        o--o (WIP3) 
+0

Dường như bản chỉnh sửa của tôi.+1 – VonC

+0

Có, đã xem bản chỉnh sửa của bạn ngay trước khi gửi, nhưng lúc đó tôi đã vẽ tất cả những gì ascii-nghệ thuật ^^ – Chronial

+0

Bạn đã thực hiện các bài kiểm tra, bạn xứng đáng nhận được tín dụng;) – VonC

1

Tôi đã gắn cờ câu hỏi này như trùng lặp. Tôi sẽ viết những gì tôi đã giải thích the other answer nhưng sử dụng ví dụ của bạn.

Phương pháp mà tôi sử dụng đối với trường hợp sử dụng như vậy là để hợp nhất tất cả các ngành được chuyển vào 1 chung nhân tạo nút, và sau đó sử dụng lệnh rebase với các tùy chọn --preserve-merges. Hợp nhất tất cả các chi nhánh sẽ phơi bày 1 điểm kết thúc sẽ được sử dụng làm thông số đầu vào cuối cùng cho rebase --onto. Các điểm bắt đầu thường là hiển nhiên, nguồn gốc của cây con để di chuyển.

Khi hợp nhất để nhận được điểm cuối subtree, các xung đột cần được giải thích tránh. Do đó, các lệnh hợp nhất sẽ được hướng dẫn để giải quyết chúng tự động với tùy chọn -Xours. Kết quả hợp nhất không quan trọng là vì các nút nhân tạo hợp nhất này sẽ bị hủy sau khi rebase.

Bạn nên tạo một chi nhánh mới gói để không bị mất các tài liệu tham khảo gốc . Trong ví dụ trên, các lệnh sau sẽ là được thực hiện:

$ git checkout -b pack WIP1 # create new branch at 'WIP1' 
$ git merge -s recursive -Xours WIP2 # merges WIP2 into pack (node p2) 
$ git merge -s recursive -Xours WIP3 # merges WIP3 into pack 

Dưới đây có thể thấy cây sẽ trở thành cái gì. Hai mới nhân tạo nút p2gói đã được tạo bằng cách hợp nhất.

 o (master) 
    /
    /  (WIP1) (p2) 
/  o-----o-----o----o (pack) 
/ /  //
o--o--o--o-----o-----o /(WIP2) 
(X)  \   /
      o------------o (WIP3) 

Bây giờ là lúc để rebase. Kể từ bây giờ có một thiết bị đầu cuối phổ biến đối với tất cả các chi nhánh (gói), thật dễ dàng để di chuyển toàn bộ cây con với:

$ git rebase --preserve-merges --onto master X pack 

nào sản xuất này:

     (WIP1') (p2') 
        o-----o-----o----o (pack') 
    (master)  /  //
o----o----o--o--o-----o-----o /(WIP2') 
(X)    \   /
        o------------o (WIP3') 

Bây giờ là thời gian để sắp xếp lại các tài liệu tham khảo. Tôi không biết tại sao, trong một số trường hợp các tham chiếu được di chuyển và trong trường hợp khác thì không. Loại này cho mỗi WIP1 tham khảo, WIP2, WIP3 hoặc bất cứ điều gì bạn cần:

$ git checkout WIP1 
$ git reset --hard <WIP1' hash> 

Và cuối cùng, thoát khỏi cam kết nhân tạo đã được tạo cho tạo ra một nút cuối cây con chung.

$ git branch -D pack 
$ git branch -D p2 # if there is any 

Vì vậy, cây cuối cùng sẽ là:

     (WIP1') 
        o-----o 
    (master)  /
o----o----o--o--o-----o-----o (WIP2') 
(X)    \ 
        o------------o (WIP3') 
Các vấn đề liên quan