Edit komit tertentu dan terapkan kembali komit berikutnya

Saat ini saya mengirimkan kode sumber terbuka dan struktur komitmennya cukup ketat. Saya memiliki tiga komit, sebut saja A, B, dan C. Penting untuk dicatat bahwa semua perubahan ada dalam file yang sama.

Selain itu, saya telah menerima umpan balik tentang kode dalam ketiga komitmen tersebut. Apakah mungkin untuk memasukkan kode bertahap, misalnya, melakukan B, mengedit beberapa baris kode, melakukan ulang, lalu menerapkan kembali C tanpa banyak kesulitan?

Cara terbaik yang dapat saya pikirkan saat ini adalah dengan membatalkan ketiga komitmen dan kemudian mengulangi pementasan potongan lagi, yang akan membutuhkan waktu untuk menjadi sempurna, karena beberapa kode berada di dekatnya.


person Hedam    schedule 29.04.2021    source sumber
comment
Saya pikir Anda menginginkan rebase interaktif. Ini akan memberi Anda daftar komitmen dan memungkinkan Anda untuk mengedit atau hanya menerapkan masing-masing komitmen sesuai keinginan.   -  person xdhmoore    schedule 29.04.2021
comment
Masalah serupa di sini dengan solusi serupa yang diusulkan. Mungkin layak untuk dilihat.   -  person RomainValeri    schedule 29.04.2021


Jawaban (2)


Bagaimanapun Anda mencapai hasilnya, setelah selesai, Anda tidak akan menggunakan tiga komitmen awal. Jika Anda diizinkan untuk membiarkan A 100% saja, Anda dapat menyimpan A yang asli, tetapi jika Anda harus menyentuh B, Anda tidak akan memiliki B yang asli lagi, dan oleh karena itu harus membuat salinan C yang baru juga.

Sejauh ini, itu hanya pernyataan fakta, dan bukan saran bagaimana mencapai apa yang Anda inginkan. Cara untuk mendapatkan apa yang inginkan adalah—biasanya—menggunakan git rebase -i.

Katakanlah Anda berada di cabang feature sekarang:

...--o--o--o--o   <-- main
               \
                A--B--C   <-- feature (HEAD)

Anda cukup menjalankan git rebase -i main dan Git muncul dengan lembar instruksi yang memberitahu Git untuk menjaga ketiga komit sebagai berikut:

# instructions
pick <hash-of-A> <subject-of-A>
pick <hash-of-B> <subject-of-B>
pick <hash-of-C> <subject-of-C>

Ubah pick kedua menjadi edit dan tulis kembali lembar instruksi dan keluar dari editor Anda.1 Git sekarang akan mulai dengan mencoba menyalin komit A langsung di tempatnya, dan ini akan berhasil. Kemudian akan dilanjutkan dengan mencoba menyalin komit B di tempatnya, yang juga akan berhasil, tetapi sekarang akan berhenti di tengah-tengah penyalinan ini:

...--o--o--o--o   <-- main
               \
                A--B   <-- HEAD
                    \
                     C   <-- feature

Anda akan berada dalam mode HEAD terpisah, dengan HEAD memilih komit B.

Anda sekarang dapat membuat perubahan pada file yang ingin Anda ubah, git add, dan menjalankan git commit --amend. --amend akan membuat Git membuat komit baru—sebut saja B'—menggunakan komit A sebagai induknya, bukan komit B. Hasilnya terlihat seperti ini:

...--o--o--o--o   <-- main
               \
                A--B'  <-- HEAD
                 \
                  B--C   <-- feature

Anda sekarang dapat menjalankan git rebase --continue untuk membuat Git melanjutkan ke perintah pick C. Ini akan memilih komit C, membuat komit baru yang akan kita sebut C'. Beberapa konflik penggabungan dapat terjadi di sini, karena cherry-pick sebenarnya adalah penggabungan. Jika demikian, Anda harus memperbaikinya dan melanjutkan lagi sebelum penerapan C' dapat dilakukan. Namun, jika tidak ada konflik yang terjadi, kita sekarang berada dalam kondisi ini:

...--o--o--o--o   <-- main
               \
                A--B'-C'  <-- HEAD
                 \
                  B--C   <-- feature

Ini menyelesaikan serangkaian operasi yang harus dilakukan oleh rebase interaktif, jadi sekarang ia melakukan trik terakhir dari apa saja rebase, yaitu menarik nama cabang ke sini (di mana pun HEAD sekarang) dan kembali lampirkan HEAD Anda:

...--o--o--o--o   <-- main
               \
                A--B'-C'  <-- feature (HEAD)
                 \
                  B--C   [abandoned]

Jika Anda ingin melihat komit asli, komit tersebut masih ada: Anda hanya perlu menemukan ID hash dari komit asli C. Ini tersedia di:

  • ORIG_HEAD, hanya sebentar (karena ORIG_HEAD terus ditimpa);
  • reflog untuk HEAD, setidaknya selama 30 hari lagi secara default; Dan
  • reflog untuk cabang feature, setidaknya selama 30 hari lagi secara default.

Entri reflog memiliki nama dengan akhiran numerik: feature@{1}. Anda juga dapat menggunakan nama yang berhubungan dengan waktu, seperti HEAD@{yesterday}. Secara umum, jika suatu nama mengalami lebih dari satu perubahan dalam jangka waktu tertentu, Anda sebaiknya menjalankan git reflog, daripada mencoba menebak sesuatu seperti kemarin.10.am.


1Jika Anda memiliki editor yang sudah berjalan lama (beberapa varian emacs, atom, dll), gunakan metode apa pun untuk memberi sinyal kembali ke Git yang menunggu bahwa file ini sudah selesai sekarang dan Git harus dilanjutkan .

person torek    schedule 29.04.2021
comment
git rebase -i menggunakan edit adalah apa yang saya cari. Terima kasih atas jawaban Anda yang sangat jelas. - person Hedam; 29.04.2021

Mungkin.

Saya paranoid dengan Git, jadi saya selalu melangkah lambat.

  1. Buat cabang baru dari komit A (komit pertama, saya berasumsi)
  2. Git mengubah komit terakhir, yang seharusnya A, dan Anda dapat memperbarui komentar. Anda mendapatkan A' - ini seperti A tetapi komitmen baru karena Anda memutasinya
  3. Git cherry pick melakukan B ke cabang baru. Git mengubah komit terakhir, yang akan menjadi B' (itu dipilih dengan baik, jadi komit baru juga)
  4. Git cherry pick komit C ke cabang baru. Anda mengerti idenya.

Ini adalah pendekatan yang aman. Komit asli Anda masih di cabang asli. Cabang baru Anda memiliki komitmen logis yang sama, tetapi dengan perubahan yang Anda inginkan.

Dorong cabang baru ke git hub. Bekerjalah dengan yang itu.

person Jevon Kendon    schedule 29.04.2021
comment
Ini adalah metode manual yang dilakukan git rebase setelah membuat nama cabang baru yang menunjuk ke komit akhir yang sama dengan cabang yang ada. Tidak ada yang salah dengan cara ini, hanya saja lebih berhasil daripada menggunakan git rebase -i. - person torek; 29.04.2021
comment
Anda adalah jiwa pemberani. Saya akan melihat apakah saya bisa merasa lebih nyaman dengan rebase. - person Jevon Kendon; 29.04.2021
comment
@JevonKendon Saya mengambil cadangan folder sebelum melakukan rebasing. Meskipun demikian, saya hanya akan menekan paksa untuk memastikan semuanya baik-baik saja, jadi saya dapat memulihkan dari jarak jauh jika saya melakukan kesalahan. - person Hedam; 29.04.2021