2014-07-31 18 views
5

Voglio usare git per mantenere un record cronologico delle dipendenze reali che un'applicazione ha utilizzato nel tempo, con maggiore fedeltà di quella che posso ottenere dal gestore pacchetti.Git - Come posso schiacciare le modifiche ai file ignorati senza perdere queste modifiche?

Sto usando questi rami:

  • maestro: solo il codice sorgente. dipendenze in .gitignore
  • costruzione: il codice sorgente e le dipendenze
  • build-$ TIMESTAMP: ramo temporaneo utilizzato per forzare l'inserimento di un file ignorati

E questo script, build-release.sh:

DEV_MODULES="mocha chai bower coffeelint" 
BUILT_FILES="node_modules build" 
DATE=$(date) 
TIMESTAMP=$(date +"%s") 
BRANCH=$(git rev-parse --abbrev-ref HEAD) 

# create a temporary branch with the current dependencies and binaries 
npm uninstall $DEV_MODULES 
git checkout -b build-$TIMESTAMP 
git add --all --force $BUILT_FILES 
git commit -m "copy $BUILT_FILES from $BRANCH" 

# merge the temporary branch into the build branch 
git branch build || echo "build branch already exists" 
git checkout build --force 
git merge build-$TIMESTAMP --strategy=subtree -m "Build as of $DATE" 
git branch -D build-$TIMESTAMP 

# restore the original branch 
git checkout $BRANCH 
git checkout build -- $BUILT_FILES 
git rm -r --cached $BUILT_FILES 

Quali opere e mi fornisce un'utile vista delle modifiche all'origine, alle dipendenze e ai binari da una versione all'altra:

Screenshot showing merge bubbles

Tuttavia, il commit richiede il doppio di quanto necessario. Voglio che l'albero a guardare come questo:

artist's concept

Come posso combinare i "file costruite copia" impegnano con il "costruire come di" impegnarsi?

Quando provo a git merge --squash, finisce con lo stato che era sul build invece dello stato che era su build-$TIMESTAMP, che non è corretto (voglio importare le modifiche ai file ignorati, ma si fondono sembra non avere la lingua di Fai questo). Quando provo a git rebase --onto build build-$TIMESTAMP perdo la parentela del nuovo commit.

voglio solo registrare i file esatto che ricevo sul ramo build-$TIMESTAMP, ma con entrambe le build e master rami come genitori, poi puntare il ramo build a quel commit.

+2

Perché esattamente si desidera eseguire il commit di file ignorati? Se vuoi semplicemente tenere traccia delle dipendenze storiche, perché non limitarti a documentarlo in un file creato manualmente? – Julian

+0

Vorrei anche raggruppare le dipendenze esatte che hanno superato i test e trasmetterli alla produzione, senza presupporre che tutti i server di produzione saranno in grado di installarli in modo identico. Usare git per trasmettere delta è sembrato un buon modo per ottenerlo e ottenere anche il change-tracking. – Phssthpok

+1

https://www.npmjs.org/doc/cli/npm-prune.html usa 'npm prune --production' per rimuovere devDependencies;) – soyuka

risposta

3

Questo è semplice territorio idraulico. Stai usando i comandi "porcellana", il sistema di controllo del codice sorgente costruito sul core del tracker di contenuti di Git, in modo da far trasparire quella porcellana nel fare ciò che desideri, ma è molto più semplice parlare direttamente con il tracker del contenuto .

Per una lettura più semplice di ciò che è nella tua domanda, vale a dire che si desidera che il "costruire" ramo per registrare istantanee di cassa corrente insieme a una selezione di ciò che è nei i "$BUILT_FILES" percorsi/directory, è

# knobs 
DEV_MODULES="mocha chai bower coffeelint" 
BUILT_FILES="node_modules build" 
DATE=$(date) 

# clean out stuff we don't care about 
npm uninstall $DEV_MODULES 

# record current checkout plus "$BUILT_FILES" to `build` branch 
git add --all --force $BUILT_FILES 
build=`git rev-parse -q --verify build` 
git update-ref refs/heads/build $(
     git commit-tree ${build:+-p $build} -p HEAD \ 
       -m "build as of $DATE" \ 
       `git write-tree` 
) 

# reset index to HEAD 
git reset # `git read-tree HEAD` will have the same effect, perhaps more quietly 

Come una breve panoramica o un promemoria a seconda dei casi, il database degli oggetti di git è un archivio di valori-chiave con indice hashcode. Chiedete a Git per qualsiasi cosa per il suo tipo e per l'hash, riguadagna con forza esattamente quello dal suo oggetto db. L'indice non è altro che un file flat, un manifest indicizzato dal percorso, che mostra quale contenuto nell'oggetto db va a quale percorso, insieme ad alcuni metadati e note per il tracciamento delle operazioni in volo. git add il contenuto in un percorso inserisce semplicemente il contenuto nell'oggetto db e l'hash del contenuto nella voce di indice per quel percorso.

(un po 'di sproloquio qui, salta se non dell'umore da predicare) La cosa da capire è che il git è assolutamente brutalmente concreto. Tutto ciò che riguarda un repository oltre l'oggetto db è pura convenzione. git checkout fa sì che HEAD si riferisca al commit che ha effettuato esclusivamente per convenzione. È possibile implementare git checkout come un involucro estremamente sottile intorno a git read-tree -um - l'operazione principale principale consiste nell'impostare HEAD nel commit da cui si ottiene quell'albero. git commit rende HEAD il genitore di ciò che stai commettendo esclusivamente per convenzione. È possibile implementare lo git commit come involucro estremamente sottile intorno a git commit-tree e git write-tree, l'operazione principale aggiuntiva consiste nel fornire HEAD come genitore e passare al nuovo commit HEAD. Il nome HEAD è di per sé puramente convenzionale. Il tracker di contenuti su cui sono costruiti non potrebbe interessare meno di HEAD, o la distinzione tra rami e tag, o qualcosa del genere. Le convenzioni sono intenzionalmente, aggressivamente e brutalmente semplici, perché (a) non c'è bisogno di astrazione, il modello di contenuto soddisfa già perfettamente i requisiti, e (b) l'intero punto di git è la mancanza di astrazione al centro: è "stupido" ".

0

A mio parere, la soluzione migliore sarebbe cambiare il modo in cui si utilizza git qui. Git è un sistema di controllo della versione e ha lo scopo di tracciare le modifiche ai file nel tempo. Poiché stai aggiungendo e rimuovendo file in modo costante, lo stai perdendo e lo utilizzi solo come archivio file. Quindi, perché non usare solo un archivio di file. Penso che la tua soluzione sia intelligente, ma mi sa di come stai "combattendo il quadro".

Penso che se si desidera mantenere una registrazione dei file creati e delle dipendenze effettive, sarebbe meglio comprimere tutto e archiviarlo da qualche parte come parte del processo di compilazione.

+0

Penso che l'OP stia cercando anche di dare una rapida occhiata a quali dipendenze cambiano nel tempo, quindi non sono sicuro che un archivio di file possa davvero scalfire il prurito qui. Sembra che stia cercando di tenere traccia dei cambiamenti, solo in un modo un po 'non ortodosso. – fox

+0

Sembra più simile alla gestione della configurazione. –

Problemi correlati