Kembalikan perubahan ke file dalam komit

126

Saya ingin mengembalikan perubahan yang dibuat oleh komit tertentu ke file tertentu saja.

Bisakah saya menggunakan perintah git revert untuk itu?

Adakah cara sederhana lainnya untuk melakukannya?

Lakshman Prasad
sumber
Aneh ... kenapa berubah setelah bertahun-tahun?
VonC

Jawaban:

222

Cara terbersih yang pernah saya lakukan untuk melakukan ini dijelaskan di sini

git show some_commit_sha1 -- some_file.c | git apply -R

Mirip dengan respon VonC tetapi menggunakan git showdan git apply.

mgalgs
sumber
10
Selamat. Solusi skrip berlebihan untuk ini. Mengapa tidak ada nama file git revert sha-1 saja?
Mark Edington
16
Ini berfungsi di Mac saya, tetapi di Windows (di bawah Cygwin) ini memberi saya:fatal: unrecognized input
Kedar Mhaswade
1
@MerhawiFissehaye: Saya pikir git checkout hanya akan mengembalikan perubahan lagi untuk kembali ke keadaan apa yang telah dilakukan. Saya melakukan 'git menambahkan nama file; git commit --amend 'untuk menghapus file dari komit.
ViFI
3
Sekadar tip, saya hampir selalu harus menambahkan -3bendera ke git apply for three-way merge ketika tambalan gagal, karena saya biasanya mengoreksi perubahan sedikit ke masa lalu.
angularsen
2
Mungkin jelas bagi sebagian besar orang tetapi pastikan some_file.cmenyertakan jalur ke file jika ada, jika tidak, Anda akan diam-diam tidak menambal apa pun :)
Warpling
35

Dengan asumsi tidak masalah untuk mengubah riwayat komit, berikut adalah alur kerja untuk mengembalikan perubahan dalam satu file dalam komit sebelumnya:

Misalnya, Anda ingin mengembalikan perubahan dalam 1 file ( badfile.txt) di komit aaa222:

aaa333 Good commit
aaa222 Problem commit containing badfile.txt
aaa111 Base commit

Basis pada basis commit, ubah masalah commit, & lanjutkan.

1) Mulai rebase interaktif:

git rebase -i aaa111

2) Tandai masalah komit untuk diedit di editor dengan mengubah pickke e(untuk edit):

e aaa222
pick aaa333

3) Kembalikan perubahan ke file buruk:

git show -- badfile.txt | git apply -R

4) Tambahkan perubahan & ubah komit:

git add badfile.txt
git commit --amend

5) Selesaikan rebase:

git rebase --continue
tee
sumber
Hanya ingin menunjukkan bahwa ini mengasumsikan Anda dapat mengedit riwayat git. Beberapa jawaban di atas membuat komit baru yang membalikkan perubahan tertentu tanpa mengedit riwayat, yang tidak selalu memungkinkan / diizinkan.
angularsen
Fantastis. Inilah yang saya cari. Saya sudah memiliki ide ini, tetapi menjadi bingung ketika melakukan rebase interaktif bahwa file saat melakukan edittidak muncul sebagai berubah. Tapi git show -- badfile.txt | git apply -Rmemberikan jawaban yang saya butuhkan <3
mraxus
jika saya mengerti ini git apply -R menghapus komit pada file itu dan menyetelnya kembali ke keadaan semula yang diubah?
DaImTo
19

git revert adalah untuk semua konten file dalam komit.

Untuk satu file, Anda bisa skrip :

#!/bin/bash

function output_help {
    echo "usage: git-revert-single-file <sha1> <file>"
}

sha1=$1
file=$2

if [[ $sha1 ]]; then
git diff $sha1..$sha1^ -- $file | patch -p1
else
output_help
fi

(Dari utilitas git-shell-scripts dari smtlaissezfaire )


catatan:

cara lain dijelaskan di sini jika Anda belum melakukan modifikasi Anda saat ini.

git checkout -- filename

git checkout memiliki beberapa opsi untuk sebuah file, memodifikasi file dari HEAD, menimpa perubahan Anda.


Dropped.on.Caprica menyebutkan di komentar :

Anda dapat menambahkan alias ke git sehingga Anda dapat melakukan git revert-file <hash> <file-loc>dan mengembalikan file tertentu.
Lihat intinya .

[alias]
  revert-file = !sh /home/some-user/git-file-revert.sh
VonC
sumber
Hanya untuk menambah diskusi di sini, Anda dapat menambahkan alias ke git sehingga Anda dapat melakukan git revert-file <hash> <file-loc>dan mengembalikan file spesifik tersebut. Saya angkat dari jawaban ini (meskipun saya harus membuat beberapa pengeditan agar berfungsi dengan benar). Anda dapat menemukan salinan .gitconfigskrip saya dan yang telah diedit di sini: gist.github.com/droppedoncaprica/5b67ec0021371a0ad438
AlbertEngelB
@ Dropped.on.Choir bagus. Saya telah memasukkannya dalam jawaban untuk lebih banyak visibilitas.
VonC
12

Saya hanya akan menggunakan --no-commitopsi untuk git-revertdan kemudian menghapus file yang tidak ingin Anda kembalikan dari indeks sebelum akhirnya melakukannya. Berikut adalah contoh yang menunjukkan bagaimana dengan mudah mengembalikan hanya perubahan ke foo.c di komit terbaru kedua:

$ git revert --no-commit HEAD~1
$ git reset HEAD
$ git add foo.c
$ git commit -m "Reverting recent change to foo.c"
$ git reset --hard HEAD

Yang pertama git-reset"menghapus" semua file, sehingga kita dapat menambahkan kembali hanya satu file yang ingin kita kembalikan. Yang terakhir git-reset --hardmenghilangkan sisa file yang tidak ingin kita simpan.

Dan Molding
sumber
9

Jauh lebih sederhana:

git reset HEAD^ path/to/file/to/revert

kemudian

git commit --amend   

lalu

git push -f

file hilang dan komit hash, pesan, dll sama.

Forrest
sumber
Untuk kelengkapan, apakah Anda membutuhkan git checkout -- path/to/file/to/revertlangkah? Juga, tidak benar bahwa hashnya sama setelahnya, bukan? Kalimat terakhir mungkin lebih baik seperti ini: "Hasilnya adalah komit terakhir diganti dengan yang baru yang hanya berbeda karena tidak berisi perubahan pada file yang dikembalikan."
Kevin
@Kevin mungkin kamu benar. Saya harus memeriksa ulang baris terakhir itu, tetapi melihat kembali ini dari beberapa tahun yang lalu saya akan terkejut jika hash komit tidak berubah.
Forrest
6
git reset HEAD^ path/to/file/to/revert/in/commit

Perintah di atas akan mengeluarkan file dari komit, tetapi akan tercermin dalam git status.

git checkout path/to/file/to/revert/in/commit

Perintah di atas akan mengembalikan perubahan (sebagai hasilnya Anda mendapatkan file yang sama dengan HEAD).

git commit

(Lulus --amenduntuk mengubah komit.)

git push

Dengan ini, file yang sudah di komit dihapus dan dikembalikan.

Langkah-langkah di atas harus diikuti dari cabang tempat komit dibuat.

Bharath TS
sumber
5

Anda dapat mengikuti prosedur ini:

  1. git revert -n <*commit*>( -nkembalikan semua perubahan tetapi tidak akan melakukannya)
  2. git add <*filename*> (nama file yang ingin Anda kembalikan & komit)
  3. git commit -m 'reverted message' (tambahkan pesan untuk kembali)
  4. setelah melakukan buang perubahan file lain sehingga file tetap diperbarui dengan perubahan yang Anda lakukan sebelum pengembalian
Imran Sahil
sumber
1

Jika Anda ingin menyetel ulang perubahan pada file dari pengubahan terakhir Anda, inilah yang biasanya saya gunakan. Saya rasa ini adalah solusi paling sederhana.

Harap perhatikan bahwa file akan ditambahkan ke area pementasan.

git checkout <prev_commit_hash> -- <path_to_your_file>

Semoga membantu :)

Gabeeka
sumber