Suggerimenti per mettere ~ sotto il controllo del codice sorgente


77

Voglio mettere la mia directory home (~) sotto il controllo del codice sorgente (git, in questo caso), poiché ho molti file di impostazione (.gitconfig, .gitignore, .emacs, ecc.) Che vorrei portare attraverso le macchine, e averli in Git lo renderebbe piacevole recuperarli.

La mia macchina principale è il mio MacBook, e il modo in cui è impostato OS X, ci sono molte cartelle che voglio ignorare (Documenti, Download, .ssh). Ci sono anche cartelle che stanno già usando Git (.emacs.d).

Il mio pensiero era quello di aggiungere tutte queste directory al mio file .gitignore, ma questo sembra un po 'noioso e potrebbe potenzialmente portare ad alcune conseguenze impreviste. Il mio prossimo pensiero è stato quello di copiare periodicamente i file che voglio archiviare in una cartella di casa, quindi eseguire il commit di quella cartella. Il problema sarà che dovrò ricordare di spostarli prima di impegnarmi.

C'è un modo pulito per farlo?


Puoi anche creare uno script eseguendo il commit delle cartelle desiderate e chiamandolo tramite cronjobs.
Shadok,

Nota che il file system HFS + predefinito su Mac OS X non fa distinzione tra maiuscole e minuscole (ma preserva le maiuscole) e che i percorsi dei file sono codificati in UTF-8 decomposto canonicamente nello spazio utente! Per ulteriori informazioni, consultare: <a href=" stackoverflow.com/questions/5581857/… e il problema Umlaut su Mac OS X</a>

Risposte:


60

Ho $HOMEsotto controllo. La prima riga del mio file .gitignore è

/*

Il resto sono schemi da non ignorare usando il !modificatore. Questa prima riga indica che l'impostazione predefinita è ignorare tutti i file nella mia directory home. Quei file che voglio controllare la versione vanno in .gitignorequesto modo:

!/.gitignore
!/.profile
[...]

Un modello più complicato che ho è:

!/.ssh
/.ssh/*
!/.ssh/config

Cioè, voglio solo la versione .ssh/config- Non voglio che le mie chiavi e altri file in .ssh entrino in git. Quanto sopra è come lo raggiungo.

Modifica: aggiunte barre per iniziare tutti i percorsi. Questo fa corrispondere i pattern ignore dalla parte superiore del repository ($ HOME) anziché ovunque. Ad esempio, se !lib/era un modello (non ignorare tutto nella directory lib) e si aggiunge un file .gitignore, in precedenza il modello ( !.gitignore) corrispondeva a quello. Con la barra iniziale ( !/.gitignore), corrisponderà solo .gitignorenella mia directory home e non in nessuna sottodirectory.

Non ho visto un caso in cui questo fa una differenza pratica con la mia lista di ignori, ma mi sembra più tecnicamente accurato.


1
Mi sembra che lo stesso possa essere realizzato in un modo molto più semplice .
Nick Volynkin,

24

Quello che faccio (con gli stessi obiettivi) è mettere i miei file di configurazione in una sottodirectory ~/libe avere collegamenti simbolici nella mia directory home, ad es .emacs -> lib/emacs/dot.emacs. Tengo solo i file di configurazione che ho scritto esplicitamente sotto il controllo della versione; la mia directory home contiene molti file dot creati automaticamente che non sono sotto il controllo della versione. Quindi ~/libè sotto il controllo della versione e la mia directory home non lo è.

Ho uno script che crea i collegamenti simbolici dai file sotto ~/lib. Quando creo un account su una nuova macchina, lo popolo estraendo ~/libed eseguendo quello script.

La mia esperienza è con CVS, non git, quindi non è trasferibile al 100%. Uno dei motivi per cui non ho inserito la mia directory home direttamente in CVS è che ~/.cvsignoresi applica a tutti i miei checkout CVS e non solo alla mia directory home; git non ha questo problema. Il rovescio della medaglia di questo approccio rispetto ad avere la home directory sotto il controllo della versione è che non puoi usare git statusper distinguere tra un file che hai esplicitamente deciso di ignorare (che sarebbe elencato nel file ignore, quindi non visualizzato) e un file di cui non hai opinioni (che verrebbe visualizzato con a ?).

Alcuni file devono essere diversi su macchine diverse. Li inserisco in una directory chiamata ~/Local/SITENAME/libe creo collegamenti simbolici anche per loro o (per i formati di file che lo supportano) hanno una direttiva include nel file sotto ~/lib. Ho anche un collegamento simbolico ~/Here -> ~/Local/SITENAME. Poiché git, a differenza di CVS, è progettato per supportare repository perlopiù simili ma non identici, potrebbe esserci un modo migliore per gestire i file specifici della macchina. Alcuni dei miei file dot non sono in realtà collegamenti simbolici, ma generati automaticamente dal contenuto in ~/libe ~/Here.


Forse hai core.excludesfile = ~/.gitignore. Senza tale configurazione, il file non viene applicato a nessun repository tranne uno archiviato ~/.git(anche in questo caso non si applicherebbe ai repository). Uso core.excludesfile = ~/.git-user-excludesper evitare il conflitto tra le esclusioni che desidero applicare a tutti i miei repository Git (indipendentemente dalla posizione) e le esclusioni che desidero applicare al repository che contiene (parti della) directory home.
Chris Johnsen,

@ Chris: So molto poco di Git. Potrei aver frainteso questa frase nella gitignorepagina man: "Pattern letti da un file .gitignore nella stessa directory del percorso, o in qualsiasi directory parent (...)" Si ferma infatti alla radice del checkout (cioè dove la .gitdirectory è)?
Gilles 'SO- smetti di essere malvagio' l'

1
Sì, la ricerca verso l'alto dei .gitignorefile è limitata dalla radice dell'albero di lavoro. La frase che hai citato continua: "(fino al livello superiore dell'albero di lavoro)".
Chris Johnsen,

@Chris: la mia versione della pagina man non ha queste parole - sembra che il testo sia stato chiarito. Ho corretto la mia risposta. Grazie!
Gilles 'SO- smetti di essere malvagio' il

questo è stato discusso di recente in chat
strugee

11

Possiamo usare la capacità di Git di continuare a tracciare i file anche se sono elencati in .gitignore. Quindi, questo è sufficiente per .gitignore:

$ cat .gitignore
/*

Per ogni file che si desidera tenere traccia, eseguire add -f(il -fparametro sovrascrive ignorando sia in .gitignoreche .git/info/exclude):

git add -f .gitignore
git add -f .profile
git add -f .zshrc
git add -f .ssh/config

Dopo aver indicizzato un file, Git terrà traccia di tutte le modifiche nonostante il file sia ignorato. Lo stesso vale per una directory, ma solo per i file effettivamente presenti:

git add -f somedirname

Se vuoi tracciare un'intera directory con tutti i nuovi file che appaiono in essa, può essere esclusa .gitignorein un modo, descritto nella risposta da camh :

!/somedirname

Se mai vuoi interrompere il tracciamento di un file, questo comando rimuove un file dall'indice di Git ma lo lascia intatto sul disco rigido:

git rm --cached .ssh/config

1
Ti darei i miei punti se potessi. Va notato che questo metodo può essere utilizzato solo per tenere traccia dei file, non delle directory. Se vuoi che git tenga traccia di tutti i file in una directory, dovrai comunque ignorare quella directory in .gitignore. Altrimenti i nuovi file in quella directory non appariranno come nuovi file.
Camh,

5

Uso il vecchio rcsper quello.

Date un'occhiata a pagine di manuale per ci, coe rcs. Anche questi siti dovrebbero essere utili:

Lo uso per la versione che controlla i miei dotfile per esempio:

ci -u .*vimrc

E se voglio modificarli:

co -l .*vimrc

Ti consiglio di creare una directory denominata RCSnella tua ~, quindi puoi facilmente eseguire il backup di quella directory da qualche parte.


2
rcs ora è piuttosto datato, e git fa tutto ciò che fa rcs e molto altro ancora. Usavo rcs per qualsiasi cosa locale in cui non volevo il sovraccarico di configurare un repository su un server, ma ora sono passato completamente a git per quel tipo di utilizzo. Ho anche scritto uno script che avvolge cvs2git per convertire una gerarchia di directory esistente con file rcs in esso in git.
Neil Mayhew,

1
Sì, lo so che è datato. La domanda era per un suggerimento su come farlo. Ho appena detto a questo ragazzo come lo faccio da molti, molti anni ("datato", suggerimento, suggerimento). Non era inteso nel modo in cui è l'unico modo ragionevole per farlo.
polemon,

5

Controllo i miei file di configurazione $HOME/.conf/da un repository Mercurial di BitBucket. Un repository GitHub funzionerebbe altrettanto bene.

Il ~/.confcheckout contiene file di configurazione e uno script di shell per popolare collegamenti simbolici in $HOMEciascun file ~/.conf. Per i formati di configurazione che supportano l'inserimento ( .bashrc, .inputrc, .vimrc, etc.) includo il ~/.conffile anziché link ad esso, in modo che io possa fare le sostituzioni locali.

Per alcuni file di configurazione collego a un file nella mia cartella Dropbox e condivido tramite dropbox.

Per alcuni mesi ho provato a mantenere il $HOMEcontrollo della versione, ma mi sono stancato di gestire gli enormi elenchi di ignorare, mi sono stancato di controllare le modifiche di configurazione apportate eseguendo app e il risultato non era nemmeno qualcosa che avrei voluto controllare su un altro computer. Riuscite a immaginare di fissaggio conflitti sopra ~/.gconfo ~/.config/monitors.xml, o ristorazione fro diverse versioni di applicazioni desktop?

Trovo più semplice il collegamento simbolico o includo un elenco limitato di file di configurazione che ho personalizzato personalmente e che voglio condividere tra le macchine come valori predefiniti globali.



1

Penso che il tuo secondo sospetto di avere una cartella non correlata sotto il controllo del codice sorgente sia buona.

Basta aggiungere 2 script di shell lì. Uno per copiare i file sotto il tuo controllo ~e l'altro per raccogliere i file ~e copiarli nuovamente nella cartella controllata dal codice sorgente e eseguire il commit.


0

Ecco un piccolo script ruby ​​che uso per configurare una nuova macchina

#!/usr/bin/env ruby
# setup.rb

#list of dirs which you don't want to symlink
ignored = %w(.gitignore .gitmodules misc setup.rb readme)

current_dir = File.expand_path(Dir.pwd)
home_dir = File.expand_path("~")

links = `git ls-tree --name-only HEAD`.lines.map(&:strip).select {|x| !ignored.include?(x)  }

links.each do |link|
  link = File.join(current_dir, link)
  symlink = File.join(home_dir, File.basename(link))
  `ln -ns #{link} #{symlink}`
end
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.