Thay đổi cơ sở chi nhánh


144

Tôi có một cái cây như thế này:

(commit 1) - master
                \-- (commit 2) - (commit 3) - demo
                                                \-- (commit 4) - (commit 5) - PRO

và tôi phải chuyển chi nhánh PRO thành chủ

(commit 1) - master
                |-- (commit 2) - (commit 3) - demo
                \-- (commit 4) - (commit 5) - PRO

Tôi đã thử một git rebase masterchi nhánh từ PRO, nhưng không có gì xảy ra.

Để làm rõ : Tôi đã làm việc trong chủ và sau đó tôi phải làm một bản demo sản phẩm ( git checkout -b demovà một số cam kết). Sau đó, do nhầm lẫn, tôi tạo một nhánh khác từ bản demo ( git checkout -b PROvà một số cam kết) và bây giờ tôi cần di chuyển nhánh PRO để làm chủ và giữ nguyên bản demo. Cuối cùng, cả demo và PRO sẽ treo từ master.


có thể trùng lặp điểm thay đổi chi nhánh
Wladimir Palant

Câu trả lời:


278

Sử dụng --ontocho điều đó:

git rebase --onto newBase oldBase feature/branch

Đưa ra trường hợp của bạn:

git checkout PRO # Just to be clear which branch to be on.
git rebase --onto master demo PRO

Về cơ bản, bạn thực hiện tất cả các cam kết từ sau demođến PROvà khởi động lại chúng vào mastercam kết.


Có phải đó cũng là con đường để đi nếu tình hình ngược lại? == Tôi kiểm tra -b từ chủ chi nhánh thứ hai, nhưng tôi muốn làm điều đó từ chi nhánh thứ nhất. Vì vậy, tôi đã làm git rebase --onto first-branch second-branch second-branchnhưng tôi không nhận được cú pháp
Fla

1
@Fla trong trường hợp đó, nó sẽ làgit rebase --onto first-branch master second-branch
nV mẹo

9
Tôi đọc hướng dẫn trên --onto, và làm thế nào họ wrote giúp tôigit rebase --onto newBase oldBase feature/branch
Gabe

@PhilipRego Điều đó không chính xác. origin/newBaselà tên của một chi nhánh, giống như newBasetrong ví dụ của tôi. Nó sẽ chỉ phụ thuộc nếu bạn đang khởi động lại một nhánh tồn tại trong kho lưu trữ cục bộ ( newBase) hoặc một nhánh tồn tại trên remote ( origin/newBase).
loganfsmyth

@PhilipRego Những thứ không độc lập. newBaselà tên của một chi nhánh địa phương và origin/newBaselà tên của một chi nhánh từ xa. Cái nào bạn muốn phụ thuộc vào những gì bạn đang nổi loạn. Không phải là một người làm việc và một người không, đó là họ nổi loạn với những thứ khác nhau. Câu hỏi ban đầu không bao giờ đề cập đến điều khiển từ xa, vì vậy sử dụng điều khiển từ xa trong ví dụ của tôi sẽ không phù hợp với câu hỏi đã được hỏi.
loganfsmyth

21

Tôi sẽ cố gắng chung chung như tôi có thể. Trước tiên, hãy chắc chắn rằng bạn đang ở trên nhánh mong muốn:

git checkout current-branch

Sau đó sử dụng lệnh sau (nơi new-base-branchlà nhánh mà bạn muốn làm cơ sở mới của bạn và current-base-branchlà nhánh là cơ sở hiện tại của bạn.)

git rebase --onto new-base-branch current-base-branch

Nếu bạn không có xung đột, thì thật tuyệt - bạn đã hoàn thành. Nếu bạn làm (trong hầu hết các trường hợp), xin vui lòng đọc tiếp.

Xung đột có thể phát sinh và bạn sẽ phải giải quyết chúng bằng tay. Git bây giờ cố gắng để làm một "3-way merge" giữa bạn current-branch, current-base-branchnew-base-branch. Đây là cách mà git sẽ hoạt động trong nội bộ:

  1. Git đầu tiên sẽ nổi loạn current-base-branchtrên đầu trang new-base-branch. Có thể có xung đột; mà bạn sẽ phải giải quyết bằng tay. Sau khi xong, bạn thường làm git add .git rebase --continue. Nó sẽ tạo ra một cam kết tạm thời mới temp-commit-hashcho việc này.

  2. Sau này, Git sẽ khởi động lại bạn current-branchtrên đầu trang temp-commit-hash. Có thể có thêm xung đột và một lần nữa bạn sẽ phải giải quyết chúng bằng tay. Sau khi hoàn thành, bạn tiếp tục một lần nữa với git add .git rebase --continuesau đó, bạn đã khởi động lại thành công của bạn current-branchtrên đầu trang new-base-branch.


Lưu ý: Nếu bạn bắt đầu gây rối, thì bạn có thể thực hiện git rebase --abortbất cứ lúc nào trong quá trình rebase và quay lại điểm bắt đầu.


Các rebaselệnh như được đăng chỉ mang lại cho tôi "chết người: thượng nguồn không hợp lệ 'hiện-base-chi nhánh". Ngoài ra, tại sao thậm chí cần phải nói với GIT rằng nhánh mẹ hiện tại của nhánh hiện tại là gì - không nên biết điều này chưa?
Matt Arnold

19

Thanh toán cho PROchi nhánh, Sao chép băm cam kết cũ nhất ( commit4 ) và mới nhất ( commit5 ) của nhánh này và dán vào một nơi khác:

$ git checkout PRO
$ git log            # see the commit history
# copy the oldest & latest commit-hash 

Xóa PROchi nhánh (giữ một bản sao lưu chỉ để an toàn). Tạo và thanh toán đến một PROchi nhánh mới từ master:

$ git branch PRO.bac    # create a new branch PRO.bac = PRO as backup

$ git checkout master
$ git branch -D PRO     # delete the local PRO branch
$ git checkout -b PRO   # create and checkout to a new 'PRO' branch from 'master'

Lấy ( cherry-pick ) phạm vi cam kết của PROnhánh trước vào PROnhánh mới :

$ git cherry-pick commit4^..commit5   # cherry-pick range of commits
# note the '^' after commit4

Bây giờ, nếu tất cả đều ổn, thì hãy ép (-f) đẩy sang remote PROnhánh và xóa PRO.bacnhánh cục bộ :

$ git log                  # check the commit history

$ git push -f origin HEAD  # replace the remote PRO by local PRO branch history
# git branch -D PRO.bac    # delete local PRO.bac branch

1

Tôi đã có một cách tiếp cận hơi khác bằng cách sử dụng thiết lập lại và stash để tránh xóa và tạo lại các nhánh cũng như loại bỏ nhu cầu chuyển đổi các nhánh:

$ git checkout PRO
$ git reset commit4 # This will set PROs HEAD to be at commit 4, and leave the modified commit 5 files in ur working index
$ git stash save -m "Commit message"
$ git reset commit 3
$ git stash save -m "Commit message"
$ git reset master --hard
$ git stash pop
$ git stash pop
$ git push --force # force if its already been push remotely

Bằng cách đặt lại chi nhánh trên một cam kết bằng cơ sở cam kết, về cơ bản bạn chỉ cần tua lại lịch sử chi nhánh một cam kết tại một thời điểm.


Bạn có nên xóa khoảng cách giữa "cam kết" và "3" trên dòng thứ 4 không?
Alexis Wilke
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.