rsync .gitignore & .hgignore & svn'ye göre hariç tut: --filter =: C gibi göz ardı et


114

Rsync, --cvs-exclude"CVS'nin yaptığı gibi dosyaları yok saymak" için şık bir seçenek içeriyor , ancak CVS yıllardır kullanılmıyor. Modern sürüm kontrol sistemleri (Git, Mercurial, Subversion) tarafından yok sayılacak dosyaları da dışarıda bırakmanın bir yolu var mı?

Örneğin, GitHub'dan kontrol ettiğim birçok Maven projem var. Tipik olarak, .gitignoreen azından bir liste içerirler target, varsayılan Maven derleme dizini (en üst düzeyde veya alt modüllerde mevcut olabilir). Bu dizinlerin içerikleri tamamen tek kullanımlık olduğundan ve kaynak koddan çok daha büyük olabileceğinden, yedeklemeler için rsync kullanırken bunları dışlamak istiyorum.

Elbette açıkça yapabilirim, --exclude=target/ancak bu, yalnızca adlandırılmış olan targetve göz ardı edilmemesi gereken ilgisiz dizinleri yanlışlıkla bastıracaktır .

Ve hiç belirtilen tüm dosya isimleri ve modelleri için mutlak yollar tam bir listesini kaynağı olabilir .gitignore, .hgignoreya da svn:ignorebenim diskte mülkiyet, ancak bu senaryo çeşit üretilen gerekecekti büyük liste olurdu.

Rsync'in CVS dışında VCS kontrolleri için yerleşik bir desteği olmadığından, onu görmezden gelme modellerini beslemek için iyi bir numara var mı? Veya bir kullanıcı komut dosyasının belirli bir dosya / dizinin dahil edilip edilmeyeceğinin sorulabileceği bir tür geri arama sistemi?

Güncelleme : --filter=':- .gitignore'LordJavac tarafından önerildiği gibi --filter=:C, en azından bulduğum örneklerde CVS'de olduğu gibi Git için de işe yarıyor gibi görünüyor , ancak sözdiziminin tam olarak eşleşip eşleşmediği belirsiz. --filter=':- .hgignore'Mercurial için pek iyi çalışmıyor; Örneğin (Git'in Mercurial eşdeğeri ) .hgignoregibi bir satır içeren bir satır , rsync tarafından düzenli bir ifade olarak tanınmaz. Ve hiçbir şey Subversion için işe yaramıyor gibi görünüyor, bunun için 1.6 veya daha önceki bir çalışma kopyası için ayrıştırmanız ve 1.7 veya sonraki bir çalışma kopyası için ellerinizi dehşet içinde kaldırmanız gerekir .^target$/target/.svn/dir-prop-base


11
Rsync için .gitignore, .hgignore, vb. İçin destek ekleyen bir yama göndermek iyi bir fikir gibi görünüyor
ThiefMaster

3
@ThiefMaster: Başlangıç ​​noktası olarak bugzilla.samba.org/show_bug.cgi?id=9744 dosyaladım .
Jesse Glick

2
sadece diğerleri için bir not, .gitignore komutun yürütüldüğü dizinde değil, rysnc'deki klasör hiyerarşisinde olmalıdır
myol

:-Tam olarak ne anlama geliyor? Kolon ne anlama geliyor? Ne çizgi?
David

Git artık, check-ignore"göz ardı edilmeyen tüm dosyaların bir listesini oluştur" seçeneğiyle gitmek istiyorsanız, çeşitli "yok sayma" dosyalarını ayrıştırmanın zor işleriyle başa çıkabilecek bir alt komuta sahiptir . Buradaki cevabım bunun nasıl yapılacağına dair ayrıntılar veriyor.
cjs

Yanıtlar:


121

Luksan'ın bahsettiği gibi, bunu --filterkonumuna geçiş yaparak yapabilirsiniz rsync. Bunu --filter=':- .gitignore'(".gitignore" dan önce bir boşluk var) rsync, .gitignoredosyalarla dizin birleştirme yapmayı ve git kurallarına göre dışlamalarını söyleyen bir şeyle başardım . Varsa, genel yok sayma dosyanızı da eklemek isteyebilirsiniz. Kullanımını kolaylaştırmak için rsync, filtreyi içeren bir takma ad oluşturdum .


İyi bir başlangıç, ancak bu yanıtı sadece Git'i kapsadığı için "kabul etmekte" tereddüt etsem de.
Jesse Glick

24
.Git dosyalarını da hariç tutan daha ayrıntılı bir sürüm:--exclude='/.git' --filter="dir-merge,- .gitignore"
VasiliNovikov

2
Şimdi buna benzer bir şeyim var: rsync -rvv --exclude='.git*' --exclude='/rsync-to-dev.sh' --filter='dir-merge,-n /.gitignore' $DIR/ development.foobar.com:~/test/.. ama [sender] hiding file .gitignore because of pattern .git*söylendiği halde, dosya hala desintasyona gönderiliyor
rolandow

2
Ayrıca kullanmak istiyorsanız --deleteseçeneği, burada çalışan komut satırı: rsync --delete-after --filter=":e- .gitignore" --filter "- .git/" -v -a .... Bu biraz zaman aldı ... efiltrede ve --delete-afterikisi de önemli. rsyncMan sayfasının "REHBER BAŞINA KURALLAR VE SİL" bölümünü okumanızı öneririm .
dbolotin

1
--delete-afterEklemeleri ve güncellemeleri olduğu kadar, silinenleri de senkronize etmek için, @ VasiliNovikov'un komut sürümüne ekleyebilirsiniz . (Bu @db kullanımları hariç komuta @ dboliton versiyonu, eşdeğer görünüyor: E i isteyerek yapmadım olan kopyalanmasını dışlar .gitignore dosyaları düşünüyorum.)
Bampfer

10

git ls-filesDepo .gitignoredosyaları tarafından dışlanan dosyaların listesini oluşturmak için kullanabilirsiniz . https://git-scm.com/docs/git-ls-files

Seçenekler:

  • --exclude-standardTüm .gitignoredosyaları düşünün .
  • -o Hazırlanmamış değişiklikleri göz ardı etmeyin.
  • -i Yalnızca yok sayılan dosyaları çıkar.
  • --directory Dizin yolunu yalnızca dizinin tamamı yok sayılırsa çıktı olarak alın.

Görmezden geleceğim tek şey şuydu .git.

rsync -azP --exclude=.git --exclude=`git -C <SRC> ls-files --exclude-standard -oi --directory` <SRC> <DEST>

4
bu çalışmıyor. ilk dosyayı git alt komutundan çıkarır ve geri kalanını SRC listesinin bir parçası olarak değerlendirir. bu işe rsync -azP --exclude-from="$(git -C SRC ls-files --exclude-standard -oi --directory > /tmp/excludes; echo /tmp/excludes)" SRC DEST
Maraton

2
Bu, satırlarınızda hem hariç tuttuğunuz hem de satırları dahil ettiğinizde işe yarayan tek yöntemdir .gitignore(yani ile başlayan satırlar !). Ayrıca deponuza eklediğiniz dosyaları da senkronize eder --force, bu genellikle iyi bir şeydir.
ostrokach

1
Aslında bu cevap ÇALIŞMIYOR, bu yüzden işe
sorin

6

ne dersin rsync --exclude-from='path/.gitignore' --exclude-from='path/myignore.txt' source destination?
Benim için çalıştı.
Senin de daha fazla --exclude-fromparametrenin olabileceğine inanıyorum .


3
Bu, .gitignoredosyalarınız ile uyumlu bir sözdizimi kullandığı sürece çalışacaktır rsync.
Jesse Glick

@JesseGlick haklı, rsync .gitignore dosyalarını ayrıştıramaz, bkz. Stackoverflow.com/a/50059607/99834 workround.
sorin

6

2018 çözümü onaylandı

rsync -ah --delete 
    --include .git --exclude-from="$(git -C SRC ls-files \
        --exclude-standard -oi --directory >.git/ignores.tmp && \
        echo .git/ignores.tmp')" \
    SRC DST 

Ayrıntılar: --exclude-from--exclude yerine zorunludur çünkü dışlama listesinin olası durumu bağımsız değişken olarak çözümlenmeyecektir. Dışlama alanı bir dosya gerektirir ve borularla çalışamaz.

Mevcut çözüm, git statuskendi kendine yeten bir durumda tutarken etkilenmemesini sağlamak için dışlama dosyasını .git klasörüne kaydeder . Eğer isterseniz / tmp kullanabilirsiniz.


3
Bu , senkronize etmek istediğiniz belirli bir Git kod deponuz varsa işe yarayacak gibi görünüyor - SRCburada - ancak belirttiğim orijinal sorun için değil, bu, çeşitli derinliklerde alt dizinler olarak binlerce Git deposuna sahip genişleyen bir dizin olan ve çoğunda kendine özgü .gitignores.
Jesse Glick

1
Süreç ikamesi (bash, zsh, vb.) Desteği olan bir kabuk kullanıyorsanız, kullanabilirsiniz--exclude-from=<(git -C SRC ls-files --exclude-standard -oi --directory)
Roland W

3

İçin cıva sen kullanabilir

hg status -i | sed 's/^I //' > /tmp/tmpfile.txt

.hgignore kısıtlamaları nedeniyle mercurial denetimi altında OLMAYAN dosyaların listesini toplamak ve ardından çalıştırmak

rsync -avm --exclude-from=/tmp/tmpfile.txt --delete source_dir/ target_dir/

göz ardı edilenler dışındaki tüm dosyaları yeniden senkronize etmek için. Hg durumu -i dizinleri değil, yalnızca dışlanan dosyaları listeleyeceği için rsync'de boş dizinleri eşitleme dışında bırakacak olan -m işaretine dikkat edin


2

Bunu dene:

rsync -azP --delete --filter=":- .gitignore" <SRC> <DEST>

".Gitignore" içindeki dosyalar hariç tüm dosyaları uzak dizine kopyalayabilir ve mevcut dizininizde olmayan dosyaları silebilir.


1

Başına rsyncadam sayfasında, dosya desenleri standart listesine ek olarak:

$ HOME / .cvsignore'da listelenen dosyalar listeye ve CVSIGNORE ortam değişkeninde listelenen tüm dosyalar eklenir

Dolayısıyla, $ HOME / .cvsignore dosyam şöyle görünüyor:

.git/
.sass-cache/

.git ve Sass tarafından oluşturulan dosyaları hariç tutmak için .


2
Aksine, kesinlikle .git/dizinleri dahil etmek istiyorum , belki de çalışan kopyadan daha güçlü bir şekilde. Hariç tutmak istediğim şey derleme ürünleridir.
Jesse Glick

Ayrıca bu ayar taşınabilir değildir. Kullanıcı başına, proje başına değil.
VasiliNovikov

@JesseGlick .git / dirs'i dahil tutma konusunda sana ikinci bir söz veriyorum. Git, dağıtılmış bir SCM olduğundan, tüm yerel depoyu yedeklemek önemlidir.
Johan Boulé

1 / rsyncBu cevapta alıntılanan man sayfasındaki cümle --cvs-excludeseçeneği açıklar , bu nedenle açıkça kullanmanız gerekir. 2 / .cvsignoreProjeye özgü yok saymak için herhangi bir dizinde dosyalar oluşturabilirsiniz , bunlar da okunur. Kılavuza göre, .gitkullandığınızda 3 / zaten göz ardı edilir --cvs-exclude, bu nedenle içeri girmek $HOME/.cvsignoregereksiz görünüyor.
Niavlys

1

Çok sayıda büyük .gitignoredosyam vardı ve "saf rsync" çözümlerinden hiçbiri benim için işe yaramadı. Bu rsync sarmalayıcı betiğini yazdım , .gitignorekurallara tam olarak saygı duyuyor ( !-stip istisnalarını ve .gitignorealt dizinlerdeki dosyaları dahil et ) ve benim için bir cazibe gibi çalıştı.


Bunu deniyorum locate -0e .gitignore | (while read -d '' x; do process_git_ignore "$x"; done), ancak birçok sorunu var. İle .gitignoredizin adından doğru şekilde ayrılmamış olarak aynı dizindeki dosyalar /. Boş satırlar ve yorumlar yanlış yorumlandı. Üzerinde Chokes .gitignoreboşluklarla yollarında dosyaları (şeytani aldırma /opt/vagrant/embedded/gems/gems/rb-fsevent-0.9.4/spec/fixtures/custom 'path/.gitignoregelen vagrantUbuntu için paketin). Belki bir Perl betiği olarak daha iyi yapılır.
Jesse Glick

@JesseGlick Komut dosyası içindeki işlevi neden çağırdığınızı bilmiyorum. rsynctırnak / boşluk kullanımının bu kadar acı verici olmasının özel bir nedeni için , bunun yerine bir drop-in yerine kullanılması amaçlanmıştır . gsyncBaşarısız olan bir komut satırı örneğiniz ve .gitignoreonunla ilişkili dosyalarınız varsa, daha yakından bakmaktan memnuniyet duyarım.
cobbzilla

rsyncEtrafına dağılmış çeşitli Git depolarıyla birlikte bütün bir dosya sistemine ihtiyacım var. Belki de betiğiniz tek bir depoyu senkronize etme durumunda iyi çalışıyor .
Jesse Glick

1
Evet kesinlikle. üzgünüm bunu netleştirmedim. Bu komut dosyasıyla, repo dizininden git repo başına bir kez çağırmanız gerekir.
cobbzilla

0

Rsync'deki (1) BİRLEŞTİRME DOSYALARI FİLTRE KURALLARI bölümüne bakın.

Dizin yapısını dolaşırken .gitignore dosyalarını içerecek bir rsync --filter kuralı yaratmak mümkün gibi görünüyor.


0

Dışlama filtreleri oluşturmak yerine, git ls-filessenkronizasyon için her dosyayı seçmek için kullanabilirsiniz :

#!/usr/bin/env bash

if [[ ! $# -eq 2 ]] ; then
    echo "Usage: $(basename $0) <local source> <rsync destination>"
    exit 1
fi

cd $1
versioned=$(git ls-files --exclude-standard)
rsync --verbose --links --times --relative --protect-args ${versioned} $2

Bu git ls-files, satırsonu ile ayrılmış yollar döndürse bile çalışır . Dosya adlarında boşluklar bulunan dosyaların sürümlerini belirlediyseniz muhtemelen çalışmayacaktır.


0

Alternatifler:

git ls-files -zi --exclude-standard |rsync -0 --exclude-from=- ...

git ls-files -zi --exclude-per-directory=".gitignore" |...

(rsync, .gitignore'u yalnızca kısmen anlar)


0

Kısa cevap

rsync -r --info=progress2 --filter=':- .gitignore' SOURCE DEST/

Parametrelerin anlamı:

-r: özyinelemeli

--info=...: ilerlemeyi göster

--filter=...: .gitignore dosyasında listelenen kurallara göre hariç tut


0

Çalışma saatlerinden sonra tam olarak ihtiyacım olan şeyi buldum: hedef klasörü kaynak klasörle senkronize etmek (kaynakta silinmişse hedefteki dosyaları da silmek) ve hedefe tarafından yok sayılan dosyaları kopyalamamak .gitignore, ancak hedefteki bu dosyaları da silmeyin :

clear && rsync -vhra /source/project/ /destination/project/ --include='**.gitignore' --exclude='/.git' --filter=':- .gitignore' --delete-after

Başka bir deyişle, bu komut hem kaynakta hem de hedefte .gitignore'daki dosyaları tamamen yok sayar . Klasörü de --exclude='/.git'kopyalamak istiyorsanız bölümü atlayabilirsiniz .git.

.Gitignore dosyalarını kaynaktan kopyalamanız GEREKİR. LordJavac'ın komutunu kullanacaksanız, .gitignore kopyalanmayacaktır. Hedef klasörde .gitignore tarafından yok sayılması gereken bir dosya oluşturursanız, bu dosya .gitignore'a rağmen silinecektir. Bunun nedeni, hedefte .gitignore-dosyalarınızın olmamasıdır. Ancak bu dosyalara sahip olacaksanız, .gitignore dosyasında açıklanan dosyalar silinmeyecek, yok sayılacaklar, beklendiği gibi.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.