Pertanyaan Bagaimana cara memodifikasi commit tertentu di git?


Saya biasanya mengajukan daftar komitmen untuk ditinjau. Jika saya punya:

  • HEAD 
  • Commit3 
  • Commit2 
  • Commit1

Saya tahu bahwa saya dapat memodifikasi komit dengan kepala git commit --amend, tapi bagaimana saya bisa memodifikasi Commit1, mengingat bahwa itu bukan HEAD melakukan?


1700
2017-07-27 05:19


asal


Jawaban:


Anda dapat menggunakan git rebase, misalnya, jika Anda ingin memodifikasi kembali untuk melakukan bbc643cd, lari

$ git rebase --interactive 'bbc643cd^'

Di editor default, ubah pick untuk edit di garis yang komit Anda ingin memodifikasi. Buat perubahan Anda dan kemudian lakukan dengan pesan yang sama seperti sebelumnya:

$ git commit --all --amend --no-edit

untuk mengubah komit, dan setelah itu

$ git rebase --continue

untuk kembali ke komit sebelumnya.

PERINGATAN: Perhatikan bahwa ini akan mengubah SHA-1 yang melakukan serta semua anak - dengan kata lain, ini menulis ulang sejarah dari titik itu ke depan. Anda dapat mematahkan repo melakukan ini jika Anda mendorong menggunakan perintah git push --force


2232
2017-07-27 05:28



Gunakan rebase interaktif yang mengagumkan:

git rebase -i @~9   # Show the last 9 commits in a text editor

Temukan komitmen yang Anda inginkan, ubah pick untuk e (edit), dan simpan dan tutup file. Git akan memundurkan ke commit itu, memungkinkan Anda untuk:

  • menggunakan git commit --amend untuk melakukan perubahan, atau
  • menggunakan git reset @~ untuk membuang commit terakhir, tetapi tidak mengubah file (yaitu membawa Anda ke titik di mana Anda mengedit file, tetapi belum melakukannya).

Yang terakhir ini berguna untuk melakukan hal-hal yang lebih kompleks seperti membagi menjadi beberapa komit.

Lalu lari git rebase --continue, dan Git akan memutar ulang perubahan selanjutnya di bagian atas komitmen Anda yang dimodifikasi. Anda mungkin diminta untuk memperbaiki beberapa konflik gabungan.

catatan: @ adalah singkatan untuk HEAD, dan ~ adalah commit sebelum commit yang ditentukan.

Baca lebih lanjut tentang menulis ulang sejarah dalam dokumen Git.


Jangan takut untuk melakukan rebase

ProTip: Jangan takut untuk bereksperimen dengan perintah "berbahaya" yang menulis ulang riwayat * - Git tidak menghapus commit Anda selama 90 hari secara default; Anda dapat menemukannya di reflog:

$ git reset @~3   # go back 3 commits
$ git reflog
c4f708b HEAD@{0}: reset: moving to @~3
2c52489 HEAD@{1}: commit: more changes
4a5246d HEAD@{2}: commit: make important changes
e8571e4 HEAD@{3}: commit: make some changes
... earlier commits ...
$ git reset 2c52489
... and you're back where you started

* Hati-hati untuk opsi seperti --hard dan --force meskipun - mereka dapat membuang data.
* Juga, jangan menulis ulang sejarah di cabang mana pun Anda berkolaborasi.



Di banyak sistem, git rebase -i akan membuka Vim secara default. Vim tidak berfungsi seperti kebanyakan editor teks modern, jadi lihatlah cara melakukan rebase menggunakan Vim. Jika Anda lebih suka menggunakan editor yang berbeda, ubahlah dengan git config --global core.editor your-favorite-text-editor.


304
2018-04-29 17:50



Interaktif rebase dengan --autosquash adalah sesuatu yang sering saya gunakan ketika saya harus memperbaiki sebelumnya melakukan lebih dalam dalam sejarah. Pada dasarnya ini mempercepat proses yang diilustrasikan oleh jawaban ZelluX, dan sangat berguna ketika Anda memiliki lebih dari satu komitmen yang perlu Anda edit.

Dari dokumentasi:

--autosquash

Ketika pesan log commit dimulai dengan "squash! ..." (atau "fixup! ..."), dan ada komit yang judulnya dimulai dengan yang sama ..., secara otomatis memodifikasi daftar todo dari rebase -i sehingga commit ditandai untuk meremas datang tepat setelah komit dimodifikasi

Asumsikan Anda memiliki riwayat yang terlihat seperti ini:

$ git log --graph --oneline
* b42d293 Commit3
* e8adec4 Commit2
* faaf19f Commit1

dan Anda memiliki perubahan yang ingin Anda ubah ke Commit2 lalu komit perubahan Anda gunakan

$ git commit -m "fixup! Commit2"

atau Anda dapat menggunakan commit-sha sebagai ganti dari pesan commit, jadi "fixup! e8adec4 atau bahkan hanya awalan pesan komit.

Kemudian lakukan rebase interaktif pada commit sebelumnya

$ git rebase e8adec4^ -i --autosquash

editor Anda akan terbuka dengan komit yang sudah dipesan dengan benar

pick e8adec4 Commit2
fixup 54e1a99 fixup! Commit2
pick b42d293 Commit3

yang perlu Anda lakukan hanyalah menyimpan dan keluar


57
2017-09-29 17:59



Menjalankan:

$ git rebase --interactive commit_hash^

setiap ^ menunjukkan berapa banyak commit yang ingin Anda edit, jika hanya satu (hash komit yang Anda tentukan), maka Anda cukup menambahkan satu ^.

Menggunakan Vim Anda mengubah kata-kata pick untuk reword untuk komit yang ingin Anda ubah, simpan dan berhenti (:wq). Kemudian git akan meminta Anda dengan setiap commit yang Anda tandai sebagai reword sehingga Anda dapat mengubah pesan commit.

Setiap pesan komit Anda harus menyimpan dan berhenti (:wq) untuk membuka pesan commit berikutnya

Jika Anda ingin keluar tanpa menerapkan perubahan, tekan :q!

EDIT: untuk menavigasi vim Kau gunakan j naik, k ke bawah, h ke kiri, dan l untuk pergi ke kanan (semua ini masuk NORMAL mode, tekan ESC pergi ke NORMAL mode). Untuk mengedit teks, tekan i sehingga Anda memasukkan INSERT mode, tempat Anda memasukkan teks. tekan ESC untuk kembali ke NORMAL mode :)

MEMPERBARUI: Ini tautan hebat dari daftar github Bagaimana cara membatalkan (hampir) apa pun dengan git 


30
2017-07-02 19:11



Jika karena alasan tertentu Anda tidak menyukai editor interaktif, Anda dapat menggunakannya git rebase --onto.

Katakanlah Anda ingin memodifikasi Commit1. Pertama, cabang dari sebelum  Commit1:

git checkout -b amending [commit before Commit1]

Kedua, ambil Commit1 dengan cherry-pick:

git cherry-pick Commit1

Sekarang, ubah perubahan Anda, buat Commit1':

git add ...
git commit --amend -m "new message for Commit1"

Dan akhirnya, setelah menyembunyikan perubahan lain, lakukan transplantasi sisa komitmen Anda master di atas kamu komit baru:

git rebase --onto amending Commit1 master

Baca: "rebase, ke cabang amending, semua komit di antaranya Commit1 (tidak inklusif) dan master (inklusif) ". Artinya, Commit2 dan Commit3, memotong Commit1 lama sepenuhnya. Anda hanya bisa memilihnya, tetapi cara ini lebih mudah.

Ingatlah untuk membersihkan cabang Anda!

git branch -d amending

12
2017-10-22 12:19



Datang ke pendekatan ini (dan itu mungkin persis sama dengan menggunakan rebase interaktif) tetapi bagi saya itu agak mudah.

Catatan: Saya menyajikan pendekatan ini demi ilustrasi tentang apa yang dapat Anda lakukan daripada alternatif sehari-hari. Karena memiliki banyak langkah (dan mungkin beberapa peringatan.)

Katakanlah Anda ingin mengubah komit 0 dan Anda sedang aktif feature-branch

some-commit---0---1---2---(feature-branch)HEAD

Checkout untuk ini berkomitmen dan membuat quick-branch. Anda juga dapat mengkloning cabang fitur Anda sebagai titik pemulihan (sebelum memulai).

?(git checkout -b feature-branch-backup)
git checkout 0
git checkout -b quick-branch

Anda sekarang akan memiliki sesuatu seperti ini:

0(quick-branch)HEAD---1---2---(feature-branch)

Perubahan panggung, menyimpan semua yang lain.

git add ./example.txt
git stash

Lakukan perubahan dan periksa kembali feature-branch

git commit --amend
git checkout feature-branch

Anda sekarang akan memiliki sesuatu seperti ini:

some-commit---0---1---2---(feature-branch)HEAD
           \
             ---0'(quick-branch)

Rebase feature-branch ke quick-branch (selesaikan setiap konflik di sepanjang jalan). Terapkan simpanan dan hapus quick-branch.

git rebase quick-branch
git stash pop
git branch -D quick-branch

Dan Anda berakhir dengan:

some-commit---0'---1'---2'---HEAD(feature-branch)

Git tidak akan menduplikasi (walaupun saya tidak bisa benar-benar mengatakan sampai sejauh mana) 0 komit ketika melakukan rebase.

Catatan: semua commit hash diubah mulai dari commit yang semula kita inginkan untuk diubah.


6
2018-06-01 11:57



Untuk mendapatkan perintah non-interaktif, letakkan skrip dengan konten ini di PATH Anda:

#!/bin/sh
#
# git-fixup
# Use staged changes to modify a specified commit
set -e
cmt=$(git rev-parse $1)
git commit --fixup="$cmt"
GIT_EDITOR=true git rebase -i --autosquash "$cmt~1"

Gunakan dengan mementaskan perubahan Anda (dengan git add) dan kemudian jalankan git fixup <commit-to-modify>. Tentu saja, ini akan tetap interaktif jika Anda mengalami konflik.


4
2018-01-16 15:27