Bagaimana cara mengubah komitmen masa lalu untuk menyertakan file yang terlewat?

98

Saya telah melakukan perubahan dan lupa menambahkan file ke set perubahan. Setelah komit lainnya, saya menyadari bahwa file tersebut sekarang hilang dari HEAD^4komit.

Bagaimana cara menulis ulang komit sebelumnya untuk menyertakan file yang hilang?

kolrie
sumber
apakah Anda mendorong 4 komit ini?
mvp
@mvp tidak, mereka hanya ada di repositori git lokal saya.
kolrie

Jawaban:

53

Gunakan git rebase --interactive HEAD~4dan setel editopsi untuk komit yang ingin Anda ubah.

Ingatlah bahwa Anda tidak boleh memodifikasi komit yang didorong ke repositori jarak jauh dengan cara ini. Lebih baik menambahkan komit baru dengan file yang hilang dalam kasus itu.

Rafał Rawicki
sumber
Terima kasih. Apakah itu masalahnya meskipun saya satu-satunya pengguna repo jarak jauh? Tidakkah itu mengizinkan saya melakukannya git push -fjika saya yakin upstream tidak berubah?
kolrie
1
Jika Anda adalah satu-satunya pengguna repo jarak jauh, tidak masalah untuk melakukan push paksa.
Rafał Rawicki
7
Saya pikir instruksi ini tidak cukup rinci. Saat mencobanya, pertama kali saya diberi tahu "Tidak bisa rebase: Indeks Anda berisi perubahan yang tidak mengikat." Saya sudah add-ed file yang hilang, jadi saya melakukan komit dengan "xxx" sebagai pesan. Kemudian saya melakukan perintah rebase, dan mengubah "xxx" commit dari "pick" menjadi "edit". Kemudian saya melakukan "git rebase --continue". Sekarang ketika saya melihat riwayat saya memiliki "xxx" sebagai komit terbaru, dan komit sebelumnya yang ingin saya tambahkan tidak berubah! Saya ingin tahu di mana kesalahan saya?
Darren Cook
2
Menekan komit terakhir tidak akan menempatkan file di HEAD ~ 4.
Justin
1
git menambahkan editedFiles; git commit -m "Blah"; git rebase -i HEAD ~ 5; // karena sekarang komit baru ditambahkan jadi kita perlu melakukan rebase dengan 5, bukan 4. sekarang pindahkan "Blah" commit ke baris kedua dan ubah dari "Pilih" menjadi "s" (squash) yang akan menghentikan komit dengan HEAD ~ 5 karena perintah dieksekusi dari atas ke bawah
zstring
274

Saya menyadari orang-orang dapat mencari di Google dan datang ke sini untuk menemukan jawaban yang lebih sederhana: Bagaimana jika itu hanya komitmen terakhir? (Pertanyaan OP adalah untuk memperbaiki komit ke-4 dalam sejarah)

Jika Anda berkomitmen dan menyadari bahwa Anda lupa untuk segera menambahkan beberapa file , lakukan saja:

# edited file-that-i-remember.txt
git add file-that-i-remember.txt
git commit

# realize you forgot a file
git add file-that-i-forgot.txt
git commit --amend --no-edit

Di mana --no-editakan menyimpan pesan komit yang sama.

Sangat mudah!

Dr Beco
sumber
21
Inilah jawabannya.
Adam Bittlingmayer
5
Perlu disebutkan, jika komit tidak didorong ke remote.
Ram Patra
1
Ya, perlu disebutkan di sini di komentar: Ini untuk digunakan sebelum push . Terima kasih telah menunjukkannya.
Dr Beco
2
Satu pemberitahuan adalah bahwa komit sebelum dan sesudah --amendmemiliki hash yang berbeda
sonlexqt
5
Terima kasih, tetapi tidak mungkin: OP diminta HEAD^4. Tidak apa-apa seperti itu, hanya sebagai tambahan untuk referensi. ;)
Dr Beco
11

Jika Anda BELUM mendorong 4 komit ini, Anda dapat melakukannya sebagai berikut:

Buat file patch untuk semua komit ini:

git format-patch -4

Mundur kembali dengan 4 komit:

git reset --hard HEAD~4

Tambahkan file yang hilang:

git add missing-file

Lakukan dengan --amend:

git commit --amend

Terapkan kembali semua tambalan yang disimpan:

git am *.patch

Jika Anda telah mendorong, Anda TIDAK boleh menggunakan metode ini. Sebagai gantinya, akui saja kesalahan Anda dan buat satu komitmen lagi di atas HEAD yang memperbaiki masalah ini.

mvp
sumber
Jika Anda ingin melakukan ini selangkah demi selangkah, lebih mudah untuk melakukan cherry-pick komit setelah yang dimodifikasi, daripada mengekspornya sebagai tambalan.
Rafał Rawicki
1
Ini masalah selera. Saya suka git format-patch/ git amjauh lebih baik. Yang terpenting, ini memberi Anda lebih percaya diri jika Anda mengacaukan sesuatu - komit disimpan sebagai tambalan dalam file fisik adalah jaring pengaman terbaik Anda.
mvp
Keyakinan sebenarnya terletak pada kenyataan, bahwa ketika mengoperasikan git repository Anda tidak pernah menghapus apa pun. git gc
Komit
Ini sepele dan jelas bagi Anda dan saya. Tetapi, untuk pengguna yang baru memulai dan mungkin tidak mengerti apa-apa tentang git - fakta ini sama sekali tidak jelas.
mvp
2
Instruksi ini tampaknya bertele-tele, tetapi cukup sederhana dan mudah diikuti. Terima kasih. (Aku baru saja menambahkan langkah terakhir: rm *.patch)
Darren Masak
9

Meskipun jawaban yang diterima benar, namun tidak memiliki instruksi rinci tentang bagaimana melakukan pengeditan komit selama proses rebase.

  • Pertama, mulailah proses rebase:

    git rebase --interactive HEAD~4
    
  • Daftar komit akan disajikan, pilih komit yang ingin Anda edit dengan mengubah kata pickmenjadi editdan simpan file.

  • Lakukan modifikasi yang diperlukan dalam kode Anda (ingat untuk meminta git addfile baru)

  • Setelah semua modifikasi selesai, terbitkan git commit --amend- ini akan mengubah komit yang ditandai sebagaiedit

  • Panggil git rebase --continueyang akan menyelesaikan proses (jika ada lebih banyak komit yang ditandai sebagai edit, langkah di atas perlu diulangi)

Catatan penting:

  • JANGAN hapus baris bertanda pickyang tidak ingin Anda edit - biarkan apa adanya. Menghapus baris ini akan mengakibatkan penghapusan komitmen terkait

  • GIT memaksa Anda stashsebelum melakukan rebasing jika direktori kerja Anda tidak bersih; Anda bisa bagaimanapun git stash pop / git stash applyselama rebase, untuk mengubah perubahan ini (yaitu perubahan disimpan sebelum memulai proses rebase) menjadi komit yang ditandai sebagaiedit

  • jika terjadi kesalahan dan Anda ingin mengembalikan perubahan yang dibuat selama proses rebase sebelum selesai (yaitu Anda ingin kembali ke titik sebelum memulai rebase), gunakan git rebase --abort- baca juga: Cara membatalkan rebase interaktif jika --abort tidak ' t bekerja?

  • Seperti yang dikatakan dalam jawaban yang diterima:

    Ingatlah bahwa Anda tidak boleh memodifikasi komit yang didorong ke repositori jarak jauh dengan cara ini. Lebih baik menambahkan komit baru dengan file yang hilang dalam kasus itu.

    Jawabannya ada di Buku Git (paragraf berjudul " The Perils of Rebasing "):

    Jangan rebase komitmen yang ada di luar repositori Anda.

    Jika Anda mengikuti pedoman itu, Anda akan baik-baik saja. Jika tidak, orang akan membenci Anda, dan Anda akan dicemooh oleh teman dan keluarga.

    Saat Anda melakukan rebase, Anda meninggalkan komitmen yang ada dan membuat yang baru yang serupa tetapi berbeda. Jika Anda mendorong komitmen di suatu tempat dan orang lain menariknya ke bawah dan mendasarkannya pada mereka, lalu Anda menulis ulang komitmen tersebut dengan git rebase dan mendorongnya lagi, kolaborator Anda harus menggabungkan kembali pekerjaan mereka dan hal-hal akan menjadi berantakan saat Anda mencoba melakukannya. menarik pekerjaan mereka kembali ke pekerjaan Anda.

    [...]

dominik
sumber