Saltiamo --onto per il momento. upstream e branch sono piuttosto semplici, e in realtà ordinano - imitano 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 questo, i nomi di questi argomenti in rebase , "upstream" e "branch" non sono IMO molto descrittivi. In genere li considero come peachoftree, <start> e <end> , che è come li userò: git rebase <start> <end> )
Quando il secondo ramo viene omesso, il risultato è quasi lo stesso di prima controllare quel ramo e poi farlo come se non avessi 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 capire cosa fa rebase quando invocato, ho iniziato a pensarlo come un tipo speciale di unione. Non è davvero, ma è stato utile quando ho iniziato a capire il rebase. Per prendere in prestito l'esempio di peachoftree:
A--B--F--G master
\
C--D--E feature
Un git merge master ha come risultato:
A--B--F-----G master
\ \
C--D--E--H feature
Mentre un get rebase master (mentre sul ramo feature !) risulta in questo:
A--B--F--G master
\
C'--D'--E' feature
In entrambi i casi, feature ora contiene il codice sia da master sia da feature . Se non sei su 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. Così sopra, se specificassi specificamente --onto , questo risulterebbe nello stesso modo:
git rebase --onto master master
git rebase --onto master master feature
(Non uso --onto senza specificare <end> semplicemente perché è più facile da analizzare mentalmente, anche se si pensa che siano uguali se già su feature .)
Per capire perché --onto è utile, ecco un esempio diverso. Diciamo che ero su feature e ho notato un bug, che ho poi iniziato a risolvere, ma che per errore era derivato da feature invece di master :
A--B--F--G master
\
C--D--E feature
\
H--I bugfix
Quello che voglio è "spostare" questi commit per bugfix in modo che non dipendano più da feature . Così com'è, qualsiasi tipo di unione o di rebase mostrata sopra in questa risposta impiegherà il tre% difeature a commit con i due commit di bugfix .
Ad esempio, git rebase master bugfix è sbagliato. L'intervallo da <start> a <end> capita di includere tutti i commit da feature , che vengono riprodotti su master :
A--B--F--G master
\ \
\ C'--D'--E'--H'--I' bugfix
\
C--D--E feature
Ciò che in realtà vogliamo è l'intervallo di commit da feature a bugfix da riprodurre su master . Questo è ciò che --onto è per: specificare un target "replay" diverso dal ramo "start":
git rebase --onto master feature bugfix
A--B--F--G master
\ \
\ H'--I' bugfix
\
C--D--E feature