Bagaimana cara melepaskan hanya file tertentu?

387

Saya menyembunyikan perubahan saya. Sekarang saya ingin melepaskan hanya beberapa file dari simpanan. Bagaimana saya bisa melakukan ini?

Morpheus
sumber
4
Saya pikir Anda harus menerapkan seluruh simpanan, tetapi kemudian Anda dapat menyimpan kembali secara selektif.
Richard
4
@AbdouTahiri Apa yang salah dengan simpanan?
alex
32
@AbdouTahiri Uhhhh .. git stash adalah fitur yang sah, dan sangat berguna. Saya menggunakannya setiap hari. Katakanlah, seorang rekan kerja membutuhkan saya untuk meninjau sesuatu tetapi saya berada di tengah-tengah perubahan yang kompleks. Saya tidak akan melakukan tumpukan kode yang rusak hanya supaya saya bisa berganti cabang. Saya akan menyembunyikan, beralih cabang, meninjau, beralih kembali, melepas. Apakah Anda peduli untuk menguraikan siapa atau mengapa simpanan git seharusnya "tidak direkomendasikan"? Hanya karena sejarah simpanan git Anda kacau dan sulit dibaca tidak berarti semua orang lain. Kumpulan git simpanan yang berantakan hanyalah alur kerja yang buruk, bukan cacat dari Git.
dudewad
6
@ alex Tidak ada. Tidak ada yang salah dengan simpanan git. Tetap gunakan itu.
dudewad

Jawaban:

462

Seperti yang disebutkan di bawah ini , dan dirinci dalam " Bagaimana cara mengekstrak satu file (atau perubahan ke file) dari simpanan git? ", Anda dapat menerapkan penggunaan git checkoutatau git showmengembalikan file tertentu.

git checkout stash@{0} -- <filename>

Itu menimpa filename : pastikan Anda tidak memiliki modifikasi lokal, atau Anda mungkin ingin menggabungkan file simpanan sebagai gantinya .

(Sebagai berkomentar oleh Jaime M. , untuk shell tertentu seperti tcsh di mana Anda perlu untuk melarikan diri karakter khusus, sintaks akan: git checkout 'stash@{0}' -- <filename>)

atau untuk menyimpannya di bawah nama file lain:

git show stash@{0}:<full filename>  >  <newfile>

(perhatikan bahwa di sini <full filename>adalah nama path lengkap dari file relatif ke direktori teratas proyek (pikirkan: relatif terhadap stash@{0})).

Yucer menyarankan dalam komentar :

Jika Anda ingin memilih secara manual, perubahan mana yang ingin Anda terapkan dari file itu:

git difftool stash@{0}..HEAD -- <filename>

Vivek menambahkan dalam komentar :

Sepertinya " git checkout stash@{0} -- <filename>" mengembalikan versi file pada saat simpanan dilakukan - TIDAK berlaku (hanya) perubahan simpanan untuk file itu.
Untuk melakukan yang terakhir:

git diff stash@{0}^1 stash@{0} -- <filename> | git apply

(seperti yang dikomentari oleh peterflynn , Anda mungkin perlu | git apply -p1dalam beberapa kasus, menghapus satu ( p1) slash utama dari jalur diff tradisional)


Seperti yang dikomentari: "unstash" ( git stash pop), maka:

  • tambahkan apa yang ingin Anda pertahankan ke indeks ( git add)
  • simpan sisanya: git stash --keep-index

Poin terakhir adalah apa yang memungkinkan Anda menyimpan beberapa file sambil menyimpan yang lainnya.
Ini diilustrasikan dalam " Cara menyimpan hanya satu file dari banyak file yang telah berubah ".

VONC
sumber
5
Ini tidak berfungsi jika Anda tidak dapat git stash popkarena konflik file. Jawaban Balamurugan A membantu saya dalam kasus itu.
Andrey
1
Jika Anda ingin memilih secara manual, perubahan mana yang ingin Anda terapkan dari file itu, Anda dapat menggunakan git difftool stash @ {0} .. HEAD - <filename>
yucer
5
Sepertinya "git checkout stash @ {0} - <filename>" mengembalikan versi file pada saat penyimpanan dilakukan - BUKAN berlaku (hanya) perubahan simpanan untuk file itu. Untuk melakukan yang terakhir: "git diff stash @ {0} ^ 1 stash @ {0} - <filename> | git apply"
Vivek
1
@Jaimem. Terima kasih. Saya telah memasukkan komentar Anda dalam jawaban untuk lebih banyak visibilitas.
VonC
1
Anggap itu unstashberarti pop, seperti yang menurut saya mungkin dalam banyak kasus, ini hanya menjawab sebagian pertanyaan. Bagaimana Anda kemudian menghapus potongan-potongan yang diterapkan secara selektif dari simpanan untuk menghindari konflik dan / atau kebingungan kemudian ketika muncul perubahan yang tersisa?
DylanYoung
115
git checkout stash@{N} <File(s)/Folder(s) path> 

Misalnya. Untuk mengembalikan hanya file ./test.c dan folder ./include dari simpanan terakhir,

git checkout stash@{0} ./test.c ./include
Balamurugan A
sumber
12
Ini jawaban yang benar! Perintah baris tunggal untuk menerapkan hanya perubahan simpanan dari file tertentu, berfungsi seperti pesona!
tingkat
1
Untuk menerapkan (hanya) perubahan simpanan untuk file: "git diff stash @ {N} ^ 1 stash @ {N} - <filename> | git apply"
Vivek
Ini juga berfungsi untuk saya. Hanya selektif memeriksa file yang diperlukan untuk digunakan dari simpanan dan Anda selesai. Saya terjebak dalam hal ini, saya menggunakan -abendera saat membuat simpanan.
Rajeev Ranjan
1
@ 4 tingkat Saya pikir "terapkan perubahan simpanan" bukan itu yang terjadi, kan? Saya pikir "menimpa apa pun yang Anda miliki dengan salinan dari simpanan" adalah yang terjadi.
msouth
35

Saya pikir jawaban VonC mungkin adalah yang Anda inginkan, tetapi inilah cara untuk melakukan "git apply" selektif:

git show stash@{0}:MyFile.txt > MyFile.txt
Mike Monkiewicz
sumber
4
Ini mungkin yang Anda inginkan dalam beberapa kasus, tetapi berhati-hatilah karena perintah ini akan menimpa daripada bergabung dengan perubahan direktori yang berfungsi.
Rhubbarb
Ini berfungsi untuk saya, karena saya hanya ingin menyalin file yang hanya ada di simpanan dan tidak peduli checkoutapa pun.
Tom Russell
1
Untuk Windows PowerShell: git show stash@`{0`}:Path/To/MyFile.txt |sc Path/To/MyFile.txt- backticks diperlukan agar PS tidak menafsirkan kawat gigi secara khusus, dan scitu diperlukan karena >operator PS default ke UTF-16 (sebenarnya UCS-2) yang mungkin bukan yang Anda inginkan. Jawaban @Balamurugan A tidak menderita dari masalah ini.
Ian Kemp
19

Pertama daftar semua simpanan

git stash list

stash@{0}: WIP on Produktkonfigurator: 132c06a5 Cursor bei glyphicon plus und close zu zeigende Hand ändern
stash@{1}: WIP on Produktkonfigurator: 132c06a5 Cursor bei glyphicon plus und close zu zeigende Hand ändern
stash@{2}: WIP on master: 7e450c81 Merge branch 'Offlineseite'

Kemudian tunjukkan file mana yang ada di simpanan (mari pilih simpanan 1):

git stash show 1 --name-only

//Hint: you can also write
//git stash show stash@{1} --name-only

 ajax/product.php
 ajax/productPrice.php
 errors/Company/js/offlineMain.phtml
 errors/Company/mage.php
 errors/Company/page.phtml
 js/konfigurator/konfigurator.js

Kemudian terapkan file yang Anda sukai:

git checkout stash@{1} -- <filename>

atau seluruh folder:

git checkout stash@{1} /errors

Ini juga berfungsi tanpa --tetapi disarankan untuk menggunakannya. Lihat posting ini .

Juga konvensional untuk mengenali tanda hubung ganda sebagai sinyal untuk menghentikan interpretasi opsi dan memperlakukan semua argumen berikut secara harfiah.

Hitam
sumber
1
Itu lebih jelas dengan hasil edit ini. +1
VonC
1
Saya mencoba banyak cara dan cara inilah yang saya butuhkan. Saya dihadapkan dengan masalah yang git stash popmenyebabkan kesalahan pada file yang tidak terlacak. Terima kasih.
Ramin Firooz
10

Jika Anda git stash pop(tanpa konflik) itu akan menghapus simpanan setelah diterapkan. Tetapi jika Anda git stash applyakan menerapkan patch tanpa menghapusnya dari daftar simpanan. Kemudian Anda dapat mengembalikan perubahan yang tidak diinginkan dengangit checkout -- files...

Ben Jackson
sumber
2
Untuk memperjelas bagian konflik pos ini, jika Anda git stash popdan ADA konflik, Anda harus memperbaikinya secara manual dan simpanan TIDAK akan dihapus.
Thomas McCabe
6

Satu lagi cara:

git diff stash@{N}^! -- path/to/file1 path/to/file2  | git apply -R
Lacho Tomov
sumber
2
Ini adalah satu-satunya jawaban yang benar IMO. Menggunakan checkoutatau showakan menimpa file Anda secara buta alih-alih hanya menerapkan perubahan. "Satu lagi jalan" adalah pernyataan yang meremehkan.
cambunctious
1
Saya tidak mendapatkan yang path/to/file2Anda inginkan berbeda dengan file yang sama di ruang kerja Anda. Meninggalkan jalan kedua berfungsi baik untukku. - Dan saya mendapatkan pesan kesalahan menggunakan -Ropsi ("terapkan tambalan secara terbalik", mencoba menambal versi simpanan ?!). Jadi versi kerja saya terlihat seperti git diff stash@{N}^! -- path/to/file | git apply -.
ThomasH
"tambalan gagal"? Coba penggabungan 3 arah. ...| git apply -3 -
John Mee
6

Untuk pengguna Windows: kurung kurawal memiliki arti khusus di PowerShell. Anda bisa mengelilinginya dengan tanda kutip tunggal atau melarikan diri dengan backtick. Sebagai contoh:

git checkout 'stash@{0}' YourFile

Tanpa itu, Anda mungkin menerima kesalahan:

Unknown switch 'e'

Janac Meena
sumber
3
Nilai penuh untuk PowerShell untuk pesan pengguna yang paling tidak membantu yang pernah saya lihat bulan ini.
holdenweb