Usando git, come posso ignorare un file in un ramo ma lo ho commesso in un altro ramo?


157

Ho un progetto che sto distribuendo a Heroku . L'albero del codice sorgente include un mucchio di file mp3 (il sito web sarà per un progetto di registrazione di cui ero fortemente coinvolto).

Vorrei inserire il codice sorgente su GitHub , ma GitHub ha un limite di 300 MB sui loro account gratuiti. Non voglio usare 50 MB del mio limite su un mucchio di file mp3. Ovviamente, potrei aggiungerli al .gitignorefile per tenerli fuori dal mio repository.

Tuttavia, mi schierò su Heroku usando git push heroku. I file mp3 devono essere presenti nel ramo che spingo su Heroku in modo che vengano distribuiti.

Idealmente, vorrei .gitignorei file mp3 nel mio ramo master locale in modo che quando lo spingo su GitHub, gli mp3 non fossero inclusi. Quindi terrei un ramo di produzione locale che ha impegnato gli mp3 piuttosto che ignorato. Per schierare, unirei il padrone in produzione e quindi spingere il ramo di produzione a Heroku.

Non riesco a farlo funzionare bene.

Ecco un esempio di ciò che sto cercando di fare ...

$ git init git-ignore-test
$ cd git-ignore-test
$ echo "*.ignored" >> .gitignore
$ git add .gitignore && git commit -m "Ignore .ignored files"
$ touch Foo.ignored

A questo punto, Foo.ignored viene ignorato nel mio ramo principale, ma è ancora presente, quindi il mio progetto può usarlo.

$ git checkout -b unignored
$ cat /dev/null > .gitignore
$ git add Foo.ignored .gitignore && git commit -m "Unignore .ignored files"

Ora ho un ramo con questi file impegnati, come voglio. Tuttavia, quando torno al mio ramo principale, Foo.ignored non c'è più.

Qualcuno ha qualche suggerimento per un modo migliore per impostare questo?

Modifica: solo per chiarire, voglio che i file mp3 siano presenti in entrambi i rami in modo che quando eseguo il sito localmente (usando entrambi i rami) il sito funzioni. Voglio solo che i file vengano ignorati in un ramo, quindi quando invio a GitHub non vengono inseriti. Di solito .gitignore funziona bene per questo tipo di cose (vale a dire mantenere una copia locale di un file che non viene incluso in un push su un telecomando), ma quando passo al ramo con i file archiviati, e poi di nuovo al ramo con i file ignorati, i file svaniscono.


Perché i file MP3 devono mai essere impegnati nel repository?
Dan Loewenherz,

4
Con heroku, il commit nel tuo repository è l'unico modo per includere i file con la tua app durante la distribuzione. L'unica alternativa è usare qualcosa come Amazon S3 per servire gli mp3, ma preferirei evitarlo.
Myron Marston,

Sembra che tu stia inciampando in dollari per risparmiare qualche soldo ... Rackspace Cloud è molto semplice da configurare, e costerebbe molto poco archiviare <1 GB di file lì ...
gahooa

3
Ho notato che hai contrassegnato una risposta come corretta ma da quello che ho letto potrebbe non essere corretta. Hai mai provato la risposta e ha funzionato per te?
loop

2
Off Topic: hai preso in considerazione l'utilizzo di un altro host di repository open source? BitBucket non ha limiti di dimensione nei propri repository Git, indipendentemente dal fatto che si trovino in un account gratuito o meno (menzionano per mantenere le dimensioni entro limiti ragionevoli). Finché il tuo repository non cresce senza controllo, questa potrebbe essere un'opzione. NOTA: non sono associato a BitBucket, solo un cliente felice.
NightOwl888,

Risposte:


84

Questa soluzione sembra funzionare solo per alcune versioni di git con patch. Vedere una nuova risposta che punta a soluzioni alternative e un'altra risposta e commenti successivi per un suggerimento su quali versioni potrebbero funzionare.

Ho scritto un post sul blog su come utilizzare in modo efficace i excludesfilediversi rami, come uno per github pubblico e uno per la distribuzione di heroku.

Ecco il veloce e sporco:

$ git branch public_viewing
$ cd .git/
$ touch info/exclude_from_public_viewing
$ echo "path/to/secret/file" > info/exclude_from_public_viewing 

quindi nel file .git / config aggiungi queste righe:

[core]
excludesfile = +info/exclude


[branch "public_viewing"]
excludesfile = +info/exclude_from_public_viewing

Ora tutte le cose ignorate globali sono nel info/excludefile e il ramo specifico è nel fileinfo/exclude_from_public_viewing

Spero che aiuti!

http://cogniton-mind.tumblr.com/post/1423976659/howto-gitignore-for-different-branches


1
Ci scusiamo per aver impiegato così tanto tempo .. ma se non elimini i file .gitignore, verranno impostati per primi su quelli.
Cognition.Mind

4
Questo non funziona per me, anche quando il progetto non utilizza .gitignore. Ti dispiace fornire una trascrizione dei comandi che la configurano da zero ( git init, ...) e la versione di Git che hai usato?
Assapora Cubranic il

34
Questa soluzione non funziona. Ci sono state alcune discussioni sul blog e nessuno è stato in grado di farlo funzionare.
spuder


2
In Vanilla Git, sono abbastanza sicuro che non funzioni e non ha mai funzionato. Chi di voi è riuscito a riprodurlo, è possibile condividere la propria versione Git e altre informazioni rilevanti sul proprio ambiente? Forse hai una versione patchata dai manutentori del pacchetto Git della tua distribuzione.
Palec,

20

Suggerimento importante : la risposta accettata da Cognition.Mind non funziona (più, ormai da diversi anni o forse per le versioni vanilla di git); vedi i commenti. Una risposta valida e una soluzione alternativa sono disponibili qui:

https://stackoverflow.com/a/29583813/2157640

Un'altra soluzione alternativa (lavorare per il mio problema specifico, ma richiedere operazioni manuali di stash o implementazione di un hook) sarebbe git stash -u -a. Questo è noioso quando le differenze sono grandi.

E infine, la soluzione che sto cercando ora è quella di aver biforcuto la mia VM in cui conserviamo il nostro ambiente di sviluppo e di configurarla in modo info/excludesappropriato per il ramo, eliminando rispettivamente i file / le cartelle offensive e senza commit.


14

Consiglio vivamente di considerare di mettere quei file MP3 su S3. Il fatto che siano parte della tua spinta Heroku (e quindi parte della tua lumaca Heroku) rallenterà notevolmente il tuo tempo di avvio della prova. Dato che Heroku utilizza EC2, se i file si trovano su S3 e sono accessibili solo dalla tua app (se gli utenti non sono direttamente collegati a S3) non pagherai nemmeno alcun costo di larghezza di banda, solo il costo per memorizzare 50 MB.


13

Diciamo che vogliamo ignorare la buildcartella da tutti gli altri rami tranne il productionramo. Come vogliamo spingere la buildcartella in produzione.

1) Non includere buildin .gitignore. Se lo fai, verrà sempre ignorato per tutti i rami.

2) Crea un file exclude_from_public_viewingnella ./.git/infocartella (questa cartella esiste già)touch ./.git/info/exclude_from_public_viewing

3) All'interno exclude_from_public_viewingscrivi una riga (Mentre stai cercando di ignorare buildper tutti i rami). !build

4) C'è un file esistente .git/info/exclude. Dobbiamo aggiungere la seguente riga in esso.

 build

Vogliamo ignorare la buildcartella ma non l'ha aggiunta in .gitignore. Quindi come git saprà cosa ignorare? La risposta è che lo stiamo aggiungendo al excludefile e lo stiamo passando in modo condizionalegit config

5) Ora dobbiamo unignore condizionale della buildcartella per il productionramo. per farlo esegui quanto segue

6) Esiste un file esistente chiamato ./.git/configche è necessario aggiungere quanto segue -

a) excludesfile = +info/excludesotto[core]

[core]
     excludesfile = +info/exclude

b) Creare una nuova sezione alla fine di ./.git/configas

[branch "production"]
    excludesfile = +info/exclude_from_public_viewing

Soluzione 2

Esiste una soluzione alternativa intelligente. Diciamo che vuoi aggiungere una build/cartella nel productionramo e ignorarla in tutti gli altri rami.

1) Aggiungilo al tuo gitignorefile.

2) Nel ramo di produzione, mentre lo fai git add, forza aggiungi buildcartella:git add -f --all build/


E questo differisce dalla soluzione accettata come? Con quale versione di Git l'hai testata? Come afferma la risposta collegata, fallisce perché non c'è supporto per branch.<name>.excludesfilein git (più?), Solo per core.excludesfile, e i miei test sembravano affermarlo.
Murphy

@murphy funziona bene con git version 2.7.4 (Apple Git-66)e non ho usato branch.<name>.excludesfile nella mia soluzione.
sapy,

4
@sapy: ho provato questo secondo il caso d'uso di OP, e il file svanisce ancora quando passo dalla produzione al master. Si noti che la cartella "build" deve essere inserita nel ramo "production". (Inoltre, noto che se non eseguo il commit della cartella "build" nel ramo "production", il ramo "production" ignora la presenza della cartella "build" - vale a dire, la [produzione "branch"] exclesfile config doesn non funziona). Uso esattamente la stessa versione di git della tua. Ho anche provato l'approccio del [ramo "produzione"] per ignorare il file solo nel ramo di produzione, inoltre non funziona, come ha detto Murphy.
solo il

La soluzione 2 era qualcosa che stavo cercando. Grazie!
Vyacheslav Cotruta,

4

Hai provato ad avere .gitignore diverso nel tuo ramo?

Dovresti essere in grado di ignorare ciò che desideri in base al ramo in cui ti trovi purché i file non vengano tracciati su quel ramo.


6
Ci ho provato. Se guardi i comandi che ho postato sopra vedrai che è esattamente quello che ho fatto. Il problema è che quando passo dal ramo con i file registrati al ramo con i file ignorati, git scarta i file. Voglio mantenere gli mp3 nel mio ramo principale in modo che il sito funzioni correttamente in modalità dev, anche se i file vengono ignorati.
Myron Marston

1
ha già detto che è quello che ha fatto. forse solo cancellare questa risposta potrebbe essere la cosa migliore :-) sta causando distrazione.
blamb

3

1. Riepilogo

  1. Uso Travis CI per la distribuzione ( supporta la distribuzione di Heroku )
  2. Aggiungo al mio .travis.yml:

    before_deploy:
    - mv misc/.gitignore .gitignore

    Dove misc : qualsiasi cartella ne contiene un'altra .gitignore.

    mvComando UNIX sposta file; sovrascrivi, se il file esiste già.

Quando Travis CI distribuisce il progetto, Travis CI non invierà la distribuzione al provider file e cartelle del , che ignorati misc/.gitignore(non nell'originale .gitignoredelle fonti).


2. Limitazioni

  1. Questa risposta potrebbe non essere adatta a tutte le condizioni dell'autore. Ma questa risposta risponde alla domanda "Usando git, come posso ignorare un file in un ramo ma lo ho impegnato in un altro ramo?"
  2. Non sono un utente di Heroku, i miei esempi per GitHub , non per Heroku. I dati di questa risposta funzionano per me in GitHub, ma potrebbero non funzionare su Heroku.

3. Rilevanza

Questa risposta è pertinente per aprile 2018. In futuro, i dati di questa risposta potrebbero essere obsoleti.


4. Dimostrazione

il mio vero progetto .

Esempio di distribuzione corretta .

4.1. Compito

Distribuisco il mio progetto dal ramo SRC al ramo dest dello stesso repository.

Voglio quel file PaletteMira.suricate-profile:

  • Macchina locale: esiste per tutte le filiali,
  • ramo remoto src - non esiste,
  • ramo remoto dest - esiste.

Se ho capito correttamente l'autore della domanda, avrebbe un compito simile.

4.2. src

ramo delle fonti - SashaYAML .

Parte di .travis.yml:

before_deploy:
- mv misc/.gitignore .gitignore

deploy:
  provider: pages
  on:
    branch: SashaYAML
  keep-history: true
  skip-cleanup: true
  target-branch: SashaDevelop
  repo: Kristinita/PaletteMira
  github-token: $GITHUB_TOKEN
  committer-from-gh: true
  project-name: PaletteMira
verbose: true

Parte di .gitignore:

*.sublime-snippet
*.suricate-profile

Parte di misc/.gitignore

*.sublime-snippet

*.suricate-profilenon dentro misc/.gitignore.

PaletteMira.suricate-profile non esiste in questo ramo in remoto, ma esiste localmente.

4.3. dest

ramo di destinazione - SashaDevelop

Parte di .gitignore:

*.sublime-snippet

*.suricate-profilenon dentro misc/.gitignore.

PaletteMira.suricate-profileesiste per questo ramo da remoto e localmente.

4.4. I passaggi per riprodurre

Abilito il repository GitHub di PaletteMira per Travis CI → Ho impostato la variabile di ambiente $GITHUB_TOKEN con valore - il mio token GitHub → commit sul mio ramo src.

Se non ci sono errori, devo ottenere il comportamento previsto .


0

Puoi impegnarti e spingere da Heroku?

ad esempio, aggiungi l'audio, spingilo su github e in heroku, rimuovi i file dalla copia di lavoro su Heroku. Rimuovere l'audio dal repository ma non dal disco, quindi riportare la modifica su github.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.