Comprensione e memorizzazione dei parametri di git rebase


12

Finora la parte più confusa di git si sta rimettendo su un altro ramo. In particolare, sono gli argomenti della riga di comando che creano confusione.

Ogni volta che voglio rifare un piccolo pezzo di un ramo sulla punta di un altro, devo rivedere la documentazione di git rebase e mi ci vogliono circa 5-10 minuti per capire quale dovrebbe essere ciascuno dei 3 argomenti principali.

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

Qual è una buona regola empirica per aiutarmi a memorizzare ciò su cui ciascuno di questi 3 parametri dovrebbe essere impostato, dato qualsiasi tipo di rebase su un altro ramo?

Ricorda che ho esaminato la documentazione di git-rebase ancora, e ancora, e ancora, e ancora (e ancora), ma è sempre difficile da capire (come un noioso white paper scientifico o qualcosa del genere). Quindi a questo punto sento il bisogno di coinvolgere altre persone per aiutarmi a coglierlo.

Il mio obiettivo è che non dovrei mai rivedere la documentazione per questi parametri di base. Finora non sono stato in grado di memorizzarli e ho già apportato molte modifiche. Quindi è un po 'insolito che sono stato in grado di memorizzare ogni altro comando e i suoi parametri finora, ma non di rifare --onto.


È possibile definire alcuni alias git per i casi d'uso più comuni oppure eliminare uno script della procedura guidata che ricorda il significato di ciascuno dei parametri prima di eseguire il comando.
Rory Hunter,

4
Ah, queste strabilianti, pura eleganza delle opzioni di comando git. Così intuitivamente da usare. Sempre un vero piacere.
JensG

Risposte:


10

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

1

Solo un aggiornamento, il rebasing è principalmente per quando vuoi che la tua cronologia di commit appaia lineare se due rami si sono sviluppati indipendentemente l'uno dall'altro, fondamentalmente riscrive la cronologia di commit.

il modo in cui mi piace farlo è git rebase --onto <target branch> <start branch> <end branch>

dov'è <target branch>il ramo su cui ti stai rigenerando, di <start branch>solito è il ramo da cui <end branch>dividere ed <end branch>è il ramo su cui stai rigenerando.

se inizi con

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

e fai

git rebase --onto master master feature

otterrete

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

un'altra cosa positiva da sapere è che per <target branch>impostazione predefinita <start branch>puoi fare lo stesso rebase di

git rebase --onto master feature

se hai bisogno di ulteriore aiuto, dai un'occhiata alla guida Rebase senza lacrime


Il tuo risultato sembra fuorviante. rebase dovrebbe lasciare masterinvariato il ramo stesso. Ottieni solo la 'funzione' di espandersi come G--C'--D'--E'mentre ti masterfermi ancora a G.
Frank,

@Frank, l'ho fatto per enfatizzare l'intera storia della storia lineare ma ora penso che tu sia il modo migliore. fisso.
peachoftree,

1
Puoi mostrare un esempio di dove <target branch>e che <start branch>sono diversi in modo da aiutare i lettori a capire il caso più generale?
Rufflewind,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.