Git'teki belirli bir düzeltmeden tek bir dosya nasıl alınır?


831

Git deposum var ve bazı dosyaların birkaç ay önce nasıl göründüğünü görmek istiyorum. Revizyonu o tarihte buldum; öyle 27cf8e84bb88e24ae4b4b3df2b77aab91a3735d8. Bir dosya neye benzediğini görmek ve aynı zamanda ("yeni") bir dosya olarak kaydetmek gerekir.

Dosyayı kullanarak görmeyi başardım gitk, ancak kaydetme seçeneği yok. Komut satırı araçlarıyla denedim, en yakınım:

git-show 27cf8e84bb88e24ae4b4b3df2b77aab91a3735d8 my_file.txt

Ancak, bu komut dosya içeriğini değil bir fark gösterir. Daha sonra böyle bir şeyi kullanabilir PAGER=catve çıktıyı bir dosyaya yönlendirebilirim, ancak gerçek dosya içeriğine nasıl ulaşacağımı bilmiyorum.

Temel olarak, svn kedi gibi bir şey arıyorum .


73
Buradaki anahtar: git show(yararsız bir şekilde) iki nokta üst üste ile farklı sözdizimi kullanır. git show 2c7cf:my_file.txt
Steve Bennett

4
Daha açıklığa kavuşturmak için, yukarıdaki komut git'den iki ayrı nesne, bir düzeltme ve bir dosya göstermesini istiyor. İki öğe arasında iki nokta üst üste işareti kullanan aşağıdaki kabul edilen yanıt, belirli bir düzeltmede belirli bir dosya istiyor.
jhclark



Checat'ın içeriğin bir dosyaya aktarılmasını isteyenler için önemli bir yorumu var. Bunun gibi bir şeye ihtiyacınız var: git show {sha}: my_file.txt> old_my_file.txt
ormurin

Yanıtlar:


743

Kendi cevabınızı tamamlamak için söz dizimi gerçekten

git show object
git show $REV:$FILE
git show somebranch:from/the/root/myfile.txt
git show HEAD^^^:test/test.py

Komut, normal revizyon stilini alır, yani aşağıdakilerden herhangi birini kullanabilirsiniz:

  1. şube adı ( kül tarafından önerildiği gibi )
  2. HEAD+ x ^karakter sayısı
  3. Belirli bir revizyonun SHA1 karması
  4. Belirli bir SHA1 karmasının ilk birkaç (belki 5) karakteri

İpucu " git show" kullanırken , her zaman geçerli dizin konumunuzu değil , deponun kökünden bir yol belirttiğinizi unutmayın.

( Mike Morearty , en azından git 1.7.5.4 ile, yolun ./başına " " koyarak göreli bir yol belirtebileceğinizden bahsetmesine rağmen - örneğin:

git show HEAD^^:./test.py

)


Git 2.23+ (Ağustos 2019) ile, kafa karıştırıcı komutungit restore yerini alacak olanı da kullanabilirsinizgit checkout

git restore -s <SHA1>     -- afile
git restore -s somebranch -- afile

Bu, çalışma ağacına yalnızca "source" ( -s) ' de mevcut olan dosyayı SHA1 veya dalda geri yükler somebranch.
Dizini de geri yüklemek için:

git restore -s <SHA1> -SW -- afile

( -SW: kısa --staged --worktree)


Git1.5.x'ten önce, bu bazı sıhhi tesisatla yapıldı:

git ls-tree <rev>
bir taahhüt içinde bir veya daha fazla 'damla' nesnenin listesini göster

git cat-file blob <file-SHA1>
belirli bir düzeltme (svn cat'a benzer) içinde yapılmış bir dosyayı katıştırır. verilen bir dosya-sha1 değerini almak için git ls-tree kullanın

git cat-file -p $(git-ls-tree $REV $file | cut -d " " -f 3 | cut -f 1)::

git-ls-tree $ REV revizyonunda $ file nesne kimliğini listeler, bu çıktıdan kesilir ve git-cat-file için bir argüman olarak kullanılır ve gerçekten git-cat-object olarak adlandırılır ve basitçe dumps bu nesne stdout'a.


Not: Git 2.11'den (4. Çeyrek 2016) git cat-fileçıktıya bir içerik filtresi uygulayabilirsiniz !

Bkz 3214594 işlemek , 7bcf341 işlemek , (2016 09 Eyl) 7bcf341 taahhüt (2016 9 Eylül) ve b9e62f6 işlemek , 16dcc29 taahhüt tarafından (24 Eki 2016) Johannes Schindelin ( dscho) .
(Göre Birleştirilmiş - Junio Cı Hamano gitster- içinde 7889ed2 tamamlama 2016, 21 Eyl)

cat-file: destek --textconv/ --filterstoplu iş modunda

git hash-objectsBir dosya sistemi veri akışı alıp Git nesne deposuna yerleştirmek için bir araç olan " ", "dünya dışı Git" dönüşümlerini (ör. Satır sonu dönüşümleri ve uygulama) gerçekleştirmesine izin verilmiş olsa da ve varsayılan olarak çok erken günlerden beri özelliği vardı, git cat-fileGit nesne deposundan bir nesneyi alıp dış dünyanın tüketimi için dışsallaşan ters işlemi " ", "Git-to-dış dünya"

git config diff.txt.textconv "tr A-Za-z N-ZA-Mn-za-m <"
git cat-file --textconv --batch

Not: " git cat-file --textconv", Git 2.15'te (4. Çeyrek 2017) düzeltilen kısa bir süre önce segfaulting yapmaya başladı (2017).

Görmek . Jeff King ( peff) tarafından cc0ea7c (21 Eyl 2017 ) .
(Göre Birleştirilmiş Junio Cı Hamano - gitster- içinde işlemek bfbc2fc , 28 Eylül 2017)


Not o geçersiz kılma / değiştirme Geçmiş içeriğe sahip bir dosya, kullanmak gerektiğini kafa karıştırıcı git checkoutkomutu artık, ama git restore(Git 2.23+ 2019 Ağustos)

git restore -s <SHA1> -- afile

Bu, çalışma ağacında yalnızca "source" ( -s) ' de mevcut olan dosyayı SHA1'e geri yükler .
Dizini de geri yüklemek için:

git restore -s <SHA1> -SW -- afile

( -SW: kısa --staged --worktree)


6
@Oscar git show, içeriği stdout(standart çıktı) üzerine döktüğünden , bu çıktıyı istediğiniz herhangi bir dosyaya yeniden yönlendirebilirsiniz ( tldp.org/LDP/abs/html/io-redirection.html ).
VonC

8
git checkout [branch | revision] filepathdoğru komuttur
Gaui

12
@Gaui ancak git checkoutediyorum geçersiz aksine, başka versiyonu ile dosyanızı git showalmak ve görmek için sırayla, farklı bir isim altında kaydetmek olanak veren hem (mevcut sürümü ve eski sürümü). OP'nin mevcut sürümünü eski bir sürümle değiştirmek isteyip istemediği sorudan belli değil .
VonC

9
Bunun ^^^daha genel olarak ~~~veya daha iyi olarak da yazılabileceğini belirtmek isterim ~3. Tildes kullanmanın bazı kabukların dosya adı eşleşmesini tetiklememesi de avantajlıdır (örneğin, zsh).
Eric O Lebigot

2
Does öncesi 1.5.x: Ben kontrol etmek için yeterince yaşlı budala yok git rev-parsesap rev:pathsözdizimi? (Daha yeni bir git'te yapabilirsiniz git cat-file -p $REV:path. Bununla birlikte, git showdizin yolları için de çalışır, bu yüzden sadece daha kısa değil, genellikle ne istediğine daha yakındır.)
torek

510

Eğer isterseniz değiştirin / üzerine bu komutlarla yapabilirsiniz, bir önceki dosyanın içeriği işlemek veya farklı bir dalı ile mevcut dalında bir dosyanın içeriğini:

git checkout 08618129e66127921fbfcbc205a06153c92622fe path/to/file.txt

veya

git checkout mybranchname path/to/file.txt

Daha sonra, mevcut branşta etkili olabilmeleri için bu değişiklikleri taahhüt etmeniz gerekecektir.


4
en basit çözüm ve git-checkout için tasarlanmış olan budur - yol adını belirtmek sadece eşleşen dosyanın teslim alındığı anlamına gelir. Git-checkout man sayfasından: git checkout master ~ 2 Makefile
RichVel

1
Peki, bu komutu çalıştırmadan önce önceki duruma nasıl geri dönersiniz?
Flint

@Filint, HEAD durumundan geliyorsanız git checkout HEAD - [tam yol] kadar basit olurdu.
Tiago Espinha

72
Bunun git show SHA1:PATHyalnızca yoldaki varolan dosyanın üzerine yazarken, çözümün yalnızca stdout'a yazdırdığını unutmayın.
Flimm

Güzel! Bunu bakarak bunu anlayamazdım git help checkout. Belirli bir tarih itibariyle bir alt dizini kontrol etmek zorunda kaldım ve bu yaklaşımı kullanarak bu sözdizimini çalıştırabilirim:git checkout @{YYYY-MM-DD} sub-dir
haridsv

150

Dosyanın tam yolunu sağlamanız gerekir:

git show 27cf8e84bb88e24ae4b4b3df2b77aab91a3735d8:full/repo/path/to/my_file.txt

7
tam yol olması gerekmez. Git kök dizininden gelen yol (gelenler git show --name-onlyde yeter
Mohsen

7
Erm, depo kökünden tam yol. Verdiğim örneğe daha iyi bakın. "Dolu" dan önce eğik çizgi yoktur.
Milan Babuškov

7
Bilginize, bir alt dizindeyseniz ./filename.ext dosyasını da başarıyla kullanabilirsiniz.
Gezgin

Bence, içeri girerseniz full/repo/path/tove denerseniz:, fatal: Path 'full / repo / path / to / my_file.txt'git show 27cf8e84:my_file.txt gibi bir mesajla ödüllendirileceksiniz , ancak 'my_file.txt' yok . Şunu mu demek istediniz: '27cf8e84: full / repo / path / to / my_file.txt' aka '27cf8e84: ./ my_file.txt'? Git, doğrudan yardımcı olabilirdi, ama burada bilgiç olmayı seçti.
Ed Randall

101

En kolay yol yazmak:

git show HASH:file/path/name.ext > some_new_name.ext

nerede:

  • HASH Git revizyonu SHA-1 karma numarasıdır
  • dosya / yol / ad.ext aradığınız dosyanın adıdır
  • some_new_name.ext , eski dosyanın kaydedilmesi gereken yol ve addır

Misal

git show 27cf8e84bb88e24ae4b4b3df2b77aab91a3735d8:my_file.txt > my_file.txt.OLD

Bu kurtaracak my_file.txt hâli 27cf8e adıyla yeni bir dosya olarak my_file.txt.OLD

Git 2.4.5 ile test edildi.

Eğer isterseniz silinen almak kullanabileceğiniz dosyayı HASH~1(bir belirtilen HASH önce taahhüt).

MİSAL:

git show 27cf8e84bb88e24ae4b4b3df2b77aab91a3735d8~1:deleted_file.txt > deleted_file.txt

1
Ek Bilgi:
HASH'ı

@xotix Teşekkürler. Kullanarak belirli bir dosya için tüm HASH geçmişini aldımgit log file/path/name.ext
Sriram Kannan

11

Windows'ta Git Bash ile:

  • çalışma alanınızda, dir dosyasını dosyanızın bulunduğu klasöre değiştirin
  • git show cab485c83b53d56846eb883babaaf4dff2f2cc46:./your_file.ext > old.ext

8

Ve bir dosyaya güzelce dökmek için (en azından Windows'ta) - Git Bash:

$ echo "`git show 60d8bdfc:src/services/LocationMonitor.java`" >> LM_60d8bdfc.java

Yeni "satırları korumak için tırnak işaretleri gereklidir.


Güzel bir. +1. git showYukarıda bahsettiğim sözdizimine iyi bir ekleme .
VonC

23
Tırnaklarla birlikte veya tırnak olmadan yankı neden kullanacağınızı gerçekten anlamıyorum. Ve çıkış yönlendirme ek formunu neden isteyeceğinizi anlamıyorum. Basitçe yazmak daha iyi olmaz mıydı: git show 60d8bdfc: src / services / LocationMonitor.java> LM_60d8bdfc.java Herhangi bir nedenle dos-line satır sonlarını zorlamak istediyseniz, unix2dos ile borulandırabilirsiniz. Ancak, Windows'ta kullandığım not defteri dışında herhangi bir metin aracı unix tarzı çizgileri iyi işlediğinden, dos satır sonlarını Windows'ta tutmanın en az yararlı olduğunu hiç bulamadım.
sootsnoot

4
git show 60d8bdfc: src / services / LocationMonitor.java >> LM_60d8bdfc.java benim için çalıştı.
Mike6679

@Mike: Pencerelerde misin?
Mr_and_Mrs_D

2
çift ​​tırnak işareti kullanmayın çünkü bir kabuk değişkeni gibi görünen dosya karakterleriniz, yani $ LANG ise, değiştirilecektir. @ LưuVĩnhPhúc tasarrufludur. ayrıca kullanmayın >> Varsa dosyayı ekler ve hatalara yol açabilir
theguy

3

Bu, silinen birçok dosyayı yolu belirtmeden almanıza yardımcı olacaktır, silinen çok sayıda dosya varsa kullanışlıdır.

git diff --name-only --diff-filter=D $commit~1 $commit | xargs git checkout $commit~1

1
git checkout {SHA1} -- filename

bu komut kopyalanan dosyayı belirli bir işlemden alır.


-2

Önceki taahhüdü kontrol ederek ve dosyayı kopyalayarak dosyayı önceki bir işlemden alın.

  • Hangi şubede olduğunuzu not edin: git branch
  • İstediğiniz önceki taahhüdü kontrol edin: git checkout 27cf8e84bb88e24ae4b4b3df2b77aab91a3735d8
  • İstediğiniz dosyayı geçici bir konuma kopyalayın
  • Başladığınız şubeyi inceleyin: git checkout theBranchYouNoted
  • Geçici bir konuma yerleştirdiğiniz dosyayı kopyalayın
  • Değişikliklerinizi git olarak kaydedin: git commit -m "added file ?? from previous commit"
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.