Dicas para colocar ~ sob controle de origem

77

Quero colocar meu diretório pessoal (~) sob controle de origem (git, neste caso), pois tenho muitos arquivos de configuração (.gitconfig, .gitignore, .emacs, etc.) por lá, gostaria de transportar máquinas, tê-los no Git seria bom para recuperá-los.

Minha máquina principal é o meu MacBook e, da maneira como o OS X está configurado, há muitas pastas que eu quero ignorar (Documentos, Downloads, .ssh). Também existem pastas que já estão usando o Git (.emacs.d).

Meu pensamento era apenas adicionar todos esses diretórios ao meu arquivo .gitignore, mas isso parece meio cansativo e pode levar a consequências imprevisíveis. Meu próximo pensamento era copiar periodicamente os arquivos que eu quero armazenar em alguma pasta da casa e confirmar essa pasta. O problema com isso será que eu tenho que lembrar de movê-los antes de cometer.

Existe uma maneira limpa de fazer isso?

Dan McClain
fonte
Você também pode criar um script executando as confirmações das pastas desejadas e chamando-o através dos cronjobs.
Shadok 6/09/11
Observe que o sistema de arquivos HFS + padrão no Mac OS X não diferencia maiúsculas de minúsculas (mas preserva maiúsculas e minúsculas) e que os caminhos dos arquivos são codificados em UTF-8 decomposto canonicamente no espaço do usuário! Para obter mais informações, consulte: <a href=" stackoverflow.com/questions/5581857/… e o problema do Umlaut no Mac OS X</a>

Respostas:

60

Eu tenho $HOMEsob git. A primeira linha do meu arquivo .gitignore é

/*

O restante são padrões para não ignorar usando o !modificador. Essa primeira linha significa que o padrão é ignorar todos os arquivos no meu diretório pessoal. Esses arquivos que eu quero controlar a versão entram .gitignoreassim:

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

Um padrão mais complicado que tenho é:

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

Ou seja, eu só quero a versão .ssh/config- não quero que minhas chaves e outros arquivos no .ssh entrem no git. O acima é como eu consegui isso.

Editar: barras adicionadas ao início de todos os caminhos. Isso faz com que os padrões de ignorar correspondam na parte superior do repositório ($ HOME) em vez de em qualquer lugar. Por exemplo, se !lib/era um padrão (não ignore tudo no diretório lib) e você adicionava um arquivo .gitignore, anteriormente o padrão ( !.gitignore) correspondia a ele. Com a barra ( !/.gitignore), ela corresponderá apenas .gitignoreno meu diretório pessoal e não em nenhum subdiretório.

Não vi um caso em que isso faça uma diferença prática na minha lista de ignorados, mas me parece ser tecnicamente mais preciso.

camh
fonte
1
Parece-me que o mesmo pode ser alcançado de uma maneira muito mais fácil .
precisa saber é o seguinte
24

O que faço (com os mesmos objetivos) é colocar meus arquivos de configuração em um subdiretório ~/libe ter links simbólicos no meu diretório pessoal, por exemplo .emacs -> lib/emacs/dot.emacs,. Eu apenas mantenho os arquivos de configuração que escrevi explicitamente sob controle de versão; meu diretório pessoal contém muitos arquivos de pontos criados automaticamente que não estão sob controle de versão. Assim, ~/libestá sob controle de versão e meu diretório inicial não.

Eu tenho um script que cria os links simbólicos dos arquivos em ~/lib. Quando crio uma conta em uma nova máquina, preencha-a fazendo check-out ~/libe executando esse script.

Minha experiência é com CVS, não com git, portanto não é 100% transferível. Uma das razões pelas quais eu não coloquei meu diretório inicial diretamente no CVS é ​​que isso ~/.cvsignorese aplicaria a todos os meus checkout do CVS e não apenas ao meu diretório inicial; O git não tem esse problema. A desvantagem dessa abordagem, em comparação com o diretório inicial sob controle de versão, é que você não pode git statusdistinguir entre um arquivo que você decidiu explicitamente ignorar (que seria listado no arquivo ignorar, portanto não exibido) e um arquivo sobre o qual você não tem opinião (que seria exibido com a ?).

Alguns arquivos precisam ser diferentes em máquinas diferentes. Eu os coloquei em um diretório chamado ~/Local/SITENAME/libe crie links simbólicos para eles também ou (para os formatos de arquivo que o suportam) têm uma diretiva de inclusão no arquivo em ~/lib. Eu também tenho um link simbólico ~/Here -> ~/Local/SITENAME. Como o git, diferentemente do CVS, foi projetado para suportar repositórios quase similares, mas não idênticos, pode haver uma maneira melhor de gerenciar arquivos específicos da máquina. Na verdade, alguns dos meus arquivos de ponto não são links simbólicos, mas são gerados automaticamente a partir de conteúdo sob ~/libe ~/Here.

Gilles
fonte
Talvez você tenha core.excludesfile = ~/.gitignore. Sem essa configuração, o arquivo não é aplicado a nenhum repositório, exceto aquele armazenado ~/.git(mesmo assim, não se aplicaria aos sub-repositórios). Eu uso core.excludesfile = ~/.git-user-excludespara evitar o conflito entre as exclusões que quero aplicar a todos os meus repositórios Git (independentemente da localização) e as exclusões que quero aplicar ao repositório que contém (partes do) meu diretório pessoal.
Chris Johnsen
@ Chris: Eu sei muito pouco sobre o Git. Talvez eu tenha entendido mal esta frase na gitignorepágina do manual: “Padrões lidos em um arquivo .gitignore no mesmo diretório que o caminho ou em qualquer diretório pai (…)” De fato, ele pára na raiz do checkout (ou seja, onde o .gitdiretório é)?
Gilles
1
Sim, a pesquisa para cima de .gitignorearquivos é limitada pela raiz da árvore de trabalho. A frase que você citou continua: “(até o nível superior da árvore de trabalho)”.
Chris Johnsen
@ Chris: minha versão da página de manual não possui essas palavras - parece que o texto foi esclarecido. Eu corrigi minha resposta. Obrigado!
Gilles
isto foi discutido no chat recentemente
strugee
11

Podemos usar a capacidade do Git para continuar rastreando arquivos, mesmo que estejam listados .gitignore. Portanto, isso é suficiente para .gitignore:

$ cat .gitignore
/*

Para cada arquivo que você deseja rastrear, execute add -f(o -fparâmetro substitui a ignorância de in .gitignoree .git/info/exclude):

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

Depois de indexar um arquivo, o Git rastreará todas as alterações, apesar do fato de o arquivo ser ignorado. O mesmo funciona para um diretório, mas apenas para os arquivos realmente presentes:

git add -f somedirname

Se você deseja rastrear um diretório inteiro com todos os novos arquivos que aparecem nele, ele pode ser excluído de .gitignoreuma maneira descrita na resposta por camh :

!/somedirname

Se você quiser parar de rastrear um arquivo, esse comando remove um arquivo do índice do Git, mas o deixa intocado no disco rígido:

git rm --cached .ssh/config
Nick Volynkin
fonte
1
Eu daria meus pontos se pudesse. Deve-se notar que esse método só pode ser usado para rastrear arquivos, não diretórios. Se você deseja que o git rastreie todos os arquivos em um diretório, você ainda precisará ignorar esse diretório no .gitignore. Caso contrário, os novos arquivos nesse diretório não aparecerão como novos arquivos.
camh 15/09/2015
5

Eu uso o antigo rcspara isso.

Ter um olhar para manpages para ci, co, e rcs. Esses sites também devem ser úteis:

Eu uso isso para controlar a versão dos meus dotfiles, por exemplo:

ci -u .*vimrc

E se eu quiser editá-los:

co -l .*vimrc

Eu recomendo criar um diretório nomeado RCSno seu ~, então você pode facilmente fazer backup desse diretório em algum lugar.

polemon
fonte
2
O rcs está bem datado agora, e o git faz tudo o que o rcs faz e muito mais. Eu costumava usar o rcs para qualquer coisa local onde não queria a sobrecarga de configurar um repositório em um servidor, mas agora mudei completamente para o git agora para esse tipo de uso. Até escrevi um script que envolve o cvs2git para converter uma hierarquia de diretórios existente com arquivos rcs nele para git.
Neil Mayhew
1
Sim, eu sei que é datado. A questão era uma dica sobre como fazer isso. Acabei de dizer a esse cara como faço isso há muitos e muitos anos ("datado", dica, dica). Não era para ser a única maneira razoável de fazer isso.
Polemon
5

$HOME/.conf/Verifico meus arquivos de configuração em um repositório do BitBucket Mercurial. Um repositório do GitHub também funcionaria.

O ~/.confcheckout contém arquivos de configuração e um script de shell para preencher links simbólicos em $HOMEcada arquivo ~/.conf. Para formatos de configuração que suportam inclusão ( .bashrc, .inputrc, .vimrc, etc.) I incluem o ~/.confarquivo em vez de um link para ele, para que eu possa fazer substituições locais.

Para alguns arquivos de configuração, vinculo-o a um arquivo na minha pasta Dropbox e os compartilho via dropbox.

Por alguns meses, tentei me manter $HOMEno controle de versão, mas cansei de gerenciar as enormes listas de ignorados, cansei de verificar as alterações de configuração feitas pelos aplicativos em execução, e o resultado nem era algo que gostaria de verificar em outro computador. Você pode imaginar a fixação conflitos mais ~/.gconfou ~/.config/monitors.xmlou restauração fro versões de aplicativos de desktop diferentes?

Acho mais fácil vincular um link simbólico ou incluir uma lista limitada de arquivos de configuração que eu personalizei pessoalmente e quero compartilhar nas máquinas como padrões globais.

Graham
fonte
3

Acabei de começar a usar o seguinte script Python Dotfiles, que é uma ferramenta útil que vincula automaticamente os arquivos para você: https://pypi.python.org/pypi/dotfiles

trojjer
fonte
1

Eu acho que o seu segundo palpite de ter uma pasta não relacionada sob controle de origem é bom.

Basta adicionar 2 scripts de shell lá. Um para copiar arquivos sob seu controle ~e outro para coletar arquivos ~e copiá-lo de volta para a pasta controlada por origem e confirmar.

Alexander Pogrebnyak
fonte
0

Aqui está um pequeno script ruby ​​que eu uso para configurar uma nova máquina

#!/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
Khaja Minhajuddin
fonte