Git deposundan yalnızca bir dosyaya nasıl ödeme yapabilirim?
Git deposundan yalnızca bir dosyaya nasıl ödeme yapabilirim?
Yanıtlar:
Başlangıçta, 2012 yılında söz git archive
(bkz Jared Forsyth 'ın cevabı ve Robert Şövalye ' nin cevabını beri) git1.7.9.5 (2012 Mart) , Paul Brannan 'ın cevabı :
git archive --format=tar --remote=origin HEAD:path/to/directory -- filename | tar -O -xf -
Ancak: 2013'te, artık uzak https://github.com URL'leri için mümkün değildi .
" Bir havuzu arşivleyebilir miyim? "
Mevcut (2018) sayfası " GitHub'daki içerik ve verilerin arşivlenmesi hakkında ", GHTorrent veya GH Arşivi gibi üçüncü taraf hizmetlerinin kullanılmasını önerir .
Böylece yerel kopyalar / klonlarla da ilgilenebilirsiniz:
Alternatif olarak, bu yanıtta belirtildiği gibi çıplak deponun yerel bir kopyasına sahipseniz aşağıdakileri yapabilirsiniz ,
git --no-pager --git-dir /path/to/bar/repo.git show branch:path/to/file >file
Veya önce repoyu klonlamalısınız, yani tüm geçmişi elde edersiniz: - .git repo - çalışma ağacında.
git config core.sparsecheckout true
).git/info/sparse-checkout
dosyada görmek istediklerinizi eklemekÇalışma ağacını yeniden okumak için:
$ git read-tree -m -u HEAD
Bu şekilde, tam olarak ne istediğinizi içeren bir çalışma ağacı elde edersiniz (sadece bir dosya olsa bile)
Richard Gomes, ( yorumlarda ) " Git deposundan tek bir dizini veya dizin listesini nasıl klonlayabilir, getirebilir veya seyrek olarak kontrol edebilirim? "
Geçmişi indirmekten kaçınan, tek bir dalı alan ve ihtiyacınız olan dosya veya dizinlerin listesini alan bir bash işlevi.
git archive
şimdi kullanabiliriz .
İlk önce, tüm dosyaların varsayılan çıkışını önleyen -n seçeneği ve --depth 1 seçeneği ile repo'yu klonlayın, bu da her dosyanın yalnızca en son revizyonunu alır
git clone -n git://path/to/the_repo.git --depth 1
Sonra sadece istediğiniz dosyayı kontrol edin:
cd the_repo
git checkout HEAD name_of_file
-n
çalışma ağacı ve dizin senkronize oluyor. Yani, tüm içerik silinmiş olarak görünür. Ya ya git reset HEAD
da git checkout HEAD file
. Git'in nasıl çalıştığını gerçekten anlamadığınız sürece bu noktada havuzla çalışmak da gerçekten zor.
rm -rf .git
NickMoore'un senaryosuna başka bir dosya ekleyerek dosyayı (repo değil) istiyorsa, klonlanmış repo'nun tüm izlerini temizler ve belki de Jefromi'nin kullanımı zor bir repoya sahip olma endişesini ortadan kaldırırdı. Bugün benim meydan okumam gibi başka bir uygulama için benim için çok yararlı hale getiriyor, başka bir post-sonra kanca otomagicaly sürümünü güncellemek için bir alma sonrası kanca oluşturmak.
git
bu tür işler için en iyisi değildir). Bu cevap için de geçerlidir bu soruya , ya bu diğer popüler biri ve birçok diğerleri: değişim name_of_file
için name_of_folder
. Git bugünlerde (2014'lerde) repo sahibine alt modüller sunuyor ve repo kullanıcıları için por dostu sunuyor.
Git git log
repo'sunun bir kopyasına zaten sahipseniz , karma kimliğini (örneğin 3cdc61015724f9965575ba954c8cd4232c8b42e4) bulmak için her zaman a kullanarak bir dosyanın sürümünü kullanıma alabilirsiniz ve şunları yazabilirsiniz:
git checkout hash-id path-to-file
İşte gerçek bir örnek:
git checkout 3cdc61015724f9965575ba954c8cd4232c8b42e4 /var/www/css/page.css
path-to-file
bir dizinse ve geçerli HEAD
değilken belirli bir dosya içeriyorsa target
(veya tersi), bu dosyayı doğru şekilde güncellemez. Üstesinden gelmenin bir yolu var mı?
Normalde git
, ilk yanıtta önerildiği gibi tüm deposu indirmeden yalnızca bir dosya indirmek mümkün değildir . Bunun nedeni Git'in dosyaları düşündüğünüz gibi depolamamasıdır (CVS / SVN'nin yaptığı gibi), ancak bunları projenin tüm geçmişine göre oluşturur.
Ancak belirli durumlar için bazı geçici çözümler vardır. İçin yer tutucular ile aşağıdaki örnekler user
, project
, branch
, filename
.
GitHub
wget https://raw.githubusercontent.com/user/project/branch/filename
GitLab
wget https://gitlab.com/user/project/raw/branch/filename
GitWeb
Sunucuda Git'i kullanıyorsanız - GitWeb , o zaman örnek deneyebilirsiniz (doğru yola değiştirin):
wget "http://example.com/gitweb/?p=example;a=blob_plain;f=README.txt;hb=HEAD"
Drupalcode.org şirketinde GitWeb
Misal:
wget "http://drupalcode.org/project/ads.git/blob_plain/refs/heads/master:/README.md"
googlesource.com
Ham dosyaların base64 kodlu sürümlerini indirmenize izin veren belgesiz bir özellik vardır:
curl "https://chromium.googlesource.com/chromium/src/net/+/master/http/transport_security_state_static.json?format=TEXT" | base64 --decode
Diğer durumlarda Git deponuzun herhangi bir web arabirimi kullanıp kullanmadığını kontrol edin.
Herhangi bir web arayüzü kullanılarak değilse, aşağıdakiler gibi harici hizmetler için kodunuzu itmek düşünebilir GitHub'dan , Bitbucket , vb . ve ayna olarak kullanıyorum.
Eğer var yoksa wget
yüklü denemek curl -O (url)
alternatif.
wget
mutlulukla birlikte bu parlak cevabı ve basitlik getirilerini bulursunuz . Teşekkürler dostum.
git checkout branch_or_version - yol / dosya
misal: git checkout HEAD -- main.c
git checkout -- <filename>
Ref: https://git-scm.com/docs/git-checkout
Dup: Git'te bir dosyanın çalışan kopya değişikliklerini geri al?
git-checkout
.
Şimdi yapabiliriz! Bu google'da ilk sonuç olduğundan, bunu en son sürüme güncelleyeceğimi düşündüm. Git 1.7.9.5'in ortaya çıkmasıyla, git archive
uzak bir ana bilgisayardan tek bir dosya almanıza izin verecek komutumuz var .
git archive --remote=git://git.foo.com/project.git HEAD:path/in/repo filename | tar -x
Cevabı tam olarak burada görebilirsiniz https://stackoverflow.com/a/5324532/290784
github.com
HEAD
ya da master
değil HEAD:directory
.
git archive --remote=git@bitbucket.org:user/repo branch:path/to file | tar -x
GIT'de Çalışma 1.7.2.2
Örneğin Uzak var some_remote dalları ile branch1 , branch32
belirli bir dosyayı teslim almak için şu komutları çağırırsınız:
git checkout remote/branch path/to/file
örnek olarak böyle bir şey olacak
git checkout some_remote/branch32 conf/en/myscript.conf
git checkout some_remote/branch1 conf/fr/load.wav
Bu ödeme komutu, conf / en ve conf / fr dosya yapısının tamamını bu komutları çağırdığınız dizine kopyalar (tabii ki daha önce bir noktada git init'i çalıştırdığınız varsayılır)
git fetch some_remote
önce koşman gerek , değil mi?
Çok basit:
git checkout from-branch-name -- path/to/the/file/you/want
Bu ödeme yapmaz from-branch-name
şubeye . Bulunduğunuz dalda kalacaksınız ve belirtilen daldan yalnızca o tek dosya teslim alınacaktır.
İşte kılavuzun ilgili bölümü git-checkout
git checkout [-p|--patch] [<tree-ish>] [--] <pathspec>...
When <paths> or --patch are given, git checkout does not switch
branches. It updates the named paths in the working tree from the
index file or from a named <tree-ish> (most often a commit). In
this case, the -b and --track options are meaningless and giving
either of them results in an error. The <tree-ish> argument can be
used to specify a specific tree-ish (i.e. commit, tag or tree) to
update the index for the given paths before updating the working
tree.
Bana bu blog yazısından bunu öğreten Ariejan de Vroom'a şapka ipucu .
git clone --filter
Git 2.19'dan
Bu seçenek aslında gereksiz nesneleri sunucudan getirmeyi atlar:
git clone --depth 1 --no-checkout --filter=blob:none \
"file://$(pwd)/server_repo" local_repo
cd local_repo
git checkout master -- mydir/myfile
Sunucu aşağıdakilerle yapılandırılmalıdır:
git config --local uploadpack.allowfilter 1
git config --local uploadpack.allowanysha1inwant 1
V2.19.0 sürümünden itibaren sunucu desteği yoktur, ancak yerel olarak test edilebilir.
YAPILACAKLAR: --filter=blob:none
Tüm lekeleri atlar, ancak yine de tüm ağaç nesnelerini getirir. Ama normal bir repoda, bu dosyaların kendilerine kıyasla çok küçük olmalı, bu yüzden bu zaten yeterince iyi. Sorduğu soru: https://www.spinics.net/lists/git/msg342006.html Devs --filter=tree:0
, bunu yapmak için çalışmalarda olduğunu söyledi.
Bunun --depth 1
zaten ima ettiğini unutmayın, --single-branch
ayrıca bakınız: Git'te tek bir dalı nasıl klonlayabilirim?
file://$(path)
git clone
protokolleri üstesinden gelmek için nasıl gereklidir : Göreceli bir yol ile bir yerel git deposunun sığ klon nasıl?
Biçimi --filter
belgelenmiştir man git-rev-list
.
Bu özelliği desteklemek için Git uzak protokolüne bir uzantı yapıldı.
Git ağacındaki dokümanlar:
Test edin
#!/usr/bin/env bash
set -eu
list-objects() (
git rev-list --all --objects
echo "master commit SHA: $(git log -1 --format="%H")"
echo "mybranch commit SHA: $(git log -1 --format="%H")"
git ls-tree master
git ls-tree mybranch | grep mybranch
git ls-tree master~ | grep root
)
# Reproducibility.
export GIT_COMMITTER_NAME='a'
export GIT_COMMITTER_EMAIL='a'
export GIT_AUTHOR_NAME='a'
export GIT_AUTHOR_EMAIL='a'
export GIT_COMMITTER_DATE='2000-01-01T00:00:00+0000'
export GIT_AUTHOR_DATE='2000-01-01T00:00:00+0000'
rm -rf server_repo local_repo
mkdir server_repo
cd server_repo
# Create repo.
git init --quiet
git config --local uploadpack.allowfilter 1
git config --local uploadpack.allowanysha1inwant 1
# First commit.
# Directories present in all branches.
mkdir d1 d2
printf 'd1/a' > ./d1/a
printf 'd1/b' > ./d1/b
printf 'd2/a' > ./d2/a
printf 'd2/b' > ./d2/b
# Present only in root.
mkdir 'root'
printf 'root' > ./root/root
git add .
git commit -m 'root' --quiet
# Second commit only on master.
git rm --quiet -r ./root
mkdir 'master'
printf 'master' > ./master/master
git add .
git commit -m 'master commit' --quiet
# Second commit only on mybranch.
git checkout -b mybranch --quiet master~
git rm --quiet -r ./root
mkdir 'mybranch'
printf 'mybranch' > ./mybranch/mybranch
git add .
git commit -m 'mybranch commit' --quiet
echo "# List and identify all objects"
list-objects
echo
# Restore master.
git checkout --quiet master
cd ..
# Clone. Don't checkout for now, only .git/ dir.
git clone --depth 1 --quiet --no-checkout --filter=blob:none "file://$(pwd)/server_repo" local_repo
cd local_repo
# List missing objects from master.
echo "# Missing objects after --no-checkout"
git rev-list --all --quiet --objects --missing=print
echo
echo "# Git checkout fails without internet"
mv ../server_repo ../server_repo.off
! git checkout master
echo
echo "# Git checkout fetches the missing file from internet"
mv ../server_repo.off ../server_repo
git checkout master -- d1/a
echo
echo "# Missing objects after checking out d1/a"
git rev-list --all --quiet --objects --missing=print
Git v2.19.0'daki çıktı:
# List and identify all objects
c6fcdfaf2b1462f809aecdad83a186eeec00f9c1
fc5e97944480982cfc180a6d6634699921ee63ec
7251a83be9a03161acde7b71a8fda9be19f47128
62d67bce3c672fe2b9065f372726a11e57bade7e
b64bf435a3e54c5208a1b70b7bcb0fc627463a75 d1
308150e8fddde043f3dbbb8573abb6af1df96e63 d1/a
f70a17f51b7b30fec48a32e4f19ac15e261fd1a4 d1/b
84de03c312dc741d0f2a66df7b2f168d823e122a d2
0975df9b39e23c15f63db194df7f45c76528bccb d2/a
41484c13520fcbb6e7243a26fdb1fc9405c08520 d2/b
7d5230379e4652f1b1da7ed1e78e0b8253e03ba3 master
8b25206ff90e9432f6f1a8600f87a7bd695a24af master/master
ef29f15c9a7c5417944cc09711b6a9ee51b01d89
19f7a4ca4a038aff89d803f017f76d2b66063043 mybranch
1b671b190e293aa091239b8b5e8c149411d00523 mybranch/mybranch
c3760bb1a0ece87cdbaf9a563c77a45e30a4e30e
a0234da53ec608b54813b4271fbf00ba5318b99f root
93ca1422a8da0a9effc465eccbcb17e23015542d root/root
master commit SHA: fc5e97944480982cfc180a6d6634699921ee63ec
mybranch commit SHA: fc5e97944480982cfc180a6d6634699921ee63ec
040000 tree b64bf435a3e54c5208a1b70b7bcb0fc627463a75 d1
040000 tree 84de03c312dc741d0f2a66df7b2f168d823e122a d2
040000 tree 7d5230379e4652f1b1da7ed1e78e0b8253e03ba3 master
040000 tree 19f7a4ca4a038aff89d803f017f76d2b66063043 mybranch
040000 tree a0234da53ec608b54813b4271fbf00ba5318b99f root
# Missing objects after --no-checkout
?f70a17f51b7b30fec48a32e4f19ac15e261fd1a4
?8b25206ff90e9432f6f1a8600f87a7bd695a24af
?41484c13520fcbb6e7243a26fdb1fc9405c08520
?0975df9b39e23c15f63db194df7f45c76528bccb
?308150e8fddde043f3dbbb8573abb6af1df96e63
# Git checkout fails without internet
fatal: '/home/ciro/bak/git/test-git-web-interface/other-test-repos/partial-clone.tmp/server_repo' does not appear to be a git repository
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
# Git checkout fetches the missing directory from internet
remote: Enumerating objects: 1, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 1 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (1/1), 45 bytes | 45.00 KiB/s, done.
remote: Enumerating objects: 1, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 1 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (1/1), 45 bytes | 45.00 KiB/s, done.
# Missing objects after checking out d1
?f70a17f51b7b30fec48a32e4f19ac15e261fd1a4
?8b25206ff90e9432f6f1a8600f87a7bd695a24af
?41484c13520fcbb6e7243a26fdb1fc9405c08520
?0975df9b39e23c15f63db194df7f45c76528bccb
Sonuç: hariç tüm lekeler d1/a
eksik. Örneğin f70a17f51b7b30fec48a32e4f19ac15e261fd1a4
, d1/b
kontrol ettikten sonra orada değild1/
.
Ayrıca root/root
ve mybranch/mybranch
eksik olduğunu unutmayın , ancak --depth 1
eksik dosyalar listesinden gizler. Kaldırırsanız --depth 1
, eksik dosyalar listesinde gösterilirler.
Daha önce verilenler üzerine iki varyant:
git archive --format=tar --remote=git://git.foo.com/project.git HEAD:path/to/directory filename | tar -O -xf -
ve:
git archive --format=zip --remote=git://git.foo.com/project.git HEAD:path/to/directory filename | funzip
Bunlar dosyayı standart çıktıya yazar.
Git'te dosyaları güncellemeden önce 'ödeme' yapmazsınız - görünüşe göre peşindesiniz.
Clearcase, csv ve benzeri birçok sistem, dosyada değişiklik yapmadan önce bir dosyayı 'teslim almanızı' gerektirir. Git bunu gerektirmez. Bir havuzu klonlar ve daha sonra yerel depo kopyanızda değişiklikler yaparsınız.
Dosyaları güncelledikten sonra şunları yapabilirsiniz:
git status
Hangi dosyaların değiştirildiğini görmek için. Önce taahhüt etmek istediklerinizi eklersiniz index
( index
check-in yapılacak bir liste gibidir):
git add .
veya
git add blah.c
Ardından git status
, hangi dosyaların değiştirildiğini ve hangilerinin işleme index
alınmaya veya teslim edilmeye hazır olduğunu gösterecektir.
Depo kopyanıza dosyalar göndermek için şunları yapın:
git commit -a -m "commit message here"
Kılavuzlara ve kılavuzlara bağlantılar için git
web sitesine bakın .
git format-patch
gönderim git format-patch -1
için bir yama oluşturmak için ( bir yama oluşturacak) yalnızca en son taahhüdünüz için).
Git deposunun içinde yalnızca belirli bir dosyayı çekmek ve itmek için eksiksiz çözüm:
git clone --no-checkout <git url>
git reset
git checkout origin/master <path to file>
git add <path to file>
git commit -m <message text>
git push
Ayrıca bazı ek bilgiler için bir bağlantıya bakın .
Görünüşe göre, doğaya göre gitmeyen merkezi sürüm kontrolünden bir fikir taşımaya çalışıyorsunuz - dağıtılmış. Git deposuyla çalışmak istiyorsanız, onu kopyalarsınız. Daha sonra , çalışma ağacının tüm içeriğine ve tüm geçmişe (iyi, en azından geçerli dalın ucuna kadar gelen her şey) sahip olursunuz, sadece tek bir dosya veya tek bir taahhütten bir anlık görüntü değil.
git clone /path/to/repo
git clone git://url/of/repo
git clone http://url/of/repo
Uzak Git deposundaki belirli bir daldan belirli bir dosyaya ihtiyacınız varsa komut şu şekildedir:
git archive --remote=git://git.example.com/project.git refs/heads/mybranch path/to/myfile |tar xf -
Gerisi @ VonC'nin cevabından elde edilebilir:
Ana daldan belirli bir dosyaya ihtiyacınız varsa:
git archive --remote=git://git.example.com/project.git HEAD path/to/myfile |tar xf -
Bir etiketten belirli bir dosyaya ihtiyacınız varsa:
git archive --remote=git://git.example.com/project.git mytag path/to/myfile |tar xf -
Burada listelenen benim için neyin işe yaradığını görmüyorum, bu yüzden benim durumumda kimse olmalı.
Benim durumum, belki 10.000 dosyadan uzak bir depom var ve Linux sistemim için bir RPM dosyası oluşturmam gerekiyor. RPM'nin yapısı her şeyin bir git klonunu içerir. Tek ihtiyacım RPM derlemeyi başlatmak için bir dosya. İhtiyacım olanı yapan tüm kaynak ağacını klonlayabilirim, ancak ihtiyacım olan tek şey olduğunda bu dosyaları indirmek için fazladan iki dakika gerekiyor. Git arşiv seçeneğini kullanmaya çalıştım ve “ölümcül: İşlem protokol tarafından desteklenmiyor” aldım. Görünüşe göre sunucuda bir çeşit arşiv seçeneğini etkinleştirmem gerekiyor ve sunucum, işleri halletmeyi zorlaştıran bürokratik haydutlar tarafından korunuyor.
Sonunda bitbucket için web arayüzüne gittim ve ihtiyacım olan tek dosyayı gördüm. Dosyanın ham bir kopyasını indirmek için bağlantıya sağ tıkladım ve ortaya çıkan açılır pencereden "kopya kısayolunu" seçtim. Sadece ham dosyayı indiremedim çünkü işleri otomatikleştirmem gerekiyordu ve Linux sunucumda bir tarayıcı arayüzüm yok.
Tartışma uğruna URL ile sonuçlandı:
https://ourArchive.ourCompany.com/projects/ThisProject/repos/data/raw/foo/bar.spec?at=refs%2Fheads%2FTheBranchOfInterest
İlk önce oturum açmam gerektiğinden bu dosyayı doğrudan bitbucket deposundan indiremedim. Biraz kazdıktan sonra, bunun işe yaradığını gördüm: Linux'ta:
echo "myUser:myPass123"| base64
bXlVc2VyOm15UGFzczEyMwo=
curl -H 'Authorization: Basic bXlVc2VyOm15UGFzczEyMwo=' 'https://ourArchive.ourCompany.com/projects/ThisProject/repos/data/raw/foo/bar.spec?at=refs%2Fheads%2FTheBranchOfInterest' > bar.spec
Bu kombinasyon, diğer her şeyi oluşturmak için ihtiyacım olan tek dosyayı indirmeme izin verdi.
Bu yanıtı resmi bir ödeme veya benzer bir yerel işlem yapmaya alternatif olarak ekliyorum. Git sağlayıcınızın web arayüzüne erişiminiz olduğunu varsayarsak, belirli bir taahhütte herhangi bir dosyayı doğrudan görüntüleyebilirsiniz. Örneğin, GitHub'da şöyle bir şey kullanabilirsiniz:
https://github.com/hubotio/hubot/blob/ed25584f/src/adapter.coffee
İşte ed25584f
SHA-1 karma ilk 8 karakter kaynak dosyasının yolu takiben, ilgi taahhüt olduğunu.
Benzer şekilde, Bitbucket'te deneyebiliriz:
https://bitbucket.org/cofarrell/stash-browse-code-plugin/src/06befe08
Bu durumda, sağlama karmasını kaynak URL'nin sonuna yerleştiririz.
Yalnızca dosyayı indirmeniz gerekiyorsa Git'e göz atmanıza gerek yoktur.
GitHub Mate bunu yapmak çok daha kolaydır, bir Chrome uzantısıdır, indirmek için dosya simgesini tıklamanıza olanak tanır. ayrıca açık kaynak
git
! =github
Bir dosyanın yerel bir sürümünü düzenlediyseniz ve merkezi sunucuda tutulan orijinal sürüme geri dönmek isterseniz, Git Uzantıları kullanılarak kolayca elde edilebilir .
Kolay!