Pertanyaan Pecahkan komitmen sebelumnya menjadi beberapa komit


Tanpa membuat cabang dan melakukan banyak pekerjaan yang funky di cabang baru, apakah mungkin untuk membobol satu komit menjadi beberapa komit yang berbeda setelah berkomitmen terhadap repositori lokal?


831
2018-06-02 16:11


asal


Jawaban:


git rebase -i akan melakukannya.

Pertama, mulailah dengan direktori kerja bersih: git status tidak boleh menunjukkan modifikasi, penghapusan, atau penambahan yang tertunda.

Untuk memecah commit terakhir Anda, pertama-tama:

$ git reset HEAD~

Sekarang lakukan potongan-potongan secara individual dengan cara biasa, menghasilkan sebanyak mungkin commit yang Anda butuhkan.

Jika itu lebih jauh kembali ke pohon, lalu

$ git rebase -i HEAD~3

dimana 3 berapa banyak yang membalasnya.

Jika itu lebih jauh kembali ke pohon dari yang Anda ingin hitung, lalu

$ git rebase -i 123abcd~

dimana 123abcd adalah SHA1 dari komitmen yang ingin Anda bagi.

Saat Anda mendapatkan layar edit rebase, temukan commit yang ingin Anda pecah. Di awal baris itu, ganti pick dengan edit (e Ringkasnya). Simpan buffer dan keluar. Rebase sekarang akan berhenti tepat setelah komit yang ingin Anda edit. Kemudian:

$ git reset HEAD~

Komit potongan-potongan individual dengan cara biasa, menghasilkan sebanyak komit yang Anda butuhkan, kemudian

$ git rebase --continue

1279
2018-06-02 16:26



Dari git-rebase manual (bagian KOMITMEN SPLITTING)

Dalam mode interaktif, Anda dapat menandai commit dengan aksi "edit". Namun, ini tidak berarti bahwa git rebase mengharapkan hasil dari pengeditan ini menjadi persis satu komit. Memang, Anda dapat membatalkan komit, atau Anda dapat menambahkan komit lain. Ini dapat digunakan untuk membagi komit menjadi dua:

  • Mulai rebase interaktif dengan git rebase -i <commit>^, dimana <commit> adalah komitmen yang ingin Anda bagi. Bahkan, setiap rentang komit akan dilakukan, selama mengandung komit itu.

  • Tandai komit yang ingin Anda bagi dengan aksi "edit".

  • Ketika datang untuk mengedit yang melakukan, jalankan git reset HEAD^. Efeknya adalah bahwa HEAD di-rewound oleh satu, dan indeks mengikuti. Namun, pohon kerja tetap sama.

  • Sekarang tambahkan perubahan pada indeks yang ingin Anda miliki pada commit pertama. Kamu dapat memakai git add (mungkin secara interaktif) atau git gui (atau keduanya) untuk melakukan itu.

  • Komit sekarang indeks saat ini dengan pesan komitmen apa pun yang sesuai sekarang.

  • Ulangi dua langkah terakhir hingga pohon kerja Anda bersih.

  • Lanjutkan rebase dengan git rebase --continue.


244
2018-01-22 15:05



Menggunakan git rebase --interactive untuk mengedit commit sebelumnya, jalankan git reset HEAD~, lalu git add -p untuk menambahkan beberapa, lalu buat komit, lalu tambahkan lagi dan buat komitmen lain, sebanyak yang Anda suka. Setelah selesai, jalankan git rebase --continue, dan Anda akan memiliki semua komitmen perpecahan sebelumnya di tumpukan Anda.

Penting: Perhatikan bahwa Anda dapat bermain-main dan membuat semua perubahan yang Anda inginkan, dan tidak perlu khawatir tentang kehilangan perubahan lama, karena Anda selalu dapat menjalankan git reflog untuk menemukan titik dalam proyek Anda yang berisi perubahan yang Anda inginkan, (sebut saja a8c4ab), lalu git reset a8c4ab.

Berikut ini serangkaian perintah untuk menunjukkan cara kerjanya:

mkdir git-test; cd git-test; git init

sekarang tambahkan file A

vi A

tambahkan baris ini:

one

git commit -am one

kemudian tambahkan baris ini ke A:

two

git commit -am two

kemudian tambahkan baris ini ke A:

three

git commit -am three

sekarang file A terlihat seperti ini:

one
two
three

dan kita git log terlihat seperti berikut (baik, saya gunakan git log --pretty=oneline --pretty="%h %cn %cr ---- %s"

bfb8e46 Rose Perrone 4 seconds ago ---- three
2b613bc Rose Perrone 14 seconds ago ---- two
9aac58f Rose Perrone 24 seconds ago ---- one

Katakanlah kita ingin membagi commit kedua, two.

git rebase --interactive HEAD~2

Ini menampilkan pesan yang terlihat seperti ini:

pick 2b613bc two
pick bfb8e46 three

Ubah yang pertama pick ke sebuah e untuk mengedit komit itu.

git reset HEAD~

git diff menunjukkan kepada kita bahwa kita baru saja menghentikan komit yang kita buat untuk komit kedua:

diff --git a/A b/A
index 5626abf..814f4a4 100644
--- a/A
+++ b/A
@@ -1 +1,2 @@
 one
+two

Mari kita pentas perubahan itu, dan tambahkan "dan yang ketiga" ke baris itu dalam file A.

git add .

Biasanya ini adalah titik saat rebase interaktif di mana kita akan berlari git rebase --continue, karena kami biasanya hanya ingin kembali ke tumpukan komit untuk mengedit commit sebelumnya. Tapi kali ini, kami ingin membuat komitmen baru. Jadi kita akan lari git commit -am 'two and a third'. Sekarang kita edit file A dan tambahkan garis two and two thirds.

git add . git commit -am 'two and two thirds' git rebase --continue

Kami memiliki konflik dengan komitmen kami, three, jadi mari kita selesaikan:

Kami akan berubah

one
<<<<<<< HEAD
two and a third
two and two thirds
=======
two
three
>>>>>>> bfb8e46... three

untuk

one
two and a third
two and two thirds
three

git add .; git rebase --continue

Sekarang kami git log -p terlihat seperti ini:

commit e59ca35bae8360439823d66d459238779e5b4892
Author: Rose Perrone <roseperrone@fake.com>
Date:   Sun Jul 7 13:57:00 2013 -0700

    three

diff --git a/A b/A
index 5aef867..dd8fb63 100644
--- a/A
+++ b/A
@@ -1,3 +1,4 @@
 one
 two and a third
 two and two thirds
+three

commit 4a283ba9bf83ef664541b467acdd0bb4d770ab8e
Author: Rose Perrone <roseperrone@fake.com>
Date:   Sun Jul 7 14:07:07 2013 -0700

    two and two thirds

diff --git a/A b/A
index 575010a..5aef867 100644
--- a/A
+++ b/A
@@ -1,2 +1,3 @@
 one
 two and a third
+two and two thirds

commit 704d323ca1bc7c45ed8b1714d924adcdc83dfa44
Author: Rose Perrone <roseperrone@fake.com>
Date:   Sun Jul 7 14:06:40 2013 -0700

    two and a third

diff --git a/A b/A
index 5626abf..575010a 100644
--- a/A
+++ b/A
@@ -1 +1,2 @@
 one
+two and a third

commit 9aac58f3893488ec643fecab3c85f5a2f481586f
Author: Rose Perrone <roseperrone@fake.com>
Date:   Sun Jul 7 13:56:40 2013 -0700

    one

diff --git a/A b/A
new file mode 100644
index 0000000..5626abf
--- /dev/null
+++ b/A
@@ -0,0 +1 @@
+one

34
2017-07-07 21:10



Jawaban sebelumnya telah mencakup penggunaan git rebase -i untuk mengedit komit yang ingin Anda bagi, dan melakukannya dalam beberapa bagian.

Ini berfungsi dengan baik saat membagi file menjadi komit yang berbeda, tetapi jika Anda ingin memecah perubahan pada file individual, ada lebih banyak yang perlu Anda ketahui.

Setelah sampai pada komitmen yang ingin Anda bagi, gunakan rebase -i dan menandainya edit, Anda memiliki dua opsi.

  1. Setelah menggunakan git reset HEAD~, pergi melalui patch secara individual menggunakan git add -p untuk memilih yang Anda inginkan di setiap commit

  2. Edit copy pekerjaan untuk menghapus perubahan yang tidak Anda inginkan; melakukan itu negara sementara; dan kemudian tarik kembali komitmen penuh untuk putaran berikutnya.

Opsi 2 berguna jika Anda membagi commit besar, karena memungkinkan Anda memeriksa bahwa versi sementara dibangun dan berjalan dengan baik sebagai bagian dari penggabungan. Ini hasil sebagai berikut.

Setelah menggunakan rebase -i dan editing komit, gunakan

git reset --soft HEAD~

untuk membatalkan komit, tetapi tinggalkan file-file yang berkomitmen dalam indeks. Anda juga dapat melakukan reset campuran dengan menghilangkan --soft, tergantung pada seberapa dekat hasil akhir dari komitmen awal Anda nantinya. Satu-satunya perbedaan adalah apakah Anda mulai dengan semua perubahan yang dipentaskan atau dengan mereka semua tidak berubah.

Sekarang masuk dan edit kodenya. Anda dapat menghapus perubahan, menghapus file yang ditambahkan, dan melakukan apa pun yang Anda inginkan untuk membangun komitmen pertama dari seri yang Anda cari. Anda juga dapat membuatnya, menjalankannya, dan mengonfirmasi bahwa Anda memiliki kumpulan sumber yang konsisten.

Setelah Anda senang, lakukan stage / unstage file sesuai kebutuhan (saya suka menggunakannya git gui untuk ini), dan komit perubahan melalui UI atau baris perintah

git commit

Itu adalah komitmen pertama yang dilakukan. Sekarang Anda ingin mengembalikan copy pekerjaan Anda ke keadaan setelah komit Anda membelah, sehingga Anda dapat mengambil lebih banyak perubahan untuk commit berikutnya. Untuk menemukan sha1 dari komit yang Anda edit, gunakan git status. Dalam beberapa baris pertama status, Anda akan melihat perintah rebase yang saat ini sedang dijalankan, di mana Anda dapat menemukan sha1 dari commit asli Anda:

$ git status
interactive rebase in progress; onto be83b41
Last commands done (3 commands done):
   pick 4847406 US135756: add debugging to the file download code
   e 65dfb6a US135756: write data and download from remote
  (see more in file .git/rebase-merge/done)
...

Dalam hal ini, komit yang saya edit memiliki SHA1 65dfb6a. Mengetahui itu, saya dapat memeriksa konten yang melakukan alih direktori kerja saya menggunakan bentuk git checkout yang mengambil baik komit dan lokasi file. Di sini saya gunakan . sebagai lokasi file untuk menggantikan seluruh copy pekerjaan:

git checkout 65dfb6a .

Jangan lewatkan titik di ujungnya!

Ini akan memeriksa, dan menampilkan, file seperti setelah komit yang Anda edit, tetapi relatif terhadap komitmen sebelumnya yang Anda buat, jadi perubahan apa pun yang sudah Anda lakukan tidak akan menjadi bagian dari commit.

Anda dapat melanjutkan sekarang dan berkomitmen untuk menyelesaikan split, atau berkeliling lagi, menghapus beberapa bagian dari commit sebelum membuat komit sementara lain.

Jika Anda ingin menggunakan kembali pesan komit asli untuk satu atau lebih commit, Anda dapat menggunakannya langsung dari file kerja rebase:

git commit --file .git/rebase-merge/message

Akhirnya, setelah Anda melakukan semua perubahan,

git rebase --continue

akan melanjutkan dan menyelesaikan operasi rebase.


19
2018-03-31 10:23



git rebase --interactive dapat digunakan untuk membagi komit menjadi komit yang lebih kecil. Itu Git docs on rebase memiliki panduan singkat dari proses - Memisahkan Komit:

Dalam mode interaktif, Anda dapat menandai commit dengan aksi "edit". Namun, ini tidak selalu berarti demikian git rebase mengharapkan hasil dari pengeditan ini menjadi tepat satu komit. Memang, Anda dapat membatalkan komit, atau Anda dapat menambahkan komit lain. Ini dapat digunakan untuk membagi komit menjadi dua:

  • Mulai rebase interaktif dengan git rebase -i <commit>^, dimana <commit> adalah komitmen yang ingin Anda bagi. Bahkan, setiap rentang komit akan dilakukan, selama mengandung komit itu.

  • Tandai komit yang ingin Anda bagi dengan aksi "edit".

  • Ketika datang untuk mengedit yang melakukan, jalankan git reset HEAD^. Efeknya adalah bahwa HEAD di-rewound oleh satu, dan indeks mengikuti. Namun, pohon kerja tetap sama.

  • Sekarang tambahkan perubahan pada indeks yang ingin Anda miliki pada commit pertama. Kamu dapat memakai git add (mungkin secara interaktif) atau git gui (atau keduanya) untuk melakukan itu.

  • Komit sekarang indeks saat ini dengan pesan komitmen apa pun yang sesuai sekarang.

  • Ulangi dua langkah terakhir hingga pohon kerja Anda bersih.

  • Lanjutkan rebase dengan git rebase --continue.

Jika Anda tidak benar-benar yakin bahwa revisi menengah konsisten (mereka mengkompilasi, lulus testsuite, dll), Anda harus menggunakan git stash untuk menyembunyikan perubahan yang belum berkomitmen setelah setiap commit, menguji, dan mengubah komitmen jika diperlukan perbaikan.


17
2017-07-14 22:25



Anda dapat melakukan rebase interaktif git rebase -i. Halaman manual memiliki apa yang Anda inginkan:

http://git-scm.com/docs/git-rebase#_splitting_commits


10
2018-06-02 16:15



Harap dicatat juga ada git reset --soft HEAD^. Ini mirip dengan git reset (yang default ke --mixed) tetapi mempertahankan isi indeks. Sehingga jika Anda telah menambahkan / menghapus file, Anda sudah memilikinya dalam indeks.

Ternyata sangat berguna dalam kasus komit raksasa.


7
2017-11-27 15:23



Sekarang di TortoiseGit terbaru di Windows Anda dapat melakukannya dengan sangat mudah.

Buka dialog rebase, konfigurasikan, dan lakukan langkah-langkah berikut.

  • Klik kanan komit yang ingin Anda bagi dan pilih "Edit"(di antara pick, squash, delete ...).
  • Klik "Start"untuk memulai rebase.
  • Setelah sampai pada komitmen untuk membagi, periksa "Edit/Split"tombol dan klik "Amend"secara langsung. Dialog komit terbuka.
    Edit/Split commit
  • Batalkan pilihan file yang ingin Anda masukkan pada commit terpisah.
  • Edit pesan commit, lalu klik "commit".
  • Sampai ada file untuk dikomit, dialog komit akan terbuka lagi dan lagi. Ketika tidak ada lagi file yang perlu dikomit, masih akan menanyakan apakah Anda ingin menambahkan satu commit lagi.

Sangat membantu, terima kasih TortoiseGit!


7
2018-04-22 10:32