Cara menghapus secara permanen beberapa commit dari cabang jarak jauh

490

Saya tahu itu penulisan ulang sejarah yang buruk yada yada.

Tetapi bagaimana cara menghapus secara permanen beberapa commit dari cabang jarak jauh?

Arnis Lapsa
sumber
96
Ya, ini benar-benar buruk, bukan, tapi untuk beberapa alasan saya perlu favoritnya.
James Morris
44
Saya tahu ini bodoh, tapi kadang-kadang terjadi - seperti menguji login dan menggunakan kata sandi teks biasa dalam kode Anda, yang merupakan kredensial login nyata. Dan
huh
6
kredensial login asli .. Ya mengingatkan saya pada beberapa whoopos
Hello Universe
1
Kemungkinan duplikat dari commit Hapus dari cabang di Git
wjandrea
2
Saya sangat lelah dengan pelajaran akademis ini tentang betapa berbahayanya hal ini dan bagaimana hal itu tidak boleh dilakukan yada yada. Ada saat-saat di mana jauh lebih baik untuk menghapus hal-hal dari sejarah git dan menangani konflik / pemecahan dev lainnya. Sangat sederhana. Orang yang mengabaikan ini mungkin tidak pernah bekerja di luar ruang kelas.
naksir

Jawaban:

369

Anda git reset --hardcabang lokal Anda untuk menghapus perubahan dari pohon dan indeks kerja, dan Anda git push --forcecabang lokal Anda yang direvisi ke jarak jauh. ( solusi lain di sini , termasuk menghapus cabang jarak jauh, dan mendorongnya kembali)

Jawaban SO ini menggambarkan bahaya dari perintah semacam itu, terutama jika orang bergantung pada sejarah jarak jauh untuk repo lokal mereka sendiri.
Anda harus siap menunjukkan orang ke bagian PEMULIHAN DARI REBASE UPSTREAM dari git rebasehalaman manual


Dengan Git 2.23 (Agustus 2019, sembilan tahun kemudian), Anda akan menggunakan perintah baru git switch.
Yaitu: (ganti dengan jumlah komitmen yang harus dihapus)git switch -C mybranch origin/mybranch~n
n

Itu akan mengembalikan indeks dan pohon yang berfungsi, seperti git reset --hardakan.

VONC
sumber
Aneh. Terasa seperti saya sudah mencobanya. Bersama dengan beberapa rebasing - bekerja seperti pesona. Terima kasih.
Arnis Lapsa
7
@Arnis: perfect then;) push --forceaway
VonC
Saya menggunakan BFG Repo-Cleaner untuk menghilangkan beberapa data sensitif, yang membuat saya memiliki cabang "tanpa nama" dengan file asli di atasnya, setelah mengatur ulang ke komit yang dicari terakhir dan sulit mendorong ke asal, semuanya berjalan dengan baik (:
Rodrirokr
Perhatikan bahwa URL komit masih hidup (setidaknya untuk beberapa waktu) jadi jika seseorang memiliki URL komit (Anda memberikannya kepada tuhan tahu mengapa), mereka akan dapat mengakses kode tersebut.
Mosh Feu
1
@MoshFeu Benar: git gctidak selalu berjalan cukup sering di sisi jarak jauh. Misalnya di GitHub: twitter.com/githubhelp/status/387926738161774592?lang=es
VonC
248

Perhatikan untuk menggunakan last_working_commit_id, saat mengembalikan komit yang tidak berfungsi

git reset --hard <last_working_commit_id>

Jadi kita tidak boleh mengatur ulang ke commit_idyang tidak kita inginkan.

Maka tentu saja, kita harus mendorong ke cabang jauh:

git push --force
hd84335
sumber
10
Sempurna, elegan, jawaban paling sederhana. Saya baru saja kembali ke komit terakhir yang saya butuhkan di remote dan lokal
lauWM
2
Ini menyebabkan saya kehilangan perubahan lokal saya juga. Saya tidak mengharapkan itu. Tapi meh, lebih baik daripada melakukan kata sandi pribadi Anda untuk repo kerja.
Airwavezx
3
Anda dapat menyimpan perubahan lokal Anda dengan git simpanan .... buat beberapa hal .... dan git simpanan pop (perubahan lokal Anda kembali)
MonTea
Ini memberi saya kesalahan sebagai "remote: error: menolak referensi / kepala / master non-fast-forward (Anda harus menarik dulu)"
Saurabhcdt
@Awwavezx itulah yang git reset --hardseharusnya dilakukan.
Luke
146

Penting: Pastikan Anda menentukan cabang mana pada "git push -f" atau Anda mungkin secara tidak sengaja memodifikasi cabang lain! [*]

Ada tiga opsi yang ditampilkan dalam tutorial ini . Jika tautan rusak, saya akan meninggalkan langkah-langkah utama di sini.

  1. Kembalikan komit penuh
  2. Hapus komit terakhir
  3. Hapus komit dari daftar

1 Kembalikan komit penuh

git revert dd61ab23

2 Hapus komit terakhir

git push <<remote>> +dd61ab23^:<<BRANCH_NAME_HERE>>

atau, jika cabang tersedia secara lokal

git reset HEAD^ --hard
git push <<remote>> -f

di mana + dd61 ... adalah komit hash dan git Anda menafsirkan x ^ sebagai induk dari x, dan + sebagai dorongan non-fastforwared yang dipaksakan.

3 Hapus komit dari daftar

git rebase -i dd61ab23^

Ini akan terbuka dan editor menunjukkan daftar semua komitmen. Hapus yang ingin Anda singkirkan. Selesai rebase dan dorong kekuatan untuk repo.

git rebase --continue
git push <remote_repo> <remote_branch> -f
reefaktor
sumber
5
Pastikan Anda menentukan cabang mana pada "git push <remote_repo> <remote_branch> -f" atau Anda mungkin secara tidak sengaja memodifikasi cabang lain!
Nigel Sheridan-Smith
Hanya langkah 1 dan 2 yang berhasil dan menjawab pertanyaan awal. (Jangan jalankan langkah 3)
Saad Benbouzid
Ini adalah opsi untuk skenario yang berbeda, bukan langkah yang harus diambil. Dalam kasus saya, rebase interaktif (Opsi 3) melakukan apa yang saya cari.
Steve Blackwell
Saya harus melakukan langkah 3. Mengapa Anda tidak menjalankan @Saad ini? Untungnya <<remote>> saya hanyalah 'asal' default dan <remote_branch> 'master' default
Bart
30

Jika Anda ingin menghapus misalnya 3komit terakhir , jalankan perintah berikut untuk menghapus perubahan dari sistem file (working tree) dan komit riwayat (indeks) pada cabang lokal Anda:

git reset --hard HEAD~3

Kemudian jalankan perintah berikut (pada mesin lokal Anda) untuk memaksa cabang jarak jauh untuk menulis ulang sejarahnya:

git push --force

Selamat! Semua selesai!

Beberapa catatan:

Anda dapat mengambil id komit yang diinginkan dengan menjalankan

git log

Maka Anda dapat mengganti HEAD~Ndengan <desired-commit-id>seperti ini:

git reset --hard <desired-commit-id>

Jika Anda ingin menyimpan perubahan pada sistem file dan hanya memodifikasi indeks (komit riwayat), gunakan --softflag like git reset --soft HEAD~3. Kemudian Anda memiliki kesempatan untuk memeriksa perubahan terbaru Anda dan menyimpan atau menjatuhkan semua atau sebagian dari mereka. Dalam kasus terakhir runnig git statusmenunjukkan file berubah sejak saat itu <desired-commit-id>. Jika Anda menggunakan --hardopsi, git statusakan memberi tahu Anda bahwa cabang lokal Anda persis sama dengan cabang jarak jauh. Jika Anda tidak menggunakan --hardatau --soft, mode default yang digunakan --mixed. Dalam mode ini, git help resetkatakan:

Atur ulang indeks tetapi bukan pohon kerja (yaitu, file yang diubah disimpan tetapi tidak ditandai untuk komit) dan melaporkan apa yang belum diperbarui.

Abdollah
sumber
10

Ini mungkin terlalu sedikit terlambat tetapi yang membantu saya adalah pilihan 'nuklir' yang terdengar keren. Pada dasarnya menggunakan perintah, filter-branchAnda dapat menghapus file atau mengubah sesuatu di atas sejumlah besar file sepanjang seluruh sejarah git Anda.

Lebih baik dijelaskan di sini .

jansmolders86
sumber
9
Tidak terlambat. Mungkin menjadi berguna bagi pengembara dengan masalah yang sama :)
Arnis Lapsa
9

Menyederhanakan dari jawaban pctroll, juga berdasarkan pada posting blog ini .

# look up the commit id in git log or on github, e.g. 42480f3, then do
git checkout master
git checkout your_branch
git revert 42480f3
# a text editor will open, close it with ctrl+x (editor dependent)
git push origin your_branch
# or replace origin with your remote
ted.strauss
sumber
2
Bekerja untuk saya, terima kasih. Dan saya ingin menghapus satu komit (mis. Berisi pwd) secara permanen dari sejarah cabang jarak jauh, bagaimana caranya?
Tersenyum
1
Bekerja untuk saya juga, tetapi saya memiliki pertanyaan yang sama dari Smiles, saya tidak ingin ada yang melihat komit / rever saya dalam sejarah .. bagaimana saya menghapus itu?
Roberto Rodriguez
4

Terkadang cara termudah untuk memperbaiki masalah ini adalah dengan membuat cabang baru dari tempat Anda tahu kodenya bagus. Kemudian Anda bisa meninggalkan sejarah cabang yang salah kalau-kalau Anda perlu mengambil tindakan lain dari itu nanti. Ini juga memastikan Anda tidak kehilangan histori komit.

Dari cabang bandel lokal Anda:

git log

salin hash komit yang Anda inginkan di cabang dan keluar dari git log

git checkout theHashYouJustCopied
git checkout -b your_new_awesome_branch

Sekarang Anda memiliki cabang baru seperti yang Anda inginkan.

Jika Anda juga perlu menyimpan komit tertentu dari cabang yang salah yang tidak ada di cabang baru Anda, Anda bisa memilih komit tertentu yang Anda butuhkan:

git checkout the_errant_branch
git log

Salin hash komit dari komitmen yang Anda butuhkan untuk menarik cabang bagus dan keluar dari log git.

git checkout your_new_awesome_branch
git cherry-pick theHashYouJustCopied

Tepuk-tepuk diri Anda.

Douglas.Sesar
sumber
sangat mudah dan siapa yang peduli jika Anda memiliki cabang berkaki mati? buat cabang baru dan selesaikan!
Andrew Fox
Ini jawaban yang sangat bagus. Saya senang saya melakukan ini alih-alih melakukan memetik ceri, atau memanipulasi cabang terpencil.
Magnilex
0
 git reset --soft commit_id
 git stash save "message"
 git reset --hard commit_id
 git stash apply stash stash@{0}
 git push --force
pandorago
sumber