Rebase satu Git commit

116

Apakah ada cara untuk mendasarkan kembali satu komit dari cabang ke cabang lain?

Saya memiliki struktur cabang ini:

-- -- -- -- -- (Master)
            \
              -- -- -- -- -- XX (Feature-branch)

Yang ingin saya lakukan adalah melakukan rebase pada commit terakhir Feature-branchke master dan mengembalikan Feature-branchsatu commit.

-- -- -- -- -- XX (Master)
            \
              -- -- -- -- -- (Feature-branch)

Bagaimana aku melakukan itu?

Kevin Meyer
sumber
3
Jika Anda dapat mendasarkan kembali sejumlah komit lalu mengapa Anda bertanya tentang rebasing satu komit? Jika saya dapat mengajukan pertanyaan dalam SO, saya akan bertanya apa perbedaan antara rebasing (komit tunggal) dan cherry-picking.
Val
9
Karena saya tidak tahu ada pemetikan ceri, dan saya melakukan "Faff tentang di cabang", "Dapatkan permintaan perbaikan di cabang yang berbeda", "perbaiki", "Komit ke cabang yang salah", "D'OH!" cukup sehingga mengajukan pertanyaan itu bermanfaat.
Kevin Meyer

Jawaban:

116

Anda dapat memilih XX untuk dikuasai.

git checkout master
git cherry-pick <commit ID of XX>

Dan hapus komit terakhir dari cabang fitur dengan git reset.

git checkout Feature-branch
git reset --hard HEAD^
tewe
sumber
64
bagaimana pertanyaan yang secara khusus disebut 'git rebase ...' memiliki jawaban yang diterima daripada berisi pilihan ceri, yang merupakan konsep yang sama sekali berbeda dan kadang-kadang dianggap tidak bersih?
Bondax
1
Tidak yakin apakah ini relevan, tetapi komit yang saya ingin rebase memiliki beberapa file yang dipindahkan, dan cherry-pickmembuatnya tampak seolah-olah telah dihapus dari lokasi lama dan dibuat di lokasi baru. Saya kira rebase akan mengatasinya, tetapi sekarang saya telah mendorong ke atas jadi saya tidak bisa mengujinya. Bagaimanapun, berhati-hatilah jika Anda memiliki situasi serupa.
waldyrious
Catatan: untuk mendorong Anda perubahan Feature-branchke asal, Anda harus melakukannya git push -f origin Feature-branchkarena Anda Feature-branchsekarang dianggap 1 komit di belakang origin/Feature-branch.
jojo
1
Apa perbedaan praktis antara solusi ini dan solusi oleh CharlesB ?
Lii
96
git rebase --onto master branch~1 branch 

Ini mengatakan "rebase rentang komit antara cabang terakhir-sebelum dan cabang (yaitu, komit XX) di ujung cabang master"

Setelah branchtip operasi ini dipindahkan saat komit XX, jadi Anda ingin menyetelnya kembali

git checkout branch
git reset --hard branch@{1}^

Yang mengatakan "setel ulang ujung cabang ke komit sebelum keadaan sebelumnya"

Jadi cherry pick adalah solusi yang lebih sederhana ...

CharlesB
sumber
5
Ini sepertinya tidak berhasil untuk saya, saya kehilangan komit sebelum XX dan cabang di-rebased menjadi master dengan satu komit, tetapi saya tidak pernah menggunakan --ontosebelumnya jadi saya mungkin melakukan sesuatu yang salah. BTW, OP mengatakan rebase tetapi sepertinya dia ingin melakukan pilihan ceri.
tewe
1
kesalahan saya, rebase memang memindahkan cabang pada master, itu harus disetel ulang
CharlesB
1
Apa perbedaan praktis antara solusi ini dan solusi per tewe ?
Lii
1
@Lii satu-satunya yang bisa saya lihat adalah bahwa ia menggunakan 3 langkah, bukan 4
CharlesB
52

Sebenarnya cukup mudah untuk dilakukan. Solusinya adalah dengan melakukan rebase interaktif dan "melepaskan" semua komit yang tidak ingin Anda sertakan dalam rebase.

git rebase -i <target_branch> dimana target_branch cabang yang ingin Anda rebase

Kemudian Anda akan mengedit file yang dibuka dan pickkomit yang Anda inginkan dan drop(atau dsingkatnya) semua komit yang tidak ingin Anda bawa.

hrdwdmrbl
sumber
6
IMO solusi yang jauh lebih baik, dan itu benar-benar menjawab pertanyaan itu.
GabrielOshiro
Ini harus menjadi solusi yang diterima mengingat seberapa umum, intuitif, dan singkatnya.
Pablo Arias
1

Tanggapan @Charles benar. Bagaimanapun, saya akhirnya menggunakan ini berkali-kali, terutama untuk mendasarkan kembali konfigurasi tertentu pada sebuah proyek

  * a8f9182 (HEAD -> produksi) konfigurasi produksi
  | * daa18b7 (pra) konfigurasi praproduksi
  | /  
  | * konfigurasi lokal d365f5f (lokal)
  | /  
  * 27d2835 (dev) fitur baru yang luar biasa yang akan menyelamatkan dunia
* | 56d2467 (master) seni membosankan untuk proyek
| /

bahwa saya membuat perintah baru untuk itu:

$ cat ~ / bin / git-rebaseshot 
KOMIT = $ 1
DEST = $ {2: -KEPALA}
git rebase $ {COMMIT} ^ $ {COMMIT} - menjadi $ DEST

biasanya Anda ingin melengkapi nama cabang secara otomatis untuk perintah itu, jadi tambahkan sumber fungsi ini (menambahkan ke .bashrc atau .profile):

_git_rebaseshot () 
{ 
    __gitcomp_nl "$ (__ git_refs)"
}

git autocomplete akan mencarinya

Anda dapat menggunakan perintah ini seperti ini:

# rebase config on prepro on actual HEAD
$ git rebaseshot prepro 
# rebase config on local onto dev
$ git rebaseshot local dev
# rebase production config on master
$ git rebaseshot pro master

Jika Anda membagi fitur dengan benar, kemungkinan tidak terbatas.

* a8f9182 (HEAD -> postgres) konfigurasi BBDD
* a8f9182 (lokal) konfigurasi lokal
* a8f9182 (debug) konfigurasi tingkat log
* a8f9182 (dev) fitur baru
|

Saya rasa inilah yang suka dilakukan orang-orang selimut .

perintah ini akan tetap bekerja dengan sha / ref apa pun yang Anda berikan:

$ git rebaseshot <Feature branch> master
$ git rebaseshot <commit of XX> master
albfan.dll
sumber
//, Dapatkah Anda menautkan ke proyek mana pun yang dapat kita lihat beraksi?
Nathan Basanese
Karena sifatnya, cabang yang tersedia untuk rebaseshot tidak berkomitmen di luar repo lokal. Cukup buat beberapa cabang di atas master (tingkat log, koneksi database, konfigurasi) dan gunakan perintah di antara mereka. Jelas untuk melihat efeknya.
albfan
//, aku mengalami beberapa masalah. Saya akan mencobanya lagi.
Nathan Basanese
0

Berikut opsi lain:

  1. Pastikan Anda memiliki remote dengan salinan cabang fitur
  2. Hapus cabang fitur lokal
  3. Buat dan lakukan pembayaran cabang baru dengan nama yang sama dengan cabang fitur lama yang baru saja Anda hapus dari master
  4. cherry-pilih satu komit dari salinan jarak jauh dari cabang fitur yang Anda inginkan.

Perintah terlihat seperti:

git checkout Feature-branch
git push -u origin HEAD
git checkout master
git branch -D Feature-branch
git checkout -b Feature-branch
git cherry-pick HASH-OF-XX

Ini bukan perintah rebase no, tapi itu rebase dalam semangat.

cdmo
sumber