Hiểu và ghi nhớ các tham số rebase git


11

Cho đến nay, phần khó hiểu nhất của git đang nổi loạn lên một nhánh khác. Cụ thể, đó là các đối số dòng lệnh gây nhầm lẫn.

Mỗi lần tôi muốn rebase một phần nhỏ của một nhánh trên đầu của nhánh khác, tôi phải xem lại tài liệu git rebase và tôi mất khoảng 5-10 phút để hiểu mỗi trong số 3 đối số chính nên là gì.

git rebase <upstream> <branch> --onto <newbase>

Một quy tắc tốt để giúp tôi ghi nhớ những gì trong số 3 tham số này nên được đặt thành, cho bất kỳ loại rebase nào trên một nhánh khác?

Hãy nhớ rằng tôi đã đi qua tài liệu git-rebase một lần nữa, và một lần nữa, và một lần nữa (và một lần nữa), nhưng nó luôn luôn khó hiểu (như một tờ giấy trắng khoa học nhàm chán hoặc một cái gì đó). Vì vậy, tại thời điểm này tôi cảm thấy tôi cần phải có sự tham gia của người khác để giúp tôi nắm bắt nó.

Mục tiêu của tôi là tôi không bao giờ phải xem lại tài liệu cho các tham số cơ bản này. Tôi đã không thể ghi nhớ chúng cho đến nay, và tôi đã thực hiện rất nhiều cuộc nổi loạn. Vì vậy, có một chút bất thường là tôi đã có thể ghi nhớ mọi lệnh khác và các tham số của nó cho đến nay, nhưng không thể phản ứng lại --onto.


Bạn có thể xác định một số bí danh git cho các trường hợp sử dụng phổ biến của mình hoặc gõ một tập lệnh trình hướng dẫn nhắc nhở bạn về từng tham số có nghĩa là gì trước khi thực hiện lệnh.
Rory Hunter

4
Ah, những suy nghĩ tinh tế, thanh lịch của các tùy chọn lệnh git. Vì vậy, trực giác để sử dụng. Luôn luôn là một niềm vui thực sự.
JensG

Câu trả lời:


9

Hãy bỏ qua --ontongay bây giờ. upstreambranchkhá cơ bản, và thực sự sắp xếp bắt chước checkoutbranch- đối số thứ hai là tùy chọn:

git branch <newbranch>
git branch <newbranch> <base>
git checkout -b <newbranch>
git checkout -b <newbranch> <base>
git rebase <upstream>
git rebase <upstream> <branch>

(Ngoài ra, tên của các đối số này trong rebase"thượng nguồn" và "nhánh" không phải là IMO mô tả. Tôi thường nghĩ về chúng như Peachoftree, <start><end>, đó là cách tôi sẽ sử dụng chúng git rebase <start> <end>:)

Khi nhánh thứ hai bị bỏ qua, kết quả gần giống như lần đầu tiên kiểm tra nhánh đó và sau đó thực hiện nó như thể bạn chưa chỉ định nhánh đó. Ngoại lệ là branchkhông thay đổi chi nhánh hiện tại của bạn:

git checkout <base> && git branch <newbranch> && git checkout <previous_branch>
git checkout <base> && git checkout -b <newbranch>
git checkout <end>  && git rebase <start>

Để hiểu những gì rebasekhi được gọi, đầu tiên tôi bắt đầu bằng cách nghĩ về nó như một kiểu hợp nhất đặc biệt. Nó không thực sự, nhưng nó đã giúp khi lần đầu tiên bắt đầu hiểu về rebase. Để mượn ví dụ của Peachoftree:

A--B--F--G master
    \
     C--D--E feature

Một git merge masterkết quả trong việc này:

A--B--F-----G master
    \        \
     C--D--E--H feature

Trong khi một git rebase master(trong khi trên nhánh feature!) Kết quả trong việc này:

A--B--F--G master
          \
           C'--D'--E' feature

Trong cả hai trường hợp, featurebây giờ chứa mã từ cả hai masterfeature. Nếu bạn không bật feature, đối số thứ hai có thể được sử dụng để chuyển sang đối số dưới dạng phím tắt: git rebase master featuresẽ thực hiện tương tự như trên.


Bây giờ, cho đặc biệt --onto. Phần quan trọng cần nhớ với điều này là nó mặc định <start>nếu không được chỉ định. Vì vậy, ở trên, nếu tôi chỉ định --ontocụ thể, điều này sẽ dẫn đến cùng:

git rebase --onto master master
git rebase --onto master master feature

(Tôi không sử dụng --ontomà không chỉ định <end>đơn giản vì dễ phân tích tâm lý hơn, thậm chí còn nghĩ hai cái đó giống nhau nếu đã bật feature.)

Để xem tại sao --ontohữu ích, đây là một ví dụ khác. Giả sử tôi đã gặp phải featurevà nhận thấy một lỗi, sau đó tôi đã bắt đầu sửa lỗi - nhưng đã phân nhánh featurethay vì masternhầm lẫn:

A--B--F--G master
    \
     C--D--E feature
            \
             H--I bugfix

Điều tôi muốn là "di chuyển" những cam kết này bugfixđể chúng không còn phụ thuộc vào feature. Như vậy, bất kỳ loại hợp nhất hoặc rebase nào được hiển thị ở trên trong câu trả lời này sẽ có ba featurecam kết cùng với hai bugfixcam kết.

Ví dụ, git rebase master bugfixlà sai. Phạm vi <start>để <end>xảy ra để bao gồm tất cả các cam kết từ feature, được tái hiện lại trên đầu trang của master:

A--B--F--G master
    \     \
     \     C'--D'--E'--H'--I' bugfix
      \
       C--D--E feature

Những gì chúng ta thực sự muốn là một loạt các cam kết từ featuređể bugfixđược tái hiện lại trên đầu trang của master. Đó là những gì --ontodành cho - chỉ định mục tiêu "phát lại" khác với nhánh "bắt đầu":

git rebase --onto master feature bugfix

A--B--F--G master
    \     \
     \     H'--I' bugfix
      \
       C--D--E feature

1

Chỉ cần làm mới lại, việc đánh lại chủ yếu là khi bạn muốn lịch sử cam kết của mình xuất hiện tuyến tính nếu hai nhánh phát triển độc lập với nhau, về cơ bản, nó viết lại lịch sử cam kết.

cách tôi thích làm là git rebase --onto <target branch> <start branch> <end branch>

<target branch>nhánh mà bạn đang nổi loạn ở đâu , <start branch>thường là nhánh mà từ đó <end branch>tách ra và <end branch>là nhánh bạn đang nổi loạn.

nếu bạn bắt đầu với

A--B--F--G master
    \
     C--D--E feature

và làm

git rebase --onto master master feature

bạn sẽ nhận được

A--B--F--G master
          \
           C'--D'--E' feature

Một điều tốt khác cần biết là <target branch>mặc định để <start branch>bạn có thể thực hiện cùng một cuộc nổi loạn như

git rebase --onto master feature

nếu bạn cần thêm trợ giúp, hãy xem hướng dẫn Rebase mà không có nước mắt


Kết quả của bạn có vẻ sai lệch. rebase nên để masterchi nhánh không thay đổi. Bạn chỉ cần nhận được 'tính năng' để phân nhánh như G--C'--D'--E'trong khi mastervẫn dừng tại G.
Frank

@Frank, tôi đã làm điều đó để nhấn mạnh toàn bộ điều lịch sử tuyến tính nhưng bây giờ tôi nghĩ cách của bạn tốt hơn. đã sửa.
Peachoftree

1
Bạn có thể đưa ra một ví dụ ở đâu <target branch><start branch>khác nhau để giúp người đọc hiểu trường hợp chung nhất không?
Rufflewind
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.