2012-02-10 11 views
274

Ho apportato alcune modifiche al mio ramo principale e voglio portarle a monte. quando ho cherry-pick seguente commette però mi rimane bloccata su fd9f578 dove git dice:git cherry-pick dice "... 38c74d è un'unione ma non è stata fornita l'opzione -m"

$ git cherry-pick fd9f578 
fatal: Commit fd9f57850f6b94b7906e5bbe51a0d75bf638c74d is a merge but no -m option was given. 

Cos'è git cercando di dirmi ed è cherry-pick la cosa giusta da essere utilizzato qui? Il ramo master include le modifiche ai file che sono state modificate nel ramo upstream, quindi sono sicuro che ci saranno alcuni conflitti di merge ma non sono così male da raddrizzare. So quali cambiamenti sono necessari dove.

Questi sono i commit che voglio portare a monte.

e7d4cff added some comments... 
23e6d2a moved static strings... 
44cc65a incorporated test ... 
40b83d5 whoops delete whitspace... 
24f8a50 implemented global.c... 
43651c3 cleaned up ... 
068b2fe cleaned up version.c ... 
fd9f578 Merge branch 'master' of ssh://extgit/git/sessions_common 
4172caa cleaned up comments in sessions.c ... 

risposta

342

Il modo in cui un cherry-pick funziona è quello di prendere il diff un changeset rappresenta (la differenza tra l'albero di lavoro in quel punto e l'albero di lavoro del suo genitore), e la sua applicazione alla vostra filiale corrente.

Quindi, se un commit ha due o più genitori, rappresenta anche due o più diff - quale dovrebbe essere applicato?

Stai provando a scegliere il fd9f578, che è stata un'unione con due genitori. Quindi è necessario dire al comando cherry-pick quale sarà il calcolo del diff, usando l'opzione -m. Ad esempio, git cherry-pick -m 1 fd9f578 per utilizzare il padre 1 come base.

Non posso dire con certezza per la vostra situazione particolare, ma usare git merge invece di git cherry-pick è generalmente consigliabile. Quando selezioni una fusione, viene compresso tutte le le modifiche apportate nella cartella principale non specificate a -m in quello un commit. Perderai tutta la loro storia e riunirai tutte le loro differenze. La tua chiamata.

+2

@wufoo Probabilmente dovresti anche imparare "git rebase" - è come un'unione, ma invece di integrare due rami ne trapianta uno per sedersi sopra l'altro. – Borealid

+21

come fai a conoscere il numero genitore? – Anentropic

+27

@Anentropic 1 è il "primo genitore", 2 è il "secondo genitore" e così via. L'ordine è quello in cui sono elencati nel commit (come visualizzato da 'git show' e simili). – Borealid

11

@ La risposta di Borealid è corretta, ma supponiamo che non ti interessi conservare la cronologia di fusione esatta di un ramo e vuoi semplicemente selezionarne una versione linearizzata. Ecco un modo semplice e sicuro per farlo:

Stato di partenza: si è sul ramo X e si desidera selezionare i commit Y..Z.

  1. git checkout -b tempZ Z
  2. git rebase Y
  3. git checkout -b newX X
  4. git cherry-pick Y..tempZ

Quello che fa è quello di creare un ramo tempZ basata su Z, ma con la storia da Y in poi linearizzati, e poi ciliegia -pick che su una copia di X chiamato newX. (È più sicuro farlo su un nuovo ramo piuttosto che mutare X.) Naturalmente ci potrebbero essere dei conflitti nel passaggio 4, che dovrai risolvere nel solito modo (cherry-pick funziona molto come rebase in questo senso).

Se il passaggio 2 restituisce il messaggio "Current tempZ del ramo è aggiornato", quindi Y..Z era già lineare, quindi ignorare il messaggio e procedere con i passaggi 3 e 4.

Quindi rivedere newX e vedere se ciò ha fatto ciò che volevi.

(Nota: questo non è lo stesso di un semplice git rebase X quando sul ramo Z, perché non dipende in alcun modo sul rapporto tra X e Y; ci possono essere impegna tra l'antenato comune e che si Y non volevo.)

+1

'git rebase Y' dice' Current branch tempZ è aggiornato ' – Basilevs

+0

Penso che ciò significhi che 'Y..Z' era già lineare. Quindi puoi ignorare quel messaggio e procedere con i passaggi 3 e 4. –

+1

Idea interessante, ho dovuto disegnarlo su carta per apprezzare appieno cosa stava succedendo = D – Chris

Problemi correlati