Posso ‘git commit’ un file e ignorare le sue modifiche del contenuto?

Ogni sviluppatore del mio team ha la propria configurazione locale. Quelle informazioni di configurazione sono memorizzate in un file chiamato devtargets.rb che è usato nelle nostre attività di rake build. Tuttavia, non voglio che gli sviluppatori clobber il file di devtarget l’uno dell’altro.

Il mio primo pensiero è stato quello di mettere quel file nell’elenco .gitignore modo che non si impegni a git.

Poi ho iniziato a chiedermi: è ansible impegnare il file, ma ignorare le modifiche al file? Quindi, importerò una versione predefinita del file e poi quando uno sviluppatore lo cambia sul proprio computer locale, git ignorerebbe le modifiche e non comparirà nell’elenco dei file modificati quando si esegue uno stato git o un commit git .

È ansible? Sarebbe certamente una bella caratteristica …

Certo, faccio esattamente questo di volta in volta usando

 git update-index --assume-unchanged [ ...] 

Per annullare e avviare nuovamente il tracciamento (se hai dimenticato quali file non sono stati tracciati, vedi questa domanda ):

 git update-index --no-assume-unchanged [ ...] 

Documentazione pertinente :

– [no-] assumere-invariata
Quando viene specificato questo flag, i nomi object registrati per i percorsi non vengono aggiornati. Invece, questa opzione imposta / distriggers il bit “assuma invariato” per i percorsi. Quando il bit “assume immutato” è attivo, l’utente promette di non modificare il file e consente a Git di assumere che il file dell’albero di lavoro corrisponda a quanto registrato nell’indice. Se vuoi cambiare il file dell’albero di lavoro, devi disinserire il bit per comunicare a Git. Questo è a volte utile quando si lavora con un grosso progetto su un filesystem che ha una chiamata di sistema lstat(2) molto lenta (es. Cifs).

Git fallirà (con garbo) nel caso in cui debba modificare questo file nell’indice, ad esempio durante l’unione in un commit; quindi, nel caso in cui il file presunto non tracciato venga modificato a monte, sarà necessario gestire la situazione manualmente.

Fallire con garbo in questo caso significa, se ci sono cambiamenti a monte di quel file (modifiche legittime, ecc.) Quando fai un pull, dirà:

 $ git pull … From https://github.com/x/y 72a914a..106a261 master -> origin/master Updating 72a914a..106a261 error: Your local changes to the following files would be overwritten by merge: filename.ext 

e rifiuterà di fondersi.

A quel punto, puoi risolvere questo problema ripristinando le modifiche locali, ecco un modo:

  $ git checkout filename.ext 

quindi tira di nuovo e modifica nuovamente il tuo file locale, oppure potresti impostare –no-assume-unchanged e puoi fare lo stash e l’unione normali, ecc. a quel punto.

Il modo migliore per farlo è usare git update-index --skip-worktree , come spiegato in questa risposta :

assume-unchanged è progettato per i casi in cui è costoso controllare se un gruppo di file è stato modificato; quando si imposta il bit, git (ovviamente) assume che i file corrispondenti a quella parte dell’indice non siano stati modificati nella copia di lavoro. Quindi evita un pasticcio di chiamate stat. Questo bit viene perso ogni volta che cambia la voce del file nell’indice (quindi, quando il file viene modificato a monte).

skip-worktree è più di questo: anche se git sa che il file è stato modificato (o deve essere modificato da un reset –hard o simile), farà finta che non lo sia stato, usando invece la versione dall’indice . Questo persiste fino a quando l’indice non viene scartato.

Per annullare ciò, utilizzare git update-index --no-skip-worktree

La pratica comune sembra essere quella di creare un devtargets.default.rb e devtargets.default.rb commit, quindi istruire ogni utente a copiare quel file su devtargets.rb (che si trova nell’elenco .gitignore). Ad esempio, CakePHP fa lo stesso per il suo file di configurazione del database che cambia naturalmente da macchina a macchina.

Per gli utenti di IntelliJ IDEA: se si desidera ignorare le modifiche per un file (o file), è ansible spostarlo in un altro gruppo di Change Set .

  • Passa alle Local Changes ( Cmd + 9 )
  • Seleziona i file che vuoi ignorare
  • F6 per spostarli in un altro Change Set