Saltiamo --ontoper il momento. upstreame branchsono piuttosto semplici, e in realtà una specie di imitazione checkoute 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 è branchche 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 rebasefa 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 masterrisultato 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, featureora contiene il codice di entrambi mastere feature. Se non sei attivo feature, il secondo argomento può essere utilizzato per passare ad esso come una scorciatoia: git rebase master featurefarà 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 --ontospecifico, ciò comporterebbe lo stesso:
git rebase --onto master master
git rebase --onto master master feature
(Non lo uso --ontosenza 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 featuree ho notato un bug, che poi ho iniziato a correggere, ma che si era ramificato featureanziché masterper errore:
A--B--F--G master
\
C--D--E feature
\
H--I bugfix
Quello che voglio è "spostare" questi commit in bugfixmodo che non dipendano più feature. Così com'è, qualsiasi tipo di unione o rebase mostrato sopra in questa risposta prenderà i tre featurecommit insieme ai due bugfixcommit.
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 featuread bugfixessere riprodotti in cima master. Ecco a cosa --ontoserve: 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