Rebase một cam kết Git duy nhất


116

Có cách nào để căn cứ lại một cam kết duy nhất từ ​​một chi nhánh sang một chi nhánh khác không?

Tôi có cấu trúc nhánh này:

-- -- -- -- -- (Master)
            \
              -- -- -- -- -- XX (Feature-branch)

Tất cả những gì tôi muốn làm là căn cứ lại cam kết cuối cùng của bản gốc Feature-branchvà khôi phục Feature-branchmột cam kết.

-- -- -- -- -- XX (Master)
            \
              -- -- -- -- -- (Feature-branch)

Làm thế nào để làm điều đó?


3
Nếu bạn có thể căn cứ lại bất kỳ số lượng cam kết nào thì tại sao bạn lại hỏi về việc khôi phục một số cam kết? Nếu tôi có thể đặt câu hỏi bằng SO, tôi sẽ hỏi sự khác biệt giữa việc phục hồi (một lần cam kết) và hái anh đào là gì.
Val

9
Bởi vì tôi không biết rằng việc hái anh đào tồn tại, và tôi thực hiện "Faff about on branch", "Get request for fix on other branch", "fix it", "Cam kết sai cành", "D'OH!" đủ để đặt câu hỏi là hữu ích.
Kevin Meyer

Câu trả lời:


116

Bạn có thể chọn XX để làm chủ.

git checkout master
git cherry-pick <commit ID of XX>

Và xóa cam kết cuối cùng khỏi nhánh tính năng bằng git reset.

git checkout Feature-branch
git reset --hard HEAD^

64
Làm thế nào một câu hỏi cụ thể được gọi là 'git rebase ...' có thể có câu trả lời được chấp nhận hơn là chứa cherry-pick, một khái niệm hoàn toàn khác và đôi khi bị coi là ô uế?
Bondax

1
Không chắc liệu điều này có liên quan hay không, nhưng cam kết mà tôi muốn rebase có một số tệp đã được di chuyển và cherry-picklàm cho chúng xuất hiện như thể chúng đã bị xóa khỏi vị trí cũ và được tạo ở vị trí mới. Tôi cho rằng rebase sẽ giải quyết vấn đề đó, nhưng hiện tại tôi đã đẩy ngược dòng nên tôi không thể kiểm tra điều đó. Trong mọi trường hợp, hãy cẩn thận nếu bạn gặp trường hợp tương tự.
waldyrious

Lưu ý: để đẩy bạn các thay đổi Feature-branchvề nguồn gốc, bạn sẽ cần git push -f origin Feature-branchFeature-branchhiện tại của bạn được coi là 1 cam kết đằng sau origin/Feature-branch.
jojo

1
Sự khác biệt thực tế giữa giải pháp này và giải pháp của CharlesB là gì?
Lii

96
git rebase --onto master branch~1 branch 

Điều này cho biết "căn cứ lại phạm vi cam kết giữa chi nhánh cuối cùng trước chi nhánh và chi nhánh (nghĩa là, cam kết XX) trên đầu của chi nhánh chính"

Sau khi branchmẹo hoạt động này được chuyển sang cam kết XX, vì vậy bạn muốn đặt lại bằng

git checkout branch
git reset --hard branch@{1}^

Có nội dung "đặt lại đầu nhánh về cam kết trước trạng thái trước đó của nó"

Vì vậy, hái anh đào là một giải pháp đơn giản hơn ...


5
Điều này dường như không hiệu quả với tôi, tôi mất các cam kết trước XX và nhánh được phục hồi để làm chủ với một cam kết duy nhất, nhưng tôi chưa bao giờ sử dụng --ontotrước đây nên có thể tôi đang làm sai. BTW OP đã nói rebase nhưng có vẻ như anh ấy muốn làm một quả cherry-pick.
tewe,

1
lỗi của tôi, rebase không thực sự di chuyển các chi nhánh trên tổng thể, nó phải được đặt lại
CharlesB

1
Sự khác biệt thực tế giữa giải pháp này và giải pháp của tewe là gì?
Lii

1
@Lii điều duy nhất tôi có thể thấy là nó sử dụng 3 bước thay vì 4
CharlesB 4/1017

52

Nó khá đơn giản để thực hiện. Giải pháp là thực hiện một rebase tương tác và "bỏ" tất cả các cam kết mà bạn không muốn đưa vào rebase.

git rebase -i <target_branch>nơi target_branchđược các chi nhánh bạn muốn rebase vào

Sau đó, bạn sẽ chỉnh sửa tệp được mở và pickcác cam kết bạn muốn và drop(hay dngắn gọn) tất cả các cam kết mà bạn không muốn mang theo.


6
IMO là một giải pháp tốt hơn nhiều và nó thực sự giải quyết được câu hỏi.
GabrielOshiro

Đây phải là giải pháp được chấp nhận vì nó chung chung, trực quan và ngắn gọn.
Pablo Arias

1

@Charles phản hồi là chính xác. Dù sao thì tôi đã sử dụng cái này rất nhiều lần, hầu hết là để rebase cấu hình cụ thể trên một dự án

  Cấu hình sản xuất * a8f9182 (HEAD -> production)
  | * cấu hình tiền sản xuất daa18b7 (pre)
  | /  
  | * cấu hình cục bộ d365f5f (cục bộ)
  | /  
  * 27d2835 (dev) tính năng mới tuyệt vời sẽ cứu thế giới
* | 56d2467 (chính) trạng thái nghệ thuật nhàm chán cho dự án
| /

mà tôi tạo một lệnh mới cho nó:

$ cat ~ / bin / git-rebaseshot 
CAM KẾT = $ 1
DEST = $ {2: -HEAD}
git rebase $ {COMMIT} ^ $ {COMMIT} --onto $ DEST

thông thường bạn muốn tự động điền tên nhánh cho lệnh đó, vì vậy hãy thêm nó vào nguồn cung cấp chức năng này (thêm vào .bashrc hoặc .profile):

_git_rebaseshot () 
{ 
    __gitcomp_nl "$ (__ git_refs)"
}

git autocomplete sẽ tìm kiếm nó

bạn có thể sử dụng lệnh này như sau:

# rebase config on prepro on actual HEAD
$ git rebaseshot prepro 
# rebase config on local onto dev
$ git rebaseshot local dev
# rebase production config on master
$ git rebaseshot pro master

Khi bạn phân chia các tính năng một cách chính xác, khả năng có thể là vô tận.

* a8f9182 (HEAD -> postgres) cấu hình BBDD
* a8f9182 (local) cấu hình cục bộ
* a8f9182 (gỡ lỗi) cấu hình mức nhật ký
* a8f9182 (dev) tính năng mới
|

Tôi đoán đây là những gì mọi người thích làm chăn bông .

lệnh này vẫn sẽ hoạt động với bất kỳ sha / ref nào bạn cung cấp:

$ git rebaseshot <Feature branch> master
$ git rebaseshot <commit of XX> master

//, Bạn có thể liên kết đến bất kỳ dự án nào mà chúng tôi có thể thấy điều này đang hoạt động không?
Nathan Basanese

Đối với bản chất của nó, các chi nhánh có sẵn để khôi phục lại không được cam kết bên ngoài repo cục bộ. Chỉ cần tạo một số nhánh trên đầu trang chủ (cấp nhật ký, kết nối cơ sở dữ liệu, cấu hình) và sử dụng lệnh giữa chúng. Rõ ràng là để xem hiệu quả.
albfan

//, tôi gặp phải một số vấn đề. Tôi sẽ thử lại lần nữa.
Nathan Basanese

0

Đây là một tùy chọn khác:

  1. Đảm bảo bạn có điều khiển từ xa với bản sao của nhánh tính năng
  2. Xóa nhánh tính năng cục bộ
  3. Tạo và kiểm tra một nhánh mới có cùng tên với nhánh tính năng cũ mà bạn vừa xóa khỏi nhánh chính
  4. cherry-chọn một cam kết từ bản sao từ xa của nhánh tính năng bạn muốn.

Các lệnh trông giống như:

git checkout Feature-branch
git push -u origin HEAD
git checkout master
git branch -D Feature-branch
git checkout -b Feature-branch
git cherry-pick HASH-OF-XX

Nó không phải là lệnh rebase no, nhưng nó là một rebase trong tinh thần.

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.