2009-07-23 18 views
13

Ho i telecomandi Foo e Bar. Foo è un'applicazione web che ha un sacco di directory, tra cui è importante /public che contiene file assortiti e altre directory.git: posso sottomettere un solo sottocampo di un repository?

La barra è un insieme di librerie e tutto ciò che viene utilizzato sul front-end, come tale, dovrebbe andare in /public/bar in Foo. Foo non ha file lì.

Sarebbe tutto un pezzo di torta con i sottomoduli o l'unione secondaria. Tuttavia ...

L'albero del bar è disordinato, ha tutti i tipi di file di pre-produzione come PSD e FLA, e l'unica parte veramente utile è ciò che è all'interno del suo /www/tools.

Quindi, quello che voglio fare è unire lo /www/tools di Bar in /public/bar di Foo e far finta che il resto dell'albero di Bar non esista nemmeno.

Può fare?

(vorrei suppongo che questo è molto simile a come si uniscono da un progetto che in origine la vostra fusa come una sottostruttura. Il che non so come fare, neanche.)

risposta

0

non credo che questo può essere fatto usando una fusione, per sé, ma questi passaggi potrebbero fare il trucco, almeno per quanto riguarda il prodotto finale. Primo:

% git fetch Bar 

Questo recupera l'ultimo commit (s) dal repository Bar, ma non cerca di unirle. Si registra il CSA per il commit in .git/FETCH_HEAD

% cat .git/FETCH_HEAD 
b91040363160aab4b5dd46e61e42092db74b65b7    branch 'Bar' of ssh://blah... 

Questo dimostra quanto l'identificatore SHA per l'ultimo commit dal ramo remoto è.

% git checkout b91040363160aab4b5dd46e61e42092db74b65b7 www/tools 

Questo prende la copia dei file in www/strumenti per la inverosimile commettono e sovrascrive ciò che è nella struttura di lavoro. È quindi possibile trasferire tali modifiche nel repository locale come normale. Il commit risultante non avrà alcun riferimento a dove proviene, ma dovrebbe almeno ottenere il tuo repository con le versioni dei file che desideri.

+0

Sì, sarei più felice di mantenere la cronologia. Forse qualcosa potrebbe essere fatto con il filtro-ramo. – kch

+1

1.) puoi usare "git checkout FETCH_HEAD www/tools" 2.) probabilmente puoi usare "git checkout --merge FETCH_HEAD www/tools" 3.) dopo aver registrato lo stato richiesto nella directory di lavoro, puoi creare unire manualmente scrivendo FETCH_HEAD su .git/MERGE_HEAD prima di git-commit –

+0

Ah, sapevo che ci doveva essere un modo migliore di fare la parte FETCH_HEAD –

2

Modifica: Mi viene in mente che è possibile farlo solo con git merge --no-commit. Questo tenterà l'unione, e anche se non è in conflitto, si fermerà solo prima di impegnarsi. A questo punto è possibile rimuovere tutta la spazzatura non necessaria (compreso il ripristino dei file in conflitto, se necessario) e creare un commit unione contenente solo la sottostruttura desiderata.

risposta originale:

si può infatti utilizzare il filtro-ramo per questo. Uno schema:

Clone la vostra fonte di pronti contro termine:

git clone --bare /path/to/bar /path/to/bar_clone 

Utilizzando un clone nuda vi farà risparmiare il tempo e lo spazio per creare una directory di lavoro.

successivo, utilizzare il filtro-ramo sul clone: ​​

git filter-branch --index-filter 'git rm -rf <unwanted files/directories>' -- --all 

Il --all lascia sapere che si desidera utilizzare tutte arbitri, non solo l'attuale capo.Ora disponi di un repository contenente solo la sottodirectory desiderata e tutta la cronologia ad essa associata.

Nota: Scusate, non conosco un modo veramente semplice per rimuovere tutto tranne quello che volete. Bisogna stare attenti con i caratteri jolly perché non si vuole rovinare le directory git. Ecco qualcosa che sarà il lavoro, anche se è più lento, soprattutto se hai un sacco di file:

git filter-branch --index-filter 'git rm -f `git ls-files | grep -v ^www/tools`' -- --all 

In ogni caso, comunque di gestire l'elenco dei file da rimuovere, si può andare avanti con la stampa sottostruttura, tirando da bar_clone a foo.

3

Provare a utilizzare git subtree per questo. Ti consente di estrarre una sottostruttura di un progetto in un altro progetto, che puoi quindi unire al tuo.

+0

Puoi specificare come fare? Sto cercando di risolvere questo problema qui: http://stackoverflow.com/questions/30704352/sub-directory-into-independent-repository-and-later-merge-back-into-main-reposit –

10

Ho eseguito correttamente questo comando utilizzando i seguenti comandi (riscritto per lo scenario).

$ git remote add Bar /path/to/bar 
$ git merge -s ours --no-commit Bar/master 
$ git read-tree --prefix=public/bar -u Bar/master:www/tools/ 

ATTENZIONE ENORME! Sono ancora in procinto di capire come eseguire il recupero/unione dalla barra. Questo porterà tutto solo una volta.

mio attuale modo di fondere cambiamenti è in questo modo:

$ get fetch Bar 
$ git pull -X subtree=public/bar Bar master 

Questo vi lascerà con conflitti dicendo che una tonnellata di file sono stati rimossi, si può solo git rm loro e poi git commit.

Sono certamente aperto a suggerimenti su un modo migliore per apportare modifiche.

Poiché si tratta di un thread vecchio, è necessario aggiungere che sto utilizzando Git 1.7.9.

+0

Un problema con questo è che porta in tutti i commit del ramo, non solo quelli che riguardano la sottodirectory. C'è un modo per aggirare questo? – pmr

+0

Se si stanno unendo diversi repository, è possibile passare a '--allow-non-related-histories' per unire. –

0

Suggerirei di usare il sottoalbero due volte - una volta per estrarre tutti gli strumenti/www/e una volta per estrarre/pubblico - sembra che/pubblico dovrebbe essere nel proprio repository quindi, vorrei suggerire di spingere/pubblico a un nuovo repository - con tutta la sua storia di sottostrutture, quindi unisci la storia del sottotree di/www/tools nel nuovo repository pubblico e aggiungilo nuovamente come sottostruttura di Foo.

cd foo 
git subtree split --prefix=public --branch=new-shared-public --annotate='(split) ' 
cd../bar 
git subtree split --prefix=www/tools --rejoin --branch=new-shared-www-tools --annotate='(split) ' 

Ora hai due nuovi rami sui tuoi repository. Uno con la cronologia dei commit del pubblico e l'altro con www/tools. Ometterò cd da qui in poi.

creare il nuovo repository pubblico (github Sto assumendo qui, ma suona come si potrebbe desiderare di farlo a livello locale) e spingere il vostro sottostruttura c'è: git checkout nuovo-shared-pubblico git [email protected] push: my_id/new-shared-repo.git TESTA: master

quindi unire la vostra altra filiale in quel:

git checkout new-shared-www-tools 
git remote add Foo [email protected]:my_id/new-shared-repo.git 
git merge -s ours --no-commit Bar/master 

Anche se ho specificato ours come la politica commit, probabilmente (probabilmente) doesn non importa.

Infine, dopo aver preformato l'unione e trasferito al nuovo repository, tornare al repository Foo.Dà la storia pubblica da lì e aggiungi il nuovo repository pubblico come sottostruttura:

git subtree add --squash --prefix shared [email protected]:my_id/new-shared-repo.git master 
git subtree pull --squash --prefix shared [email protected]:my_id/new-shared-repo.git master 
git push 
Problemi correlati