Saya memiliki repositori git yang terlihat seperti ini:
A -> B -> C -> D -> HEAD
Saya ingin kepala cabang menunjuk ke A, yaitu saya ingin B, C, D, dan HEAD menghilang dan saya ingin kepala bersinonim dengan A.
Sepertinya saya bisa mencoba rebase (tidak berlaku, karena saya sudah mendorong perubahan di antaranya), atau kembali. Tetapi bagaimana cara mengembalikan beberapa komitmen? Apakah saya mengembalikan satu per satu? Apakah urutannya penting?
git
commit
git-revert
Tagihan
sumber
sumber
git push -f HEAD~4:master
(dengan anggapan cabang remote adalah master). Ya, Anda dapat mendorong komit seperti itu.git revert
.Jawaban:
Memperluas apa yang saya tulis dalam komentar
Aturan umum adalah bahwa Anda tidak boleh menulis ulang (mengubah) sejarah yang telah Anda terbitkan, karena seseorang mungkin telah mendasari pekerjaan mereka di atasnya. Jika Anda menulis ulang (mengubah) riwayat, Anda akan membuat masalah dengan menggabungkan perubahan mereka dan dengan memperbarui untuk mereka.
Jadi solusinya adalah untuk membuat komit baru yang muallaf perubahan yang Anda ingin menyingkirkan. Anda dapat melakukan ini menggunakan perintah git revert .
Anda memiliki situasi berikut:
(panah di sini merujuk ke arah penunjuk: referensi "induk" dalam kasus komit, komit atas dalam kasus kepala cabang (cabang ref), dan nama cabang dalam kasus referensi KEPALA).
Yang perlu Anda buat adalah sebagai berikut:
di mana "[(BCD) ^ - 1]" berarti komit yang mengembalikan perubahan dalam komit B, C, D. Matematika memberi tahu kita bahwa (BCD) ^ - 1 = D ^ -1 C ^ -1 B ^ -1, jadi Anda bisa mendapatkan situasi yang diperlukan menggunakan perintah berikut:
Solusi alternatif adalah dengan checkout konten dari commit A, dan komit pada kondisi ini:
Maka Anda akan memiliki situasi berikut:
Komit A 'memiliki konten yang sama dengan komit A, tetapi komit berbeda (pesan komit, orang tua, tanggal komit).
The solusi dengan Jeff Ferland, dimodifikasi oleh Charles Bailey dibangun berdasarkan ide yang sama, tetapi menggunakan ulang git :
sumber
git checkout -f A -- .
Tidak akan menghapus ini, Anda harus melakukannya secara manual. Saya menerapkan strategi ini sekarang, terima kasih Jakubgit checkout foo
mungkin berarti cabang checkoutfoo
(beralih ke cabang) atau checkout file foo (dari indeks).--
digunakan untuk disambiguasi, misalnyagit checkout -- foo
selalu tentang file.git revert --no-commit D C B
git revert
ini tidak menerima banyak komitmen; itu adalah tambahan yang cukup baru.Cara bersih yang menurut saya berguna
Perintah ini mengembalikan 3 commit terakhir dengan hanya satu commit.
Juga tidak menulis ulang sejarah.
sumber
git commit
dari sana benar-benar akan melakukan komit.HEAD~3..
sama denganHEAD~3..HEAD
Untuk melakukannya, Anda hanya perlu menggunakan perintah revert , menentukan rentang komit yang ingin Anda pulihkan .
Mempertimbangkan contoh Anda, Anda harus melakukan ini (dengan asumsi Anda menggunakan 'master' cabang):
Ini akan membuat komit baru di lokal Anda dengan komit terbalik B, C dan D (artinya akan membatalkan perubahan yang dilakukan oleh komit ini):
sumber
git revert --no-commit HEAD~2..
adalah cara yang sedikit lebih idiomatis untuk melakukannya. Jika Anda berada di cabang master, tidak perlu menentukan master lagi. The--no-commit
pilihan memungkinkan git mencoba untuk kembali semua komit sekaligus, bukan mengotori sejarah dengan beberaparevert commit ...
pesan (dengan asumsi bahwa ini apa yang Anda inginkan).master~3
.--no-commit
(jadi Anda mendapatkan komit terpisah untuk setiap pengembalian), dan kemudian hancurkan semuanya bersama dalam rebase interaktif. Pesan komit gabungan akan berisi semua SHA, dan Anda dapat mengaturnya sesuka Anda menggunakan editor pesan komit Anda.Mirip dengan jawaban Jakub, ini memungkinkan Anda untuk dengan mudah memilih komit berturut-turut untuk dikembalikan.
sumber
B^..HEAD
, kalau tidak B dikecualikan.git revert --no-commit B^..HEAD
ataugit revert --no-commit A..HEAD
Itu akan bertindak sebagai pengembalian bagi mereka semua sekaligus. Berikan pesan komit yang baik.
sumber
HEAD
terlihat sepertiA
maka dia mungkin ingin indeks cocok jadigit reset --soft D
mungkin lebih tepat.git checkout A
kemudian digit commit
atas tidak bekerja untuk saya, tetapi jawaban ini berhasil.git reset --mixed D
diperlukan? Khususnya mengapareset
? Apakah karena, tanpa mengatur ulang ke D, itu, KEPALA akan menunjuk ke A, menyebabkan B, C, dan D menjadi "menggantung" dan mengumpulkan sampah - yang bukan yang ia inginkan? Tapi mengapa--mixed
? Anda sudah menjawab "--soft
mengatur ulang tidak memindahkan indeks ..." Jadi dengan memindahkan indeks, ini berarti indeks akan berisi perubahan D, sedangkan Direktori Kerja akan berisi perubahan A - dengan cara ini agit status
ataugit diff
(yang membandingkan Indeks [D] ke Direktori Kerja [A]) akan menunjukkan substansi; pengguna yang pergi dari D kembali ke A?Pertama-tama pastikan bahwa copy pekerjaan Anda tidak diubah. Kemudian:
dan kemudian lakukan saja. Jangan lupa untuk mendokumentasikan apa alasan untuk kembali.
sumber
error: cannot apply binary patch to 'some/image.png' without full index line error: some/image.png: patch does not apply
git diff --binary HEAD commit_sha_you_want_to_revert_to | git apply
git revert A..Z
Anda akan mendapatkanerror: commit X is a merge but no -m option was given.
Saya sangat frustrasi karena pertanyaan ini tidak bisa dijawab begitu saja. Setiap pertanyaan lain terkait dengan bagaimana memulihkan dengan benar dan menjaga sejarah. Pertanyaan ini mengatakan, "Saya ingin kepala cabang menunjuk ke A, yaitu saya ingin B, C, D, dan HEAD menghilang dan saya ingin kepala bersinonim dengan A."
Saya belajar banyak membaca posting Jakub, tetapi beberapa orang di perusahaan (dengan akses untuk mendorong ke cabang "pengujian" kami tanpa Pull-Request) mendorong seperti 5 komitmen buruk yang mencoba untuk memperbaiki dan memperbaiki dan memperbaiki kesalahan yang ia buat 5 komit yang lalu. Bukan hanya itu, tetapi satu atau dua Permintaan Tarik diterima, yang sekarang buruk. Jadi lupakan saja, saya menemukan good commit terakhir (abc1234) dan baru saja menjalankan skrip dasar:
Saya mengatakan kepada 5 orang lain yang bekerja di repo ini bahwa mereka lebih baik membuat catatan tentang perubahan mereka selama beberapa jam terakhir dan Hapus / Re-Cabang dari pengujian terbaru. Akhir cerita.
sumber
git push --force-with-lease
, yang akan menulis ulang sejarah hanya jika tidak ada orang lain yang berkomitmen untuk cabang setelah atau dalam kisaran komitmen untuk menguap. Jika orang lain telah menggunakan cabang, maka sejarahnya seharusnya tidak pernah ditulis ulang, dan komit harus secara sederhana dikembalikan.Ini adalah perluasan dari salah satu solusi yang disediakan dalam jawaban Jakub
Saya dihadapkan dengan situasi di mana komit yang saya butuhkan untuk mundur agak rumit, dengan beberapa komit digabung komit, dan saya perlu menghindari penulisan ulang sejarah. Saya tidak dapat menggunakan serangkaian
git revert
perintah karena saya akhirnya mengalami konflik antara perubahan pengembalian yang ditambahkan. Saya akhirnya menggunakan langkah-langkah berikut.Pertama, periksa isi komit target sambil meninggalkan KEPALA di ujung cabang:
(The - memastikan
<target-commit>
ditafsirkan sebagai komit daripada file;. Yang merujuk ke direktori saat ini.)Kemudian, tentukan file apa yang ditambahkan dalam komit yang sedang diputar kembali, dan dengan demikian perlu dihapus:
File yang ditambahkan harus muncul dengan "A" di awal baris, dan seharusnya tidak ada perbedaan lainnya. Sekarang, jika ada file yang perlu dihapus, tahap file ini untuk dihapus:
Akhirnya, lakukan pengembalian:
Jika diinginkan, pastikan kita kembali ke kondisi yang diinginkan:
Seharusnya tidak ada perbedaan.
sumber
git
KEPALA hanya dengan ujung cabang?Cara mudah untuk mengembalikan sekelompok komit pada repositori bersama (yang digunakan orang dan Anda ingin melestarikan sejarah) adalah menggunakan
git revert
bersama dengan gitrev-list
. Yang terakhir akan memberi Anda daftar komitmen, yang pertama akan melakukan pengembalian itu sendiri.Ada dua cara untuk melakukan itu. Jika Anda ingin mengembalikan beberapa komit dalam penggunaan komit tunggal:
ini akan mengembalikan sekelompok komit yang Anda butuhkan, tetapi tinggalkan semua perubahan pada pohon kerja Anda, Anda harus mengkomit semuanya seperti biasa.
Pilihan lain adalah memiliki satu komit per perubahan yang dikembalikan:
Misalnya, jika Anda memiliki pohon komit suka
untuk mengembalikan perubahan dari eee ke bbb , jalankan
sumber
Tidak satu pun dari mereka yang bekerja untuk saya, jadi saya punya tiga komitmen untuk kembali (tiga komitmen terakhir), jadi saya melakukannya:
Bekerja seperti pesona :)
sumber
Menurut saya cara yang sangat mudah dan bersih adalah:
kembali ke A
arahkan kepala master ke kondisi saat ini
menyimpan
sumber
git checkout master; git reset --hard A
? Atau jika tidak, bisakah Anda menjelaskan sedikit lebih banyak tentang apa ini?Jika Anda ingin sementara mengembalikan komit fitur, maka Anda dapat menggunakan serangkaian perintah berikut.
Inilah cara kerjanya
git log --pretty = oneline | grep 'feature_name' | cut -d '' -f1 | xargs -n1 git revert --no-edit
sumber