Rsync zawiera sprytną opcję --cvs-exclude
„ignorowania plików w taki sam sposób, jak robi to CVS”, ale CVS był przestarzały od lat. Czy istnieje sposób, aby wykluczyć również pliki, które byłyby ignorowane przez nowoczesne systemy kontroli wersji (Git, Mercurial, Subversion)?
Na przykład mam wiele projektów Mavena pobranych z GitHub. Zazwyczaj zawierają .gitignore
przynajmniej listę target
, domyślny katalog kompilacji Mavena (który może znajdować się na najwyższym poziomie lub w modułach podrzędnych). Ponieważ zawartość tych katalogów jest całkowicie jednorazowa i może być znacznie większa niż kod źródłowy, chciałbym je wykluczyć podczas używania rsync do tworzenia kopii zapasowych.
Oczywiście mogę wyraźnie, --exclude=target/
ale spowoduje to przypadkowe zablokowanie niepowiązanych katalogów, które akurat zostały nazwane target
i nie powinny być ignorowane.
I mogę dostarczyć kompletną listę ścieżek bezwzględnych dla wszystkich nazw plików i wzorów wymienionych w dowolnym .gitignore
, .hgignore
lub svn:ignore
mienia na moim dysku, ale to byłaby ogromna lista, która musiałaby być produkowane przez jakiegoś skryptu.
Ponieważ rsync nie ma wbudowanej obsługi wyewidencjonowania VCS innej niż CVS, czy jest jakaś dobra sztuczka do podawania mu wzorców ignorowania? Lub jakiś system wywołań zwrotnych, w którym skrypt użytkownika może zostać zapytany, czy dany plik / katalog powinien być uwzględniony, czy nie?
Aktualizacja : --filter=':- .gitignore'
zgodnie z sugestią LordJavaca wydaje się działać tak samo dobrze dla Gita, jak --filter=:C
dla CVS, przynajmniej na przykładach, które znalazłem, chociaż nie jest jasne, czy składnia jest dokładnie zgodna. --filter=':- .hgignore'
nie działa zbyt dobrze w przypadku Mercurial; np. .hgignore
wiersz zawierający linię taką jak ^target$
(Mercurial odpowiednik Git /target/
) nie jest rozpoznawany przez rsync jako wyrażenie regularne. Wydaje się, że nic nie działa dla Subversion, dla której musiałbyś przeanalizować .svn/dir-prop-base
kopię roboczą 1.6 lub wcześniejszą i wznieść ręce z konsternacją, aby uzyskać kopię roboczą 1.7 lub nowszą.
:-
dokładnie znaczy? Co oznacza okrężnica? Co za kreska?check-ignore
podkomendę, która może poradzić sobie z ciężką pracą polegającą na parsowaniu różnych plików „ignoruj”, jeśli chcesz skorzystać z opcji „wygeneruj listę wszystkich niezignorowanych plików”. Moja odpowiedź zawiera szczegóły, jak to zrobić.Odpowiedzi:
Jak wspomniał luksan, możesz to zrobić,
--filter
przełączając się narsync
. Osiągnąłem to z--filter=':- .gitignore'
(jest spacja przed ".gitignore"), który mówi,rsync
aby wykonać połączenie katalogów z.gitignore
plikami i wykluczyć je zgodnie z regułami gita. Możesz także dodać swój globalny plik ignorowania, jeśli taki masz. Aby ułatwić korzystanie z niego, utworzyłem alias, dorsync
którego dołączyłem filtr.źródło
--exclude='/.git' --filter="dir-merge,- .gitignore"
rsync -rvv --exclude='.git*' --exclude='/rsync-to-dev.sh' --filter='dir-merge,-n /.gitignore' $DIR/ development.foobar.com:~/test/
... ale mimo, że jest napisane[sender] hiding file .gitignore because of pattern .git*
, plik nadal jest wysyłany do desintacji--delete
opcji, tutaj jest wiersz poleceń pracy:rsync --delete-after --filter=":e- .gitignore" --filter "- .git/" -v -a ...
. Zajęło mi to trochę czasu ...e
w filtrze i--delete-after
oba są ważne. Proponuję przeczytać rozdział "PER-DIRECTORY RULES AND DELETE" narsync
stronie podręcznika .--delete-after
do wersji polecenia @ VasiliNovikov. (Wydaje się, że jest to równoważne z wersją polecenia @ dboliton, z wyjątkiem @db używa: e, co moim zdaniem wyklucza pliki .gitignore z kopiowania, co nie jest tym, czego chciałem.)Możesz użyć
git ls-files
do zbudowania listy plików wykluczonych przez.gitignore
pliki repozytorium . https://git-scm.com/docs/git-ls-filesOpcje:
--exclude-standard
Rozważ wszystkie.gitignore
pliki.-o
Nie ignoruj zmian niestopowych.-i
Wyprowadzaj tylko ignorowane pliki.--directory
Podaj ścieżkę katalogu tylko wtedy, gdy cały katalog jest ignorowany.Jedyne, co mogłem zignorować, to
.git
.źródło
rsync -azP --exclude-from="$(git -C SRC ls-files --exclude-standard -oi --directory > /tmp/excludes; echo /tmp/excludes)" SRC DEST
.gitignore
(tj. Wiersze zaczynające się od!
). Rsyntuje również pliki, które--force
dodałeś do repozytorium, co zwykle jest dobrą rzeczą.co powiesz na to
rsync --exclude-from='path/.gitignore' --exclude-from='path/myignore.txt' source destination
?U mnie to zadziałało.
Uważam, że możesz mieć też więcej
--exclude-from
parametrów.źródło
.gitignore
pliki będą używać składni zgodnej zrsync
.Rozwiązanie 2018 potwierdzone
Szczegóły:
--exclude-from
jest obowiązkowe zamiast --exclude, ponieważ prawdopodobny przypadek, który zawiera listę wykluczeń, nie zostałby przeanalizowany jako argument. Wyklucz z wymaga pliku i nie może działać z potokami.Bieżące rozwiązanie zapisuje plik wykluczenia w folderze .git, aby zapewnić, że nie wpłynie
git status
to na jego niezależność. Jeśli chcesz, możesz użyć / tmp.źródło
SRC
tutaj - ale nie w przypadku pierwotnego problemu, który wskazałem, który jest rozległym katalogiem z tysiącami repozytoriów Git jako podkatalogami na różnych głębokościach, z których wiele ma idiosynkratyczne.gitignore
s.--exclude-from=<(git -C SRC ls-files --exclude-standard -oi --directory)
W przypadku rtęci możesz użyć
aby zebrać listę plików, które NIE są pod kontrolą rtęci z powodu ograniczeń .hgignore, a następnie uruchomić
rsync wszystkie pliki poza ignorowanymi. Ogłoszenie flaga -m w rsync wyklucza puste katalogi z synchronizacji, ponieważ hg status -i wyświetla tylko wykluczone pliki, a nie katalogi
źródło
Spróbuj tego:
rsync -azP --delete --filter=":- .gitignore" <SRC> <DEST>
Może kopiować wszystkie pliki do zdalnego katalogu z wyjątkiem plików z „.gitignore” i usuwać pliki, których nie ma w bieżącym katalogu.
źródło
Na
rsync
stronie podręcznika , oprócz standardowej listy wzorców plików:Tak więc mój plik $ HOME / .cvsignore wygląda następująco:
aby wykluczyć .git i pliki wygenerowane przez Sass .
źródło
.git/
katalogi, być może nawet silniej niż kopia robocza. Chcę wykluczyć produkty budowlane.rsync
cytowanej w tej odpowiedzi opisuje--cvs-exclude
opcję, więc musisz jej użyć jawnie. 2 / Możesz tworzyć.cvsignore
pliki w dowolnym katalogu, aby mieć ignorowania specyficzne dla projektu, one również są odczytywane. 3 /.git
jest już ignorowany, gdy używasz--cvs-exclude
, zgodnie z instrukcją, więc posiadanie go$HOME/.cvsignore
wydaje się zbędne.Miałem wiele bardzo dużych
.gitignore
plików i żadne z rozwiązań „czystego rsync” nie działało. Napisałem ten skrypt opakowujący rsync , w pełni szanuje.gitignore
reguły (!
wyjątki w stylu dołączania i.gitignore
pliki w podkatalogach) i działa dla mnie jak urok.źródło
locate -0e .gitignore | (while read -d '' x; do process_git_ignore "$x"; done)
, ale ma wiele problemów. Pliki w tym samym katalogu, co.gitignore
niepoprawnie oddzielone od nazwy katalogu za pomocą/
. Puste wiersze i komentarze zostały błędnie zinterpretowane. Dławiki na.gitignore
plikach w ścieżkach ze spacjami (nie wspominając o diabelskim/opt/vagrant/embedded/gems/gems/rb-fsevent-0.9.4/spec/fixtures/custom 'path/.gitignore
zvagrant
pakietu dla Ubuntu). Być może lepiej zrobione jako skrypt Perla.rsync
, z tego konkretnego powodu, że obsługa cytatów / białych znaków jest tak uciążliwa. Jeśli masz przykładgsync
niedziałającej linii poleceń i.gitignore
powiązanych z nią plików, z przyjemnością przyjrzę się bliżej.rsync
całego systemu plików z rozrzuconymi wokół niego różnymi repozytoriami Git. Być może twój skrypt działa dobrze w przypadku synchronizacji pojedynczego repozytorium.Sprawdź sekcję ZASADY FILTROWANIA PLIKÓW MERGE w rsync (1).
Wygląda na to, że można utworzyć regułę rsync --filter, która będzie obejmować pliki .gitignore podczas przeglądania struktury katalogów.
źródło
Zamiast tworzyć filtry wykluczania, możesz użyć
git ls-files
do wybrania każdego pliku do rsync:Działa to nawet wtedy, gdy
git ls-files
zwraca ścieżki oddzielone znakiem nowej linii. Prawdopodobnie nie zadziała, jeśli masz wersjonowane pliki ze spacjami w nazwach plików.źródło
Alternatywy:
git ls-files -zi --exclude-standard |rsync -0 --exclude-from=- ...
git ls-files -zi --exclude-per-directory=".gitignore" |...
(rsync tylko częściowo rozumie .gitignore)
źródło
Krótka odpowiedź
Znaczenie parametrów:
-r
: rekurencyjny--info=...
: pokaż postęp--filter=...
: wyklucz według reguł wymienionych w pliku .gitignoreźródło
Po godzinach poszukiwań znalazłem dokładnie to, czego potrzebuję: synchronizację folderu docelowego z folderem źródłowym (również usuwanie plików w miejscu docelowym, jeśli zostały usunięte w źródle) i nie kopiowanie do miejsca docelowego plików, które są ignorowane przez .gitignore, ale też nie usuwać tych plików w miejscu docelowym :
Innymi słowy, to polecenie całkowicie ignoruje pliki z .gitignore, zarówno w źródle, jak iw miejscu docelowym . Możesz pominąć
--exclude='/.git'
część, jeśli chcesz skopiować plik.git
folder.MUSISZ skopiować pliki .gitignore ze źródła. Jeśli użyjesz polecenia LordaJavaca, plik .gitignore nie zostanie skopiowany. A jeśli utworzysz plik w folderze docelowym, który powinien zostać zignorowany przez .gitignore, ten plik zostanie usunięty pomimo .gitignore. Dzieje się tak, ponieważ nie masz plików .gitignore w miejscu docelowym. Ale jeśli będziesz mieć te pliki, pliki opisane w .gitignore nie zostaną usunięte, zostaną zignorowane, po prostu oczekiwane.
źródło