Saya sedang bekerja dengan seorang teman di sebuah proyek, dan dia mengedit banyak file yang seharusnya tidak diedit. Entah bagaimana aku menggabungkan karyanya menjadi milikku, baik ketika aku menariknya, atau ketika aku mencoba untuk hanya mengambil file tertentu yang aku inginkan. Saya sudah mencari dan bermain untuk waktu yang lama, mencoba mencari cara untuk menghapus komit yang berisi pengeditan ke file-file itu, tampaknya menjadi lemparan antara revert dan rebase, dan tidak ada contoh langsung, dan dokter menganggap saya tahu lebih banyak daripada saya.
Jadi, inilah versi pertanyaan yang disederhanakan:
Dengan skenario berikut, bagaimana cara menghapus commit 2?
$ mkdir git_revert_test && cd git_revert_test
$ git init
Initialized empty Git repository in /Users/josh/deleteme/git_revert_test/.git/
$ echo "line 1" > myfile
$ git add -A
$ git commit -m "commit 1"
[master (root-commit) 8230fa3] commit 1
1 files changed, 1 insertions(+), 0 deletions(-)
create mode 100644 myfile
$ echo "line 2" >> myfile
$ git commit -am "commit 2"
[master 342f9bb] commit 2
1 files changed, 1 insertions(+), 0 deletions(-)
$ echo "line 3" >> myfile
$ git commit -am "commit 3"
[master 1bcb872] commit 3
1 files changed, 1 insertions(+), 0 deletions(-)
Hasil yang diharapkan adalah
$ cat myfile
line 1
line 3
Berikut ini adalah contoh bagaimana saya telah berusaha untuk mengembalikan
$ git revert 342f9bb
Automatic revert failed. After resolving the conflicts,
mark the corrected paths with 'git add <paths>' or 'git rm <paths>'
and commit the result.
sumber
Jawaban:
Algoritma yang digunakan Git ketika menghitung diff untuk dikembalikan memerlukannya
Definisi "berdekatan" didasarkan pada jumlah garis default dari perbedaan konteks, yaitu 3. Jadi jika 'myfile' dibuat seperti ini:
Kemudian semuanya bekerja seperti yang diharapkan.
Jawaban kedua sangat menarik. Ada fitur yang belum dirilis secara resmi (meskipun tersedia di Git v1.7.2-rc2) yang disebut Strategi Kembalikan. Anda dapat memanggil git seperti ini:
dan itu harus melakukan pekerjaan yang lebih baik mencari tahu apa yang Anda maksudkan. Saya tidak tahu apa daftar strategi yang tersedia, dan saya juga tidak tahu definisi strategi apa pun.
sumber
perl -p
berguna untuk menulis program yang sangat pendek (satu baris) yang loop dan meneruskan input mereka ke output, mirip dengan sed.perl -i
digunakan untuk mengedit file di tempat .perl -e
adalah cara mengirim kode yang akan dievaluasi .Ada empat cara untuk melakukannya:
Bersihkan cara, kembali tetapi tetap log revert:
Cara kasar, hapus semuanya hanya komit terakhir:
Catatan: Hindari
git reset --hard
karena ini juga akan membuang semua perubahan dalam file sejak komit terakhir. Jika--soft
tidak berhasil, lebih baik coba--mixed
atau--keep
.Rebase (tampilkan log dari 5 commit terakhir dan hapus baris yang tidak Anda inginkan, atur ulang, atau remas beberapa commit dalam satu komit, atau lakukan apa pun yang Anda inginkan, ini adalah alat yang sangat serbaguna):
Dan jika ada kesalahan:
Rebase cepat: hapus hanya komit tertentu menggunakan id:
Alternatif: Anda juga dapat mencoba:
Alternatif lain:
Sebagai upaya terakhir, jika Anda membutuhkan kebebasan penuh untuk mengedit riwayat (misalnya, karena git tidak mengizinkan Anda untuk mengedit apa yang Anda inginkan), Anda dapat menggunakan aplikasi open source yang sangat cepat ini : reposurgeon .
Catatan: tentu saja, semua perubahan ini dilakukan secara lokal,
git push
setelah itu Anda harus menerapkan perubahan ke remote. Dan jika repo Anda tidak ingin menghapus komit ("tidak diizinkan maju cepat", yang terjadi ketika Anda ingin menghapus komit yang sudah Andagit push -f
tekan ), Anda dapat menggunakan untuk memaksa mendorong perubahan.Note2: jika bekerja pada cabang dan Anda perlu mendorong, Anda harus benar-benar menghindari
git push --force
karena ini dapat menimpa cabang lain (jika Anda telah membuat perubahan di dalamnya, bahkan jika checkout Anda saat ini di cabang lain). Lebih memilih untuk selalu menentukan cabang terpencil ketika Anda memaksa mendorong :git push --force origin your_branch
.sumber
git rebase -i HEAD~5
bekerja untukku. Kemudian saya hanya menghapus komit yang tidak saya butuhkan dan saya bisa menyelesaikan masalah dalam waktu kurang dari 30 detik. Terima kasih.Ini adalah solusi mudah:
(Catatan:
x
adalah jumlah komit)setelah mengeksekusi file notepad akan terbuka. Masukkan
drop
selain komit Anda.Jika Anda tidak tahu Vim, cukup klik pada setiap kata yang ingin Anda edit lalu tekan tombol "I" (untuk mode penyisipan). Setelah selesai mengetik, tekan tombol "esc" untuk keluar dari mode penyisipan.
dan itu saja, Anda sudah selesai ... Cukup sinkronisasi dashboard git dan perubahan akan didorong ke jarak jauh.
Jika komit yang Anda jatuhkan sudah ada di remote, Anda harus memaksakan dorongan. Karena --force dianggap berbahaya , gunakan
git push --force-with-lease
.sumber
Pilihan Anda ada di antara
Anda harus memilih (1) jika perubahan yang salah telah diambil oleh orang lain dan (2) jika kesalahan terbatas pada cabang pribadi yang tidak didorong.
Git revert adalah alat otomatis untuk melakukan (1), itu membuat komit baru membatalkan beberapa komit sebelumnya. Anda akan melihat kesalahan dan penghapusan dalam riwayat proyek tetapi orang-orang yang menarik dari repositori Anda tidak akan mengalami masalah ketika mereka memperbarui. Ini tidak berfungsi secara otomatis dalam contoh Anda sehingga Anda perlu mengedit 'myfile' (untuk menghapus baris 2), lakukan
git add myfile
dangit commit
untuk menangani konflik. Anda kemudian akan berakhir dengan empat komit dalam riwayat Anda, dengan komit 4 reverting komit 2.Jika tidak ada yang peduli bahwa riwayat Anda berubah, Anda dapat menulis ulang dan menghapus komit 2 (pilihan 2). Cara mudah untuk melakukannya adalah menggunakan
git rebase -i 8230fa3
. Ini akan membuat Anda menjadi editor dan Anda dapat memilih untuk tidak memasukkan komit yang salah dengan menghapus komit (dan menyimpan "pilih" di sebelah pesan komit lainnya. Bacalah tentang konsekuensi dari melakukan ini .sumber
Approch 1
Pertama dapatkan hash komit (mis: 1406cd61) yang harus Anda kembalikan. perbaikan sederhana akan di bawah perintah,
jika Anda telah melakukan lebih banyak perubahan terkait dengan 1406cd61 file setelah 1406cd61 komit, perintah sederhana di atas tidak akan berfungsi. Maka Anda harus melakukan langkah-langkah di bawah ini, yaitu memetik ceri.
Approch 2
Silakan ikuti langkah tindakan berikut, Karena kami menggunakan - memaksa Anda harus memiliki hak admin atas repo git untuk melakukan ini.
Langkah 1: Temukan komit sebelum komit yang ingin Anda hapus
git log
Langkah 2: Periksa komit itu
git checkout <commit hash>
Langkah 3: Buat cabang baru menggunakan komit checkout Anda saat ini
git checkout -b <new branch>
Langkah 4: Sekarang Anda perlu menambahkan komit setelah komit dihapus
git cherry-pick <commit hash>
Langkah 5: Sekarang ulangi Langkah 4 untuk semua komitmen lain yang ingin Anda pertahankan.
Langkah 6: Setelah semua komitmen ditambahkan ke cabang baru Anda dan telah dilakukan. Periksa apakah semuanya dalam kondisi yang benar dan berfungsi sebagaimana mestinya. Periksa kembali semuanya telah dilakukan:
git status
Langkah 7: Beralih ke cabang Anda yang rusak
git checkout <broken branch>
Langkah 8: Sekarang lakukan hard reset pada cabang yang rusak ke komit sebelum yang ingin Anda hapus
git reset --hard <commit hash>
Langkah 9: Gabungkan cabang tetap Anda ke cabang ini
git merge <branch name>
Langkah 10: Dorong perubahan yang digabungkan kembali ke asal. PERINGATAN: Ini akan menimpa repo jarak jauh!
git push --force origin <branch name>
Anda dapat melakukan proses tanpa membuat cabang baru dengan mengganti Langkah 2 & 3 dengan Langkah 8 kemudian tidak menjalankan Langkah 7 & 9.
sumber
Anda dapat menghapus komitmen yang tidak diinginkan dengan
git rebase
. Katakanlah Anda menyertakan beberapa komitmen dari cabang topik rekan kerja ke cabang topik Anda, tetapi kemudian putuskan bahwa Anda tidak ingin komitmen tersebut.Pada titik ini editor teks Anda akan membuka tampilan rebase interaktif. Sebagai contoh
Jika rebase tidak berhasil, hapus cabang sementara dan coba strategi lain. Kalau tidak, lanjutkan dengan instruksi berikut.
Jika Anda mendorong cabang topik Anda ke jarak jauh, Anda mungkin perlu memaksa push karena histori komit telah berubah. Jika orang lain bekerja di cabang yang sama, beri mereka kepala.
sumber
Dari jawaban lain di sini, saya agak bingung dengan bagaimana
git rebase -i
bisa digunakan untuk menghapus komit, jadi saya harap tidak apa-apa untuk menuliskan test case saya di sini (sangat mirip dengan OP).Berikut ini adalah
bash
skrip yang dapat Anda tempel untuk membuat repositori tes di/tmp
folder:Pada titik ini, kami memiliki
file.txt
konten berikut:Pada titik ini, KEPALA berada pada komit ke-5, KEPALA ~ 1 akan menjadi ke-4 - dan KEPALA ~ 4 akan menjadi komit ke-1 (jadi KEPALA ~ 5 tidak akan ada). Katakanlah kita ingin menghapus komit ke-3 - kita dapat mengeluarkan perintah ini di
myrepo_git
direktori:( Perhatikan bahwa
git rebase -i HEAD~5
hasil dengan "fatal: Membutuhkan satu revisi; HEAD hulu tidak valid ~ 5". ) Editor teks (lihat tangkapan layar di jawaban @Dennis ' ) akan terbuka dengan konten ini:Jadi kami mendapatkan semua komitmen sejak (tetapi tidak termasuk ) KEPALA yang kami minta ~ 4. Hapus baris
pick 448c212 3rd git commit
dan simpan file; Anda akan mendapatkan respons ini darigit rebase
:Pada titik ini buka myrepo_git /
folder/file.txt
dalam editor teks; Anda akan melihatnya telah dimodifikasi:Pada dasarnya,
git
melihat bahwa ketika KEPALA sampai komit ke-2, ada kontenaaaa
+bbbb
; dan kemudian ia memiliki patchcccc
+dddd
yang ditambahkan yang tidak tahu cara menambahkan ke konten yang ada.Jadi di sini
git
tidak dapat memutuskan untuk Anda - Anda yang harus membuat keputusan: dengan menghapus komit ke-3, Anda tetap menyimpan perubahan yang diperkenalkan olehnya (di sini, bariscccc
) - atau Anda tidak. Jika tidak, cukup hapus baris tambahan - termasukcccc
- dalamfolder/file.txt
menggunakan editor teks, sehingga terlihat seperti ini:... lalu simpan
folder/file.txt
. Sekarang Anda dapat mengeluarkan perintah berikut dalammyrepo_git
direktori:Ah - sehingga untuk tanda bahwa kita sudah memecahkan konflik, kita harus
git add
yangfolder/file.txt
, sebelum melakukangit rebase --continue
:Di sini editor teks terbuka lagi, menunjukkan baris
4th git commit
- di sini kita memiliki kesempatan untuk mengubah pesan komit (yang dalam hal ini dapat diubah secara bermakna4th (and removed 3rd) commit
atau serupa). Katakanlah Anda tidak ingin - jadi keluar saja dari editor teks tanpa menyimpan; setelah Anda melakukannya, Anda akan mendapatkan:Pada titik ini, sekarang Anda memiliki riwayat seperti ini (yang juga dapat Anda periksa dengan say
gitk .
atau alat lain) dari isifolder/file.txt
(dengan, tampaknya, stempel waktu yang tidak berubah dari komitmen asli):Dan jika sebelumnya, kami memutuskan untuk mempertahankan garis
cccc
(isi dari komit ke-3 yang kami hapus), kami akan memiliki:Nah, ini adalah jenis bacaan yang saya harap akan saya temukan, untuk mulai mempelajari cara
git rebase
kerjanya dalam menghapus komitmen / revisi; jadi harap itu bisa membantu orang lain juga ...sumber
Jadi sepertinya komit buruk dimasukkan dalam komit gabungan di beberapa titik. Sudahkah gabungan komit Anda ditarik? Jika ya, maka Anda ingin menggunakannya
git revert
; Anda harus mengertakkan gigi dan mengatasi konflik. Jika tidak, maka Anda bisa melakukan rebase atau memulihkan, tetapi Anda bisa melakukannya sebelum penggabungan berkomitmen, lalu ulangi penggabungan tersebut.Tidak banyak bantuan yang bisa kami berikan untuk kasus pertama, sungguh. Setelah mencoba mengembalikan, dan menemukan bahwa yang otomatis gagal, Anda harus memeriksa konflik dan memperbaikinya dengan tepat. Ini persis proses yang sama dengan memperbaiki konflik gabungan; Anda dapat menggunakan
git status
untuk melihat di mana konflik berada, mengedit file yang tidak di-unmerged, menemukan bakhil yang berkonflik, mencari cara untuk menyelesaikannya, menambahkan file yang berkonflik, dan akhirnya melakukan. Jika Anda menggunakangit commit
dengan sendirinya (tidak-m <message>
), pesan yang muncul di editor Anda harus berupa pesan templat yang dibuat olehgit revert
; Anda dapat menambahkan catatan tentang bagaimana Anda memperbaiki konflik, lalu menyimpan dan berhenti untuk melakukan.Untuk kasus kedua, memperbaiki masalah sebelum penggabungan Anda, ada dua sub-bagian, tergantung pada apakah Anda telah melakukan lebih banyak pekerjaan sejak penggabungan. Jika belum, Anda bisa langsung
git reset --hard HEAD^
menghapus penggabungan, melakukan pengembalian, lalu mengulangi penggabungan. Tapi saya rasa Anda punya. Jadi, Anda akhirnya akan melakukan sesuatu seperti ini:git rebase -i <something before the bad commit> <temporary branch>
untuk menghapus komit buruk)git rebase --onto <temporary branch> <old merge commit> <real branch>
sumber
Jadi Anda melakukan beberapa pekerjaan dan mendorongnya, mari kita sebut mereka melakukan A dan B. Rekan kerja Anda melakukan beberapa pekerjaan juga, melakukan C dan D. Anda menggabungkan kerja rekan kerja Anda ke dalam Anda (menggabungkan komit E), kemudian terus bekerja, melakukan itu, juga (melakukan F), dan menemukan bahwa rekan kerja Anda mengubah beberapa hal yang seharusnya tidak dimiliki.
Jadi riwayat komit Anda terlihat seperti ini:
Anda benar-benar ingin menyingkirkan C, D, dan D '. Karena Anda mengatakan Anda telah menggabungkan rekan kerja Anda menjadi milik Anda, komit ini sudah "ada", jadi menghapus komit menggunakan mis. Git rebase adalah no-no. Percayalah, saya sudah mencoba.
Sekarang, saya melihat dua jalan keluar:
jika Anda belum mendorong E dan F ke rekan kerja Anda atau orang lain (biasanya server "asal" Anda), Anda masih bisa menghapusnya dari sejarah untuk saat ini. Ini adalah pekerjaan Anda yang ingin Anda simpan. Ini dapat dilakukan dengan a
(ganti D 'dengan hash komit aktual yang dapat Anda peroleh dari a
git log
Pada titik ini, komit E dan F hilang dan perubahan tersebut adalah perubahan yang tidak dikomit di ruang kerja lokal Anda lagi. Pada titik ini saya akan memindahkan mereka ke cabang atau mengubahnya menjadi patch dan menyimpannya untuk nanti. Sekarang, kembalikan pekerjaan rekan kerja Anda, baik secara otomatis dengan
git revert
atau secara manual. Setelah selesai, putar ulang pekerjaan Anda di atas itu. Anda mungkin memiliki menggabungkan konflik, tetapi setidaknya mereka akan berada dalam kode yang Anda tulis, bukan kode rekan kerja Anda.Jika Anda sudah mendorong pekerjaan yang Anda lakukan setelah komitmen rekan kerja Anda, Anda masih bisa mencoba dan mendapatkan "tambalan terbalik" baik secara manual atau menggunakan
git revert
, tetapi karena pekerjaan Anda "di jalan", jadi untuk berbicara Anda mungkin akan mendapatkan lebih banyak menggabungkan konflik dan lebih membingungkan. Sepertinya itu yang akhirnya Anda ...sumber
git revert --strategy resol jika komit adalah gabungan: use git revert --strategy resol -m 1
sumber