Cara unstage sejumlah besar file tanpa menghapus konten

454

Saya tidak sengaja menambahkan banyak file sementara menggunakan git add -A

Saya berhasil menghapus file dengan menggunakan perintah berikut dan berhasil menghapus indeks kotor.

git ls-files -z | xargs -0 rm -f
git diff --name-only --diff-filter=D -z | xargs -0 git rm --cached

Perintah di atas tercantum dalam git help rm. Namun sayangnya, file saya juga dihapus saat eksekusi, meskipun saya telah memberikan opsi cache. Bagaimana saya bisa menghapus indeks tanpa kehilangan konten?

Juga akan sangat membantu jika seseorang dapat menjelaskan cara operasi pipa ini.

sarat
sumber
8
rm -fbukan perintah git dan tidak memiliki --cachedopsi. File lokal Anda telah dihapus sebelum Anda dieksekusi git rmjadi saya tidak berpikir Anda bisa menyalahkan git rmapa pun secara sah .
CB Bailey
8
@sarat, harap pertimbangkan untuk mengubah jawaban yang benar ke jawaban yang sangat terpilih dari Ian Maddox , karena jawaban git reset --harditu bukan jawaban yang benar dan pada kenyataannya akan menghapus konten. Ini akan membingungkan pengguna - seperti halnya saya.
Marco Pashkov
2
@sarat seperti yang dikatakan Marco, terus. Halaman ini mendapat banyak traffic.
Ross
@MarcoPashkov & Ross terima kasih semuanya. Selesai
sarat

Jawaban:

986

git reset

Jika semua yang Anda inginkan adalah membatalkan menjalankan "git add" terlalu bersemangat:

git reset

Perubahan Anda tidak akan bertahap dan siap untuk Anda tambahkan kembali sesuka Anda.


JANGAN LARI git reset --hard.

Ini tidak hanya akan menghapus stage dari file yang ditambahkan, tetapi akan mengembalikan semua perubahan yang Anda buat di direktori kerja Anda. Jika Anda membuat file baru di direktori kerja, itu tidak akan menghapusnya.

Ian Maddox
sumber
15
Saya berhutang pada Anda satu pint Ian
DasBooten
1
Saya sering menemukan saya harus melakukan git checkout -- *juga
Den-Jason
1
Anda menghemat banyak usaha. Terima kasih
kawan
35

Jika Anda memiliki repo yang masih asli (atau HEAD tidak disetel) [1] Anda bisa saja

rm .git/index

Tentu saja, ini mengharuskan Anda untuk menambahkan kembali file yang memang ingin Anda tambahkan.


[1] Catatan (seperti yang dijelaskan dalam komentar) ini biasanya hanya terjadi ketika repo baru ("asli") atau jika tidak ada komitmen yang dibuat. Lebih teknis, setiap kali tidak ada checkout atau pohon kerja.

Hanya membuatnya lebih jelas :)

lihat
sumber
Ya itu lebih seperti menghapus indeks yang dibuat itu sendiri. Untunglah, saya tidak perlu menginisialisasi ulang git. Terima kasih!
sarat
Apakah ini operasi yang aman? Saya hanya melakukan ini (benar-benar memindahkan indeks keluar dari jalan) dan mendapatkan semua file lainnya dipentaskan untuk dihapus.
inger
@inger "Jika Anda memiliki repo yang masih asli". Anda jelas tidak memilikinya.
lihat
Sebenarnya, saya bertanya-tanya apa yang Anda maksud dengan "repo murni" (saya juga tidak merasa beruntung dengan google) .. Jadi sebenarnya yang Anda maksud adalah repo kosong?
inger
1
@inger Setuju. Saya harus berasumsi bahwa OP kebetulan memiliki situasi yang tepat ini - dia tidak menentukannya, tetapi uraiannya meninggalkan kemungkinan. Ngomong-ngomong, saya hanya berbagi informasi, dan tidak dapat memengaruhi pemungutan suara :(. Telah menambahkan kata peringatan pada teks jawaban, kalau-kalau itu membantu orang lain di masa depan.
lihat
15

Gunakan git reset HEADuntuk mengatur ulang indeks tanpa menghapus file. (Jika Anda hanya ingin mengatur ulang file tertentu dalam indeks, Anda dapat menggunakannya git reset HEAD -- /path/to/fileuntuk melakukannya.)

Operator pipa, dalam sebuah shell, mengambil stdoutproses di sebelah kiri dan meneruskannya stdinke proses di sebelah kanan. Ini pada dasarnya setara dengan:

$ proc1 > proc1.out
$ proc2 < proc1.out
$ rm proc1.out

tetapi sebaliknya $ proc1 | proc2, proses kedua dapat mulai mendapatkan data sebelum yang pertama selesai mengeluarkannya, dan tidak ada file sebenarnya yang terlibat.

Amber
sumber
tetapi untuk bagaimana menggunakannya dengan banyak file. Saya tidak pernah melakukan file-file ini sebelumnya.
sarat
3
Cukup ketik git reset HEADtanpa menentukan yang lain, dan itu akan mengatur ulang seluruh indeks. Anda kemudian dapat menambahkan kembali hanya file yang Anda inginkan.
Amber
Saya mendapat kesalahan berikut. Saya tidak pernah melakukan hal-hal ini sebelumnya. $ git reset HEAD fatal: ambiguous argument 'HEAD': unknown revision or path not in the working tree. Use '--' to separate paths from revisions
sarat
1
Coba saja git reset, tanpa HEAD.
Amber
Saya sudah mencoba bahwa saya berakhir dengan kesalahan berikut. $ git reset fatal: Failed to resolve 'HEAD' as a valid ref.
sarat
9
git stash && git stash pop
Bijan
sumber
2
Saya akan melakukan 'git simpanan && git simpanan pop' sehingga simpanan juga terhapus. 'mendaftar' akan meninggalkan simpanan dalam simpanan daftar.
chitti
8

Jika KEPALA tidak diatur (yaitu, Anda belum memiliki komitmen, tetapi Anda tidak ingin hanya membuang .gitkarena Anda sudah menyiapkan konfigurasi repo lain yang ingin Anda pertahankan), Anda juga dapat melakukan

git rm -rf --cached .

untuk unstage segalanya. Ini secara efektif sama dengan solusi sehe, tetapi menghindari mucking dengan internal Git.

jjlin
sumber
ini sebenarnya memberitahu Git untuk menghapus semua yang ada di area cache.
Solusi Perangkat Lunak Visioner
1
Cache juga dikenal sebagai area pementasan, jadi saya tidak yakin apa yang Anda maksud.
jjlin
Dari sehe, rm .git / index sangat berbahaya - pastikan untuk membaca CATATAN yang dia miliki tentang repo baru! Ini jauh lebih aman untuk 99,999% lainnya dari waktu. Saya tidak membaca dengan seksama dan harus membuang copy pekerjaan saya dan mengkloning ulang setelah melakukan rm .git / index pada copy pekerjaan saya.
phpguru
JANGAN gunakan perintah ini! Ini akan mengubah SEMUA proyek ke status tidak terlacak (termasuk yang tidak dipentaskan). Ini bukan solusi untuk pertanyaan awal. Solusi yang benar menggunakan perintah 'git rm' adalah HANYA menentukan file yang Anda inginkan unstaged: git rm -rf --cached <file yang ingin Anda hapus stage>.
Monte Creasor
Anda hanya boleh menggunakan perintah ini ketika Anda memiliki repo baru tanpa komit (ini artinya "HEAD not set"), tetapi Anda tidak ingin langsung menghindar .gitkarena Anda sudah mengatur repo lain yang mengonfigurasi Anda ingin tetap. Saya telah mengedit untuk memperjelas ini.
jjlin
5

Peringatan: jangan gunakan perintah berikut kecuali Anda ingin kehilangan pekerjaan yang tidak berkomitmen!

Menggunakan git resettelah dijelaskan, tetapi Anda meminta penjelasan tentang perintah yang di-piped juga, jadi begini:

git ls-files -z | xargs -0 rm -f
git diff --name-only --diff-filter=D -z | xargs -0 git rm --cached

Perintah ini git ls-filesmencantumkan semua file yang diketahui git. Opsi -zmemaksakan format tertentu pada mereka, format yang diharapkan oleh xargs -0, yang kemudian memanggil rm -fmereka, yang berarti menghapusnya tanpa memeriksa persetujuan Anda.

Dengan kata lain, "daftarkan semua file yang diketahui git dan hapus salinan lokal Anda".

Lalu kita mulai git diff, yang menunjukkan perubahan antara berbagai versi item yang diketahui git. Itu bisa berupa perubahan antara pohon yang berbeda, perbedaan antara salinan lokal dan salinan jarak jauh, dan sebagainya.
Seperti yang digunakan di sini, ini menunjukkan perubahan yang tidak dipentaskan; file yang telah Anda ubah tetapi belum berkomitmen. Opsi ini --name-onlyberarti Anda hanya menginginkan nama file (lengkap) dan --diff-filter=Dberarti Anda hanya tertarik pada file yang dihapus. (Hei, bukankah kita hanya menghapus banyak hal?) Ini kemudian disalurkan ke yang xargs -0kita lihat sebelumnya, yang memanggil git rm --cachedmereka, yang berarti bahwa mereka dihapus dari cache, sementara pohon yang bekerja harus dibiarkan sendiri - kecuali bahwa Anda baru saja menghapus semua file dari pohon kerja Anda. Sekarang mereka juga dihapus dari indeks Anda.

Dengan kata lain, semua perubahan, dipentaskan atau tidak dipentaskan, hilang, dan pohon kerja Anda kosong. Menangis, checkout file Anda segar dari asal atau jarak jauh, dan ulangi pekerjaan Anda. Mengutuk sadis yang menulis garis-garis neraka ini; Saya tidak tahu sama sekali mengapa ada orang yang mau melakukan ini.


TL; DR: Anda baru saja menyemprot semuanya; mulai lagi dan gunakan git resetmulai sekarang.

SQB
sumber
2

Saya khawatir baris perintah pertama dihapus tanpa syarat dari copy pekerjaan semua file yang ada di area stage git. Yang kedua tidak menampilkan semua file yang dilacak tetapi sekarang telah dihapus. Sayangnya ini berarti Anda akan kehilangan modifikasi yang tidak dikomit ke file-file tersebut.

Jika Anda ingin mendapatkan copy pekerjaan Anda dan indeks kembali ke bagaimana mereka pada komit terakhir , Anda dapat ( hati-hati ) menggunakan perintah berikut:

git reset --hard

Saya katakan "hati-hati" karena git reset --hard akan menghapus perubahan yang tidak dikomit di copy pekerjaan Anda dan indeks. Namun, dalam situasi ini kedengarannya seolah-olah Anda hanya ingin kembali ke keadaan di komit terakhir Anda, dan perubahan yang tidak dikomit telah hilang pula.

Pembaruan: kedengarannya dari komentar Anda pada jawaban Amber bahwa Anda belum membuat komitmen (karena HEAD tidak dapat diatasi), jadi ini tidak akan membantu, saya khawatir.

Adapun cara kerja pipa-pipa itu: git ls-files -zdan git diff --name-only --diff-filter=D -zkeduanya menampilkan daftar nama file yang dipisahkan dengan byte 0. (Ini berguna, karena, tidak seperti baris baru, 0byte dijamin tidak muncul dalam nama file pada sistem mirip Unix.) Program ini xargspada dasarnya membangun baris perintah dari input standar, secara default dengan mengambil baris dari input standar dan menambahkannya ke akhir. dari baris perintah. The -0pilihan kata untuk mengharapkan standar input oleh dipisahkan oleh 0byte. xargsmungkin memanggil perintah beberapa kali untuk menggunakan semua parameter dari input standar, memastikan bahwa baris perintah tidak pernah menjadi terlalu panjang.

Sebagai contoh sederhana, jika Anda memiliki file yang dipanggil test.txt, dengan konten berikut:

hello
goodbye
hello again

... maka perintah tersebut xargs echo whatever < test.txtakan memanggil perintah:

echo whatever hello goodbye hello again
Mark Longair
sumber
Saya tidak pernah membuat komitmen sehingga akan berkata seperti tidak bisa menyelesaikan KEPALA. Apa yang kita lakukan dalam situasi seperti itu. Terima kasih banyak untuk menjelaskan pipa secara detail.
sarat
8
Jika Anda baru saja mengubah git, abaikan dan lakukan git, tambahkan --semua untuk memasukkan banyak file, JANGAN jalankan git atur ulang --hard untuk menghapus stage mereka. MEREKA AKAN DIHAPUS !!
Ajoy
5
Uwaaahh !! Mungkin Anda perlu menyoroti kata "hati-hati" . Saya baru saja melihat tiga kata ini "git reset --hard" dan semua file saya yang tidak dipentaskan adalah ... fufff !! pergi !!!!!
Vineeth Chitteti
1

Jika Anda ingin membatalkan tahapan semua perubahan gunakan perintah di bawah ini,

git reset --soft HEAD

Jika Anda ingin membatalkan perubahan dan mengembalikannya dari direktori kerja,

git reset --hard HEAD
027
sumber