Come posso fare in modo che git ignori le future revisioni di un file?


140

Ho creato una versione predefinita di un file incluso in un repository git. È importante che quando qualcuno clona il repository ottenga una copia di questo file. Tuttavia, vorrei impostare git in modo che ignori le modifiche a questo file in seguito. .gitignorefunziona solo su file non tracciati.

La mia motivazione è che questo file contiene informazioni specifiche della macchina. Vorrei fornire valori predefiniti, consentendo allo stesso tempo alle persone di apportare modifiche locali che non verranno rimandate al repository di origine, creando conflitti di unione quando vengono apportate nuove modifiche.

In genere siamo abbastanza pigri e usiamo git add .molto, quindi sono abbastanza sicuro che se non riesco a dire a git di ignorare questo file, le modifiche finiranno per essere impegnate e spinte.

Riassumere,

  1. Vorrei creare un file, chiamarlo default_values.txtche viene aggiunto al mio repository git ed è incluso quando qualcuno clona quel repository.
  2. git add .non dovrebbe aggiungere default_values.txtal commit.
  3. Questo comportamento deve essere trasmesso a tutti i cloni del repository.

1
Puoi usare git hook per avere un hook pre-commit che interromperebbe un commit se il file modificato fosse default_values.txt (diciamo)?
Sateesh,

1
I puristi di Git direbbero di non essere pigri e di usare correttamente l'area di stadiazione, ecco a cosa serve.
Xint0

I puristi di Git direbbero che usano script smudge / clean. È la soluzione più mantenibile.
Adam Dymitruk, il

1
Xint0: vero. ma come evitare che altre persone effettuino il check-in accidentale?
Alan

Risposte:


115

Come molti altri hanno già detto, una buona soluzione moderna è:

git update-index --skip-worktree default_values.txt

Ciò ignorerà le modifiche a quel file, sia locale che upstream, fino a quando non deciderai di consentirle nuovamente con:

git update-index --no-skip-worktree default_values.txt

È possibile ottenere un elenco di file contrassegnati come ignorati con:

git ls-files -v . | grep ^S

Si noti che --skip-worktree, a differenza di , lo --assume-unchangedstato andrà perso una volta che viene apportata una modifica a monte.


2
Se qualcun altro estrae il repository e modifica il file, le modifiche nella loro directory vengono ignorate? Spero che dovrebbero digitare --no-skip-worktreeper aggiungere le loro modifiche.
neaumusica il

3
Ciò che viene fatto con i loro cambiamenti è controllato da loro. In altre parole, dovrebbero impostare skip-worktree sul file nel loro repository se non volessero che le loro modifiche venissero inviate. Se si tratta di un file che deve essere inviato a tutti e quindi ignorare tutte le modifiche successive, tutti dovrebbero seguire le stesse istruzioni.
moodboom l'

3
Si noti che potrebbe essere necessario annullare lo --skip-worktreestato di un file prima di poter cambiare ramo, se lo stesso file viene tracciato nell'altro ramo.
moodboom

3
hmm, funziona ... dopo che ho apportato alcune modifiche al file non è stato mostrato in git status, ma quando ho provato a fare il checkout in un ramo diverso, ho error: Your local changes to the following files would be overwritten by checkout: , anche -f non aiutaerror: Entry 'wix-stores-merchant-app/demo/credentials.js' not uptodate. Cannot merge.
ykravv

1
Ho questi alias di git ignoree git unignore.
Michael

48

Quello che stai cercando è git update-index --assume-unchanged default_values.txt.

Vedi i documenti per maggiori dettagli: http://www.kernel.org/pub/software/scm/git/docs/git-update-index.html


11
questo non funziona. sebbene faccia aggiungere git. ignora il file sul ramo locale, un clone dell'archivio non ha questo comportamento (se cambi default_values.txt nell'archivio clonato, verrà aggiunto al commit con "git add.")
Marc

6
Sì, perché lo stai impostando solo per il repository locale. Non è possibile inviare questo tipo di informazioni.
tamasd,

8
@Indradhanush - questa soluzione non soddisfa il criterio 3 - "il comportamento deve essere trasmesso a qualsiasi clone del repository" - motivo per cui non l'ho accettato. Non significa che non sia una buona risposta.
Marc,

Non ho mai notato il terzo criterio. Perché non lo stavo cercando. :)
Indradhanush Gupta,

3
Per i file di configurazione locali con impostazioni di app private, è probabile che tu voglia utilizzare skip-worktreeinvece di assume-unchangedulteriori informazioni stackoverflow.com/questions/13630849/…
Aaron Hoffman,

22

L'approccio che ho visto generalmente è quello di creare un file con un nome diverso, ad esempio: default_values_template.txt e inserire default_values.txt nel tuo .gitignore. Chiedere alle persone di copiare default_values_template.txt in default_values.txt nelle loro aree di lavoro locali e apportare le modifiche necessarie.


hmmm ... forse potrei scrivere un hook per copiare automaticamente default_values_template in default_values ​​se default_values ​​non esiste?
Marc

2
Questo è il modo più comune di risolverlo nella mia esperienza. È praticamente il percorso di minor resistenza in quanto "funziona" e puoi facilmente controllare il tuo codice se esiste il file di configurazione locale e fornire un errore utile in caso contrario.
Jani Hartikainen,

Penso che la soluzione sia effettivamente fare qualcosa del genere, preferibilmente con una sceneggiatura eseguita ogni volta che tiri o cloni. Un'idea sarebbe che qualsiasi cosa con una particolare estensione (diciamo .basefile) viene copiata in un file con l'estensione rilasciata e quindi il nome del file viene aggiunto a .gitignore in quella directory. Quindi vorrei creare un file default_values.txt.basefile e impegnarlo. Non ho le costolette git o perl per farlo, ma chiederò a un amico che lo fa e ti farò sapere come funziona.
Marc,

1
@AdamDymitruk: Sì, in questo caso è possibile utilizzare clean / smudge, ma è tutt'altro che chiaro che sia l'opzione migliore. Ad esempio, questo renderà piuttosto difficile se le persone vogliono davvero cambiare il file, poiché clean / smudge si metterà in mezzo. Preferirei in realtà l'approccio descritto qui.
sleske,

1
Prendo spunto da git stesso (in particolare git git) e uso il .samplesuffisso. Quindi nel tuo casodefault_values.txt.sample
tir38,

5

Dai un'occhiata a sbudge / scripting pulito. In questo modo è possibile controllare la versione del file ma quando viene estratto, lo si "macchia" sostituendo i dati generici / segnaposto con i dati specifici della macchina nel file.

Quando lo commetti, lo "pulirai" sostituendo le informazioni specifiche della macchina con informazioni generiche o segnaposto.

Gli script sfumino / pulito devono essere deterministici in quanto applicarli più volte, in diversi ordini equivale a eseguire l'ultimo nella sequenza.

Lo stesso può essere applicato con le password se è necessario esporre il proprio repository ma i contenuti possono contenere informazioni riservate.


Gli script Clean and Smudge sono locali o fanno parte del repository?
Alan,

sì. :) ... cioè, puoi condividere la sfumatura pulita tramite il repository, ma non è una buona idea quando contengono dati sensibili come le password di produzione. Se questo non è un problema, git richiede di abilitare esplicitamente lo script. Altrimenti, le persone potrebbero fare cose dannose tramite github e altri repository condivisi ad altri utenti.
Adam Dymitruk,

Ho bisogno di leggere qualcosa in più su questo. Fondamentalmente voglio impostare un progetto che ha un valore predefinito user.jsonche deve essere sovrascritto con i crediti di ogni sviluppatore, ma non voglio che lo sviluppatore controlli accidentalmente i propri crediti.
Alan,

Vorrei andare in giro per gli script di esempio di sbavature pulite. Guarda cosa succede. Inoltre, salta nella stanza git irc su freenode. Riceverai aiuto immediatamente.
Adam Dymitruk,

3

Ho risolto questo definendo il filtro "pulito" per semplicemente cat il contenuto del file nell'indice.

git show :path/to/myfile dovrebbe semplicemente stampare il contenuto dell'indice per il file specificato, quindi possiamo usarlo in uno script per sostituire la copia funzionante con la copia non trattata nell'indice:

#! /bin/sh

git show :$1

Impostalo come filtro "pulito" per il file in questione (supponendo di averlo inserito in "discard_changes"):

$ git config filter.ignore_myfile.clean "discard_changes path/to/myfile"
$ echo "path/to/myfile filter=ignore_myfile" >> .gitattributes

Sfortunatamente non riesco a trovare un modo per rendere questo generalizzabile a più file, poiché non c'è modo di dire quale file stiamo elaborando dall'interno dello script pulito. Ovviamente, non c'è nulla che ti impedisca di aggiungere una diversa regola di filtro per ogni file, ma è un po 'confusa.


1

Ho trovato una soluzione che funziona per il mio team. Condividiamo i nostri githook tramite link simbolici e dopo aver aggiunto un file modello a git ho aggiunto un hook pre-commit che controlla se il file modello è stato modificato e, in caso affermativo, io git reset -- templatefile.txt. Se è l'unico file modificato, interrompo anche il commit.


-1

Suggerisco di esaminare i sottomoduli. Se si inseriscono i file specifici della macchina in un sottomodulo, git add dovrebbe ignorarlo.


questa è una buona idea, ma poi devo anche mettere il repository di file singolo sul server git, il che è meno che ottimale, solo perché stiamo usando github e abbiamo un numero limitato di repository.
Marc,

@Marc dai un'occhiata a Visual Studio Team Services, progetti privati ​​gratuiti illimitati e repository git. Bacheche kanban, oggetti di lavoro e tracciamento dei bug, associa check-in ad oggetti di lavoro, gestisci gli sprint se sei in mischia o altri tipi di progetto. Oltre a questo ha eccellenti strumenti di costruzione per la costruzione su più piattaforme, troppe cose da dire che sono tutte gratuite. Alcune persone lo sculacciano perché è Microsoft, ma tramanda chiaramente ciò che Github ha da offrire in termini di strumenti oltre al semplice hosting di repository. Ci sono limiti a ciò che puoi fare gratuitamente ma raramente li supero.
Aran Mulholland,

@Marc un'altra cosa che trovo davvero utile al riguardo è che posso creare tutti gli account che voglio, quindi se sto scrivendo un progetto per un cliente che vuole possedere il controllo del codice sorgente posso creare un account, usarlo per pianificare, progettare ed eseguire il progetto e quando ho finito posso passare la proprietà dell'account al cliente.
Aran Mulholland,
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.