Bagaimana cara saya menghapus komit git yang tidak dicuri?


948

Saya tidak sengaja berkomitmen pada cabang yang salah. Bagaimana cara saya menghapus komit itu?

Jawaban:


1811

Hapus komit terbaru, menjaga pekerjaan yang telah Anda lakukan:

git reset --soft HEAD~1

Hapus komit terbaru, hancurkan pekerjaan yang telah Anda lakukan:

git reset --hard HEAD~1

13
pastikan KEPALA menunjuk ke cabang .. (lihat dulu)
Frank Schwieterman

128
Dan pastikan KEPALA ~ 1 adalah komit ... Anda juga bisa melakukannyagit reset --hard origin
Daenyth

13
git remoteAsal pikir daftar bagi saya, git reset --hard originkata fatal: ambiguous argument 'origin': unknown revision or path not in the working tree.. Mengapa?
trss

7
Ini luar biasa. Baru saja menyelamatkan hidupku.
NinjaBoy

2
git reset HEAD~1juga akan menyimpan semua perubahan Anda tetapi akan meninggalkan Anda dengan indeks kosong daripada menyimpan semuanya (seperti yang --softakan dilakukan).
Holloway

139

Saya heran mengapa jawaban terbaik yang saya temukan hanya di komentar! ( oleh Daenyth dengan 86 suara )

git reset --hard origin

Perintah ini akan menyinkronkan repositori lokal dengan repositori jarak jauh yang menyingkirkan setiap perubahan yang Anda lakukan pada lokal Anda. Anda juga dapat melakukan hal berikut untuk mengambil cabang persis yang Anda miliki di asal.

git reset --hard origin/<branch>

16
Terima kasih untuk ini, perluas sedikit penjelasan: untuk cabang tertentu:git reset --hard origin/<branch>
cleary

4
Atau git reset --soft origin/<branch>, jika Anda ingin menghilangkan komit tetapi tetap bekerja lokal.
Riverhorse

1
saya mengerti fatal: ambiguous argument 'origin': unknown revision or path not in the working tree., Anda perlu menentukan cabang seperti:git reset --hard origin/feature/my-cool-stuff
Kip

Cemerlang! Ini benar-benar berfungsi, tidak seperti jawaban "diterima" yang hanya melepaskan kepala dan membuat Anda menggantung.
mae

55

Jangan hapus itu: hanya satu komit saja git cherry-picksudah cukup.

Tetapi jika Anda memiliki beberapa komit di cabang yang salah, di situlah git rebase --ontobersinar:

Misalkan Anda memiliki ini:

 x--x--x--x <-- master
           \
            -y--y--m--m <- y branch, with commits which should have been on master

, maka Anda dapat menandai masterdan memindahkannya ke tempat yang Anda inginkan:

 git checkout master
 git branch tmp
 git checkout y
 git branch -f master

 x--x--x--x <-- tmp
           \
            -y--y--m--m <- y branch, master branch

, setel ulang cabang y ke tempat yang seharusnya:

 git checkout y
 git reset --hard HEAD~2 # ~1 in your case, 
                         # or ~n, n = number of commits to cancel

 x--x--x--x <-- tmp
           \
            -y--y--m--m <- master branch
                ^
                |
                -- y branch

, dan akhirnya pindahkan komit Anda (aplikasikan kembali, buat komit yang benar-benar baru)

 git rebase --onto tmp y master
 git branch -D tmp


 x--x--x--x--m'--m' <-- master
           \
            -y--y <- y branch

Sayangnya, itu bukan pertanyaannya.
KatariaA

1
@KatariaA Itu adalah alternatif yang valid untuk menghapus komit yang dilakukan pada cabang yang salah dan akan membantu orang lain dalam situasi yang sama (komit baik dilakukan pada cabang yang salah).
VonC

14

Lakukan git rebase -i FAR_ENOUGH_BACKdan lepaskan garis untuk komit yang tidak Anda inginkan.


6

Jika Anda ingin memindahkan komit ke cabang lain, dapatkan SHA dari komit tersebut

git rev-parse HEAD

Kemudian pindahkan cabang saat ini

git checkout other-branch

Dan cherry-pickkomitmen untukother-branch

git cherry-pick <sha-of-the-commit>

Dari pengalaman saya, ini tidak membatalkan komit dari cabang asli, sehingga mengharuskan git reset --hard HEAD~1setelah itu. Saya pikir menggunakan reset --softkemudian beralih cabang dan melakukan lagi akan menghemat pekerjaan ekstra. Kemudian lagi saya menggunakan SourceTree untuk melakukan sebagian besar hal-hal dasar saya, hanya perintah baris-ing dengan ini setelah kesalahan saya.
jusopi

3

Untuk referensi Anda, saya yakin Anda dapat "memotong" melakukan dari cabang Anda saat ini tidak hanya dengan git reset --hard, tetapi juga dengan perintah berikut:

git checkout -B <branch-name> <SHA>

Bahkan, jika Anda tidak peduli untuk memeriksa, Anda dapat mengatur cabang ke apa pun yang Anda inginkan dengan:

git branch -f <branch-name> <SHA>

Ini akan menjadi cara terprogram untuk menghapus komit dari cabang, misalnya, untuk menyalin komit baru ke dalamnya (menggunakan rebase).

Misalkan Anda memiliki cabang yang terputus dari master karena Anda telah mengambil sumber dari beberapa lokasi lain dan membuangnya ke cabang.

Anda sekarang memiliki cabang tempat Anda menerapkan perubahan, sebut saja "topik".

Anda sekarang akan membuat duplikat cabang topik Anda dan kemudian rebase ke dump kode sumber yang duduk di cabang "dump":

git branch topic_duplicate topic
git rebase --onto dump master topic_duplicate

Sekarang perubahan Anda diterapkan kembali dalam branch topic_duplicate berdasarkan pada titik awal "dump" tetapi hanya komit yang telah terjadi sejak "master". Jadi perubahan Anda sejak master sekarang diterapkan kembali di atas "dump" tetapi hasilnya berakhir pada "topic_duplicate".

Anda kemudian dapat mengganti "dump" dengan "topic_duplicate" dengan melakukan:

git branch -f dump topic_duplicate
git branch -D topic_duplicate

Atau dengan

git branch -M topic_duplicate dump

Atau hanya dengan membuang sampah

git branch -D dump

Mungkin Anda juga bisa memilih ceri setelah menghapus "topic_duplicate" saat ini.

Apa yang ingin saya katakan adalah bahwa jika Anda ingin memperbarui cabang "duplikat" saat ini berdasarkan dari leluhur yang berbeda, Anda harus terlebih dahulu menghapus komit "cherrypicked" yang sebelumnya dilakukan dengan melakukan git reset --hard <last-commit-to-retain>atau git branch -f topic_duplicate <last-commit-to-retain>dan kemudian menyalin komit lainnya atas (dari utama cabang topik) baik dengan rebasing atau memetik ceri.

Rebasing hanya berfungsi pada cabang yang sudah memiliki komit, jadi Anda perlu menduplikasi cabang topik Anda setiap kali Anda ingin melakukannya.

Memetik ceri lebih mudah:

git cherry-pick master..topic

Jadi seluruh urutan akan turun ke:

git reset --hard <latest-commit-to-keep>
git cherry-pick master..topic

Ketika cabang duplikat topik Anda telah diperiksa. Itu akan menghapus komit yang sebelumnya dipetik cherry dari duplikat saat ini, dan hanya menerapkan kembali semua perubahan yang terjadi di "topik" di atas "dump" Anda saat ini (leluhur yang berbeda). Tampaknya cara yang cukup mudah untuk mendasarkan pengembangan Anda pada master hulu "nyata" sambil menggunakan master "hilir" yang berbeda untuk memeriksa apakah perubahan lokal Anda juga masih berlaku untuk itu. Atau Anda bisa membuat diff dan menerapkannya di luar pohon sumber Git. Tetapi dengan cara ini Anda dapat menyimpan versi yang dimodifikasi (ditambal) terbaru yang didasarkan pada versi distribusi Anda sementara pengembangan Anda yang sebenarnya bertentangan dengan master hulu nyata.

Jadi hanya untuk menunjukkan:

  • reset akan membuat cabang Anda menunjuk ke komit yang berbeda (--hampir juga memeriksa komit sebelumnya, --soft menyimpan file yang ditambahkan dalam indeks (yang akan dikomit jika Anda komit lagi) dan default (--mixed) tidak akan lihat komit sebelumnya (menghapus perubahan lokal Anda) tetapi itu akan menghapus indeks (belum ada yang ditambahkan untuk komit)
  • Anda bisa saja memaksa cabang untuk menunjuk ke komit yang berbeda
  • Anda dapat melakukannya sambil segera memeriksa komit itu juga
  • rebasing bekerja pada komit yang ada di cabang Anda saat ini
  • memetik ceri berarti menyalin dari cabang yang berbeda

Semoga ini bisa membantu seseorang. Saya bermaksud menulis ulang ini, tetapi saya tidak bisa mengelola sekarang. Salam.


0

Mengikuti perintah yang berfungsi untuk saya, semua perubahan yang dikomit dijatuhkan & lokal diset ulang ke yang sama dengan cabang asal / master jarak jauh.

git reset --barang asli

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.