Come interrompere il tracciamento e ignorare le modifiche a un file in Git?


1731

Ho clonato un progetto che include alcuni .csprojfile. Non ho bisogno / mi piace che i miei csprojfile locali vengano tracciati da Git (o che vengano visualizzati durante la creazione di una patch), ma chiaramente sono necessari nel progetto.

Ho aggiunto *.csproja LOCAL .gitignore, ma i file sono già nel repository.

Quando digito lo stato git, mostra le mie modifiche alle csprojquali non sono interessato a tenere traccia o inviare le patch.

Come rimuovo il "tracciamento" di questi file dal mio repository personale (ma li conservo nella fonte in modo da poterli usare) in modo da non vedere le modifiche quando faccio uno stato (o creo una patch)?

Esiste un modo corretto / canonico per gestire questa situazione?


18
Una domanda molto utile, ma sono curioso di sapere perché non vorresti tracciare le modifiche al .csprojfile, che è una parte molto importante di qualsiasi progetto. Modifiche al .csproj.userfile o qualsiasi .Publish.XMLfile che posso capire completamente non il monitoraggio, ma sono incuriosito dal motivo per cui non vorresti tracciare il .csproj...
Owen Blacker

7
Forse usano un IDE diverso?
Jarrett,

3
Ironia della sorte, sono arrivato a questo thread perché sto cercando di rimuovere i file .suo da un repository ma di mantenerli localmente. Per i posteri, lo sviluppo di .Net richiede di mantenere i file .csproj nel repository e tali modifiche devono sempre essere monitorate a meno che non si desideri provare l'ira di altri sviluppatori sul progetto. Se mai incerti, dai un'occhiata al repository dei file gitignore su GitHub: github.com/github/gitignore/blob/master/VisualStudio.gitignore
longda

1
@Cupcake, la domanda che hai collegato è stata scritta 15 giorni dopo questa? Forse ne hai un altro in mente?
stephenmurdoch,

Le domande canoniche di @marflar non devono necessariamente essere le più vecchie, solo le migliori . Quello a cui ho collegato ha 20 risposte, mentre questo ha solo 5.

Risposte:


2129

Basta chiamare git rm --cachedtutti i file che si desidera rimuovere dal controllo di revisione dovrebbe andare bene. Finché i tuoi pattern di ignore locali sono corretti, non vedrai questi file inclusi nell'output dello stato git.

Si noti che questa soluzione rimuove i file dal repository, quindi tutti gli sviluppatori dovrebbero mantenere le proprie copie locali (non controllate da revisione) del file

Per impedire a git di rilevare le modifiche in questi file dovresti anche usare questo comando:

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

Cosa probabilmente vuoi fare: (dal basso @Ryan Taylor rispondi )

  1. Questo per dire a git che vuoi la tua versione indipendente del file o della cartella. Ad esempio, non si desidera sovrascrivere (o eliminare) i file di configurazione di produzione / stadiazione.

git update-index --skip-worktree <path-name>

La risposta completa è qui in questo URL: http://source.kohlerville.com/2009/02/untrack-files-in-git/


187
"git rm --cached <file>" rimuove <file> dal controllo versione, mantenendolo nel repository funzionante. Se è quello che vuoi ...
Jakub Narębski,

51
Ma quando altri tireranno il repository, il loro file * .csproj verrà rimosso? Perché se vogliamo che il file non sia tracciato, ma non cancellato.
FMaz008

23
Se stai cercando di rimuovere TUTTI i file in una directory, combinalo con git ls-files: git ls-files | xargs git rm --cached- questo rimuoverà tutto dall'indice git in una data directory senza cancellare i file effettivi.
Marco,

129
git rm --cached -r <dir>funziona in modo ricorsivo su una cartella e su tutti i file in essa contenuti.
Chris K,

41
Questo interromperà il tracciamento del file, lo conserverà localmente, ma lo farà eliminare per chiunque tira
Edward Newell,

249

Se lo fai git update-index --assume-unchanged file.csproj, git non controlla automaticamente le modifiche a file.csproj: ciò impedirà loro di venire nello stato git ogni volta che le cambi. Quindi puoi contrassegnare tutti i tuoi file .csproj in questo modo, anche se dovrai contrassegnare manualmente quelli nuovi che ti inviano il repository upstream. (Se li hai nel tuo .gitignoreo .git/info/exclude, quelli che crei verranno ignorati)

Non sono del tutto sicuro di quali siano i file .csproj ... se sono qualcosa sulla falsariga delle configurazioni IDE (simili ai file .eclipse e .classpath di Eclipse), suggerirei che semplicemente non dovrebbero mai essere controllati dal codice sorgente in tutti. D'altra parte, se fanno parte del sistema di compilazione (come Makefile), allora chiaramente dovrebbero --- e un modo per raccogliere le modifiche locali opzionali (ad esempio da un local.csproj a la config.mk) sarebbe utile : dividere l'accumulo in parti globali e sostituzioni locali.


8
csproj è un file di progetto C #, che tiene traccia dei file inclusi nel progetto e di altre poche configurazioni, DEVE essere controllato dal codice sorgente affinché il progetto funzioni
SparK

4
Questa è l'unica risposta giusta qui! Uso la risposta di @araqnids da anni e funziona esattamente come richiesto per risolvere questo problema.
NHDaly

Qual è il significato del prefisso 'file' nell'argomento del comando? Perché non è solo .csproj?
GreenAsJade,

1
Esiste un modo per rilevare che ciò è stato fatto per un file o per quali file è stato fatto in un repository? Sono un po 'nervoso nel dimenticare di averlo fatto, quindi mi chiedo perché diamine questo file non venga aggiornato, in seguito!
GreenAsJade,

4
@GreenAsJade: git ls-files -vmostrerà i file che vengono considerati invariati con un indicatore minuscolo (ad es. hInvece del solito Hper i file memorizzati nella cache).
Amadan,

238

Ci sono 3 opzioni, probabilmente vuoi # 3

1. Ciò manterrà il file locale per te, ma lo eliminerà per chiunque altro quando tirerà.

git rm --cached <file-name> o git rm -r --cached <folder-name>

2. Questo è per l'ottimizzazione, come una cartella con un gran numero di file, ad esempio SDK che probabilmente non cambierà mai. Dice a git di smettere di controllare quell'enorme cartella ogni volta per modifiche, localmente, dal momento che non ne avrà alcuna. L' assume-unchangedindice verrà ripristinato e i file verranno sovrascritti in caso di modifiche a monte del file / cartella (quando si estrae).

git update-index --assume-unchanged <path-name>

3. Questo per dire a git che vuoi la tua versione indipendente del file o della cartella. Ad esempio, non si desidera sovrascrivere (o eliminare) i file di configurazione di produzione / stadiazione.

git update-index --skip-worktree <path-name>

È importante sapere che git update-index non si propagherà con git e ogni utente dovrà eseguirlo in modo indipendente.


8
Questa risposta è la più completa: offre varie soluzioni con le ramificazioni di ciascuna. Il caso specifico con cui sto lavorando ha una password incorporata in un file di configurazione. Voglio propagare un file modello quindi aggiungere la password alla mia copia. La copia con la password deve essere ignorata e non sovrascritta.
bmacnaughton,

1
Come posso verificare, nel mio locale, quali file si applicano per 'assume-invariato' o 'skip-worktree'?
Supawat Pusavanno,

3
@SupawatPusavanno per vedere quali file hai selezionato in precedenza per assumere-invariato o saltare-worktree guarda questa risposta stackoverflow.com/questions/42363881/… - utilizza grepegit ls-files
Ryan Taylor,

1
Ottima risposta Ma git genera un errore quando provo a passare a un altro ramo: errore: "Le tue modifiche locali ai seguenti file verrebbero sovrascritte dal checkout ....." e la soluzione è di archiviare le modifiche prima di passare e annullare lo stash quando ritorni al ramo.
PhantomReference

@RyanTaylor: ho provato ad assumere prima invariato (non ha funzionato) e saltare il comando worktree (non ha funzionato), quando controllo con lo stato git i file non vengono visualizzati significa che il comando ha funzionato. Ma quando estraggo di nuovo il codice dal repository git origin it gives me error that your local changes would be overwrittenin quei 2 file, ciò significa che non sta tracciando, giusto?
NeverGiveUp161,

152

Questo è un processo in due fasi:

  1. Rimuovere il tracciamento di file / cartella - ma tenerli su disco - usando

    git rm --cached 
    

    Ora non vengono visualizzati come "modificati", ma vengono comunque visualizzati come

        untracked files in  git status -u  
    
  2. Aggiungili a .gitignore


56
No, questo rimuoverà il file dal tracciamento, lo manterrà localmente, ma lo farà eliminare per chiunque tira .
Edward Newell,

1
Nel mio caso, ho aggiunto accidentalmente una cartella che non volevo rintracciare, quindi questo è ciò di cui avevo bisogno.
Sonny,

4
Sì, è davvero la risposta sbagliata alla domanda, ma probabilmente è la risposta giusta per la maggior parte delle persone che trovano questa domanda nei risultati di ricerca (come me).
Andrew Spencer,

95

La risposta accettata non ha ancora funzionato per me

ero solito

git rm -r --cached.

git add.

git commit -m "fixing .gitignore"

Ho trovato la risposta da qui


Questo link è molto utile, soprattutto per rimuovere in modo ricorsivo tutti i file in
.gitignore

9
Sono tornato qui 3 volte, spero di potermi impegnare a memoria prima della prossima volta!
Harry Bosh

Il commento di @Edward Newell come nel risposta sopra si applica anche qui: "questo rimuoverà il file dal tracciamento, lo manterrà localmente, ma lo farà eliminare per chiunque tira ".
Giovedì

47

Hai dimenticato il tuo .gitignore?

Se hai l'intero progetto localmente ma hai dimenticato di aggiungere git ignore e ora stai monitorando alcuni file non necessari, usa questo comando per rimuovere tutto

git rm --cached -r .

assicurati di essere alla radice del progetto.

Quindi puoi fare il solito

Inserisci

git add .

Commettere

git commit -m 'removed all and added with git ignore'

Spingere

git push origin master

Conclusione

Spero che questo aiuti le persone che devono apportare modifiche alle loro .gitignoreo hanno dimenticato tutto insieme.

  • Rimuove l'intera cache
  • Guarda il tuo .gitignore
  • Aggiunge i file che si desidera tenere traccia
  • Invia al tuo repository

4
Quando parli di rimuovere o aggiungere, stai dimenticando di dire quando e dove. Rimozione dall'elenco dei brani? Dal repository? Dallo spazio del progetto locale? Rimozione a pull? A commettere? A spinta? Purtroppo, tutti gli autori qui hanno lo stesso problema.
Gangnus,

3
@Gangnus Non credo che nessuno abbia 'chiarito' il punto che stai cercando di chiarire perché è del tutto ovvio che il file non viene effettivamente rimosso dal disco o dal repository. Questa risposta specifica l'ordine cronologico dei comandi. Non è misterioso o mal spiegato come suggerirebbe il tuo commento.
Anthony,

Il commento di @Edward Newell come nella risposta sopra si applica anche qui: "questo rimuoverà il file dal tracciamento, lo manterrà localmente, ma lo farà eliminare per chiunque tira ".
Giovedì

26

Come sottolineato in altre risposte, la risposta selezionata è errata.

La risposta a un'altra domanda suggerisce che potrebbe essere necessario saltare il worktree.

git update-index --skip-worktree <file>

2
No, non proprio: --skip-worktreeviene utilizzato per conservare il file nel repository ma interrompere il monitoraggio delle modifiche . Come dice la tua risposta: --skip-worktree è utile quando chiedi a git di non toccare un file specifico perché gli sviluppatori dovrebbero cambiarlo
Erdal G.

4
@ErdalG. Esattamente. Secondo la domanda, vogliono ignorare qualsiasi modifica nel file ma mantenerlo nel repository
the_new_mr

Sono d'accordo con @the_new_mr --assume-unchangede --skip-worktreehanno un effetto simile ma i loro scopi sono completamente diversi. Il primo è per accelerare le prestazioni di git ingannando git per non controllare determinati file , mentre il secondo serve per ignorare le modifiche future su determinati file , che sono adatti per i file di runtime ma essenziali.
Victor Wong,

22

Per risparmiare un po 'di tempo, le regole che aggiungi al tuo .gitignore possono essere usate per rimuovere più file / cartelle, ad es

git rm --cached app/**/*.xml

o

git rm --cached -r app/widgets/yourfolder/

eccetera


Questa è un'ottima soluzione perché in ogni caso tu voglia sistemare passo dopo passo il
gitignore

15

Per impedire il monitoraggio di un file tramite git

git update-index --assume-unchanged [file-path]

E per ripristinare l'uso

git update-index --no-assume-unchanged [file-path]

Un repository per fare riferimento a casi d'uso simili https://github.com/awslabs/git-secrets


1
Il suggerimento di ripristino è stato un salvavita, grazie!
Hamman Samuel,

9

Molte persone ti consigliano di usare git update-index --assume-unchanged . In effetti, questa potrebbe essere una buona soluzione, ma solo a breve termine.

Quello che probabilmente vuoi fare è questo: git update-index --skip-worktree .

(La terza opzione, che probabilmente non vuoi è è: git rm --cached Manterrà il file locale, ma verrà contrassegnato come rimosso dal repository remoto.)

Differenza tra le prime due opzioni?

  • assume-unchangedè consentire temporaneamente di nascondere le modifiche da un file. Se si desidera nascondere le modifiche apportate a un file, modificare il file, quindi verificare un altro ramo, è necessario utilizzare no-assume-unchangedquindi probabilmente le modifiche apportate.
  • skip-worktree ti seguirò qualunque sia la tua filiale, con le tue modifiche!

Caso d'uso di assume-unchanged

Presuppone che questo file non debba essere modificato e ti dà un risultato più pulito quando lo fai git status. Ma quando effettui il checkout su un altro ramo, devi ripristinare il flag e confermare o archiviare le modifiche prima. Se tiri con questa opzione attivata, dovrai risolvere i conflitti e git non si fonderà automaticamente. In realtà nasconde solo le modifiche ( git statusnon ti mostrerà i file contrassegnati).

Mi piace usarlo quando voglio smettere di tracciare le modifiche solo per un po '+ commettere un mucchio di file ( git commit -a) relativi alla stessa modifica.

Caso d'uso di skip-worktree

Hai una classe di installazione che contiene parametri (es. Incluse le password) che i tuoi amici devono cambiare di conseguenza alla loro configurazione.

  • 1: crea una prima versione di questa classe, compila i campi che puoi compilare e lascia gli altri vuoti / nulli.
  • 2: eseguire il commit e inviarlo al server remoto.
  • 3: git update-index --skip-worktree MySetupClass.java
  • 4: aggiorna la tua classe di configurazione con i tuoi parametri.
  • 5: torna a lavorare su un'altra funzionalità.

Le modifiche apportate ti seguiranno indipendentemente dal ramo. Avvertenza: se anche i tuoi amici vogliono modificare questa classe, devono avere la stessa configurazione, altrimenti le loro modifiche verrebbero trasferite al repository remoto. Durante il pull, la versione remota del file dovrebbe sovrascrivere la tua.

PS: fai l'uno o l'altro, ma non entrambi poiché avrai effetti collaterali indesiderati. Se vuoi provare un'altra bandiera, dovresti prima disabilitare quest'ultima.


7

Per dire a Git di non tenere traccia delle modifiche al tuo file / cartella locale (il che significa che lo stato di Git non rileverà le modifiche ad esso), fai:

git update-index --skip-worktree path/to/file

E per dire a Git di tenere di nuovo traccia delle modifiche alla tua versione locale (in modo da poter eseguire il commit delle modifiche), esegui:

git update-index --no-skip-worktree path/to/file

1

risposta a una riga git update-index --assume-unchanged [path]

Utilizzare questo ogni volta che si dispone di un file che si trova nel repository centrale e anche in un repository locale. È necessario apportare modifiche a quel file ma non è necessario eseguire la messa in scena / il commit nel repository centrale. Questo file non deve essere aggiunto in.gitignore . perché nuove modifiche al file se introdotte dagli amministratori di sistema, gli sviluppatori senior devono essere distribuiti tra tutti i repository locali.

Esempio migliore: file di configurazione per le connessioni DB . In un repository centrale, avrai tutti i nomi utente, password, host, porta con valori di un server DB di produzione. Ma negli sviluppatori locali, dovresti usare solo un server DB di sviluppo locale o di altro tipo (che il tuo team ha installato). In questo caso, si desidera apportare modifiche al file di configurazione, ma non è necessario eseguire il commit nel repository centrale.

Migliore


0

Suppongo che tu stia chiedendo come rimuovere TUTTI i file in una cartella specifica o nella cartella bin, piuttosto che selezionare ciascun file separatamente.

È possibile utilizzare questo comando:

git rm -r -f /<floder-name>\*

Assicurarsi di trovarsi nella directory principale della directory.
Questo comando "eliminerà" ricorsivamente tutti i file che si trovano nel bin / o build / cartelle. Con la parola cancella intendo che git farà finta che quei file siano "cancellati" e quei file non saranno tracciati. Git contrassegna davvero quei file in modalità di eliminazione.

Assicurati di avere il tuo .gitignore pronto per i prossimi commit.
Documentazione: git rm


0

Il problema potrebbe essere causato dall'ordine di funzionamento. Se hai modificato prima il file .gitignore, quindi git rm --cached xxx, potresti dover continuare a riscontrare questo problema.

Soluzione corretta :

  1. git rm - cache xxx
  2. modificato il .gitignore

Ordine invariante!

Il .gitignore si ricarica dopo la modifica!


0

Presumo che tu stia provando a rimuovere un singolo file da git tacking. per questo vorrei raccomandare sotto il comando.

git update-index --assume-invariato

Ex - git update-index --assume-immutato .gitignore .idea / compiler.xml


0

Per ignorare qualsiasi modifica a tutti i file (di un certo tipo) in una directory, ho dovuto combinare alcuni di questi approcci, altrimenti i file sarebbero stati creati se non esistevano in precedenza.

Nel seguito, "excludedir" è il nome della directory in cui desidero non guardare le modifiche.

Innanzitutto, rimuovere eventuali nuovi file esistenti dalla cache di rilevamento delle modifiche (senza rimuoverli dal file system).

git status | grep "new file:" | cut  --complement -d " " -f1-4 | grep "^excludedir" | xargs git rm --cache

Puoi fare lo stesso con modified:. renamed:è un po 'più complicato, dato che dovrai guardare il post ->bit per il nuovo nome file e fare il pre ->bit come descritto di deleted:seguito.

deleted: i file si dimostrano un po 'più complicati, in quanto non è possibile aggiornare-index per un file che non esiste sul sistema locale

echo .deletedfiles >> .gitignore
git status | grep "deleted:" | cut  --complement -d " " -f1-4 | grep "^excludedir" > .deletedfiles
cat .deletedfiles | xargs -d '\n' touch
cat .deletedfiles | xargs -d '\n' git add -f
cat .deletedfiles | xargs -d '\n' git update-index --assume-unchanged
cat .deletedfiles | xargs -d '\n' rm

L'ultimo comando nell'elenco sopra rimuoverà nuovamente i file dal tuo file system, quindi sentiti libero di ometterlo.

Quindi, bloccare il rilevamento delle modifiche da quella directory

git ls-files excludedir/ | xargs git update-index --skip-worktree
git update index --skip-worktree excludedir/

0

In questa risposta è stato fornito un approccio quasi privo di comandi :

Per ignorare determinati file per ogni repository locale :

  1. Crea un file ~/.gitignore_global, ad es. touch ~/.gitignore_globalNel tuo terminale.
  2. Corri git config --global core.excludesfile ~/.gitignore_globalper una volta.
  3. Scrivi i percorsi di file / dir che desideri ignorare ~/.gitignore_global. ad esempio modules/*.H, che si presume si trovi nella directory di lavoro, ad es $WORK_DIR/modules/*.H.

Per ignorare determinati file per un singolo repository locale :

  1. Eseguire il terzo passaggio precedente per il file .git/info/excludeall'interno del repository, ovvero scrivere i percorsi file / dir che si desidera ignorare .git/info/exclude. ad esempio modules/*.C, che si presume si trovi nella directory di lavoro, ad es $WORK_DIR/modules/*.C.

0

Applica .gitignore al presente / futuro

Questo metodo applica il comportamento standard .gitignore e non richiede di specificare manualmente i file che devono essere ignorati .

Non è --exclude-from=.gitignorepiù possibile utilizzare : / - Ecco il metodo aggiornato:

Consiglio generale: inizia con un repository pulito - tutto impegnato, nulla in sospeso nella directory o nell'indice di lavoro ed esegui un backup !

#commit up-to-date .gitignore (if not already existing)
#this command must be run on each branch
git add .gitignore
git commit -m "Create .gitignore"

#apply standard git ignore behavior only to current index, not working directory (--cached)
#if this command returns nothing, ensure /.git/info/exclude AND/OR .gitignore exist
#this command must be run on each branch
git ls-files -z --ignored --exclude-standard | xargs -0 git rm --cached

#optionally add anything to the index that was previously ignored but now shouldn't be:
git add *

#commit again
#optionally use the --amend flag to merge this commit with the previous one instead of creating 2 commits.

git commit -m "re-applied modified .gitignore"

#other devs who pull after this commit is pushed will see the  newly-.gitignored files DELETED

Se è anche necessario eliminare i file appena ignorati dalla cronologia di commit del ramo o se non si desidera che i file appena ignorati vengano eliminati da pull futuri , vedere questa risposta .


-1

dopo una lunga ricerca, trova un modo per farlo. alias un comando git in .gitconfig.like nel progetto Android Studio , prima che il ramo di checkout ripristini il file di configurazione e poi lo salti , dopo il ramo di checkout usa sedcambia il file di configurazione nella mia configurazione locale. checkoutandmodifylocalproperties = !git update-index --no-skip-worktree local.properties && git checkout local.properties && git checkout $1 && git update-index --skip-worktree local.properties && sed -i '' 's/.*sdk.dir.*/sdk.dir=\\/Users\\/run\\/Library\\/Android\\/sdk/g' local.properties && :

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.