2012-02-02 16 views
18

Sto lavorando a un progetto Rails su larga scala e il team con cui lavoro sta utilizzando Github per gestire il progetto. Mentre molte modifiche vengono elaborate localmente e quindi inviate direttamente al nostro ramo di sviluppo, creiamo un ramo quando lavoreremo a una modifica molto ampia. Quando arriva il momento di unire nuovamente questo ramo allo sviluppo, spesso cerco di rebase lo sviluppo nel mio branch di funzionalità prima di fondere il mio branch di funzionalità in sviluppo (per evitare di sovrascrivere il lavoro di altre persone). Trovo che quando faccio questo, mi sembra di incontrare gli stessi conflitti di fusione due volte. Eseguo un'intera lista di conflitti durante la ridefinizione, quindi eseguo nuovamente la stessa lista di conflitti durante l'unione. Devo rebase sviluppare nel mio branch funzionalità prima di fondere la mia funzionalità in sviluppo, o dovrei semplicemente fondere la mia funzionalità in sviluppo?Quando utilizzo Git, devo eseguire il rebase prima di unire?

Diciamo che il mio ramo di funzionalità è chiamato "nuova_funzione". Il mio processo per la fusione con il ramo "sviluppare", va in questo modo:

git checkout develop 

git pull (this is set up on our rig to always pull rebase) 

git checkout new_feature 

git rebase develop 

(lots of merge conflicts ensue) 

git checkout develop 

git merge -no-ff new_feature 

(same set of merge conflicts again) 

E 'come se la timeline cambia dal mio rebase causare la mia nuova filiale funzione per specie di specchio sviluppare tutta la strada, e quindi sviluppare conflitti con una psudo-copia di se stesso.

+3

perché 'git merge -no-ff'? Se hai appena ridefinito new_feature in sviluppo, _should_ essere un avanzamento rapido. – Useless

+0

Onestamente non sono sicuro. Per un po ', abbiamo avuto un ragazzo qui che conosceva davvero Git, e mi ha detto che avrei dovuto farlo in quel modo per qualche motivo che aveva a che fare con la pulizia della timeline. Non so davvero quale fosse la ragione. –

+1

Posso vedere che potrebbe rendere la timeline confusa ... hmm. Il rebase sta sostituendo tutti i commit su 'new_feature' con modifiche equivalenti applicate a' develop' invece che al punto di diramazione originale, il che significa che otterrete (copie di) vecchi commit, i cui genitori (tra il punto di diramazione originale e 'sviluppano/HEAD') sono più vecchi di loro. – Useless

risposta

29

OK, questo è troppo lungo per un commento ora.

Parafrasando il manuale (git help rebase)

Assume the following history exists and the current branch is "new_feature": 

       A---B---C new_feature 
       /
      D---E---F---G develop 


    From this point, the result of either of the following commands: 

     git rebase develop 
     git rebase develop new_feature 

    would be: 

         A'--B'--C' <new_feature 
         /
      D---E---F---G <develop 

Ora, se tu avessi i conflitti, allo stato attuale dopo la prima esecuzione rebase sarà

   A'--B'--C'--[local state] 
      / ^
D---E---F---G   new_feature 
      ^develop 

dove [local state] è l'unione in conflitto avete ancora aggiustare. Una volta risolti i conflitti di unione e aggiunto i file risolti all'indice, si esegue git rebase --continue: ora il vostro stato sarà

   A'--B'--C'--H <new_feature 
      /
D---E---F---G <develop 

Ovviamente a questo punto fusione new_feature indietro sulla sviluppare può essere veloce-inoltrato in questo modo :

   A'--B'--C'--H <new_feature <develop 
      /
D---E---F---G 

, ma se non lo è si otterrà questo, invece

   A'--B'--C'--H <new_feature 
      /   \ 
D---E---F---G---------------I <develop 

Ora a seconda di quale di questi si preferisce da un prospettiva cronologica, non è ovvio perché entrambi avrebbero un problema ... a meno che tu non abbia mai completato il rebase e risolto i conflitti con H, ma penserei che git si lamenterebbe di ciò.

+0

"ma se non lo riceverai otterrai"? "non è" cosa? Non capisco come causare uno di questi scenari. Qual è stata la differenza? – Umagon

+1

"_... può essere inoltrato rapidamente ... ma se non è ..._". Se si sceglie di non eseguire l'avanzamento rapido dell'unione, con '--no-ff', si ottiene un commit merge invece di spostare semplicemente il puntatore del ramo, come mostra il diagramma. Se inizialmente non capisci nessuno dei due scenari, probabilmente dovrai fare la tua domanda o altrimenti saperne di più su git, perché non posso davvero indovinare dove questa risposta ti ha fatto perdere. – Useless

4

Mi sembra che tu stia utilizzando rebase all'indietro ma potrebbe essere solo un fraseggio confuso.

Avrei rebase il ramo di funzionalità su sviluppare e quindi (su sviluppo) fare un git merge --ff-only feature.

+0

Sto lavorando alla modifica del mio post per mostrare il processo, per vedere se mi sto sbagliando. –

+1

Come @Divertito inutile, l'unione dovrebbe essere un avanzamento rapido (preferisco forzarlo usando l'opzione --ff-only). Tutto il resto sembra ok anche se il tuo modo di esprimerlo a parole non è lo standard. Consiglierei di leggere http://progit.org/book/ – madth3

-1

Poiché si specifica "su larga scala" e "rebase" nella stessa domanda, si consiglia di non farlo. Utilizzare invece le unioni.

L'utilizzo di --no-ff in merges è ottimo allo scopo di preservare il punto di diramazione originale. Supporto per l'utilizzo.