Saltiamo --onto
per il momento. upstream
e branch
sono piuttosto semplici, e in realtà una specie di imitazione checkout
e branch
- il secondo argomento è facoltativo:
git branch <newbranch>
git branch <newbranch> <base>
git checkout -b <newbranch>
git checkout -b <newbranch> <base>
git rebase <upstream>
git rebase <upstream> <branch>
(A parte, i nomi di questi argomenti rebase
, "a monte" e "ramo" non sono molto descrittivo IMO Io di solito penso a loro come peachoftree,. <start>
E <end>
, che è come sarò con loro: git rebase <start> <end>
)
Quando il secondo ramo viene omesso, il risultato è quasi lo stesso del primo controllo di quel ramo e quindi farlo come se non si fosse specificato quel ramo. L'eccezione è branch
che non cambia il tuo ramo attuale:
git checkout <base> && git branch <newbranch> && git checkout <previous_branch>
git checkout <base> && git checkout -b <newbranch>
git checkout <end> && git rebase <start>
Per quanto riguarda la comprensione di ciò che rebase
fa quando viene invocato, ho iniziato a pensarlo come un tipo speciale di unione. Non è davvero, ma ha aiutato quando ha iniziato a capire rebase. Per prendere in prestito l'esempio di peachoftree:
A--B--F--G master
\
C--D--E feature
Un git merge master
risultato in questo:
A--B--F-----G master
\ \
C--D--E--H feature
Mentre un git rebase master
(while on branch feature
!) Risulta in questo:
A--B--F--G master
\
C'--D'--E' feature
In entrambi i casi, feature
ora contiene il codice di entrambi master
e feature
. Se non sei attivo feature
, il secondo argomento può essere utilizzato per passare ad esso come una scorciatoia: git rebase master feature
farà la stessa cosa di cui sopra.
Ora, per lo speciale --onto
. La parte importante da ricordare con questo è che per impostazione predefinita è <start>
se non specificato. Quindi sopra, se ho specificato in modo --onto
specifico, ciò comporterebbe lo stesso:
git rebase --onto master master
git rebase --onto master master feature
(Non lo uso --onto
senza specificare <end>
semplicemente perché è più facile analizzare mentalmente, anche se quei due sono uguali se già attivi feature
.)
Per capire perché --onto
è utile, ecco un esempio diverso. Diciamo che ero acceso feature
e ho notato un bug, che poi ho iniziato a correggere, ma che si era ramificato feature
anziché master
per errore:
A--B--F--G master
\
C--D--E feature
\
H--I bugfix
Quello che voglio è "spostare" questi commit in bugfix
modo che non dipendano più feature
. Così com'è, qualsiasi tipo di unione o rebase mostrato sopra in questa risposta prenderà i tre feature
commit insieme ai due bugfix
commit.
Ad esempio, git rebase master bugfix
è sbagliato. L'intervallo <start>
da <end>
includere include tutti i commit da feature
, che vengono riprodotti in cima a master
:
A--B--F--G master
\ \
\ C'--D'--E'--H'--I' bugfix
\
C--D--E feature
Quello che vogliamo davvero è la gamma di commit da feature
ad bugfix
essere riprodotti in cima master
. Ecco a cosa --onto
serve: specificare un target "replay" diverso rispetto al ramo "start":
git rebase --onto master feature bugfix
A--B--F--G master
\ \
\ H'--I' bugfix
\
C--D--E feature