Kembalikan atau checkout perubahan file secara selektif di Git?

89

Apakah ada perintah yang memungkinkan Anda untuk membatalkan sebagian perubahan ke file (atau file) di direktori kerja?

Misalkan Anda telah banyak mengedit file tetapi Anda menyadari bahwa Anda ingin membatalkan beberapa perubahan kembali ke status yang dikomit, tetapi bukan perubahan lainnya.

Saya membayangkan opsi untuk git checkoutitu bekerja sangat mirip git add -p, yaitu melewati file hunk demi hunk dan menanyakan apakah Anda ingin menyimpannya atau tidak.

1800 INFORMASI
sumber

Jawaban:

85

Anda bisa menggunakan

git add -p <path>

ke tahap potongan yang ingin Anda simpan dalam file tertentu, lalu

git checkout -- <path>

untuk membuang perubahan pohon kerja yang tidak ingin Anda pertahankan, dengan memeriksa versi bertahap dari file tersebut.

Akhirnya, Anda bisa menggunakan

git reset -- <path>

untuk mengembalikan versi bertahap file ke versi file yang berkomitmen terbaru agar perubahan Anda tidak bertahap.

CB Bailey
sumber
Untuk kasus penggunaan sederhana ini, yang oleh setiap sistem kontrol versi lain hanya memanggil "kembali", mengapa perintah Git begitu tidak jelas?
Jan Hettich
5
@Jan Apakah revertperintah sistem kontrol versi lain memungkinkan Anda memilih perubahan mana di dalam file yang dikembalikan? Benar-benar bertanya, karena saya hanya memiliki pengalaman dengan CVS dan Git. Di Git, git checkout -- path/to/fileada satu perintah yang mengembalikan semua perubahan dalam file itu, tetapi ini tidak sama seperti di atas.
michiakig
3
Ada juga git checkout --patchdan git reset --patchyang berfungsi seperti git add --patchdi git terbaru.
Matt Connolly
2
@ Rudie, --biasanya menunjukkan akhir dari penguraian opsi, dan argumen apa pun yang muncul setelahnya harus diinterpretasikan secara harfiah. Ini berarti Anda tidak perlu menambahkan ./sebelum nama file yang dimulai dengan tanda minus, jika nama file muncul setelahnya --.
zrajm
ketika saya menggunakan git checkout --patchdiff tampaknya mundur. Simbol minus adalah MENAMBAHKAN teks ke copy pekerjaan saya, dan simbol plus adalah MENGHAPUS baris dari copy pekerjaan saya.
Felipe Alvarez
115

Dengan versi git> = 1.7.1 saya bisa

git checkout -p

Saya tidak yakin kapan fitur ini diperkenalkan.

thisgeek
sumber
11
Perlu disebutkan bahwa Anda juga dapat melakukan git reset -pperubahan secara selektif untuk menghapus pentas dari area / indeks pementasan. Saya juga tidak tahu kapan versi Git ini diperkenalkan.
Ini adalah jawaban yang benar, mengapa tidak diterima.
wukong
1
@wukong karena jawaban ini telah diposting 2 tahun setelah pertanyaan. Pada saat ini (2009), jawaban Charles adalah solusi terbaik
pomeh
8

git checkout $filemengembalikan status file $fileke status komitmen terakhir. Saya rasa Anda dapat menggunakan git checkout SHA-1 -- $fileuntuk mengembalikan file ke komit yang diidentifikasi oleh SHA-1.

Koraktor
sumber
1
ya, tidak persis seperti yang saya inginkan, karena saya ingin menyimpan beberapa perubahan yang telah saya buat dalam file dan mengembalikan yang lain
1800 INFORMATION
1

Berapa banyak komitmen yang Anda perlukan untuk kembali dan memilih dari? Jika hanya satu, mungkin ambil cabang sebelum itu, periksa file yang Anda komit dan kemudian gunakan git add -puntuk menambahkannya sesuai keinginan Anda. Kemudian Anda dapat kembali ke tempat Anda sebelumnya dan melakukan pembayaran file dari cabang sementara Anda.

itu adalah:

git checkout -b temp troublesome-commit^
git checkout troublesome-commit -- path/to/file
git add -p path/to/file
git commit -c troublesome-commit
git checkout @{-1}
git checkout temp -- path/to/file
git commit path/to/file
git branch -D temp

Alternatif lain termasuk kembali dan mengedit komit dengan git rebase -i(menandai komit sebagai edit, lalu melakukan git reset HEAD^dan mengulangi komit ketika jatuh kembali ke shell).

Jika perubahan yang perlu Anda pilih tersebar pada serangkaian komit, mungkin lebih baik mengekstraknya sebagai tambalan (atau tambalan yang mencakup semuanya) dan mengedit tambalan secara manual, mengambil perubahan yang ingin Anda pertahankan, dan memasukkan sisa ke git apply --reverse.

araqnid
sumber
Saya sebenarnya tidak ingin mengembalikan apa pun yang telah dikomitmenkan, saya ingin membatalkan perubahan yang hanya ada di copy pekerjaan saya
1800 INFORMATION