Bagaimana cara mengembalikan repositori Git ke komit sebelumnya?

7630

Bagaimana cara mengembalikan dari kondisi saya saat ini ke snapshot yang dibuat pada komit tertentu?

Jika saya melakukannya git log, maka saya mendapatkan output berikut:

$ git log
commit a867b4af366350be2e7c21b8de9cc6504678a61b`
Author: Me <[email protected]>
Date:   Thu Nov 4 18:59:41 2010 -0400

blah blah blah...

commit 25eee4caef46ae64aa08e8ab3f988bc917ee1ce4
Author: Me <[email protected]>
Date:   Thu Nov 4 05:13:39 2010 -0400

more blah blah blah...

commit 0766c053c0ea2035e90f504928f8df3c9363b8bd
Author: Me <[email protected]>
Date:   Thu Nov 4 00:55:06 2010 -0400

And yet more blah blah...

commit 0d1d7fc32e5a947fbd92ee598033d85bfc445a50
Author: Me <[email protected]>
Date:   Wed Nov 3 23:56:08 2010 -0400

Yep, more blah blah.

Bagaimana saya kembali ke komit mulai 3 November, yaitu komit 0d1d7fc?

Orang gila
sumber
116
Berikut ini adalah posting yang sangat jelas dan menyeluruh tentang membatalkan hal-hal di git, langsung dari Github.
Nobita
3
Terkait: Kembalikan ke Git lama yang melakukan repo publik . Perhatikan bahwa pertanyaan itu menambah kendala bahwa repo bersifat publik.
58
Saya suka git, tetapi kenyataan bahwa ada 35 jawaban untuk sesuatu yang seharusnya sangat sederhana memperlihatkan masalah besar dengan git. Atau apakah itu dokumen?
The Muffin Man
2
Bagaimana bahasa "jebakan" dalam menggunakan kata untuk kembali sebagai bahasa sehari-hari untuk mengatur ulang bahkan tidak ditekankan di sini ??? 6594 upvotes sejauh ini dan bukan suntingan dengan cara ini, untuk menekankan perbedaannya? Tidak akan lebih membingungkan untuk merujuk ke "menyimpan file" di sini dengan ekspresi "melakukan" ...
RomainValeri

Jawaban:

9732

Ini sangat tergantung pada apa yang Anda maksud dengan "kembalikan".

Beralih sementara ke komit yang berbeda

Jika Anda ingin sementara kembali ke sana, main-main, lalu kembali ke tempat Anda sekarang, yang harus Anda lakukan adalah memeriksa komit yang diinginkan:

# This will detach your HEAD, that is, leave you with no branch checked out:
git checkout 0d1d7fc32

Atau jika Anda ingin membuat komitmen saat berada di sana, silakan dan buat cabang baru saat Anda berada di sana:

git checkout -b old-state 0d1d7fc32

Untuk kembali ke tempat Anda berada sekarang, periksa cabang tempat Anda berada lagi. (Jika Anda telah membuat perubahan, seperti biasa ketika berpindah cabang, Anda harus menghadapinya sebagaimana mestinya. Anda dapat mengatur ulang untuk membuangnya; Anda dapat menyimpan, checkout, menyimpan pop untuk membawanya, Anda dapat melakukan mereka ke cabang di sana jika Anda ingin cabang di sana.)

Sulit menghapus komitmen yang tidak dipublikasikan

Sebaliknya, jika Anda ingin benar-benar menyingkirkan semua yang telah Anda lakukan sejak itu, ada dua kemungkinan. Pertama, jika Anda belum menerbitkan salah satu dari komitmen ini, cukup setel ulang:

# This will destroy any local modifications.
# Don't do it if you have uncommitted work you want to keep.
git reset --hard 0d1d7fc32

# Alternatively, if there's work to keep:
git stash
git reset --hard 0d1d7fc32
git stash pop
# This saves the modifications, then reapplies that patch after resetting.
# You could get merge conflicts, if you've modified things which were
# changed since the commit you reset to.

Jika Anda kacau, Anda sudah membuang perubahan lokal Anda, tetapi Anda setidaknya bisa kembali ke tempat Anda sebelumnya dengan mengatur ulang.

Batalkan komitmen yang dipublikasikan dengan komitmen baru

Di sisi lain, jika Anda telah menerbitkan karya, Anda mungkin tidak ingin mengatur ulang cabang, karena itu secara efektif menulis ulang sejarah. Dalam hal ini, Anda memang dapat mengembalikan komit. Dengan Git, kembalikan memiliki arti yang sangat spesifik: buat komit dengan tambalan terbalik untuk membatalkannya. Dengan cara ini Anda tidak menulis ulang riwayat apa pun.

# This will create three separate revert commits:
git revert a867b4af 25eee4ca 0766c053

# It also takes ranges. This will revert the last two commits:
git revert HEAD~2..HEAD

#Similarly, you can revert a range of commits using commit hashes:
git revert a867b4af..0766c053 

# Reverting a merge commit
git revert -m 1 <merge_commit_sha>

# To get just one, you could use `rebase -i` to squash them afterwards
# Or, you could do it manually (be sure to do this at top level of the repo)
# get your index and work tree into the desired state, without changing HEAD:
git checkout 0d1d7fc32 .

# Then commit. Be sure and write a good message describing what you just did
git commit

The git-revertmanualnya sebenarnya mencakup banyak ini dalam deskripsi. Tautan lain yang bermanfaat adalah bagian git-scm.com yang membahas git-revert .

Jika Anda memutuskan bahwa Anda tidak ingin mengembalikannya, Anda dapat mengembalikannya (seperti dijelaskan di sini) atau mengatur ulang kembali sebelum kembali (lihat bagian sebelumnya).

Anda juga dapat menemukan jawaban ini bermanfaat dalam kasus ini:
Bagaimana cara memindahkan HEAD kembali ke lokasi sebelumnya? (Kepala terpisah)

Cascabel
sumber
118
@ Komentar Rod pada git revert HEAD~3sebagai wat terbaik untuk kembali 3komit adalah am konvensi penting.
New Alexandria
19
Bisakah Anda menulis bilangan bulat? seperti:git reset --hard 0d1d7fc32e5a947fbd92ee598033d85bfc445a50
Spoeken
16
@MathiasMadsenStav Ya, tentu saja Anda dapat menentukan komit oleh SHA1 lengkap. Saya menggunakan hash yang disingkat untuk membuat jawaban lebih mudah dibaca, dan Anda juga cenderung menggunakannya jika Anda mengetik. Jika Anda menyalin dan menempel, tentu saja gunakan hash lengkap. Lihat Menentukan Revisi di man git rev-parse untuk deskripsi lengkap tentang bagaimana Anda dapat memberi nama commit.
Cascabel
59
Anda dapat menggunakan git revert --no-commit hash1 hash2 ...dan setelah ini, lakukan saja setiap pengembalian dalam satu komitgit commit -m "Message"
Mirko Akov
6
Apa yang dimaksud 'terbitkan' dalam konteks ini?
Howiecamp
1852

Banyak jawaban rumit dan berbahaya di sini, tetapi sebenarnya mudah:

git revert --no-commit 0766c053..HEAD
git commit

Ini akan mengembalikan segala sesuatu dari HEAD kembali ke hash komit, yang berarti akan membuat ulang kondisi komit di pohon kerja seolah-olah setiap komit sejak telah berjalan kembali. Anda kemudian dapat mengkomit pohon saat ini, dan itu akan membuat komit baru yang pada dasarnya setara dengan komit yang Anda "kembalikan".

(Itu --no-commit Bendera memungkinkan git mengembalikan semua komit sekaligus - jika tidak, Anda akan diminta pesan untuk setiap komit di dalam rentang, mengotori riwayat Anda dengan komit baru yang tidak perlu.)

Ini adalah cara yang aman dan mudah untuk mengembalikan ke keadaan sebelumnya . Tidak ada riwayat yang dimusnahkan, sehingga dapat digunakan untuk komitmen yang telah dipublikasikan.

Yarin
sumber
23
Jika Anda benar-benar ingin memiliki komit individu (bukan mengembalikan segala sesuatu dengan satu besar komit), maka Anda dapat melewati --no-editbukan --no-commit, sehingga Anda tidak perlu mengedit pesan komit untuk setiap pengembalian.
88
Jika salah satu dari komit antara 0766c053 .. KEPALA adalah gabungan maka akan ada kesalahan muncul (harus dilakukan tanpa -m ditentukan). Ini dapat membantu mereka yang mengalami hal itu: stackoverflow.com/questions/5970889/…
timhc22
7
Untuk melihat perbedaan sebelum Anda menggunakan git diff --cached.
John Erck 6-15
21
$ git revert --no-commit 53742ae..HEADkembalifatal: empty commit set passed
Alex G
10
@AlexG itu karena Anda harus memasukkan hash sebelum yang Anda ingin kembali. Dalam kasus saya, hash seperti: 81bcc9e HEAD{0}; e475924 HEAD{1}, ...(dari git reflog), dan saya ingin membatalkan apa yang saya lakukan 81bcc9e, maka saya harus melakukannyagit revert e475924..HEAD
EpicPandaForce
1611

Rogue Coder?

Bekerja sendiri dan hanya ingin itu berhasil? Ikuti instruksi di bawah ini, mereka telah bekerja dengan andal untuk saya dan banyak lainnya selama bertahun-tahun.

Bekerja dengan orang lain? Git itu rumit. Baca komentar di bawah jawaban ini sebelum Anda melakukan sesuatu yang gegabah.

Mengembalikan Copy Pekerjaan ke Komit Terkini

Untuk kembali ke komitmen sebelumnya, abaikan perubahan apa pun:

git reset --hard HEAD

di mana HEAD adalah komit terakhir di cabang Anda saat ini

Mengembalikan Copy Pekerjaan ke Komit yang Lama

Untuk kembali ke komit yang lebih lama dari komit terbaru:

# Resets index to former commit; replace '56e05fced' with your commit code
git reset 56e05fced 

# Moves pointer back to previous HEAD
git reset --soft HEAD@{1}

git commit -m "Revert to 56e05fced"

# Updates working copy to reflect the new commit
git reset --hard

Kredit pergi ke pertanyaan Stack Overflow serupa, Kembalikan ke komit oleh hash SHA di Git? .

boulder_ruby
sumber
33
Saya melakukan itu, tetapi kemudian saya tidak dapat melakukan dan mendorong ke repositori jarak jauh. Saya ingin komitmen lama yang lebih spesifik untuk menjadi KEPALA ...
Lennon
7
Ini berarti Anda telah mendorong komitmen yang ingin Anda kembalikan. Itu dapat menciptakan banyak masalah bagi orang-orang yang telah memeriksa kode Anda dan mengerjakannya. Karena mereka tidak dapat menerapkan komit Anda dengan lancar di atas komitmen mereka. Dalam kasus seperti itu lebih baik lakukan git revert. Jika Anda satu-satunya yang menggunakan repo. Lakukan git push -f (Tapi pikirkan dua kali sebelum melakukan itu)
vinothkr
6
Saya hanya juga ingin menunjukkan bahwa, alternatif untuk solusi soft reset, bukannya melakukan reset campuran pertama dan hard reset terakhir, Anda benar-benar dapat melakukan hard reset pertama, sebagai berikut: git reset --hard 56e05fc; git reset --soft HEAD@{1}; git commit.
5
@nuton linus pauling sendiri, pencipta git, mengkritiknya karena terlalu rumit. Dia dalam catatan mengatakan bahwa dia "kaget", git menjadi sangat populer mengingat kerumitannya
boulder_ruby
5
@ Boulder_ruby Saya pikir maksud Anda Linus Torvalds adalah pencipta git. Tapi saya pikir Linus Pauling mungkin akan setuju bahwa git itu rumit.
Suncat2000
215

Opsi terbaik untuk saya dan mungkin yang lain adalah opsi reset Git:

git reset --hard <commidId> && git clean -f

Ini telah menjadi pilihan terbaik bagi saya! Sederhana, cepat dan efektif!


** Catatan: ** Seperti yang disebutkan dalam komentar jangan lakukan ini jika Anda berbagi cabang dengan orang lain yang memiliki salinan dari komitmen lama

Juga dari komentar, jika Anda menginginkan metode yang kurang 'gampang' yang bisa Anda gunakan

git clean -i
Pogrindis
sumber
37
Peringatan Wajib: jangan lakukan ini jika Anda membagikan cabang Anda dengan orang lain yang memiliki salinan komitmen lama, karena menggunakan hard reset seperti ini akan memaksa mereka harus menyinkronkan kembali pekerjaan mereka dengan cabang yang baru reset. Untuk solusi yang menjelaskan secara rinci cara mengembalikan komit dengan aman tanpa kehilangan pekerjaan dengan pengaturan ulang yang sulit, lihat jawaban ini .
7
Saya kedua @ peringatan Cupcake ... sangat menyadari konsekuensinya. Namun, perlu diketahui bahwa jika kebutuhan Anda benar-benar adalah untuk membuat komit-komit tersebut hilang dari sejarah selamanya, metode reset + clean ini akan melakukannya, dan Anda akan perlu memaksa mendorong cabang-cabang Anda yang telah dimodifikasi kembali ke sembarang dan semua remote.
ashnazg
5
git clean -f BAHAYA BAHAYA
Tisch
2
Ini menetapkan kepala salinan lokal saya ke komit yang diinginkan. Tetapi kemudian saya tidak dapat mendorong perubahan apa pun karena berada di belakang remote. Dan jika saya menarik dari jarak jauh itu berakhir di tempat itu pada komit terbaru di cabang jauh. Bagaimana cara saya sepenuhnya melenyapkan (dari mana-mana) beberapa melakukan keduanya pada salinan lokal saya yang telah didorong?
Ade
2
@Ade .. Anda bisa menggunakan git push -fbendera .. Tapi hati-hati, itu akan menimpa remote .. Pastikan Anda tahu apa yang ingin Anda lakukan ...
Pogrindis
176

Sebelum menjawab, mari tambahkan beberapa latar belakang, jelaskan apa ini HEAD.

First of all what is HEAD?

HEADhanyalah referensi ke komit saat ini (terbaru) di cabang saat ini. Hanya ada satu HEADpada waktu tertentu (tidak termasuk git worktree).

Konten HEADdisimpan di dalam .git/HEAD, dan mengandung 40 byte SHA-1 dari komit saat ini.


detached HEAD

Jika Anda tidak menggunakan komit terbaru - artinya HEADmenunjuk komit sebelumnya dalam sejarah, itu disebut detached HEAD.

Masukkan deskripsi gambar di sini

Pada baris perintah akan terlihat seperti ini - SHA-1 bukan nama cabang karena HEADtidak menunjuk ke ujung cabang saat ini:

Masukkan deskripsi gambar di sini


Beberapa opsi tentang cara memulihkan dari HEAD yang terpisah:


git checkout

git checkout <commit_id>
git checkout -b <new branch> <commit_id>
git checkout HEAD~X // x is the number of commits t go back

Ini akan mengecek cabang baru yang menunjuk ke komit yang diinginkan. Perintah ini akan checkout ke komit yang diberikan.

Pada titik ini Anda dapat membuat cabang dan mulai bekerja dari titik ini pada:

# Checkout a given commit.
# Doing so will result in a `detached HEAD` which mean that the `HEAD`
# is not pointing to the latest so you will need to checkout branch
# in order to be able to update the code.
git checkout <commit-id>

# Create a new branch forked to the given commit
git checkout -b <branch name>

git reflog

Anda selalu dapat menggunakan itu reflogjuga. git reflogakan menampilkan perubahan apa pun yang memperbarui HEADdan memeriksa entri reflog yang diinginkan akan mengatur HEADkembali komitmen ini.

Setiap kali KEPALA diubah akan ada entri baru di reflog

git reflog
git checkout HEAD@{...}

Ini akan membuat Anda kembali ke komit yang Anda inginkan

Masukkan deskripsi gambar di sini


git reset HEAD --hard <commit_id>

"Gerakkan" kepala Anda kembali ke komit yang diinginkan.

# This will destroy any local modifications.
# Don't do it if you have uncommitted work you want to keep.
git reset --hard 0d1d7fc32

# Alternatively, if there's work to keep:
git stash
git reset --hard 0d1d7fc32
git stash pop
# This saves the modifications, then reapplies that patch after resetting.
# You could get merge conflicts, if you've modified things which were
# changed since the commit you reset to.
  • Catatan: ( Karena Git 2.7 ) Anda juga bisa menggunakan itu git rebase --no-autostash.

Skema ini menggambarkan perintah mana melakukan apa. Seperti yang Anda lihat ada reset && checkoutmodifikasi HEAD.

Masukkan deskripsi gambar di sini

Panduan Kode
sumber
6
Petunjuk yang sangat bagus untuk git reflog, itulah yang saya butuhkan
smac89
4
Aduh! Ini semua tampak sangat rumit ... bukankah ada perintah sederhana yang hanya membawa Anda selangkah ke belakang dalam proses? Suka pergi dari versi 1.1 di proyek Anda kembali ke versi 1.0? Saya mengharapkan sesuatu seperti: git stepback_one_commit atau sesuatu ....
Kokodoko
ada: git reset HEAD^--hard`
CodeWizard
3
@Kododoko Ya, ini sangat rumit ... dan contoh sempurna tentang betapa sedikitnya pertimbangan ahli bagi orang-orang yang baru memulai. Silakan merujuk jawaban saya di sini, dan juga ke buku yang saya rekomendasikan di dalamnya. Git BUKAN sesuatu yang bisa Anda ambil secara intuitif. Dan saya dapat benar-benar yakin CodeWizard tidak melakukannya.
mike rodent
145

Jika Anda ingin "uncommit", hapus pesan komit terakhir, dan kembalikan file yang dimodifikasi ke dalam pementasan, Anda akan menggunakan perintah:

git reset --soft HEAD~1
  • --softmenunjukkan bahwa file yang tidak dikomit harus disimpan sebagai file yang berfungsi yang berlawanan dengan --hardyang akan dibuang.
  • HEAD~1adalah komit terakhir. Jika Anda ingin mengembalikan komitmen, Anda dapat menggunakannya HEAD~3. Jika Anda ingin mengembalikan ke nomor revisi tertentu, Anda juga bisa melakukannya menggunakan hash SHA-nya.

Ini adalah perintah yang sangat berguna dalam situasi di mana Anda melakukan hal yang salah dan Anda ingin membatalkan komitmen terakhir itu.

Sumber: http://nakkaya.com/2009/09/24/git-delete-last-commit/

Stephen Ostermiller
sumber
3
Ini lunak dan lembut: bebas risiko jika Anda belum mendorong pekerjaan Anda
nilsM
124

Anda dapat melakukan ini dengan dua perintah berikut:

git reset --hard [previous Commit SHA id here]
git push origin [branch Name] -f

Ini akan menghapus komit Git Anda sebelumnya.

Jika Anda ingin menyimpan perubahan, Anda juga dapat menggunakan:

git reset --soft [previous Commit SHA id here]

Maka itu akan menyimpan perubahan Anda.

kiran boghra
sumber
2
Saya mencoba 1/2 lusin jawaban dalam posting ini sampai saya mendapatkan yang ini .. semua yang lain, konfigurasi git saya terus memberi saya kesalahan ketika mencoba untuk mendorong. Jawaban ini berhasil. Terima kasih!
Gene Bo
Satu detail untuk saya adalah bahwa saya kehilangan diff .. yang saya ingin tetap melihat apa yang telah saya lakukan dalam komit yang tidak berhasil. Jadi lain kali saya hanya akan menyimpan data itu sebelum mengeluarkan perintah reset ini
Gene Bo
1
Ini adalah satu-satunya cara bagi saya untuk membatalkan penggabungan yang buruk, memulihkan tidak bekerja dalam kasus itu. Terima kasih!
Dave Cole
Jawaban Terbaik. Terima kasih
Imran Pollob
Jawaban terbaik, terima kasih.
user1394
114

Saya telah mencoba banyak cara untuk mengembalikan perubahan lokal di Git, dan tampaknya ini bekerja paling baik jika Anda hanya ingin kembali ke keadaan komit terbaru.

git add . && git checkout master -f

Deskripsi Singkat:

  • Ini TIDAK akan membuat komitmen seperti git reverthalnya.
  • TIDAK akan melepaskan KEPALA Anda seperti git checkout <commithashcode>halnya.
  • Ini AKAN mengesampingkan semua perubahan lokal Anda dan HAPUS semua file yang ditambahkan sejak komit terakhir di cabang.
  • Ini hanya berfungsi dengan nama cabang, jadi Anda bisa kembali hanya ke komit terbaru di cabang dengan cara ini.

Saya menemukan cara yang jauh lebih mudah dan sederhana untuk mencapai hasil di atas:

git add . && git reset --hard HEAD

di mana HEAD menunjuk komit terbaru pada Anda cabang saat ini.

Ini adalah kode kode yang sama seperti yang disarankan boulder_ruby, tetapi saya telah menambahkan git add .sebelumnya git reset --hard HEADuntuk menghapus semua file baru yang dibuat sejak komit terakhir karena ini adalah apa yang kebanyakan orang harapkan saya percaya ketika kembali ke komit terbaru.

Roman Minenok
sumber
83

BAIK, kembali ke komit sebelumnya di Git cukup mudah ...

Kembalikan kembali tanpa menyimpan perubahan:

git reset --hard <commit>

Kembalikan kembali dengan menyimpan perubahan:

git reset --soft <commit>

Penjelasan: menggunakangit reset , Anda dapat mengatur ulang ke kondisi tertentu. Sudah biasa menggunakannya dengan hash komit seperti yang Anda lihat di atas.

Tapi seperti yang Anda lihat perbedaannya menggunakan dua flag --softdan --hard, secara default git resetmenggunakan --softflag, tapi itu praktik yang baik selalu menggunakan flag, saya jelaskan setiap flag:


--lembut

Bendera default seperti yang dijelaskan, tidak perlu menyediakannya, tidak mengubah pohon yang berfungsi, tetapi ia menambahkan semua file yang berubah siap untuk dikomit, jadi Anda kembali ke status komit yang perubahan pada file menjadi tidak bertahap.


--keras

Hati-hati dengan bendera ini. Ini me-reset pohon yang berfungsi dan semua perubahan untuk melacak file dan semua akan hilang!


Saya juga membuat gambar di bawah ini yang mungkin terjadi dalam kehidupan nyata bekerja dengan Git:

Set ulang ke komit

Alireza
sumber
Default git resetadalah git reset --mixed, bukan git reset --soft. Silakan periksa Apa perbedaan antara reset git --mixed, --soft, dan --hard? dan Dalam bahasa Inggris biasa, apa yang dilakukan “git reset”?
Fabio mengatakan Reinstate Monica
70

Dengan asumsi Anda berbicara tentang master dan pada cabang masing-masing (yang mengatakan, ini bisa menjadi cabang kerja yang Anda khawatirkan):

# Reset local master branch to November 3rd commit ID
git reset --hard 0d1d7fc32e5a947fbd92ee598033d85bfc445a50

# Reset remote master branch to November 3rd commit ID
git push -f origin 0d1d7fc32e5a947fbd92ee598033d85bfc445a50:master

Saya menemukan jawabannya dari dalam posting blog (sekarang tidak ada lagi)

Perhatikan bahwa ini adalah Reset dan Memaksa perubahan ke remote, sehingga jika orang lain di tim Anda sudah git menarik, Anda akan menimbulkan masalah bagi mereka. Anda menghancurkan sejarah perubahan, yang merupakan alasan penting mengapa orang menggunakan git.

Lebih baik menggunakan kembali (lihat jawaban lain) daripada mengatur ulang. Jika Anda tim satu orang maka mungkin tidak masalah.

markreyes
sumber
6
Bagaimana jawaban ini berbeda dari yang lainnya?
Matsmath
Sangat disayangkan. Saya mengirim email ke blogger - mudah-mudahan dia masih memilikinya!
markreyes
2
Sintaks push tidak ada dari sebagian besar saran lain untuk cara memperbaikinya. Bekerja dengan baik.
jpa57
61

Katakanlah Anda memiliki komit berikut dalam file teks bernama ~/commits-to-revert.txt(Saya biasa git log --pretty=onelinemendapatkannya)

fe60adeba6436ed8f4cc5f5c0b20df7ac9d93219
0c27ecfdab3cbb08a448659aa61764ad80533a1b
f85007f35a23a7f29fa14b3b47c8b2ef3803d542
e9ec660ba9c06317888f901e3a5ad833d4963283
6a80768d44ccc2107ce410c4e28c7147b382cd8f
9cf6c21f5adfac3732c76c1194bbe6a330fb83e3
fff2336bf8690fbfb2b4890a96549dc58bf548a5
1f7082f3f52880cb49bc37c40531fc478823b4f5
e9b317d36a9d1db88bd34831a32de327244df36a
f6ea0e7208cf22fba17952fb162a01afb26de806
137a681351037a2204f088a8d8f0db6e1f9179ca

Buat skrip Bash shell untuk mengembalikan masing-masing:

#!/bin/bash
cd /path/to/working/copy
for i in `cat ~/commits-to-revert.txt`
do
    git revert $i --no-commit
done

Ini mengembalikan semuanya kembali ke keadaan sebelumnya, termasuk kreasi file dan direktori, dan penghapusan, komit ke cabang Anda dan Anda mempertahankan histori, tetapi Anda mengembalikannya ke struktur file yang sama. Mengapa Git tidak memiliki git revert --to <hash>adalah di luar saya.

Lance Caraccioli
sumber
41
Anda dapat melakukan git revert HEAD~3untuk menghapus 3 komit terakhir
Rod
25
@Rod - Tidak, itu tidak benar. Perintah itu akan mengembalikan komit yang merupakan nenek ketiga dari HEAD (bukan tiga komit terakhir).
Kflorence
1
@ kflorence Ok terima kasih atas informasinya. Akan git revert -n master~3..master~1bekerja (Seperti yang terlihat dari kernel.org/pub/software/scm/git/docs/git-revert.html )
Rod
3
@ Rad - Kedengarannya benar, tentu saja sintaks yang jelek bukan? Saya selalu menemukan memeriksa komit yang ingin saya "kembalikan" ke dan kemudian melakukan itu lebih intuitif.
kflorence
7
Ada cara yang lebih mudah untuk melakukan ini sekarang daripada dengan skrip seperti ini, cukup gunakan git revert --no-commit <start>..<end>, karena git revertmenerima rentang komit dalam versi Git yang baru (atau semua?). Perhatikan bahwa awal rentang tidak termasuk dalam pengembalian.
58

Alternatif Ekstra untuk Solusi Jefromi

Solusi Jefromi jelas yang terbaik, dan Anda harus menggunakannya. Namun, demi kelengkapan, saya juga ingin menunjukkan solusi alternatif lain yang juga dapat digunakan untuk mengembalikan komit (dalam arti bahwa Anda membuat komit baru yang membatalkan perubahan komit sebelumnya , sama seperti apa yang git revertdilakukan).

Agar lebih jelas, alternatif ini bukan cara terbaik untuk mengembalikan komit , solusi Jefromi adalah , tetapi saya hanya ingin menunjukkan bahwa Anda juga dapat menggunakan metode lain ini untuk mencapai hal yang sama git revert.

Alternatif 1: Reset Keras dan Lunak

Ini adalah versi yang sangat sedikit dimodifikasi dari solusi Charles Bailey untuk Kembali ke komit oleh hash SHA di Git? :

# Reset the index to the desired commit
git reset --hard <commit>

# Move the branch pointer back to the previous HEAD
git reset --soft HEAD@{1}

# Commit the changes
git commit -m "Revert to <commit>"

Ini pada dasarnya bekerja dengan menggunakan fakta bahwa soft reset akan meninggalkan status komit sebelumnya yang dipentaskan dalam area indeks / staging, yang kemudian dapat Anda komit.

Alternatif 2: Hapus Pohon Saat Ini dan Ganti dengan yang Baru

Solusi ini berasal dari solusi svick untuk Checkout komit lama dan menjadikannya komit baru :

git rm -r .
git checkout <commit> .
git commit

Demikian pula dengan alternatif # 1, ini mereproduksi keadaan <commit>dalam copy pekerjaan saat ini. Hal ini perlu dilakukan git rmterlebih dahulu karena git checkouttidak akan menghapus file yang telah ditambahkan sejak itu <commit>.

user456814
sumber
Tentang Alternatif 1, satu pertanyaan cepat: Dengan melakukan itu kita tidak kehilangan waktu di antara komitmen, bukan?
Bogac
2
@ Bogac - titik-titik menunjukkan path file, dalam hal ini direktori saat ini, jadi diasumsikan Anda menjalankannya dari root copy pekerjaan Anda.
Tom
Peringatan ini diulang beberapa kali dalam jawaban, tetapi dapatkah seseorang menambahkan mengapa ini bukan cara terbaik - dibandingkan dengan sesuatu seperti git revert HEAD~2..HEADdari solusi terkait @ Cascabel (@ Jefromi). Saya tidak melihat masalahnya.
Joshua Goldberg
55

Berikut adalah cara yang lebih sederhana untuk kembali ke komit sebelumnya (dan membuatnya dalam keadaan tidak terikat, untuk melakukan apa pun yang Anda suka):

git reset HEAD~1

Jadi, tidak perlu untuk melakukan id dan sebagainya :)

Paul Walczewski
sumber
tidak bekerja, tarikan git setelah hasil ini: error: Perubahan lokal Anda ke file berikut akan ditimpa oleh penggabungan:
malhal
1
@malhal Itu karena Anda memiliki perubahan yang tidak dikomit. Simpan / reset mereka dan kemudian akan berfungsi tanpa kesalahan itu.
Paul Walczewski
39

Ada perintah (bukan bagian dari core Git, tetapi ada dalam paket git-extras ) khusus untuk mengembalikan dan mementaskan commit lama:

git back

Per halaman manual , itu juga dapat digunakan seperti:

# Remove the latest three commits
git back 3
Manusia bayangan
sumber
38

Cara terbaik adalah:

git reset --hard <commidId> && git push --force

Ini akan mengatur ulang cabang ke komit tertentu dan kemudian akan mengunggah server jauh dengan komit yang sama seperti yang Anda miliki di lokal (ini akan sepenuhnya menghilangkan perintah setelah komit tertentu)

Hati-hati dengan --forcebendera menghapus semua komit berikutnya setelah komit yang dipilih tanpa opsi untuk memulihkannya.

david.t_92
sumber
3
bekerja seperti pesona!
Gaurav Gupta
Saya downvoted karena saya gagal melihat bagaimana jawaban Anda memberikan informasi baru yang belum diberikan misalnya stackoverflow.com/a/37145089/1723886 , stackoverflow.com/a/27438379/1723886 atau stackoverflow.com/a/48756719/1723886 . Sebenarnya sebagian besar commit sudah menyebutkan git reset --hard, dan banyak lagi yang menyebutkan menggunakan --force atau -f untuk mendorong.
Alex Telon
Ia bekerja hanya dengan satu perintah, jelas dan sederhana. Anda bebas untuk membatalkan jawaban saya jika Anda tidak menyukainya.
david.t_92
1
Opsi lain untuk dipertimbangkan di masa mendatang adalah menyarankan edit pada jawaban sebelumnya atau menambahkan komentar yang mengatakan bahwa 'ini juga dapat dilakukan dalam satu baris dengan menggunakan &&' misalnya. Dengan begitu semua orang dapat melihat jawaban yang ditingkatkan di satu tempat.
Alex Telon
36

Setelah semua perubahan, saat Anda mendorong semua perintah ini, Anda mungkin harus menggunakan:

git push -f ...

Dan tidak hanya itu git push.

sivi
sumber
15
Peringatan Wajib: jangan lakukan ini jika Anda berbagi cabang Anda dengan orang lain yang memiliki salinan komitmen lama, karena menggunakan dorongan gaya seperti ini akan memaksa mereka harus melakukan sinkronisasi ulang pekerjaan mereka. Untuk solusi yang menjelaskan secara rinci cara mengembalikan komit dengan aman tanpa kehilangan pekerjaan dengan dorongan gaya, lihat jawaban ini .
3
Terkadang inilah yang Anda inginkan. Contoh: berkomitmen dan mendorong beberapa komitmen ke cabang yang salah (cabang A). Setelah memetik ceri ke cabang B, saya ingin komit ini dihapus dari cabang A. Saya tidak ingin kembali, karena pengembalian nanti akan diterapkan ketika cabang A dan B digabung menjadi satu. Melakukan reset --dengan <commitId> di cabang A diikuti oleh dorongan paksa menghilangkan komit ini dari cabang sambil melestarikannya di cabang B. Saya bisa lolos dengan ini karena saya tahu tidak ada orang lain yang berkembang di cabang A.
Doug R
Terima kasih! Saya tidak tahu bagaimana cara mendapatkan cabang terpencil agar cocok dengan cabang lokal saya, Hanya perlu melakukan push force.
Mido
32

Anda bisa menyelesaikan semua langkah awal ini sendiri dan mendorong kembali ke repositori Git.

  1. Tarik versi terbaru repositori Anda dari Bitbucket menggunakan git pull --allperintah.

  2. Jalankan perintah Git log dengan -n 4dari terminal Anda. Angka setelah -nmenentukan jumlah komit dalam log mulai dari komit terbaru dalam sejarah lokal Anda.

    $ git log -n 4
    
  3. Setel ulang kepala riwayat repositori Anda menggunakan di git reset --hard HEAD~Nmana N adalah jumlah komit yang ingin Anda ambil kembali. Dalam contoh berikut ini, head akan mengembalikan satu komit, ke komit terakhir dalam riwayat repositori:

  4. Dorong perubahan ke repositori Git menggunakan git push --forceuntuk memaksa mendorong perubahan.

Jika Anda ingin repositori Git melakukan commit sebelumnya:

git pull --all
git reset --hard HEAD~1
git push --force
Nanhe Kumar
sumber
30

Kembalikan ke komit terbaru dan abaikan semua perubahan lokal:

git reset --hard HEAD
Mohammed Irfan Tirupattur
sumber
28

Pilih komit yang diperlukan Anda, dan periksa dengan

git show HEAD
git show HEAD~1
git show HEAD~2 

sampai Anda mendapatkan komit yang diperlukan. Untuk membuat KEPALA menunjukkan hal itu, lakukan

git reset --hard HEAD~1

atau git reset --hard HEAD~2atau apalah.

tonythomas01
sumber
7
Peringatan Wajib: jangan lakukan ini jika Anda membagikan cabang Anda dengan orang lain yang memiliki salinan dari komitmen lama, karena menggunakan hard reset seperti ini akan memaksa mereka harus menyinkronkan kembali pekerjaan mereka dengan cabang yang baru reset. Untuk solusi yang menjelaskan secara rinci cara mengembalikan komit dengan aman tanpa kehilangan pekerjaan dengan pengaturan ulang yang sulit, lihat jawaban ini .
2
Juga, harus jelas, git show HEADsetara dengan hanya menggunakan git log HEAD -1.
25

Jika situasinya mendesak , dan Anda hanya ingin melakukan apa yang diminta penanya dengan cepat dan kotor , anggap proyek Anda berada di bawah direktori yang disebut, misalnya, "proyek saya":


CEPAT DAN KOTOR : tergantung pada keadaan, cepat dan kotor mungkin sebenarnya sangat BAIK. Apa solusi saya di sini adalah TIDAK mengganti file yang Anda miliki dalam direktori kerja dengan file yang ditarik / diekstraksi dari kedalaman repositori git yang bersembunyi di bawah direktori .git / Anda menggunakan perintah git yang sangat pintar dan sangat kuat, di antaranya ada banyak. ANDA TIDAK HARUS MELAKUKAN PENYIMPANAN TERSEBUT TERSEBUT DI LAUT UNTUK MEMULIHKAN apa yang kelihatannya merupakan situasi bencana, dan upaya untuk melakukannya tanpa keahlian yang memadai dapat berakibat fatal .


  1. Salin seluruh direktori dan sebut itu sesuatu yang lain, seperti "proyek saya - salin". Dengan asumsi file repositori git Anda ("repo") berada di bawah direktori "proyek saya" (tempat default untuk mereka, di bawah direktori yang disebut ".git"), Anda sekarang akan menyalin file kerja dan file repo Anda.

  2. Lakukan ini di direktori "proyek saya":

    .../my project $ git reset --hard [first-4-letters&numbers-of-commit's-SHA]
    

Ini akan mengembalikan status repo di bawah "proyek saya" ke keadaan semula ketika Anda membuat komit ("komit" berarti snapshot dari file Anda yang sedang bekerja). Semua komitmen sejak saat itu akan hilang selamanya di bawah "proyek saya", TAPI ... mereka masih akan ada dalam repo di bawah "proyek saya - salin" karena Anda menyalin semua file - termasuk yang ada di ... /. Git /.

Anda kemudian memiliki dua versi di sistem Anda ... Anda dapat memeriksa atau menyalin atau memodifikasi file yang menarik, atau apa pun, dari komit sebelumnya. Anda dapat benar-benar membuang file di bawah "proyek saya - salin", jika Anda telah memutuskan pekerjaan baru sejak komit yang dipulihkan tidak akan kemana-mana ...

Hal yang jelas jika Anda ingin melanjutkan dengan keadaan proyek tanpa benar-benar membuang pekerjaan karena komit yang diambil ini adalah mengubah nama direktori Anda lagi: Hapus proyek yang mengandung komit yang diambil (atau berikan nama sementara) dan ganti nama Anda " proyek saya - salin "direktori kembali ke" proyek saya ". Maka mungkin cobalah untuk memahami beberapa jawaban lain di sini, dan mungkin melakukan komitmen lain dengan segera.

Git adalah ciptaan yang brilian tetapi sama sekali tidak ada yang bisa "mengambilnya dengan cepat": juga orang yang mencoba menjelaskannya terlalu sering mengasumsikan pengetahuan sebelumnya tentang VCS [Sistem Kontrol Versi] lainnya dan menggali terlalu jauh ke dalam terlalu cepat, dan melakukan kejahatan lain, seperti menggunakan istilah yang dapat dipertukarkan untuk "memeriksa" - dengan cara yang kadang-kadang tampak hampir diperhitungkan untuk membingungkan pemula.

Untuk menghemat banyak stres, belajarlah dari bekas luka saya. Anda harus membaca buku tentang Git - saya akan merekomendasikan "Kontrol Versi dengan Git" . Lakukan lebih cepat daripada nanti. Jika ya, ingatlah bahwa banyak kerumitan Git berasal dari percabangan dan kemudian dibuat ulang: Anda dapat melewati bagian-bagian itu di buku mana pun. Dari pertanyaan Anda, tidak ada alasan mengapa orang harus membutakan Anda dengan sains .

Terutama jika, misalnya, ini adalah situasi yang menyedihkan dan Anda seorang pemula dengan Git!

PS: Satu pemikiran lain: Ini (sekarang) sebenarnya cukup sederhana untuk menyimpan repo Git di direktori selain dari yang memiliki file yang berfungsi. Ini berarti Anda tidak perlu menyalin seluruh repositori Git menggunakan solusi cepat & kotor di atas. Lihat jawabannya oleh Fryer gunakan di --separate-git-dir sini . Namun, berhati-hatilah : Jika Anda memiliki repositori "direktori terpisah" yang tidak Anda salin, dan Anda melakukan hard reset, semua versi setelah commit reset akan hilang selamanya, kecuali jika Anda memiliki, seperti yang seharusnya, secara teratur mencadangkan repositori Anda, lebih disukai ke Cloud (mis. Google Drive ) di antara tempat-tempat lain.

Mengenai masalah "mencadangkan ke Cloud", langkah selanjutnya adalah membuka akun (gratis tentu saja) dengan GitHub atau (lebih baik dalam pandangan saya) GitLab . Anda kemudian dapat secara teratur melakukan git pushperintah untuk membuat repo Cloud Anda mutakhir "dengan benar". Tetapi sekali lagi, membicarakan hal ini mungkin terlalu cepat.

mike rodent
sumber
23

Ini adalah satu lagi cara untuk mengatur ulang secara langsung ke komit terbaru

git stash
git stash clear

Itu secara langsung menghapus semua perubahan yang telah Anda buat sejak komit terakhir.

PS: Ada sedikit masalah; itu juga menghapus semua perubahan simpanan Anda yang baru disimpan. Yang saya kira dalam banyak kasus seharusnya tidak masalah.

Point Networks
sumber
CATATAN: File baru yang tidak ditambahkan dalam indeks tidak disimpan. Anda telah menambahkan atau menghapusnya secara manual.
andreyro
Kenapa oh mengapa membersihkan simpanan? Selain menjadi non-solusi, ini sebenarnya berbahaya. Membaca kalimat pertama dari pertanyaan segera membatalkan solusi simpanan (yang HANYA berguna untuk mereset ke komit TERAKHIR).
RomainValeri
22

Untuk benar-benar membersihkan direktori pembuat kode dari beberapa perubahan yang tidak disengaja, kami menggunakan:

git add -A .
git reset --hard HEAD

Hanya git reset --hard HEADakan menghilangkan modifikasi, tetapi itu tidak akan menyingkirkan file "baru". Dalam kasus mereka, mereka secara tidak sengaja menyeret folder penting di suatu tempat secara acak, dan semua file itu diperlakukan sebagai baru oleh Git, jadi file reset --hardtidak memperbaikinya. Dengan menjalankan git add -A .sebelumnya, ia secara eksplisit melacak mereka semua dengan git, untuk dihapus oleh reset.

Chris Moschini
sumber
21

Untuk menjaga perubahan dari komit sebelumnya ke HEAD dan pindah ke komit sebelumnya, lakukan:

git reset <SHA>

Jika perubahan tidak diperlukan dari komit sebelumnya ke HEAD dan buang semua perubahan, lakukan:

git reset --hard <SHA>
Wisnu Atrai
sumber
20

Saya percaya beberapa orang mungkin datang ke pertanyaan ini ingin tahu bagaimana mengembalikan perubahan yang dilakukan pada tuannya - yaitu membuang semuanya dan kembali ke asal / master, dalam hal ini, lakukan ini:

git reset --hard origin/master

/superuser/273172/how-to-reset-master-to-origin-master

nevster
sumber
18

Kembalikan adalah perintah untuk mengembalikan komit.

git revert <commit1> <commit2> 

Sampel:

git revert 2h3h23233

Itu mampu mengambil jarak dari KEPALA seperti di bawah ini. Di sini saya mengatakan "kembalikan komit terakhir."

git revert HEAD~1..HEAD

dan kemudian lakukan git push

Sireesh Yarlagadda
sumber
14

Cobalah mengatur ulang ke komit yang diinginkan -

git reset <COMMIT_ID>

(untuk memeriksa penggunaan COMMIT_ID git log)

Ini akan mengatur ulang semua file yang diubah ke status tidak ditambahkan.

Sekarang Anda dapat checkoutmenghapus semua file dengan

git checkout .

Periksa git loguntuk memverifikasi perubahan Anda.

MEMPERBARUI

Jika Anda memiliki satu dan hanya komit di repo Anda, cobalah

git update-ref -d HEAD

optimistanoop
sumber
13

Saat komit Anda didorong dari jarak jauh, Anda harus menghapusnya. Biarkan saya menganggap cabang Anda berkembang dan didorong asal .

Anda harus terlebih dahulu menghapus pengembangan dari asal :

git push origin :develop (note the colon)

Maka Anda perlu mengembangkan ke status yang Anda inginkan, izinkan saya menganggap hash komit adalah EFGHIJK:

git reset --hard EFGHIJK

Terakhir, dorong berkembang lagi:

git push origin develop
George Ninan
sumber
13

Peringatan! Perintah ini dapat menyebabkan hilangnya komit, jika pengguna salah memasukkan komit. Selalu miliki cadangan ekstra git Anda di tempat lain untuk berjaga-jaga jika Anda melakukan kesalahan, daripada Anda sedikit lebih aman. :)

Saya memiliki masalah serupa dan ingin kembali ke komit sebelumnya. Dalam kasus saya, saya tidak tertarik untuk menyimpan komit yang lebih baru, maka saya gunakan Hard.

Beginilah cara saya melakukannya:

git reset --hard CommitId && git clean -f

Ini akan kembali ke repositori lokal, dan di sini setelah menggunakan git push -fakan memperbarui repositori jarak jauh.

git push -f
maytham-ɯɐɥʇʎɐɯ
sumber
13

Di GitKraken Anda dapat melakukan ini:

  1. Klik kanan pada komit yang ingin Anda reset, pilih: Reset ke komit ini / Hard :

    Masukkan deskripsi gambar di sini

  2. Klik kanan pada komit lagi, pilih: Nama cabang saat ini / Push :

    Masukkan deskripsi gambar di sini

  3. Klik pada Push Angkatan :

    Masukkan deskripsi gambar di sini

Obs. : Anda harus berhati-hati, karena semua riwayat komit setelah hard reset hilang dan tindakan ini tidak dapat dibatalkan. Anda harus yakin apa yang Anda lakukan.

Polo Ângelo
sumber
11

Jika Anda ingin memperbaiki beberapa kesalahan pada komit terakhir, alternatif yang baik akan menggunakan perintah git commit --amend . Jika komit terakhir tidak diarahkan oleh referensi, ini akan melakukan trik, karena membuat komit dengan induk yang sama dengan komit terakhir. Jika tidak ada referensi ke komit terakhir, komis tersebut akan dibuang dan komit ini akan menjadi komit terakhir. Ini adalah cara yang baik untuk mengoreksi komitmen tanpa mengembalikan komitmen. Namun memiliki keterbatasan sendiri.

Upul Doluweera
sumber