Saya ingin memindahkan beberapa komit terakhir yang telah saya komit untuk dikuasai ke cabang baru dan membawa master kembali sebelum komit dibuat. Sayangnya, Git-fu saya belum cukup kuat, ada bantuan?
Yaitu Bagaimana saya bisa pergi dari ini
master A - B - C - D - E
untuk ini?
newbranch C - D - E
/
master A - B
git
git-branch
branching-and-merging
Mark A. Nicolosi
sumber
sumber
Jawaban:
Pindah ke cabang yang ada
Jika Anda ingin memindahkan komit Anda ke cabang yang ada , itu akan terlihat seperti ini:
The
--keep
pilihan mempertahankan perubahan uncommitted yang mungkin Anda miliki di file yang tidak terkait, atau dibatalkan jika perubahan tersebut akan menjadi ditimpa - mirip dengan apa yanggit checkout
dilakukannya. Jika gagal,git stash
perubahan dan coba lagi, atau gunakan--hard
untuk kehilangan perubahan (bahkan dari file yang tidak berubah di antara komitmen!)Pindah ke cabang baru
Metode ini berfungsi dengan membuat cabang baru dengan perintah pertama (
git branch newbranch
) tetapi tidak beralih ke sana. Kemudian kami memutar kembali cabang saat ini (master) dan beralih ke cabang baru untuk terus bekerja.Tetapi pastikan berapa banyak yang berkomitmen untuk kembali. Atau, alih-alih
HEAD~3
, Anda cukup memberikan hash dari commit (atau referensi sepertiorigin/master
) yang ingin Anda kembalikan, misalnya:PERINGATAN: Dengan Git versi 2.0 dan yang lebih baru, jika nanti Anda
git rebase
cabang baru pada cabang asli (master
), Anda mungkin memerlukan--no-fork-point
opsi eksplisit selama rebase untuk menghindari kehilangan komit yang Anda pindahkan dari cabang master. Memilikibranch.autosetuprebase always
set membuat ini lebih mungkin. Lihat jawaban John Mellor untuk detailnya.sumber
Bagi mereka yang bertanya-tanya mengapa ini bekerja (seperti saya pada awalnya):
Anda ingin kembali ke C, dan memindahkan D dan E ke cabang baru. Begini tampilannya pada awalnya:
Setelah
git branch newBranch
:Setelah
git reset --hard HEAD~2
:Karena cabang hanyalah sebuah pointer, master menunjuk ke komit terakhir. Saat Anda membuat newBranch , Anda cukup membuat pointer baru ke komit terakhir. Kemudian gunakan
git reset
Anda memindahkan pointer master kembali dua komit. Tetapi karena Anda tidak memindahkan newBranch , itu masih menunjuk ke komit yang awalnya.sumber
git push origin master --force
agar perubahan muncul di repositori utama.git rebase
, 3 komit tersebut akan dibuang secara diam-diamnewbranch
. Lihat jawaban saya untuk detail dan alternatif yang lebih aman.origin/master
tidak muncul dalam diagram di atas. Jika Anda mendorong keorigin/master
dan kemudian membuat perubahan di atas, tentu saja, semuanya akan menjadi lucu. Tapi itu masalah "Dokter, sakit kalau aku melakukan ini". Dan itu di luar ruang lingkup untuk apa pertanyaan awal diajukan. Saya sarankan Anda menulis pertanyaan Anda sendiri untuk menjelajahi skenario Anda alih-alih membajak yang ini.git branch -t newbranch
". Kembali dan baca jawabannya lagi. Tidak ada yang menyarankan melakukan itu.newbranch
didasarkan padamaster
cabang lokal mereka yang ada . Setelah melakukan jawaban yang diterima, ketika pengguna mendapatkan sekitar untuk berjalangit rebase
dinewbranch
, git akan mengingatkan mereka bahwa mereka lupa untuk mengatur cabang hulu, sehingga mereka akan menjalankangit branch --set-upstream-to=master
kemudiangit rebase
dan memiliki masalah yang sama. Mereka mungkin juga digunakangit branch -t newbranch
di tempat pertama.Secara umum...
Metode yang diekspos oleh sykora adalah pilihan terbaik dalam kasus ini. Tetapi kadang-kadang bukan yang termudah dan itu bukan metode umum. Untuk metode umum, gunakan git cherry-pick :
Untuk mencapai apa yang diinginkan OP, ini adalah proses 2 langkah:
Langkah 1 - Catat komit mana yang Anda inginkan pada a
newbranch
Menjalankan
Perhatikan hash dari (katakanlah 3) komit yang Anda inginkan
newbranch
. Di sini saya akan menggunakan:C commit:
9aa1233
D commit:
453ac3d
E commit:
612ecb3
Langkah 2 - Tempatkan mereka di
newbranch
ATAU (pada Git 1.7.2+, gunakan rentang)
git cherry-pick menerapkan ketiga komitmen pada cabang baru.
sumber
Namun cara lain untuk melakukan ini, hanya menggunakan 2 perintah. Juga menjaga pohon kerja Anda saat ini utuh.
Versi lama - sebelum saya pelajari
git branch -f
Mampu
push
melakukannya.
adalah trik yang bagus untuk diketahui.sumber
git branch -f
sini?.
adalah direktur saat ini. git dapat mendorong ke URL REMOTES atau GIT.path to local directory
didukung sintaks URL Git. Lihat bagian GIT URL digit help clone
.Sebagian besar jawaban sebelumnya salah!
Jangan lakukan ini:
Saat lain kali Anda menjalankan
git rebase
(ataugit pull --rebase
) 3 komit itu akan dibuang secara diam-diamnewbranch
! (lihat penjelasan di bawah)Alih-alih lakukan ini:
--keep
seperti--hard
, tapi lebih aman, karena gagal daripada membuang perubahan yang tidak dikomit).newbranch
.newbranch
. Karena mereka tidak lagi direferensikan oleh cabang, ia melakukannya dengan menggunakan reflog git :HEAD@{2}
adalah komit yangHEAD
digunakan untuk merujuk ke 2 operasi yang lalu, yaitu sebelum kita 1. memeriksanewbranch
dan 2. digunakangit reset
untuk membuang 3 commit.Peringatan: reflog diaktifkan secara default, tetapi jika Anda telah menonaktifkannya secara manual (misalnya dengan menggunakan repositori git "bare"), Anda tidak akan bisa mendapatkan 3 komit kembali setelah menjalankan
git reset --keep HEAD~3
.Alternatif yang tidak bergantung pada reflog adalah:
(jika Anda mau, Anda bisa menulis
@{-1}
- cabang yang sebelumnya diperiksa - bukanoldbranch
).Penjelasan teknis
Mengapa
git rebase
membuang 3 komit setelah contoh pertama? Ini karenagit rebase
tanpa argumen memungkinkan--fork-point
opsi secara default, yang menggunakan reflog lokal untuk mencoba menjadi kuat terhadap cabang hulu yang didorong paksa.Misalkan Anda bercabang asal / master ketika berisi komit M1, M2, M3, lalu buat tiga komit sendiri:
tapi kemudian seseorang menulis ulang sejarah dengan memaksa asal / master untuk menghapus M2:
Dengan menggunakan reflog lokal Anda,
git rebase
dapat melihat bahwa Anda melakukan forked dari inkarnasi awal dari cabang asal / master, dan karenanya M2 dan M3 commit tidak benar-benar bagian dari cabang topik Anda. Oleh karena itu cukup beralasan bahwa sejak M2 telah dihapus dari cabang hulu, Anda tidak lagi menginginkannya di cabang topik Anda begitu cabang cabang dimundurkan:Perilaku ini masuk akal, dan umumnya hal yang benar untuk dilakukan ketika rebasing.
Jadi alasan mengapa perintah berikut gagal:
karena mereka meninggalkan reflog dalam kondisi yang salah. Git melihat
newbranch
telah memotong cabang upstream pada revisi yang menyertakan 3 commit, lalureset --hard
menulis ulang sejarah upstream untuk menghapus commit, dan lain kali Anda menjalankannyagit rebase
membuangnya seperti halnya komit lain yang telah dihapus dari upstream.Tetapi dalam kasus khusus ini kami ingin 3 komitmen tersebut dianggap sebagai bagian dari cabang topik. Untuk mencapai itu, kita perlu memotong upstream pada revisi sebelumnya yang tidak termasuk 3 komitmen. Itulah yang dilakukan solusi yang saya sarankan, karena itu keduanya meninggalkan reflog dalam kondisi yang benar.
Untuk lebih jelasnya, lihat definisi
--fork-point
di git rebase dan git merge-base docs.sumber
master
. Jadi tidak, mereka tidak salah secara berbahaya.-t
Anda maksud adalahgit branch
terjadi secara implisit jika Anda telahgit config --global branch.autosetuprebase always
mengatur. Bahkan jika Anda tidak melakukannya, saya sudah menjelaskan kepada Anda bahwa masalah yang sama terjadi jika Anda mengatur pelacakan setelah melakukan perintah-perintah ini, karena OP kemungkinan bermaksud untuk memberikan pertanyaan mereka.Solusi yang jauh lebih sederhana dengan menggunakan git stash
Inilah solusi yang jauh lebih sederhana untuk komitmen ke cabang yang salah. Mulai dari cabang
master
yang memiliki tiga kesalahan komitmen:Kapan harus menggunakan ini?
master
Apa ini, dengan nomor baris
master
, namun membiarkan semua file yang bekerja tetap utuhmaster
pohon yang bekerja sama persis dengan status HEAD ~ 3newbranch
Anda sekarang dapat menggunakan
git add
dangit commit
seperti biasa. Semua komit baru akan ditambahkan kenewbranch
.Apa yang tidak dilakukan ini?
Tujuan
OP menyatakan tujuannya adalah untuk "mengambil alih kembali sebelum komitmen itu dibuat" tanpa kehilangan perubahan dan solusi ini melakukan itu.
Saya melakukan ini setidaknya seminggu sekali ketika saya secara tidak sengaja membuat komitmen baru
master
sebagai gantinyadevelop
. Biasanya saya hanya memiliki satu komit untuk rollback dalam hal ini menggunakangit reset HEAD^
jalur 1 adalah cara yang lebih sederhana untuk mengembalikan hanya satu komit.Jangan lakukan ini jika Anda mendorong perubahan master ke atas
Orang lain mungkin telah menarik perubahan itu. Jika Anda hanya menulis ulang master lokal Anda, tidak ada dampak ketika didorong ke hulu, tetapi mendorong sejarah yang ditulis ulang ke kolaborator dapat menyebabkan sakit kepala.
sumber
git add
dangit commit
perintah yang saya gunakan sehingga yang harus saya lakukan adalah menekan panah dan memasukkan beberapa kali dan boom! Semuanya kembali, tetapi di cabang kanan sekarang.Ini tidak "memindahkan" mereka dalam arti teknis tetapi memiliki efek yang sama:
sumber
rebase
untuk hal yang sama?rebase
pada cabang terpisah dalam skenario di atas.Untuk melakukan ini tanpa menulis ulang riwayat (yaitu jika Anda sudah mendorong komit):
Kedua cabang kemudian dapat didorong tanpa kekuatan!
sumber
Baru saja situasi ini:
Saya tampil:
Saya berharap komit itu saya akan menjadi KEPALA, tetapi komit L itu sekarang ...
Untuk memastikan untuk mendarat di tempat yang tepat dalam sejarah lebih mudah untuk bekerja dengan hash dari commit
sumber
Bagaimana saya bisa pergi dari ini
untuk ini?
Dengan dua perintah
memberi
dan
memberi
sumber
Jika Anda hanya perlu memindahkan semua komitmen Anda yang belum dicabut ke cabang baru , maka Anda hanya perlu,
membuat sebuah cabang baru dari yang sekarang:
git branch new-branch-name
dorong cabang baru Anda :
git push origin new-branch-name
kembalikan cabang lama Anda (saat ini) ke kondisi push / stable terakhir:
git reset --hard origin/old-branch-name
Beberapa orang juga memiliki
upstreams
selainorigin
mereka harus menggunakan yang sesuaiupstream
sumber
1) Buat cabang baru, yang memindahkan semua perubahan Anda ke new_branch.
2) Kemudian kembali ke cabang lama.
3) Lakukan git rebase
4) Kemudian editor yang dibuka berisi 3 informasi komit terakhir.
5) Ubah
pick
kedrop
dalam semua 3 komitmen tersebut. Kemudian simpan dan tutup editor.6) Sekarang 3 komit terakhir dihapus dari cabang saat ini (
master
). Sekarang dorong cabang dengan paksa, dengan+
tanda sebelum nama cabang.sumber
Anda dapat melakukan ini hanya 3 langkah sederhana yang saya gunakan.
1) buat cabang baru tempat Anda ingin melakukan pembaruan terkini kepada Anda.
git branch <branch name>
2) Temukan Id Komit Terbaru untuk komit di cabang baru.
git log
3) Salin catatan komit yang daftar komit terbaru terjadi di atas. sehingga Anda dapat menemukan komit Anda. Anda juga menemukan ini melalui pesan.
git cherry-pick d34bcef232f6c...
Anda juga dapat memberikan beberapa nomor komit.
git cherry-pick d34bcef...86d2aec
Sekarang pekerjaanmu selesai. Jika Anda memilih id yang benar dan cabang yang benar maka Anda akan berhasil. Jadi sebelum ini berhati-hatilah. kalau tidak masalah lain bisa terjadi.
Sekarang Anda dapat mendorong kode Anda
git push
sumber
Cara lain untuk melakukan ini:
[1] Ubah nama
master
cabang menjadi milik Andanewbranch
(dengan asumsi Anda ada dimaster
cabang):[2] Buat
master
cabang dari komit yang Anda inginkan:sumber