2015-08-04 22 views
11

Trovo che lavorando con i sottomoduli git, mi capita spesso di incontrare problemi di fusione tra commit che contengono un dato sottomodulo e quelli che rappresentano lo stesso codice di una normale directory. Piccolo esempio riproduzione:Fusione dopo che la directory è stata trasformata in sottomodulo

# Create one project, to be used as a subproject later on 
git init a 
cd a 
echo aaa > aa 
git add -A 
git commit -m a1 
cd .. 

# Create a second project, containing a as a normal directory initially 
git init b 
cd b 
mkdir a b 
echo aaa > a/aa 
echo bbb > b/bb 
git add -A 
git commit -m b1 

# Replace directory with submodule 
git rm -r a 
git submodule add ../a a 
git commit -m b2 

# Try to create branch from the pre-submodule state of affairs 
git checkout -b branch HEAD^ 

Questo dà già un errore:

error: The following untracked working tree files would be overwritten by checkout: 
    a/aa 
Please move or remove them before you can switch branches. 
Aborting 

Al fine di evitare l'errore, ho deinitialize tutti i sottomoduli primi:

# Create feature brach starting at version without submodule 
git submodule deinit . 
git checkout -b branch HEAD^ 
echo abc > b/bb 
git commit -a -m b3 

Come si può vedere, la il ramo di funzione non è completamente correlato al sottomodulo, modificando un diverso set di file. Ciò rende particolarmente fastidioso tutto questo problema.

# Try to merge the feature branch 
git checkout master 
git merge branch 

Questo non riesce ancora una volta, con un messaggio di errore non comprendere appieno:

CONFLICT (file/directory): There is a directory with name a in branch. Adding a as a~HEAD 
Automatic merge failed; fix conflicts and then commit the result. 

ottengo lo stesso errore se faccio un git submodule update --init prima della git merge branch. Non vedo alcun a~HEAD da nessuna parte, né nel mio albero di directory né in uscita dal git status, che recita così:

On branch master 
You have unmerged paths. 
    (fix conflicts and run "git commit") 

Changes to be committed: 

    modified: b/bb 

Unmerged paths: 
    (use "git add <file>..." to mark resolution) 

    added by us:  a 

Se faccio git add a come suggerito, ottengo un altro errore:

error: unable to index file a 
fatal: updating files failed 

Se faccio git submodules update --init appena prima dell'unione, allora posso fare con successo git add a. Ma se ho dimenticato di farlo, e quindi provare a farlo dopo l'unione, ricevo questo messaggio di errore:

Submodule 'a' (…/a) registered for path 'a' 
Skipping unmerged submodule a 

Come faccio a uscire da questa situazione? Qualcosa di diverso da git merge --abort, dal momento che mi piacerebbe usarlo per cose come git rebase pure, e dato che in alcuni scenari (non so come riprodurre) non ho potuto nemmeno interrompere l'unione in modo pulito, e ho dovuto fare un hard reset invece.

Come posso evitarlo in primo luogo? C'è qualche impostazione magica che rende git fare la cosa giusta con i sottomodati e le directory durante le unioni, così che non devo manualmente post-processare una fusione che modifica solo i file non correlati ai sottomoduli?

+0

FYI il flag '--abort' funziona anche per rebase. – approxiblue

+0

@ user880772: Sì, ma abortisce l'intero rebase, il che significa che uno sforzo considerevole potrebbe andare perso se ci fossero dei conflitti lungo il percorso. – MvG

+1

Git [non gestisce la fusione del submodulo] (https://codingkilledthecat.wordpress.com/2012/04/28/why-your-company-shouldnt-use-git-submodules/). Non nel suo solito modo magico. Se non vuoi dimenticare di eseguire l'aggiornamento del sottomodulo prima di un'unione, puoi trasformare "unisci" in un alias (mi sento orribile a suggerirlo). Non vedo un modo pulito intorno a questo. – approxiblue

risposta

2

No non dovresti aggiungere un, l'unione non dovrebbe cambiarlo. Che cosa si dovrebbe eseguire è

git reset a 

Così si ignora il "chage" per una.

PS: a quanto pare git si limita a controllare existense di una directory, quindi se si

git submodule deinit a 
rmdir a 

prima della fusione, che avrà successo. Non sono sicuro se questo è quello che vuoi.

0

Ho un problema simile quando unisco il codice che contiene la cartella che deve essere convertita nel sottomodulo.

Ho risolto il problema utilizzando BFG --delete-folders per rimuovere la cartella dal nuovo codice sorgente e git gc per pulire il repository, quindi avrò git rebase senza conflitti.

Problemi correlati