Bagaimana cara memperbaiki komit ke cabang Git yang salah?


621

Saya baru saja membuat komitmen yang sangat baik ke cabang yang salah. Bagaimana cara membatalkan komit terakhir di cabang master saya dan kemudian mengambil perubahan yang sama dan memasukkannya ke cabang upgrade saya?

Jawaban:


975

Jika Anda belum mendorong perubahan, Anda juga dapat melakukan soft reset:

git reset --soft HEAD^

Ini akan mengembalikan komit, tetapi memasukkan perubahan komit kembali ke indeks Anda. Dengan asumsi bahwa cabang-cabang tersebut relatif mutakhir terkait satu sama lain, git akan memungkinkan Anda melakukan checkout ke cabang lain, di mana Anda hanya dapat melakukan:

git checkout branch
git commit

Kerugiannya adalah Anda harus memasukkan kembali pesan komit Anda.


10
perhatikan bahwa soft reset membuat perubahan Anda siap dan siap untuk dikomit. membuat saya sedikit bingung ketika IDE saya tidak menunjukkan file kembali ke keadaan yang dimodifikasi setelah soft reset.
mtjhax

9
perbaikan sempurna, sebenarnya ada pasangan yang melakukan begitu juga KEPALA ^^ dan semuanya enak
pablo

8
Terima kasih. Ini telah menyelamatkan saya dua kali. Jika cabang agak berbeda, setelah reset dan sebelum checkout Anda mungkin harus menyimpan perubahan Anda sebelum Anda dapat checkout cabang lain. Mengajukan permohonan simpanan setelah checkout
Kirby

17
Pengguna zsh: Anda mungkin perlu melarikan diri dari ^ seperti:git reset --soft HEAD\^
Stephen Fuhry

54
Jika Anda mendapatkan Lebih Banyak? di baris perintah Windows Anda, gunakan tanda kutip untuk mengelilingi HEAD ^ seperti: git reset --soft "HEAD ^"
Nate Cook

141

4 tahun terlambat pada topik, tetapi ini mungkin bermanfaat bagi seseorang.

Jika Anda lupa membuat cabang baru sebelum melakukan dan melakukan semua pada master, tidak peduli berapa banyak yang Anda lakukan, pendekatan berikut lebih mudah:

git stash                       # skip if all changes are committed
git branch my_feature
git reset --hard origin/master
git checkout my_feature
git stash pop                   # skip if all changes were committed

Sekarang Anda memiliki cabang utama Anda sama dengan origin/masterdan semua komit baru aktif my_feature. Perhatikan bahwa itu my_featureadalah cabang lokal, bukan cabang jarak jauh.


Terima kasih atas jawabannya. Sekarang saya menggunakan egit dan saya bertanya-tanya apakah saya dapat melakukan hal yang sama dengan melakukan hal berikut: 1) Ubah nama 'master' saat ini menjadi 'my_feature'. 2) Menciptakan 'master' lokal dari 'asal / master'. Saya tidak yakin apa yang dilakukan egit di bawah tenda untuk operasi ini tetapi ini tampaknya menjadi solusi yang layak
mjj1409

mengapa bergabung? Anda bisa membuat cabang langsung master, lalu mengatur ulang masterke origin/master.
caesarsol

1
Itu bagian yang paling menarik: Anda tidak perlu sejumlah komit, karena origin/mastersudah ada di komit yang ingin Anda atur ulang! Namun kredit untuk tipnya adalah halaman ini: github.com/blog/…
caesarsol

4
Ini harus menjadi jawaban yang diterima. Sederhana, jelas, lugas, bekerja terlepas dari jumlah komit dan hanya menggunakan fungsionalitas dasar Git. Saya melakukan langkah-langkah ini dengan TortoiseGit. Terima kasih! :)
Ian Grainger

1
Saya pikir ini adalah jawaban terbaik, tetapi memiliki keterbatasan. Ini hanya membantu jika Anda baru saja menarik dari jarak jauh. Dan itu mengasumsikan Anda memiliki remote untuk memulai. Jika Anda hanya memiliki cabang "master" lokal dan perbaikan fitur baru Anda, satu-satunya jawaban yang tepat adalah reset keras pada master menghitung kembali sejumlah komit.
pauljohn32

111

Jika Anda memiliki copy pekerjaan yang bersih (tidak dimodifikasi)

Untuk mengembalikan satu komit (pastikan Anda mencatat hash komit untuk langkah selanjutnya):

git reset --hard HEAD^

Untuk menarik komit itu ke cabang lain:

git checkout other-branch
git cherry-pick COMMIT-HASH

Jika Anda telah memodifikasi atau membatalkan perubahan

Perhatikan juga bahwa git reset --hardakan membunuh perubahan yang tidak terlacak dan dimodifikasi yang mungkin Anda miliki, jadi jika Anda memilikinya, Anda mungkin lebih suka:

git reset HEAD^
git checkout .

git rev-parse BRANCH_NAMEuntuk mendapatkan sha.
wilhelmtell

12
Jika Anda lupa untuk mencatat hash terlebih dahulu, gunakan saja git reflog show <branch>!
Cascabel

2
@ Jeffromi saya takut di sana sebentar.
Ian Hunter

13
Untuk perasaan ekstra aman, lakukan pemetikan ceri terlebih dahulu di cabang yang benar dan baru kemudian atur ulang cabang yang salah.
Usia Mooij

1
Juga jika terjadi perubahan yang tidak terlacak, seseorang dapat git stashsebelum reset dan menggunakan git stash popsetelahnya untuk mengembalikannya, jadi tidak perlu takut pada --hardbagian tersebut
Clemens Klein-Robbenhaar

20

Jika Anda sudah mendorong perubahan, Anda harus memaksakan dorongan berikutnya setelah menyetel ulang HEAD.

git reset --hard HEAD^
git merge COMMIT_SHA1
git push --force

Peringatan: hard reset akan membatalkan setiap modifikasi yang tidak dikomit dalam copy pekerjaan Anda, sementara push force akan sepenuhnya menimpa keadaan cabang jarak jauh dengan keadaan cabang lokal saat ini.

Untuk jaga-jaga, pada Windows (menggunakan baris perintah Windows, bukan Bash) sebenarnya empat ^^^^bukan satu, jadi itu

git reset --hard HEAD^^^^

6
Perhatikan bahwa Anda tidak boleh memaksa-mendorong ke cabang yang digunakan orang lain kecuali benar-benar diperlukan - jika tidak mereka tidak akan bisa mendorong sampai mereka rebase. Namun, jika Anda adalah satu-satunya pengembang yang menggunakan git, ini tidak masalah.
Blair Holloway

2
Atau kecuali Anda cukup cepat menyadarinya sebelum ada orang lain yang melakukan kesalahan.
Michael Mior

Jika komit Anda lebih dari satu, Anda dapat menentukan komit yang Anda butuhkan: git reset --hard COMMIT_HASH git push --force
David Cramblett

17

Baru-baru ini saya melakukan hal yang sama, di mana saya secara tidak sengaja melakukan perubahan untuk menguasai, ketika saya seharusnya berkomitmen pada cabang lain. Tapi saya tidak mendorong apa pun.

Jika Anda baru saja berkomitmen ke cabang yang salah, dan belum mengubah apa pun sejak itu, dan belum mendorong ke repo, maka Anda dapat melakukan hal berikut:

// rewind master to point to the commit just before your most recent commit.
// this takes all changes in your most recent commit, and turns them into unstaged changes. 
git reset HEAD~1 

// temporarily save your unstaged changes as a commit that's not attached to any branch using git stash
// all temporary commits created with git stash are put into a stack of temporary commits.
git stash

// create other-branch (if the other branch doesn't already exist)
git branch other-branch

// checkout the other branch you should have committed to.
git checkout other-branch

// take the temporary commit you created, and apply all of those changes to the new branch. 
//This also deletes the temporary commit from the stack of temp commits.
git stash pop

// add the changes you want with git add...

// re-commit your changes onto other-branch
git commit -m "some message..."

CATATAN: pada contoh di atas, saya memutar ulang 1 commit dengan git reset HEAD ~ 1. Tetapi jika Anda ingin memundurkan n komit, maka Anda dapat melakukan git reset HEAD ~ n.

Juga, jika Anda akhirnya melakukan ke cabang yang salah, dan juga akhirnya menulis beberapa kode sebelum menyadari bahwa Anda berkomitmen pada cabang yang salah, maka Anda bisa menggunakan git simpanan untuk menyimpan pekerjaan Anda yang sedang dalam proses:

// save the not-ready-to-commit work you're in the middle of
git stash 

// rewind n commits
git reset HEAD~n 

// stash the committed changes as a single temp commit onto the stack. 
git stash 

// create other-branch (if it doesn't already exist)
git branch other-branch

// checkout the other branch you should have committed to.
git checkout other-branch

// apply all the committed changes to the new branch
git stash pop

// add the changes you want with git add...

// re-commit your changes onto the new branch as a single commit.
git commit -m "some message..."

// pop the changes you were in the middle of and continue coding
git stash pop

CATATAN: Saya menggunakan situs web ini sebagai referensi https://www.clearvision-cm.com/blog/what-to-do-when-you-commit-to-the-wrong-git-branch/


Hal serupa terjadi pada saya, saya melakukan beberapa perubahan pada master, tetapi saya seharusnya melakukan di cabang baru dan mengirim PR, saya akhirnya hanya melakukan yang git checkout -b new_branchbenar dari sana, melakukan yang utuh, hanya mendorong, dan menciptakan PR, bukan t harus berkomitmen lagi.
Nishchal Gautam

11

Jadi, jika skenario Anda adalah komitmen Anda mastertetapi dimaksudkan untuk berkomitmen another-branch(yang mungkin atau tidak mungkin belum ada) tetapi Anda belum mendorongnya, ini cukup mudah untuk diperbaiki.

// if your branch doesn't exist, then add the -b argument 
git checkout -b another-branch
git branch --force master origin/master

Sekarang semua komitmen Anda masterakan aktif another-branch.

Berasal dari cinta dari: http://haacked.com/archive/2015/06/29/git-migrate/


tampaknya menjadi pendekatan yang paling mudah! Tidak yakin mengapa begitu sedikit cinta dan upwotes
keligijus

4
Ini sepertinya tidak berhasil untuk saya. another-branchsudah ada. Dalam hal ini, itu hanya membatalkan komitmen yang saya buat untuk dikuasai dan tidak memakainya another-branch.
Giselle Serate

6

Untuk menguraikan jawaban ini , jika Anda memiliki beberapa komitmen untuk berpindah, misalnya developke new_branch:

git checkout develop # You're probably there already
git reflog # Find LAST_GOOD, FIRST_NEW, LAST_NEW hashes
git checkout new_branch
git cherry-pick FIRST_NEW^..LAST_NEW # ^.. includes FIRST_NEW
git reflog # Confirm that your commits are safely home in their new branch!
git checkout develop
git reset --hard LAST_GOOD # develop is now back where it started

1
Saya punya tiga komitmen untuk kembali, dan pertanyaan ini tampaknya telah menarik saya keluar dari api. Terima kasih!
holdenweb

3

Jika Anda mengalami masalah ini dan Anda memiliki Visual Studio, Anda dapat melakukan hal berikut:

Klik kanan pada cabang Anda dan pilih View History:

masukkan deskripsi gambar di sini

Klik kanan pada komit yang ingin Anda kembali. Dan Kembalikan atau Atur Ulang sesuai kebutuhan.

masukkan deskripsi gambar di sini


3

Untuk banyak komit di cabang yang salah

Jika untuk Anda, ini hanya sekitar 1 komit, maka ada banyak solusi pengaturan ulang lainnya yang lebih mudah. Bagi saya, saya memiliki sekitar 10 komitmen yang dibuat secara tidak sengaja masteralih-alih, sebut saja branch_xyz, dan saya tidak ingin kehilangan riwayat komit.

Apa yang dapat Anda lakukan, dan apa yang menyelamatkan saya menggunakan jawaban ini sebagai referensi, menggunakan proses 4 langkah, yaitu -

  1. Buat cabang sementara baru dari master
  2. Gabungkan ke cabang yang awalnya dimaksudkan untuk melakukan, yaitu branch_xyz
  3. Batalkan komitmen master
  4. Hapus cabang sementara.

Berikut langkah-langkah di atas dalam rincian -

  1. Buat cabang baru dari master(tempat saya secara tidak sengaja melakukan banyak perubahan)

    git checkout -b temp_branch_xyz
    

    Catatan: -bflag digunakan untuk membuat cabang baru.
    Hanya untuk memverifikasi jika kita mendapatkan ini dengan benar, saya akan melakukan cepat git branchuntuk memastikan kita berada di temp_branch_xyzcabang dan git loguntuk memeriksa apakah kita memiliki komit yang benar.

  2. Gabungkan cabang sementara ke cabang yang awalnya dimaksudkan untuk komit, yaitu branch_xyz.
    Pertama, beralih ke cabang asli yaitu branch_xyz(Anda mungkin perlu git fetchjika Anda belum)

    git checkout branch_xyz
    

    Catatan: Tidak menggunakan -bflag
    Sekarang, mari gabungkan cabang sementara ke cabang yang saat ini kami checkoutbranch_xyz

    git merge temp_branch_xyz
    

    Anda mungkin harus mengurus beberapa konflik di sini, jika ada. Anda dapat mendorong (saya akan) atau melanjutkan ke langkah berikutnya, setelah berhasil menggabungkan.

  3. Batalkan yang tidak disengaja berkomitmen mastermenggunakan jawaban ini sebagai referensi, pertama beralih kemaster

    git checkout master
    

    kemudian batalkan semuanya kembali untuk mencocokkan remote (atau untuk komit tertentu, jika Anda mau)

    git reset --hard origin/master
    

    Sekali lagi, saya akan melakukan git logsebelum dan sesudah hanya untuk memastikan bahwa perubahan yang dimaksudkan mulai berlaku.

  4. Menghapus bukti, yaitu menghapus cabang sementara. Untuk ini, pertama-tama Anda perlu checkout cabang yang temp digabungkan, yaitu branch_xyz(Jika Anda tetap masterdan menjalankan perintah di bawah ini, Anda mungkin mendapatkan a error: The branch 'temp_branch_xyz' is not fully merged), jadi mari kita

    git checkout branch_xyz
    

    dan kemudian hapus bukti kecelakaan ini

    git branch -d temp_branch_xyz
    

Ini dia.


1

Jika cabang tempat Anda ingin menerapkan perubahan Anda sudah ada (cabang berkembang , misalnya), ikuti instruksi yang disediakan oleh fotanus di bawah ini, kemudian:

git checkout develop
git rebase develop my_feature # applies changes to correct branch
git checkout develop # 'cuz rebasing will leave you on my_feature
git merge develop my_feature # will be a fast-forward
git branch -d my_feature

Dan jelas Anda bisa menggunakan tempbranch atau nama cabang lain, bukan my_feature jika Anda mau.

Juga, jika berlaku, tunda pop up (berlaku) sampai setelah Anda bergabung di cabang target Anda.


Saya pikir perintah pertama (checkout berkembang) tidak perlu ... rebase hanya akan checkout "my_feature" sebagai hal pertama yang dilakukannya.
JoelFan

Anda juga dapat mengabaikan parameter "my_feature" dari perintah "rebase" (karena Anda sudah memeriksa "my_feature"). Anda juga dapat
mengabaikan

1

Bagi saya, ini diselesaikan dengan mengembalikan komit yang saya dorong, lalu memetik ceri yang komit ke cabang lain.

git checkout branch_that_had_the_commit_originally
git revert COMMIT-HASH
git checkout branch_that_was_supposed_to_have_the_commit
git cherry pick COMMIT-HASH

Anda dapat menggunakan git loguntuk menemukan hash yang benar, dan Anda dapat mendorong perubahan ini kapan pun Anda mau!

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.