2009-05-14 13 views
51

Ho un master branch nel mio progetto, che uso per estrarre le modifiche da altre persone. Da quello, di solito ho diverse sezioni tematiche su cui sto lavorando al momento.Git: Come riassegnare più rami (con lo stesso commit di base) in una volta?

La mia domanda è: c'è un modo per me di inserire nuove modifiche nel mio master e quindi ridimensionare TUTTI i rami del mio argomento su quello in una volta?

Questa è la situazione:

 D--E topic1 
    /
A--B--C master 
     \ 
     F--G topic2 

e voglio fare questo con un unico comando (H proveniva da monte):

 
       D'--E' topic1 
      /
    A--B--C--H master 
       \ 
       F'--G' topic2 

Ora, so che posso ottenere questo risultato rebasing topic1 e topic2 su master, e potrei persino scrivere uno script per automatizzarlo. Ma cosa succede se ho diversi altri rami, ne creo di nuovi ed elimini frequentemente altri e ricevo continuamente modifiche a monte?

Questa operazione (diversi rebasi), quando eseguita a mano, è stancante e soggetta a errori.

C'è un modo più semplice?

Grazie!

+1

[questa nuova domanda] (http://stackoverflow.com/questions/5600659/rebasing- a-branch-inclusa, ing-all-its-children/5600770 # 5600770) è probabilmente un duplicato, ma non sono sicuro che sarebbe mai stato effettivamente chiuso come duplicato di una domanda precedente senza una risposta reale. – Cascabel

+1

Vedere anche [in che modo rebase un'intera sottodoria: diverse diramazioni, con alcuni collegamenti tra di loro risultanti dall'unione] (http://stackoverflow.com/a/9706495/94687). –

+0

'git rebase --onto' dovrebbe anche essere citato nel caso in cui' topic1' o 'topic2' abbia filiali figlio https://coderwall.com/p/xzsr9g/rebasing-dependent-branches-with-git – quimnuss

risposta

17

Sono abbastanza sicuro che non c'è un modo per farlo automaticamente. Ricorda che "git rebase master" può anche riportarti alla shell che necessita di risolvere i conflitti di merge, quindi se vuoi scrivere uno script per automatizzare tutto questo devi tenerne conto.

Si può facilmente tenere traccia delle filiali che devono essere aggiornate. Hmm, per ogni ramo, "git rev-list branch..master" produrrà output se il branch non è aggiornato wrt (cioè si limita a commettere in cima a) master. Quindi è necessario scorrere tutti i capi locali, tranne le padrone di produrre una relazione (nb "git show-branch" sarà di circa fare questo):

git for-each-ref 'refs/heads/*' | \ 
    while read rev type ref; do 
    branch=$(expr "$ref" : 'refs/heads/\(.*\)') 
    revs=$(git rev-list $rev..master) 
    if [ -n "$revs" ]; then 
     echo $branch needs update 
     git diff --summary --shortstat -M -C -C $rev master 
    fi 
    done 

Quindi, se ti sentivi coraggioso, è possibile sostituire che "git diff "con qualcosa come" git checkout $ branch & & git rebase master "(o forse solo" git pull --rebase "se lo hai impostato). Penso che dovresti verificare l'esistenza di una directory ".git/rebase-apply" o controllare l'indice per i file non divisi ("git ls-files -u") per verificare se siamo rimasti in attesa di fare unire.

Naturalmente, se non ci sono conflitti, allora è facile ... è la produzione di qualcosa che funziona anche quando non è facile che è il problema: p

E questo non risolve necessariamente quello che succede se uno dei le tue diramazioni si basano su qualcos'altro ... è per questo che ho menzionato l'uso di "git pull --rebase", perché questo sarebbe stato rebase in base alla configurazione del ramo, non ciecamente dal master. Anche se il rilevamento non è basato sulla configurazione del ramo ... forse sarebbe più semplice controllare ogni ramo e fare "git pull" e lasciare che la configurazione del ramo gestisca tutto, incluso se rebase o unire?

+1

Grazie per l'aiuto ! Immagino che questo sia solo un problema più difficile di quanto pensassi, quindi continuerò con la ridefinizione manuale. :) – malvim

+3

Io uso 'git branch --no-merged' per elencare i rami che voglio portare all'ultima master. – rjmunro

+1

@rjmunro bello, non sapevo di quella bandiera. Tuttavia, non penso sia appropriato per il caso in cui i tuoi rami hanno bisogno di una ridefinizione piuttosto che di una fusione. – araqnid

7

Si può sempre e solo scrivere un guscio di one-liner in questo modo:

for branch in topic1 topic2 topic3;do git rebase master $branch;done 

Dal momento che i rami argomento che si desidera rebase probabilmente cambierà nel corso del tempo, questo è un rapido e-dir^H^H^soluzione Hflexible :-)

+1

Vedere [questa risposta] (http://stackoverflow.com/a/5632027/396967) a una domanda correlata per una versione "più intelligente", determinando automaticamente i rami contenenti un particolare commit di base. – kynan

0

ho girato questo in uno script robusta, mantenuta in my git-extensions repository:

$ git-urebaselocalbr --help 
Rebase all/the last committed N local branches (except for the current branch 
and master) to the updated upstream head. 
Usage: git-urebaselocalbr [--continue|--skip|--abort] [--branches "<branch1> ..."] [N] [-i|--interactive] [options]