Posso 'git commit' un file e ignorarne le modifiche al contenuto?


355

Ogni sviluppatore del mio team ha la propria configurazione locale. Le informazioni di configurazione sono memorizzate in un file chiamato devtargets.rbche viene utilizzato nelle nostre attività di generazione del rake. Tuttavia, non voglio che gli sviluppatori si facciano a vicenda il file devtargets.

Il mio primo pensiero è stato quello di mettere quel file .gitignorenell'elenco in modo che non si impegnasse con git.

Poi ho iniziato a chiedermi: è possibile eseguire il commit del file, ma ignorare le modifiche al file? Quindi, commetterei una versione predefinita del file e quindi quando uno sviluppatore lo modifica sul proprio computer locale, git ignorerebbe le modifiche e non verrebbe visualizzato nell'elenco dei file modificati quando si esegue uno stato git o git commit .

È possibile? Sarebbe sicuramente una bella caratteristica ...


1
Vedi anche stackoverflow.com/questions/3318043/… su un argomento simile.
VonC,


Risposte:


458

Certo, lo faccio di tanto in tanto usando

git update-index --assume-unchanged [<file> ...]

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

git update-index --no-assume-unchanged [<file> ...]

Documentazione pertinente :

- [no-] assume-invariato
Quando viene specificato questo flag, i nomi degli oggetti registrati per i percorsi non vengono aggiornati. Al contrario, questa opzione imposta / annulla il bit "assume invariato" per i percorsi. Quando il bit "assume invariato" è attivo, l'utente promette di non modificare il file e consente a Git di supporre che il file dell'albero di lavoro corrisponda a ciò che è registrato nell'indice. Se vuoi cambiare il file dell'albero di lavoro, devi disinserire il bit per dire a Git. Questo a volte è utile quando si lavora con un grande progetto su un filesystem che ha una lstat(2)chiamata di sistema molto lenta (es. Cifs).

Git fallirà (con garbo) nel caso in cui debba modificare questo file nell'indice, ad es. Quando si unisce in un commit; pertanto, nel caso in cui il file presupposto non tracciato venga modificato a monte, sarà necessario gestire la situazione manualmente.

Fallire con garbo in questo caso significa che, 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 superarlo ripristinando le modifiche locali, ecco un modo:

 $ git checkout filename.ext

quindi tirare di nuovo e modificare nuovamente il file locale, oppure è possibile impostare –no-assume-unchangede si può fare normale stash e unire, ecc. a quel punto.


10
questo comando fa la propria cosa localmente nella cartella .git? Voglio dire, se eseguo questo comando per un file config.php, questo si propaga ad altri utenti che stanno usando il repository?
Magus,

16
@Magus: No. Funzionerà solo per te.
Rob Wilkerson,

3
E presto dopo si sta andando a voler sapere come determinare è un file si presume invariato: stackoverflow.com/questions/2363197/...
Ciro Santilli郝海东冠状病六四事件法轮功

10
Le modifiche ai file ignorate in questo modo vanno perse quando si usa "git stash". C'è un modo per aggirare questo?
Alexis,

5
Questo non git update-index --assume-unchangedè ciò che serve. public-inbox.org/git/…
jsageryd

97

Il modo preferito per farlo è usare git update-index --skip-worktree <file>, come spiegato in questa risposta :

assume-unchangedè progettato per i casi in cui è costoso verificare se un gruppo di file è stato modificato; quando si imposta il bit, git (ovviamente) presuppone 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 simili), farà finta di non esserlo, usando invece la versione dall'indice. Ciò persiste fino a quando l'indice viene scartato.

Per annullare l'operazione, utilizzare git update-index --no-skip-worktree <file>

Dalla versione 2.25.1 di git, neanche questo è più il metodo raccomandato, citando:

Gli utenti spesso provano a usare i bit assume-invariato e skip-worktree per dire a Git di ignorare le modifiche ai file tracciati. Questo non funziona come previsto, poiché Git può comunque verificare i file dell'albero di lavoro rispetto all'indice durante l'esecuzione di determinate operazioni. In generale, Git non fornisce un modo per ignorare le modifiche ai file tracciati, quindi sono consigliate soluzioni alternative.

Ad esempio, se il file che si desidera modificare è una sorta di file di configurazione, il repository può includere un file di configurazione di esempio che può quindi essere copiato nel nome ignorato e modificato. Il repository può anche includere uno script per trattare il file di esempio come modello, modificandolo e copiandolo automaticamente.


Funziona su tutti gli utenti che effettuano il checkout del repository? Otterranno determinati file ma non saranno più in grado di aggiungere modifiche, per errore, a meno che non lo dica esplicitamente?
mmm

2
@momomo il flag è memorizzato nell'indice quindi no, è solo per un singolo utente. Vedi la risposta di erjiang per qualcosa che funziona su tutti gli utenti.
1615903,

Sto cercando di capire quale dovrebbe essere il contenuto del file. Ho commentato la risposta a cui ti riferivi, ma non ho ricevuto risposta. Dove dovrebbe trovarsi e quali sono i suoi contenuti? Lo sai?
mmm

Non sto seguendo. Il comando viene utilizzato per ignorare un file specifico specificato nel comando. Il contenuto di quel file non è pertinente.
1615903,

1
La documentazione di Git afferma specificamente di non utilizzare git update-index --skip-worktreea questo scopo.
bk2204,

43

La pratica comune sembra essere quella di crearne uno devtargets.default.rbe di impegnarlo, quindi istruire ogni utente a copiare quel file 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.


6
Non puoi .gitignore un file che viene monitorato. .gitignore ha effetto solo per i file che non sono nell'indice.
CB Bailey,

1
stavo cercando di evitare di farlo, anche se in realtà non ho una buona ragione. lo stiamo facendo ora e penso che sia doloroso ricordare che devo creare la mia versione senza ".default" nel nome.
Derick Bailey,

11
@DerickBailey Ma per essere onesti, è più facile ricordare di copiare il file che ricordare di usare l' --assume-unchangedopzione per tutti coloro che clonano il repository.
Dan,

1
@DerickBailey potresti anche impostare la tua build di rake sui valori predefiniti devtargets.default.rbse devtargets.rbnon esiste.
Luca,

@erjang cosa c'è in quel file devtargets.default.rb? Un esempio?
mmm,

2

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

  • Vai a Local Changes( Cmd + 9)
  • Seleziona i file che desideri ignorare
  • F6 per spostarli in un altro Change Set
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.