Czy istnieją pułapki, aby umieścić $ HOME w git zamiast symbolizować pliki dot?

38

Przez wiele lat cały mój $HOMEkatalog był sprawdzany jako subversion. Obejmuje to wszystkie moje pliki dot i profile aplikacji, wiele skryptów, narzędzi i hacków, moją preferowaną podstawową strukturę katalogu domowego, a nie kilka dziwnych projektów i losowe dane o wartości hurtowej. To była dobra rzecz. Podczas gdy to trwało.

Ale wymknęło się spod kontroli. Podstawowa kasa jest taka sama dla kilkudziesięciu systemów, ale nie wszystkie rzeczy są odpowiednie dla wszystkich moich komputerów. To nie wszystko dobrze gra z różnymi dystrybucjami.

Jestem w trakcie sprzątania domu - oddzielanie danych tam, gdzie należy, rozdzielanie niektórych skryptów jako osobnych projektów, naprawianie uszkodzonych linków w rzeczach, które powinny zostać zautomatyzowane itp.

Moim zamiarem jest, aby wymienić subversionz gitna kasie, będąc w głównym z $HOME, ale chciałbym pare to w dół po prostu rzeczy, chciałbym mieć na wszystkich moich systemów, co oznacza dotfiles, kilka katalogów i niektóre podstawowe skrypty.

Podczas czytania online wiele osób robi to przy użyciu metody dowiązań symbolicznych: klonuj do podkatalogu, a następnie twórz dowiązania symboliczne z $HOMErepozytorium. Mając $HOMEpełną kontrolę nad wersją przez ponad dekadę, nie podoba mi się to podejście i nie mogę zrozumieć, dlaczego ludzie wydają się tak niechętni prostej metodzie kasowania. Czy są jakieś pułapki, o których muszę wiedzieć, gitjako konkretne dla kasy najwyższego poziomu $HOME?

PS Częściowo, jako ćwiczenie z dobrego kodowania, planuję również upublicznić moje konto roota na github. Przerażające jest to, jak wiele poufnych informacji, które pozwoliłem zebrać w plikach, które można podzielić bez zastanowienia! Hasło Wi-Fi, niepasujące klucze RSA itp. Eeek!

Caleb
źródło
5
Ciekawe, co doprowadziło do przekonania, że ​​$ HOME powinno być możliwe do współdzielenia bez zastanowienia się. Nawet zaszyfrowanych kluczy prywatnych RSA nie należy udostępniać.
derobert
3
jeśli w rzeczywistości mówisz o umieszczeniu zawartości katalogu domowego w git, pamiętaj: trudno jest (ale nie niemożliwe) przekopać się przez historię git i ostrożnie usunąć na stałe wrażliwe elementy (git ma na celu zapobieganie utracie rzeczy), oraz pamiętaj również, że po zmianie gałęzi lub kasie wcześniejsza wersja gitzmieni uprawnienia do plików na 644kasę, co jest niekorzystne dla takich rzeczy jak prywatne klucze ssh. etckeeperjest jednak rozwiązanie do używania git z uprawnieniami do / etc /
cwd
@derobert: Jestem tego świadomy. Nie mówiłem o upublicznieniu $ HOME, tylko plikach dot i skryptach wygody. Tam właśnie znajdowałem rzeczy, które nie należą. I tak, będę mógł podzielić się moją .zshrc, .vimrci podobne rzeczy bez konieczności zdezynfekować je pierwszy!
Caleb
4
Jeśli jeszcze tego nie widziałeś, zajrzyj na wiki i listy mailingowe vcs-home , czyli w zasadzie ludzie dyskutują właśnie o tym - jak utrzymać kontrolę nad $ HOME.
Jim Paris,
Nie wiem, jak bardzo możesz zmienić zachowanie git, ale przynajmniej sposób, w jaki działa poza repozytorium debian, jest bardzo chciwy, jeśli chodzi o wyszukiwanie śledzonych / nieśledzonych / zmodyfikowanych plików i automatycznie czuje się odpowiedzialny za każdy plik. mrb już to stwierdził. Czasami denerwuje mnie to zachłanne zachowanie, nawet w stosunkowo małych projektach, nie chciałbym tego w moim katalogu domowym. Dlaczego chcesz korzystać z git? Używam również systemu kontroli wersji do synchronizacji plików konfiguracyjnych między hostami i jestem całkiem zadowolony z CVS, ponieważ to takie proste! Git jest do tego bardzo (bardzo!) Potężny
Bananguin

Odpowiedzi:

17

Tak , istnieje co najmniej jeden poważny problem przy rozważaniu gitzarządzania katalogiem domowym, który nie stanowi problemu subversion.

Git jest domyślnie zarówno chciwy, jak i rekurencyjny .

Subversion naiwnie zignoruje wszystko, o czym nie wie i przestanie przetwarzać foldery w górę lub w dół od kasy, gdy dotrze do takiego, o którym nie wie (lub który należy do innego repozytorium). Z drugiej strony Git ciągle się rekursuje we wszystkich katalogach potomnych, co sprawia, że ​​zagnieżdżone kasy są bardzo skomplikowane z powodu problemów z przestrzenią nazw. Ponieważ twój katalog domowy jest prawdopodobnie miejscem, w którym kasujesz i pracujesz nad różnymi innymi repozytoriami git, posiadanie twojego katalogu domowego w git prawie na pewno sprawi, że twoje życie stanie się niemożliwym bałaganem.

Jak się okazuje, jest to główny powód, dla którego ludzie pobierają swoje pliki dot do osobnego folderu, a następnie umieszczają w nim dowiązanie symboliczne. Uniemożliwia gitowi wykonywanie innych czynności w dowolnym katalogu podrzędnym $HOME. Chociaż jest to wyłącznie kwestia preferencji, jeśli sprawdzasz swój dom w subwersji, staje się kwestią konieczności, jeśli używasz git.

Istnieje jednak alternatywne rozwiązanie. Git pozwala na coś, co nazywa się „fałszywym rootem”, w którym cała maszyneria repozytorium jest ukryta w alternatywnym folderze, który można fizycznie oddzielić od katalogu roboczego kasy. W rezultacie zestaw narzędzi git się nie pomyli: nawet NIE ZOBACZ repozytorium, tylko kopia robocza. Ustawiając kilka zmiennych środowiskowych, możesz wskazać git, gdzie znaleźć towary na te chwile, kiedy zarządzasz katalogiem domowym. Bez ustawionych zmiennych środowiskowych nikt nie jest mądrzejszy, a Twój dom wygląda jak klasyczna własność pliku.

Aby sprawić, by ta sztuczka płynęła trochę płynniej, istnieje kilka świetnych narzędzi. Lista dyskusyjna VCS-dom wydaje się de facto miejsce, aby rozpocząć, a o stronie posiada wygodny omotać z HOWTO i doświadczeń ludzi. Po drodze są jakieś fajne małe narzędzia, takie jak vcsh , mr . Jeśli chcesz przechowywać katalog domowy bezpośrednio w git, vcsh jest prawie niezbędnym narzędziem. Jeśli w końcu podzielisz swój katalog domowy na kilka repozytoriów za kulisami, połącz go vcshz, mraby uzyskać szybki i niezbyt brudny sposób zarządzania nim jednocześnie.

Caleb
źródło
2
ale dlaczego po prostu nie dodać „*” do pliku .gitignore? W ten sposób git zignoruje wszystko oprócz plików, które są już w repozytorium, i możesz dodawać nowe pliki za pomocą git add -f <file>.
ALiX
@ALiX: Ponieważ gitnarzędzia nadal uważają, że pracujesz nad swoim domowym repozytorium, nawet jeśli byłeś w jakimś podkatalogu, który był oddzielnym repozytorium git dla jakiegoś projektu. Takie rozwiązanie spowodowałoby, że cały katalog domowy nie byłby ograniczony do wszystkich innych operacji git.
Caleb
5
ale „*” w .gitignore oznacza, że ​​wszystkie pliki nie znajdujące się w twoim repozytorium home-dir są ignorowane. a kiedy sprawdzasz nowe repozytorium git w jakimś podkatalogu, wszystko powinno nadal działać zgodnie z oczekiwaniami (tak myślę). O ile mi wiadomo, narzędzia git będą szukały pierwszego katalogu .git podczas przenoszenia hierarchii katalogów. Tak więc podczas pracy w podkatalogu zostanie użyte prawidłowe repozytorium git. Oczywiście, jeśli używasz zmiennych środowiskowych git, myślę, że sprawy mogą się popsuć. Ale poza tym nie rozumiem, dlaczego to nie zadziałałoby.
ALiX
@ALiX ma rację. Zagnieżdżone repozytorium git wydaje się działać dobrze, dopóki gitignore je w repozytorium nadrzędnym. Zastanawiam się, jakie są wady tego bardzo prostego podejścia, oprócz możliwych problemów ze zmiennymi środowiskowymi git.
evanrmurphy
1
Eksperymentowałem z tym dzisiaj. Myślę, że /*działa lepiej niż *dlatego, że nadal domyślnie ignoruje wszystko, ale znacznie ułatwia dodawanie katalogów. Zamiast git add -fużywać !wzorców z prefiksem, takich jak !/.vimrci !/.gitignore(dla samego pliku .gitignore ), aby jawnie uwzględniać rzeczy w repozytorium.
evanrmurphy
14

Nie chciałbym, aby cały mój katalog domowy był sprawdzany pod kontrolą wersji po prostu dlatego, że oznacza to, że każdy podkatalog, do którego wchodzę, miałby kontekst kontroli wersji mojego katalogu domowego. Polecenia takie git checkoutmiałyby w takim przypadku rzeczywiste działanie, powodując problemy, jeśli przypadkowo uruchomię coś z niewłaściwego katalogu, niezależnie od tego, czy jest to coś innego git, czy skrypt wywołujący git.

Zwiększa także prawdopodobieństwo dodania do repozytorium czegoś, czego nie chcesz, co nie byłoby problemem, gdy wszystko się zameldowałeś, ale teraz staje się problemem. Co jeśli przypadkowo dodasz plik klucza prywatnego (być może z przyzwyczajenia) i wypchniesz go do github?

Powiedziawszy to, uważam, że główne wady nie są tak naprawdę techniczne - po prostu chcą mnie uratować od siebie.

Co do symlinkowania: możesz sklonować swoje repozytorium do podkatalogu i mieć skrypt, który aktualizuje wszelkie dowiązania symboliczne, które wymagają aktualizacji. Jednak ilość konserwacji wymaganej dla tego skryptu może przeważać nad korzyściami z posiadania go; dowiązanie symboliczne może okazać się mniej pracy.

Za pomocą dowiązań symbolicznych możesz także łatwo dodawać specyficzne dla dystrybucji (lub nawet hosta) dodatki, które są sprawdzane w git. Twój skrypt aktualizacji dowiązań symbolicznych zignoruje pliki przeznaczone dla niezgodnych platform lub różnych hostów i zaktualizuje tylko te odpowiednie.

Coś jak:

HOMEREPO=$HOME/homerepo
HOST=$(hostname)
UNAME=$(uname)

for dotfile in $HOMEREPO/shared/* $HOMEREPO/host-$HOST/* $HOMEREPO/uname-$UNAME/*
do
    target=$HOME/$(basename $dotfile)
    [ ! -r $target ] && ln -s $dotfile $target
done

Osobiście: Używam dowiązań symbolicznych i nie symbolizuję katalogów dowiązań; tylko pliki wewnątrz. Daje mi to pewną elastyczność w dokonywaniu lokalnych zmian w tych katalogach (np. Dodawanie / usuwanie plików). Założenie mojego konta w nowym systemie jest żmudne, ponieważ muszę ręcznie odtworzyć wszystkie dowiązania symboliczne.

mrb
źródło
Wszelkie gitpolecenia, które uruchamiam, byłyby albo dla samego katalogu domowego, albo byłyby zakopane co najmniej jedno głęboko w katalogu niezaangażowanym. Korzystanie z svntej izolacji jednego folderu jest dość skuteczne i nie sprawiło mi żadnych problemów przez dekadę. Twój pierwszy akapit wskazuje coś innego. Czy to rzeczywiście różnica w sposobie gitdziałania?
Caleb
Również moje konfiguracje i skrypty mają już wbudowaną logikę warunkową dla różnych hostów i platform, więc używanie skryptu do konfigurowania różnych linków, ponieważ warunkowe nie wydaje się dużym zyskiem w stosunku gitdo łatwych w zarządzaniu gałęzi. Ciągle czegoś mi brakuje, czy sprowadzi się to do preferencji?
Caleb
3
Izolacja jednego folderu tak naprawdę nie izoluje git- nie jestem pewien svn- ale na przykład git init foo && mkdir -p foo/bar/baz/spam && cd foo/bar/baz/spam && git status(lub inne polecenia git) pokazują, że nadal jesteś w fookontekście kontroli wersji.
mrb
Konfiguracje i skrypty: Nie wszystkie pliki kropkowe obsługują warunki warunkowe, dlatego zasugerowałem alternatywne podejście. Są to wszystkie powody, dla których myślę, że ludzie wolą nie używać kontroli wersji $HOME- a wersjonowanie nie jest tak naprawdę cenne dla plików doto - imo - ale ostatecznie jest to twój katalog domowy, więc jeśli wolisz używać git i nie są to dla ciebie problemy, idź po to!
mrb
Dzięki za informację. W rzeczywistości twój komentarz na temat git nie pozwalający na izolację jest najbardziej przydatny. Możesz w znaczący sposób wykorzystać swoją odpowiedź. Subversion zachowuje się bardzo różnie w tym punkcie i jego znaczeniu dla tego przypadku użycia.
Caleb
6

Żeby dać inny punkt widzenia: od jakiegoś czasu mam $ GITta i nie znalazłem żadnych wad. Oczywiście nie synchronizuję tego repozytorium git z github; Korzystam z usługi, która ma prywatne repozytorium. Nie poddaję również żadnych plików multimedialnych, plików do pobrania ani pakietów kontrolom git.

  • git status jest rodzajem listy kontrolnej „robić, czyścić”.

  • Mam ~/tmptymczasowe rzeczy, które są gitignored.

  • Lubię widzieć we git statuswszystkim, co ostatnio zainstalowane oprogramowanie odważy się dodać do mojego $ HOME, i często usuwam te pliki, a nawet odinstalowuję winowajców.

  • Dodaję ręcznie bardzo przydatne lokalne pliki i katalogi .gitignore, które mają zaletę „wiesz, co robisz podczas instalowania rzeczy”.

  • Jeśli zbuduję nową maszynę wirtualną lub zainstaluję nowy komputer, po prostu sklonuję mój zdalny dom do $ HOME i od razu mam wszystko, czego potrzebuję.

  • Rzeczy takie jak vundle dla wtyczek vim nie są już potrzebne.

Nie lubię złożoności. Kiedy poprawiam dowolny plik rc, po prostu robię to, zatwierdzam i pcham. Następnie, odruchowo, ściągam $ HOME co drugi dzień i zawsze mam najnowszą konfigurację. To takie proste.

Komputery obecnie objęte tym schematem: laptop domowy, komputer stacjonarny, maszyna wirtualna oraz 3 lub 4 zdalne serwery.

gb.
źródło
Czy masz jeszcze jakieś kasy w domu?
Caleb
Nie, umieszczam inne rzeczy w katalogu / work i nie klonuję małych narzędzi, takich jak vim pugins.
gb.
1
Mam pracę wewnątrz ~ / Sites i robię to samo, nie ma problemu z zagnieżdżonymi
repozytoriami
1
Używam tej konfiguracji od jakiegoś czasu. Mam „alias sq = git status -uno” i nie przejmuję się zbytnio .gitignore (co jakiś czas patrzę na wszystkie cruft, a potem mówię „meh”). Nigdy nie miałem problemów z zagnieżdżonymi repozytoriami git. Mam prywatny serwer, na którym zrobiłem polecenie, git init --barektóre przerzucam na ssh (chociaż nie umieszczam haseł w repozytorium, mam tam swoje pliki notatek).
młotek
5

Próbowałem obu i na końcu wolałem podejście do dowiązania symbolicznego :

  • Sprawdź gdziekolwiek
  • make install
  • Wyloguj się i zaloguj ponownie, aby załadować ustawienia X.

Niedogodności:

  • Musisz przenieść pliki do repozytorium przed ich dodaniem
  • Muszę utrzymywać listę dowiązań symbolicznych w pliku Makefile

Zalety:

  • Nie ma potrzeby masywnego .gitignore(mam 133 pliki dot ~na moim skromnym pudełku Ubuntu)
  • Może trzymać skrypty serwisowe i inne ~powiązane rzeczy (takie jak Makefilei cleanup.sh) na uboczu
  • Czy wersja może kontrolować ustawienia osobiste i publiczne osobno

Ograniczenia:

  • W przeciwieństwie do @mrb, tworzę tylko dowiązania symboliczne ~. Dzięki temu symlinkowanie jest proste i sprawia, że ​​zauważenie na przykład nowych plików jest trywialne ~/.vim, kosztem bardzo rzadkiej .gitignorekonserwacji.

Te dwie ostatnie zalety przewróciły wagę w moim przypadku - nie chcę zaśmiecać katalogu domowego i chcę wyraźnie oddzielić prywatne i publiczne treści.

Jedyną znaną mi aplikacją, która ma (lub przynajmniej miała) problemy z obsługą dowiązań symbolicznych, był Pidgin - Nadpisywał moje dowiązania symboliczne zwykłymi plikami.

l0b0
źródło
Dziękujemy za Twój wkład w zalety i wady każdego podejścia. W moich dalszych poszukiwaniach odkryłem, że istnieje trzecie podejście, które może najlepiej wykorzystać oba światy, jeśli jesteś w stanie skonfigurować dodatkowe okablowanie, aby zacząć.
Caleb
3

Oto jedna: jeśli spróbujesz to zrobić git rebase -i --rooti zalogowałeś się .gitconfigprzy pierwszym zatwierdzeniu w repozytorium, git tymczasowo usunie .gitconfigplik, co z kolei uniemożliwi wykonanie operacji zmiany bazy, ponieważ wymaga do tego twojego imienia i adresu e-mail które są przechowywane w tym pliku.

Możesz je skonfigurować ponownie i zrobić to ponownie git rebase --continue, ale po tym , jak to zrobiłem i zakończyłem operację bazowania, moje repozytorium git zyskało puste zatwierdzenie bez komunikatu zatwierdzenia przed zatwierdzeniem, które było wcześniej pierwszym zatwierdzeniem w repozytorium, którego nie znam jak się pozbyć.

Nie wiem, co się stanie, jeśli to zrobisz git rebase -i <commit>, i .gitconfigjest rejestrowane wraz z każdym zatwierdzeniem po <commit>.

Być może najłatwiejszym rozwiązaniem jest powstrzymanie się od dodawania .gitconfigdo repozytorium i wpisanie go .gitignore.

Cześć Żegnaj
źródło
2

Tak to robię:

  1. zainstaluj czysty linux (nie jest to konieczne, ale uprzyjemnia życie w kroku 4)
  2. zainstaluj etckeeper
  3. biegnij git initw swoim domu
  4. utwórz .gitignore i dodaj wszystko, co wygląda na to, że Cię nie interesuje lub które może wiele zmienić. Pamiętaj, aby dodać takie rzeczy *.cache, *.lockitd. I nie polecam dodanie/*ponieważ nie będziesz automatycznie powiadamiany o dodaniu czegoś nowego do domu. Jest to podejście oparte na czarnej liście w porównaniu do białej listy, w której zasadniczo chcę zachować moją konfigurację dla wszystkich programów oprócz niestabilnych rzeczy i niektórych programów, na których mi nie zależy. Kiedy później scalisz, migrujesz lub porównujesz systemy, możliwość różnicowania wszystkiego jest całkiem przydatna. Możesz skonfigurować nowe systemy znacznie szybciej niż gdybyś tylko miał .bashrc i kilka innych plików dot. W ten sposób zachowasz konfigurację, którą możesz ustawić za pomocą GUI i nie będziesz wiedział, które pliki dot przechują ustawienia. (Jeśli kiedykolwiek okaże się, że popełniłeś niestabilne pliki, nadal możesz powiedzieć gitowi, aby zakładał niezmienione)
  5. biegać etckeeper init -d /home/username
  6. biegać git commit -d /home/username
  7. skonfiguruj aliasy w swojej powłoce, aby wiersz poleceń był ładniejszy homekeeper checkout

Powodem użycia etckeepera jest to, że będzie on przechowywał metadane, takie jak uprawnienia do plików (raczej ważne dla niektórych rzeczy, takich jak klucze ssh). Powinieneś teraz mieć przechwytywanie przed zatwierdzeniem, które automatycznie zapisuje metadane. Nie jestem pewien co do realizacji transakcji po zakończeniu transakcji. Prawdopodobnie powinieneś użyć etckeeper checkout xxx -d /home/user, przyjrzę się temu nieco więcej i opracuję tę odpowiedź.


źródło
-1

Mój główny problem z używaniem Git w katalogu domowym polega na tym, że Git nie przechowuje atrybutów plików, takich jak uprawnienia do plików i znaczniki czasu. Dla mnie ważne jest, aby wiedzieć, kiedy zostały utworzone określone pliki, co może, ale nie musi, dotyczyć Ciebie. Ponadto utrata uprawnień do plików i katalogów, taka jak .sshjest problematyczna. Rozumiem, że planujesz trzymać .sshsię z dala od Gita, ale będą inne miejsca, w których uprawnienia mogą mieć znaczenie (takie jak nieskompresowane kopie zapasowe witryn).

dotancohen
źródło
Jest to mylące, jeśli nie faktyczne. Git domyślnie zachowuje wiele atrybutów plików, w tym uprawnienia. Od .sshjakiegoś czasu trzymam git bez problemu, odpowiednie bezpieczne uprawnienia są zachowane. To, czego nie robi w konfiguracji podstawowej, to zachowanie własności lub znaczników czasu; jednak jeśli którykolwiek z nich stanowi problem w konkretnym przypadku użycia, istnieją wtyczki, które mogą uczynić obsługę tych dodatkowych właściwości częścią zwykłego przepływu pracy (zobacz metastore lub git-cache-meta).
Caleb
Nawet jeśli ich nie przechowuje, to co może być gorszego niż to, że nie ma katalogu domowego w vcs? git nie zamierza aktywnie nadpisywać mimów, chyba że poprosisz go o zmianę pliku.
poolie
-1

Rozwiązanie oparte na git jest szczególnie przydatne, jeśli chcesz wdrożyć pliki na różnych komputerach, a tym bardziej, jeśli masz części wspólne dla wszystkich komputerów i części specyficzne dla niektórych komputerów. Możesz utworzyć wiele repozytoriów i użyć narzędzia takiego jak multigit lub vcsh, aby sklonować je w tym samym katalogu (w tym przypadku katalog domowy).

capr
źródło
Dzięki, ale może przegapiłeś pytanie. Jestem w pełni świadomy zastosowań tego (dlatego dlaczego chciałem to zrobić w pierwszej kolejności), to pytanie dotyczyło wszelkich pułapek, które ktoś nowy w robieniu tego z gitem (tak jak wtedy, kiedy go zapytałem) może nie być świadomy . To wcale nie odpowiada na to pytanie.
Caleb