Capire e memorizzare i parametri di git rebase

8

Finora la parte più confusa di git è la ridefinizione su un altro ramo. In particolare, sono gli argomenti della riga di comando che sono confusi.

Ogni volta che voglio rebase 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 uno dei tre argomenti principali.

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

Che cosa è una buona regola empirica per aiutarmi a memorizzare su quale dovrebbe essere impostato ognuno di questi 3 parametri, dato qualsiasi tipo di rebase su un altro ramo?

Tenete a mente che ho ripassato la documentazione di git-rebase, 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 di dover coinvolgere altre persone per aiutarmi a capirlo.

Il mio obiettivo è che non dovrei mai rivedere la documentazione per questi parametri di base. Non sono stato in grado di memorizzarli finora, e ho già fatto un sacco di rebase. Quindi è un po 'strano che sia stato in grado di memorizzare ogni altro comando e i suoi parametri fino ad ora, ma non di rebase con --onto .

    
posta void.pointer 25.03.2014 - 14:31
fonte

2 risposte

7

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
    
risposta data 29.06.2014 - 06:18
fonte
1

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

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

dove <target branch> è il ramo su cui stai riposizionando, <start branch> è normalmente il ramo da cui <end branch> split e <end branch> è il ramo che stai ridefinendo.

se inizi con

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

e fai

git rebase --onto master master feature

otterrai

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

un'altra cosa buona da sapere è che <target branch> imposta di default <start branch> in modo da poter eseguire lo stesso rebase di

git rebase --onto master feature

se hai bisogno di ulteriore assistenza, consulta Rebase senza lacrime guida

    
risposta data 26.03.2014 - 00:18
fonte

Leggi altre domande sui tag