GIT: Belirli bir klasöre ödeme yapın


Yanıtlar:


57

Do a "git export" ("svn export" gibi) gereğince ?

Bunun için kullanabilirsiniz git checkout-index, bu düşük seviyeli bir komuttur, her şeyi dışa aktarmak istiyorsanız, kullanabilirsiniz -a,

git checkout-index -a -f --prefix=/destination/path/

Man sayfalarından alıntı yapmak için:

Son "/" [ön ekteki] önemlidir. Dışa aktarılan ad, kelimenin tam anlamıyla yalnızca belirtilen dizeyle ön eklenmiştir.

Belirli bir dizini dışa aktarmak istiyorsanız, bazı hileler vardır. Komut dizinleri değil yalnızca dosyaları alır. Bunu dizinlere uygulamak için, 'bul' komutunu kullanın ve çıktıyı git'e yönlendirin.

find dirname -print0 | git checkout-index --prefix=/path-to/dest/ -f -z --stdin

Ayrıca man sayfalarından:

Burada amaç sezgisellik değil. Tekrarlanabilirlik.


Ne yazık ki bu, --prefix set :-( (git 1.9.1 ile test edildi)
apeiros

1
çıplak bir git deposunun bir dalını / işlemesini kontrol etmek istiyorsanızGIT_WORK_TREE=../path/to/place git checkout
allicoder'ı

4
git worktree(aşağıya bakın) imho bugün kanonik cevaptır ve buraya eklenebilir.
geek-merlin

213

Biraz daha temiz olan başka bir çözüm - sadece farklı bir çalışma ağacı belirtin.

HEAD'inizden (dizin değil) belirli bir çıkış dizinine kadar her şeyi kontrol etmek için:

git --work-tree=/path/to/outputdir checkout HEAD -- .

HEAD'inizden belirli bir dizine bir alt dizin veya dosya almak için:

git --work-tree=/path/to/outputdir checkout HEAD -- subdirname

4
Minör notu - Eğer genişleme yaklaşık işareti kabuk oluşmaz olarak yani mutlak bir yol gerekiyor --work-tree=/home/thomasg/okcopyziyade --work-tree=~/okcopy(aynı git ağacın içinde oturan çok çalışırken muhtemelen göreli bir yol kullanarak, ancak bu şekilde yalan delilik ve git statusR'lyehian içinde çıkışlar)
Tom Goodfellow

10
Eski işlemlerde de beklendiği gibi çalışır (örneğin HEAD yerine bir SHA verin), ancak git statusdaha sonra birçok mod gösterir (muhtemelen indeks artık el değmemiş normal çalışma ağacıyla değil diğer dizinle eşleştiği için). git resetiyi bir duruma geri döndürdü.
Tom Goodfellow

2
Burada aynı git statusşey çok sayıda modu gösteriyor ve git resetyardımcı olmuyor. git checkout -f HEADDepomun durumunu eski haline getirmek zorunda kaldım .
DUzun

11
Bilginize: dizini kendiniz oluşturmanız gerekir, aksi takdirde şu hatayı alırsınız:fatal: This operation must be run in a work tree
timaschew

13
Bu , genellikle kötü olan ana çalışma ağacının dizinini feci bir şekilde değiştirir . @TomGoodfellow'un önerdiği gibi, git resetana çalışma ağacını akıl sağlığına kavuşturmak yeterlidir. Güvenle herhangi SHA1, şube ya etiketine depo alt dizinleri aktarmak için olmadan ana çalışma ağacı değiştirerek, bkz Charles Bailey'nin rezil git archiveçözüm . Aynı şekilde, aynı anda birden fazla şubeyi güvenle ödünç almak için yeni git worktree addalt komut sizin arkadaşınızdır.
Cecil Curry

25

Tek bir dosya için:

git show HEAD:abspath/to/file > file.copy

2
+1 ve "önceki kesinleştirmeyi" netleştirmek için (HEAD yerine): Bu, SHA1 IDaracılığıyla kolayca bulunabilene işaret eder gitk. Bu dosyayı yalnızca geçici bir konuma "teslim etmem" showgit show 82e54378856215ef96c5db1ff1160a741b5dcd70:MyProj/proguard/mapping.txt > myproj_mapping.txt
gerekirse

19

Yukarıdaki çözümler benim için işe yaramadı çünkü ağacın belirli bir etiketli versiyonuna bakmam gerekiyordu. Bu cvs exportarada, kullanılması amaçlanan bu. git checkout-indexdosyaları dizinden teslim aldığından etiket bağımsız değişkenini almaz. git checkout <tag>çalışma ağacından bağımsız olarak dizini değiştirirdi, bu yüzden orijinal ağacı sıfırlamam gerekirdi. Benim için işe yarayan çözüm, depoyu klonlamaktı. Paylaşılan klon oldukça hızlıdır ve fazla yer kaplamaz. .gitİstenirse dizin çıkarılabilir.

git clone --shared --no-checkout <repository> <destination>
cd <destination>
git checkout <tag>
rm -rf .git

Git'in daha yeni sürümleri git clone --branch <tag>, belirtilen etiketi otomatik olarak kontrol etmeyi desteklemelidir :

git clone --shared --branch <tag> <repository> <destination>
rm -rf <destination>/.git

3
git --work-tree=/path/to/outputdir checkout <tag> -- .senin için çalışmadı mı
warvariuc

1
Hayır değil. Orijinal çalışma dizinindeki asıl dosya değişmez, ancak aşamalı sürüm kaybolur ve etiketindeki sürümle değiştirilir. Aşamalı sürümün dikkatle seçilmiş bir dizi değişiklik içermesi özellikle kötüdür. Dışa aktar komutunun indeksime, noktaya dokunmasını istemiyorum.
proski

19

Özelliğiniz altında çalışıyorsanız ve uzmanlığa geri dönmek istemiyorsanız, şunları çalıştırabilirsiniz:

cd ./myrepo

git worktree add ../myrepo_master master

git worktree remove ../myrepo_master

Çalışmaya devam edebileceğiniz şube taahhütleri ../myrepo_masteriçeren bir dizin oluşturacaktır.master


1
En iyi yanıt - basittir ve git --work-tree=/path/to/outputdir checkout HEAD -- .dizine hiçbir şey yapmaz, sadece seçilen dalı belirtilen konuma kopyalar (bir .git dosyası ekleyerek).
Roger Dueck

Ve bu değişikliği nasıl geri alırım?
Scott P.

@ ScottP. just myrepo_masterdizini kaldır
itsnikolay

1
bunu geri almak, worktree'nin bir alt komutudur:git worktree remove ../myrepo_master
Martijn Dashorst

8

Adrian'ın cevabı "ölümcül: Bu işlem bir iş ağacında yürütülmelidir" dedi. Aşağıdakiler bizim için çalıştı.

git worktree add <new-dir> --no-checkout --detach
cd <new-dir>
git checkout <some-ref> -- <existing-dir>

Notlar:

  • --no-checkout Yeni çalışma ağacına hiçbir şey koymayın.
  • --detach Yeni çalışma ağacı için yeni bir dal oluşturmayın.
  • <some-ref>herhangi bir ref ile çalışır, örneğin birlikte çalışır HEAD~1.
  • İle temizleyin git worktree prune.

Nasıl temizleneceğine dair yorum yapmak için +1 - diğer herkes mevcut depoyu karıştırmaktan mutluluk duyar. sadece bunun yan etkisi yoktur.
Andrew Hill

1

@ Hasen'in cevabına ek . Kullanıma alınacak dosyaları listelemek için , aşağıdakileri git ls-filesyerine kullanmak isteyebilirsiniz find:

git ls-files -z *.txt | git checkout-index --prefix=/path-to/dest/ -f -z --stdin

Doğru kullandığınız için teşekkür ederiz -z! Belli türdeki enjeksiyon saldırılarına karşı savunmasız olmayan komut dosyası sağlamanız çok güzel.
ErikE

0

Bunu başarmak için bir git takma adı tanımladım (bu soruyu bulmadan önce).

Geçerli yolu kaydeden, git deposuna geçiş yapan, ödeme yapan ve başladığı yere geri dönen kısa bir bash işlevidir.

git check geliştirmek için ~ / projem_git

Bu örneğin geliştirme dalını "~ / projem_git" dizinine teslim eder.

Bu, içindeki takma ad kodudur ~/.gitconfig:

[alias]
    checkTo = "!f(){ [ -z \"$1\" ] && echo \"Need to specify branch.\" && \
               exit 1; [ -z \"$2\" ] && echo \"Need to specify target\
               dir\" && exit 2; cDir=\"$(pwd)\"; cd \"$2\"; \
               git checkout \"$1\"; cd \"$cDir\"; };f"

0

Bu takma adı geçici bir dizindeki bir dalı kontrol etmek için kullanıyorum:

[alias]
    cot = "!TEMP=$(mktemp -d); f() { git worktree prune && git worktree add $TEMP $1 && zsh -c \"cd $TEMP; zsh\";}; f" # checkout branch in temporary directory

Kullanımı:

git cot mybranch

Daha sonra, şube üzerinde çalışabileceğiniz geçici dizindeki yeni bir kabuğa bırakılırsınız. Bu dizinde git komutlarını bile kullanabilirsiniz.

İşiniz bittiğinde dizini silin ve çalıştırın:

git worktree prune

Bu aynı zamanda yeni bir çalışma ağacı eklemeden önce takma adda otomatik olarak yapılır.


0

git archive branch-index | tar -x -C your-folder-on-PCBir dalı başka bir klasöre klonlamak için kullanın . Sanırım o zaman ihtiyacınız olan herhangi bir dosyayı kopyalayabilirsiniz

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.