git selektif mengembalikan perubahan lokal dari file

149

Dalam repo git saya yang melacak repo svn saya telah membuat sejumlah pengeditan untuk satu file.

Sekarang saya ingin mengembalikan perubahan itu (seperti svn revert), tetapi hanya sebagian file.

Saya ingin dapat melihat perbedaan pada file, membuang (mengembalikan) perubahan yang tidak saya inginkan dan menyimpan perubahan yang saya inginkan.

itu

git add -i 

Perintah tampaknya memiliki opsi untuk melakukan itu, tetapi saya belum ingin melakukan ini.

Pradeep
sumber

Jawaban:

91

Anda dapat melakukannya langsung dengan git checkout -p. Lihat jawaban Daniel Stutzbach di bawah ini.


Jawaban lama (sebelum checkout -pdiperkenalkan):

Anda dapat melakukannya seperti ini:

git add -i

(pilih bakhil yang ingin Anda pertahankan)

git commit -m "tmp"

Sekarang Anda memiliki komitmen dengan hanya perubahan yang ingin Anda pertahankan, dan sisanya tidak dipentaskan.

git reset --hard HEAD

Pada titik ini, perubahan yang tidak dikomit telah dibuang, jadi Anda memiliki direktori kerja yang bersih, dengan perubahan yang Anda ingin tetap komit di atas.

git reset --mixed HEAD^

Ini menghapus komit terakhir ('tmp'), tetapi menjaga modifikasi di direktori kerja Anda, tidak dipentaskan.

EDIT: diganti --softdengan --mixed, untuk membersihkan area pementasan.

Paolo Capriotti
sumber
ini akan melakukan perubahan yang ingin saya pertahankan bukan? Saya belum ingin melakukan perubahan itu. mm mungkin saya menganggap komitmen terlalu serius. Mungkin saya harus santai sekarang karena semuanya dalam repo lokal. btw apa yang dilakukan git reset --soft HEAD ^?
Pradeep
"git reset --soft HEAD ^" membatalkan komit dalam arti bahwa ia tetap bekerja direktori dan indeks seperti itu, dan memindahkan cabang saat ini satu komit kembali.
Jakub Narębski
Terima kasih Jakub. Paolo mengapa soft reset ke head - 1 diperlukan di sini? komit parsial dan hard reset seharusnya cukup bukankah untuk menyimpan beberapa perubahan dan membuang yang lain?
Pradeep
1
Jawaban Daniel di bawah ini sangat sederhana dan sepertinya cara yang tepat untuk melakukannya.
Umang
309

Saya percaya Anda dapat melakukannya paling sederhana dengan:

git checkout -p <optional filename(s)>

Dari halaman manual:

   −p, −−patch
       Interactively select hunks in the difference between the <tree−ish>
       (or the index, if unspecified) and the working tree. The chosen
       hunks are then applied in reverse to the working tree (and if a
       <tree−ish> was specified, the index).
       This means that you can use git checkout −p to selectively discard
       edits from your current working tree.
Daniel Stutzbach
sumber
1
Juga, jika Anda tidak ingin melakukan ini secara selektif, Anda dapat menggunakan "git checkout - <file> ..." untuk membuang perubahan.
db42
Apakah ini berhubungan dengan direktori?
bbum
1
Ini sepertinya banyak gagal bagi saya ketika membuang perubahan ("error: patch gagal <file>", "error: <file> patch tidak berlaku"). Anehnya saya akan menerima kesalahan-kesalahan itu ketika menggunakan aopsi dalam mode tambalan untuk membuang seluruh file, namun git checkout -- <file>berfungsi seperti yang diharapkan. Adakah yang tahu kenapa?
chrnola
Saya memiliki kesalahan itu beberapa kali jika file telah ditambal, dan tambalan interaktif sudah ketinggalan zaman dengan tambalan yang diterapkan file saat ini. Itu terjadi ketika menggunakan alat gui seperti pohon sumber jika saya membuang bongkahan dua kali secara tidak sengaja. Kali kedua akan menghasilkan kesalahan itu.
phyatt
3

Anda dapat menjalankan git diffpada file, menyimpan diff yang dihasilkan, mengeditnya untuk menghapus perubahan yang ingin Anda simpan, kemudian jalankan melalui patch -Runtuk membatalkan diff yang tersisa.

git beda file.txt> patch.tmp
# edit patch.tmp untuk menghapus bakhil yang ingin Anda pertahankan
patch -R <patch.tmp
Greg Hewgill
sumber
Saya memiliki 2 bakhil di file tambalan saya dan menghapus satu. Tidak yakin apa alasannya tetapi tambalan -R terus ditolak dengan ini.
Pradeep
2
Anda menyebutkan dalam komentar lain yang git diffmenunjukkan seluruh file berubah. Ini biasanya terjadi ketika Anda menyimpan file menggunakan akhiran baris yang berbeda dari sebelumnya. Ini juga akan menyebabkan patchmenolak file tambalan. Apakah itu terdengar seperti apa yang mungkin terjadi?
Greg Hewgill
kamu benar. akhir baris menjadi toggle setiap kali saya menggunakan perintah patch. Saya di windows dan menggunakan cream / vim. Saya perlu mengatasinya terlebih dahulu.
Pradeep
Saya tidak dapat menyelesaikan masalah dengan tambalan di windows. Meskipun aku yakin ini berhasil, aku lebih suka menggunakan resep Paolo. Demi cinta perintah-perintah interaktif untuk bekerja dengan diff menggunakan git add -i.
Pradeep
3

Sepertinya kamu mau

 git revert --no-commit $REVSISON 

Anda kemudian dapat menggunakan

 git diff --cached

untuk melihat perubahan apa yang akan dilakukan sebelum melakukan (karena mengembalikan hanyalah komit ke arah depan yang mereplikasi kebalikan dari perubahan di masa lalu)

Jika Anda menggunakan repositori Git murni, Anda bisa, tergantung pada tujuan Anda, menggunakan rebase interaktif ( git rebase -i) untuk kembali ke komit yang tidak Anda sukai dan mengedit komit secara surut sehingga perubahan yang tidak Anda sukai tidak pernah terjadi , tapi itu umumnya hanya karena jika Anda TAHU Anda tidak akan pernah ingin melihatnya lagi.

Kent Fredric
sumber
Saya memang mengembalikan seperti yang Anda sebutkan ke revisi sebelumnya (apakah itu benar?) Dan sekarang git diff hanya menampilkan seluruh file yang diubah. Seharusnya menunjukkan suntingan yang telah saya lakukan?
Pradeep
1

Membaca ulang pertanyaan itu, sepertinya Anda ingin mengembalikan perubahan yang ada di pohon kerja Anda dan bukan perubahan yang telah dilakukan sebelumnya tetapi beberapa jawaban lain membuatnya terdengar seperti bacaan saya mungkin salah. Bisakah Anda mengklarifikasi?

Jika perubahan hanya ada di copy pekerjaan Anda, maka cara termudah untuk melakukannya adalah dengan membuat perubahan yang ingin Anda pertahankan:

git add -i <file>

Kemudian buang perubahan yang tidak ingin Anda pertahankan dengan memeriksa versi indeks:

git checkout -- <file>

Kemudian hapus tahapan perubahan jika Anda belum menginginkannya dipentaskan:

git reset -- <file>

Resep ini hanya mengembalikan perubahan yang dipilih ke file (atau file yang Anda tentukan) dan tidak membuat komit sementara yang membutuhkan reverting.

Jika Anda ingin secara selektif menerapkan hanya beberapa perubahan yang dilakukan pada komit sebelumnya maka Anda dapat mengatur ulang file ke status komitmen sebelumnya terlebih dahulu:

git reset <commit_before_first_unwanted_change> -- <file>

Kemudian Anda dapat mengikuti resep sebelumnya untuk mem git add -i <file>-stage perubahan yang ingin Anda simpan, git checkout -- <file>untuk membuang perubahan yang tidak diinginkan dan git reset -- <file>untuk 'unstage' perubahan.

CB Bailey
sumber
0

Opsi baris perintah yang dijelaskan dalam jawaban di sini berguna ketika file ada di server yang saya akses melalui terminal ssh. Namun, ketika file ada di mesin lokal saya, saya lebih suka cara berikut:

Buka file di editor netbeans (yang dilengkapi dengan dukungan git). Netbeans menempatkan tanda merah / hijau / biru pada nomor baris untuk menunjukkan di mana barang dihapus / ditambahkan / dimodifikasi (masing-masing).

Mengklik kanan salah satu dari tanda-tanda ini memberi Anda opsi untuk membatalkan perubahan itu. Selain itu, Anda dapat mengeklik kanan tanda merah dan biru untuk menemukan versi lama di sembulan.

Abhishek Anand
sumber