Dwa repozytoria git w jednym katalogu?

86

Czy można mieć 2 repozytoria git w jednym katalogu? Nie sądzę, ale pomyślałem, że zapytam. Zasadniczo chciałbym sprawdzić pliki konfiguracyjne mojego katalogu domowego (np. Emacs), które powinny być wspólne dla wszystkich maszyn, na których pracuję, ale mam drugie repozytorium dla plików lokalnych (np. .Emacs.local), które zawiera konfiguracje specyficzne dla maszyny. Jedynym sposobem, o jakim mogę to zrobić, jest umieszczenie lokalnej konfiguracji w podkatalogu i zignorowanie tego podkatalogu z głównego repozytorium git. Jakieś inne pomysły?

Joe Casadonte
źródło
git subtreewykona pracę.
Syd Pao
Jeśli nie masz do czynienia ze zbyt dużą liczbą plików, możesz również utworzyć dowiązania symboliczne / połączenia.
czwartek

Odpowiedzi:

37

Jeśli rozumiem, co robisz, możesz to wszystko obsłużyć w jednym repozytorium, używając oddzielnych gałęzi dla każdego komputera i gałęzi zawierającej wspólne pliki konfiguracyjne katalogu domowego.

Zainicjuj repozytorium i zatwierdź do niego wspólne pliki, być może zmieniając nazwę gałęzi MASTER na Common. Następnie utwórz stamtąd oddzielną gałąź dla każdego komputera, z którym pracujesz, i zatwierdź pliki specyficzne dla komputera w tej gałęzi. Za każdym razem, gdy zmieniasz swoje wspólne pliki, połącz wspólną gałąź z każdą gałęzią maszyny i wypchnij ją na inne maszyny (napisz do tego skrypt, jeśli jest ich wiele).

Następnie na każdym komputerze wyewidencjonuj gałąź tego komputera, która będzie również zawierać typowe pliki konfiguracyjne.

Paweł
źródło
Chociaż podmoduły również będą działać, myślę, że jest to dla mnie najlepsze podejście. Pliki lokalne będą podążać za szablonem, a kiedy wprowadzę zmiany w szablonie w gałęzi MASTER, mogę scalić je w lokalne gałęzie maszyny, przyrostowo aktualizując lokalne pliki konfiguracyjne. Dzięki za pomoc!
Joe Casadonte
używaj zarówno Mercurial, jak i Git.
Linc
172

Ten artykuł opisuje to stosunkowo dobrze:

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

Zasadniczo, jeśli pracujesz z wiersza poleceń, jest to prostsze niż mogłoby się wydawać. Załóżmy, że chcesz 2 repozytoria git:

.gitone
.gittwo

Możesz je skonfigurować tak:

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

Możesz dodać plik i zatwierdzić go tylko do jednego w ten sposób:

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

Zatem najpierw są opcje dla git, potem polecenie, a na końcu opcje polecenia git. Możesz łatwo aliasować polecenie git, takie jak:

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

Możesz więc zobowiązać się do jednego lub drugiego, nieco mniej wpisując, na przykład gitone commit -m "blah".

To, co wydaje się być trudniejsze, jest ignorowane. Ponieważ .gitignore zwykle znajduje się w katalogu głównym projektu, musiałbyś znaleźć sposób na zmianę tego również bez przełączania całego katalogu głównego. Lub możesz użyć .git / info / exclude, ale wszystkie ignorowania, które następnie wykonujesz, nie zostaną zatwierdzone ani przesunięte - co może zepsuć innych użytkowników. Inni używający któregokolwiek repozytorium mogą wypchnąć plik .gitignore, co może powodować konflikty. Nie jest dla mnie jasne, jak najlepiej rozwiązać te problemy.

Jeśli wolisz narzędzia GUI, takie jak TortoiseGit, będziesz miał również pewne wyzwania. Możesz napisać mały skrypt, który tymczasowo zmienia nazwę .gitone lub .gittwo na .git, aby spełnić założenia tych narzędzi.

Chris Moschini
źródło
1
Ustawienie go jako aliasu powoduje wyświetlenie tego błędu: $ git config --global alias.pub '--git-dir = ~ / Server / www / .gitpublic' $ git pub add. fatal: alias 'pub' zmienia zmienne środowiskowe Możesz użyć '! git' w aliasie, aby to zrobić. Gdzie w tym przypadku ustawiasz "! Git"?
JaredBroad
1
@JaredBroad Interesujące - sugerowałem użycie aliasu Bash, a nie aliasu git. Na przykładalias gitone='git --git-dir=.gitone'
Chris Moschini,
10
Można skonfigurować repo do wykorzystania własnej wykluczyć pliki i można śledzić tych, IE gitone config core.excludesfile gitone.excludei gitone add gitone.exclude. Zrobiłem skrypt, który rozwija to rozwiązanie: github.com/capr/multigit
2
@JaredBroad Zrobiłem to git config --global alias.youralias '!git --git-dir="/d/MyProject/_git"'wtedy tak git youralias status:)
starikovs
1
Jeśli przyjmiesz założenie, że .gitignorepliki są zwykle ustawiane i zapomniane, możesz wykonać różne kopie dla każdego repozytorium, a następnie skopiować odpowiednią wersję do katalogu jako część aliasu. Dotyczy to innych plików w katalogu głównym, które mogą powodować konflikty, takich jak README.mdi .gitattributes.
czwartek
15

Przyjrzyj się podmodułowi git .

Podmoduły pozwalają na osadzenie obcych repozytoriów w dedykowanym podkatalogu drzewa źródłowego, zawsze wskazując na konkretne zatwierdzenie.

Hates_
źródło
8
Nie nadaje się do plików, które muszą znajdować się w katalogu głównym twojego katalogu. Jedyną szansą jest wypełnienie korzenia linków do nich.
WhyNotHugo
6

RichiH napisał narzędzie o nazwie vcsh, które jest narzędziem do zarządzania plikami dotfiles przy użyciu fałszywych gołych repozytoriów git w celu umieszczenia więcej niż jednego katalogu roboczego w $ HOME. Nie ma to nic wspólnego z csh AFAIK.

Jeśli jednak masz wiele katalogów, alternatywą dla git-submodules (które są uciążliwe w najlepszych okolicznościach, a to przykładowe użycie nie jest najlepsze) jest gitslave, które pozostawia niewolnicze repozytoria sprawdzone na czubku rozgałęzienia przez cały czas i nie wymaga trzyetapowego procesu, aby dokonać zmiany w repozytorium zależnym (wyewidencjonowanie do właściwej gałęzi, dokonanie i zatwierdzenie zmiany, a następnie przejście do superprojektu i zatwierdzenie nowego modułu podrzędnego).

Seth Robertson
źródło
6

Jest to możliwe przy użyciu zmiennej, GIT_DIRale wiąże się z wieloma zastrzeżeniami, jeśli nie wiesz, co robisz.

tzervo
źródło
4

Tak, podmoduły są prawdopodobnie tym, czego chcesz. Inną opcją byłoby umieszczenie kopii roboczej w podkatalogu, a następnie wskazanie dowiązań symbolicznych z katalogu domowego do interesujących nas plików.

Pat Notz
źródło
3

moją preferowaną metodą jest użycie repozytorium w podkatalogu i rekurencyjne dowiązania symboliczne:

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

gdzie plik ' repo / build ' wygląda następująco:

#!/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

uwaga : nie używaj „git add”.

coderofsalvation
źródło
0

Inną opcją jest umieszczenie ich w oddzielnych folderach i utworzenie symbolicznych twardych łączy z jednego folderu do drugiego.

Na przykład, jeśli istnieją repozytoria:

  1. Repo1 / Folder A.
  2. Repo1 / FolderB

I:

  1. Repo2 / FolderC

Możesz utworzyć dowiązanie symboliczne do folderów FolderAi FolderBz Repo1 do Repo2. W przypadku systemu Windows polecenie do uruchomienia na Repo1 wyglądałoby tak:

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

W przypadku plików w głównych repozytoriach musiałbyś dowiązać symboliczne do każdego z nich, dodając je również do repozytorium, .gitignoreaby uniknąć szumów, chyba że chcesz.

użytkownik
źródło
0

Zastrzeżenie: to nie jest reklama. Jestem programistą dostarczonej biblioteki.

Stworzyłem rozszerzenie git do obsługi przypadków, w których chcesz mieszać wiele repozytoriów w jednym folderze. Zaletą lib jest śledzenie repozytoriów i konfliktów plików. można go znaleźć na githubie . Istnieją również 2 przykładowe repozytoria do wypróbowania.

user1810087
źródło