2011-01-12 1 views
16

Diciamo che ho un ramo chiamato master e un ramo chiamato upstream_lib.Come forzare un antenato comune in una git merge?

Il ramo master ha una sottodirectory lib basata sul codice presente sul ramo upstream_lib; le modifiche in upstream_lib vengono unite (con la strategia della sottostruttura) al ramo master periodicamente. La directory lib in master ha alcune sue modifiche che non sono in upstream_lib.

Tuttavia, diciamo che i due rami o non hanno una storia comune (perché il repository è stato appena migrato a git, per esempio) o la base di fusione non è corretto perché le fonde in upstream_lib sono stati schiacciati, c'è stata una certa rebasing o qualunque cosa.

La domanda è: dato una nuova serie di modifiche su upstream_lib, come forzare l'unione di considerare come l'antenato comune una revisione specifica di upstream_lib?

risposta

9

non ho mai usato la strategia subtree, così forse questa è una soluzione non ottimale (e forse non funziona ^^), ma è possibile applicare tutti i nuovi commit in upstream_lib ad un ramo temporaneo fuori del master linea e quindi unire quello. Quello che ho in mente non fondamentalmente risolvere la vostra situazione, quindi dovrete fare questo tipo di "merge manuale" ogni volta che si vuole tirare in nuovi cambiamenti, ma ecco come funziona:

  1. Determinare il falso antenato comune nella linea di discendenza master, ad esempio master~100.
  2. Determinare l'antenato comune falso nella riga upstream_lib, ad esempio upstream_lib~150.
  3. Eseguire una copia usa e getta del ramo upstream_lib: git branch --no-track new_upstream_lib upstream_lib
  4. Rebase new_upstream_lib sul master~100 usando la strategia ricorsiva con l'opzione sottostruttura. (Non credo che si può semplicemente utilizzare la strategia sottostruttura perché, come dici tu, la directory lib in master ha cambiamenti di sua iniziativa.) Ecco un comando completamente testati per questo:

    git rebase -s recursive -X subtree=lib --onto master~100 upstream_lib~150 new_upstream_lib 
    

    noti che new_upstream_lib ora contiene l'intero albero master, anche se ti interessa solo la directory lib.

  5. Unisci: git checkout master && git merge new_upstream_lib && git branch -d new_upstream_lib.
+0

Ha funzionato perfettamente, grazie! – Artefacto

+1

Immagino che l'unico problema è che non ci sono cronologia condivisa o commit con il ramo upstream_lib, ma posso conviverci. – Artefacto

+0

Felice di sentirlo! Se si volesse forzare la discendenza condivisa, è possibile creare un commit vuoto iniziale e rebase sia su 'master' che su upstream_lib'. Supponendo ovviamente che 'upstream_lib' è il tuo ramo piuttosto che un telecomando. Tuttavia, se l'importazione iniziale di 'upstream_lib' nella directory' lib' era solo un 'cp' piuttosto che un'unione (come descritto su http://www.kernel.org/pub/software/scm/git/docs/ howto/using-merge-subtree.html), avrai ancora i problemi che descrivi. –