Dois repositórios git em um diretório?

86

É possível ter 2 repositórios git em um diretório? Acho que não, mas pensei em perguntar. Basicamente, gostaria de verificar meus arquivos de configuração do diretório inicial (por exemplo, .emacs), que devem ser comuns a todas as máquinas em que trabalho, mas tenho um segundo repositório para arquivos locais (por exemplo, .emacs.local), que contém configurações específicas da máquina. A única maneira que consigo pensar em fazer isso é ter a configuração local em um subdiretório e ignorar esse subdiretório do repositório git principal. Alguma outra ideia?

Joe Casadonte
fonte
git subtreefará o trabalho.
Syd Pao
Se não estiver lidando com muitos arquivos, você também pode criar links simbólicos / junções.
thdoan

Respostas:

37

Se eu entendi o que você está fazendo, você pode lidar com tudo em um repositório, usando branches separados para cada máquina, e um branch contendo seus arquivos de configuração de diretório home comuns.

Inicialize o repo e envie os arquivos comuns para ele, talvez renomeando o branch MASTER como Comum. Em seguida, crie um branch separado a partir daí para cada máquina com a qual você trabalha e envie os arquivos específicos da máquina para esse branch. Sempre que você alterar seus arquivos comuns, mescle a ramificação comum em cada uma das ramificações da máquina e envie para as outras máquinas (escreva um script para isso, se houver muitos).

Então, em cada máquina, verifique o branch dessa máquina, que também incluirá os arquivos de configuração comuns.

Paulo
fonte
Embora os submódulos também funcionem, acho que essa é a melhor abordagem para mim. Os arquivos locais seguirão um modelo e, conforme eu faço alterações no modelo no branch MASTER, posso mesclá-los nos branches locais da máquina, atualizando incrementalmente os arquivos de configuração locais. Obrigado pela ajuda!
Joe Casadonte
use Mercurial e Git ambos.
Linc
172

Este artigo cobre isso relativamente bem:

https://github.com/rrrene/gitscm-next/blob/master/app/views/blog/progit/2010-04-11-environment.markdown

Basicamente, se você estiver trabalhando na linha de comando, isso é mais simples do que você pode imaginar. Suponha que você queira 2 repositórios git:

.gitone
.gittwo

Você pode configurá-los assim:

git init .
mv .git .gitone
git init .
mv .git .gittwo

Você pode adicionar um arquivo e confirmá-lo em apenas um, desta forma:

git --git-dir=.gitone add test.txt
git --git-dir=.gitone commit -m "Test"

Portanto, as opções do git vêm primeiro, depois o comando e, a seguir, as opções do comando git. Você poderia facilmente criar um alias para um comando git como:

#!/bin/sh
alias gitone='git --git-dir=.gitone'
alias gittwo='git --git-dir=.gittwo'

Então você pode se comprometer com um ou outro com um pouco menos de digitação, como gitone commit -m "blah".

O que parece ficar mais complicado é ignorar. Visto que .gitignore normalmente fica na raiz do projeto, você também precisa encontrar uma maneira de mudar isso sem mudar a raiz inteira. Ou você pode usar .git / info / exclude, mas todos os ignora que você executa não serão confirmados ou enviados - o que pode atrapalhar outros usuários. Outros que usam qualquer um dos repositórios podem enviar um .gitignore, o que pode causar conflitos. Não está claro para mim a melhor maneira de resolver esses problemas.

Se você preferir ferramentas GUI como o TortoiseGit, você também terá alguns desafios. Você pode escrever um pequeno script que renomeie .gitone ou .gittwo para .git temporariamente para que as suposições dessas ferramentas sejam atendidas.

Chris Moschini
fonte
1
Configurá-lo como um alias gera este erro: $ git config --global alias.pub '--git-dir = ~ / Server / www / .gitpublic' $ git pub add. fatal: alias 'pub' altera as variáveis ​​de ambiente Você pode usar '! git' no alias para fazer isso. Onde você definiria o "! Git" neste caso?
JaredBroad de
1
@JaredBroad Interessante - Eu estava sugerindo que você use um alias Bash, não um alias git. Likealias gitone='git --git-dir=.gitone'
Chris Moschini
10
Você pode configurar os repositórios para usar seus próprios arquivos de exclusão e pode rastreá-los, ou seja, gitone config core.excludesfile gitone.excludee gitone add gitone.exclude. Fiz um script que expande essa solução: github.com/capr/multigit
2
@JaredBroad eu fiz isso como este git config --global alias.youralias '!git --git-dir="/d/MyProject/_git"', em seguida, git youralias status:)
starikovs
1
Se você presumir que os .gitignorearquivos geralmente são configurados e esquecidos, você pode fazer cópias diferentes para cada repositório e, em seguida, copiar a versão relevante para o diretório como parte do alias. Isso se aplica a outros arquivos na raiz que podem entrar em conflito, como README.mde .gitattributes.
dia
15

Dê uma olhada no submódulo git .

Submódulos permitem que repositórios externos sejam embutidos em um subdiretório dedicado da árvore de origem, sempre apontado para um commit particular.

Hates_
fonte
8
Não é bom para arquivos que precisam estar na raiz do seu diretório. A única chance é preencher a raiz dos links simbólicos para eles.
WhyNotHugo
6

RichiH escreveu uma ferramenta chamada vcsh, que é uma ferramenta para gerenciar dotfiles usando os repositórios nus falsos do git para colocar mais de um diretório de trabalho em $ HOME. Nada a ver com csh AFAIK.

No entanto, se você tivesse vários diretórios, uma alternativa para git-submodules (que são uma dor na melhor das circunstâncias e este exemplo de uso não é a melhor das circunstâncias) é gitslave, que deixa os repositórios escravos verificados na ponta de um branch o tempo todo e não requer o processo de três etapas para fazer uma mudança no repositório subsidiário (checkout no branch correto, fazer e confirmar a mudança, então vá para o superprojeto e faça o commit do novo submódulo).

Seth Robertson
fonte
6

É possível usar a variável, GIT_DIRmas tem muitas ressalvas se você não souber o que está fazendo.

tzervo
fonte
4

Sim, submódulos provavelmente são o que você deseja. Outra opção seria ter sua cópia de trabalho em um subdiretório e então apontar links simbólicos de seu diretório pessoal para os arquivos de interesse.

Pat Notz
fonte
3

meu método preferido é usar um repo em um subdiretório e usar links simbólicos recursivos:

git clone repo1
cd somerepo
git clone repo2
cd repo2
./build

onde o arquivo ' repo / build ' se parece com:

#!/bin/bash 
SELF_PATH="$(dirname "$(readlink -f "$0")" )"  # get current dir 
cd .. && git stash && git clean -f -d ''       # remove previous symlinks
cp -sR "$SELF_PATH"/* ../.                     # create recursive symlinks in root

cuidado : não use 'git add.'

coderofsalvation
fonte
0

A outra opção é colocá-los em pastas separadas e criar links físicos simbólicos de uma pasta para outra.

Por exemplo, se houver os repositórios:

  1. Repo1 / FolderA
  2. Repo1 / FolderB

E:

  1. Repo2 / FolderC

Você pode criar links simbólicos para as pastas FolderAe FolderBdo Repo1 para o Repo2. Para Windows, o comando a ser executado no Repo1 seria:

User@Repo1$ mklink /J FullPath/Repo2/FolderA FullPath/Repo1/FolderA
User@Repo1$ mklink /J FullPath/Repo2/FolderB FullPath/Repo1/FolderB
User@Repo1$ printf "/FolderA/*\n/FolderB/*\n" >> .gitignore

Para os arquivos nos repositórios principais, você precisa criar um link simbólico para cada um deles, também adicionando-os ao repositório .gitignorepara evitar ruído, a menos que você queira.

do utilizador
fonte
0

Aviso: Isso não é publicidade. Sou o desenvolvedor da biblioteca fornecida.

Eu criei uma extensão git para lidar com casos em que você deseja misturar vários repositórios em uma pasta. A vantagem da lib é manter o controle dos repositórios e dos conflitos de arquivo. você pode encontrá-lo no github . Existem também 2 repositórios de exemplo para experimentá-lo.

user1810087
fonte