Edit root komit di Git?

328

Ada beberapa cara untuk mengubah pesan dari commit di kemudian hari:

git commit --amend                    # for the most recent commit
git rebase --interactive master~2     # but requires *parent*

Bagaimana Anda bisa mengubah pesan komit dari komit pertama (yang tidak memiliki orang tua)?

13rn
sumber
Secara khusus: penggunaan variabel lingkungan GIT_COMMIT dalam skripgit filter-branch --msg-filter
fork0
1
lihat juga stackoverflow.com/a/2309391/264607
BlackICE

Jawaban:

284

Dengan asumsi bahwa Anda memiliki pohon kerja yang bersih, Anda dapat melakukan hal berikut.

# checkout the root commit
git checkout <sha1-of-root>

# amend the commit
git commit --amend

# rebase all the other commits in master onto the amended root
git rebase --onto HEAD HEAD master
CB Bailey
sumber
23
Saya percaya ini seharusnya git rebase --onto HEAD <sha1-of-root> master.
Andrew
5
Benar, tetapi Anda ingin komit root asli untuk <upstream> dari git rebase. git rebaseberlaku komit di <branch> ( master) yang tidak ada di <upstream>; HEADtidak ada master, jadi versi Anda mencoba menerapkan semuanya master.
Andrew
7
Ya, pastikan itu git rebase --onto HEAD <sha1-of-root>master, di mana <sha1-of-root>sama digunakan di git checkout <sha1-of-root>. Kalau tidak, Anda akan memiliki 2 first commit.
Andy
2
@Cupcake: Apakah Anda menguji versi perintah yang lama? Seharusnya bekerja dengan baik. Amend mengubah pesan komit hanya sehingga komit lama dan baru memberikan perubahan yang sama persis sehingga komit root lama dilewati secara otomatis. Yang kedua HEADmemastikan bahwa semua komit dipertimbangkan dan bahwa kita dapat menggunakan dua versi parameter rebase untuk kembali ke master. Harap perhatikan bahwa jawaban ini mendahului adanya --rootopsi untuk rebase.
CB Bailey
9
Jawaban ecdpalma di bawah ini jauh lebih mudah dan sederhana dan memiliki lebih banyak suara, gulir ke bawah orang!
Flimm
567

Pada Git versi 1.7.12 , Anda sekarang dapat menggunakan

git rebase -i --root

Dokumentasi

ecdpalma
sumber
2
apakah mungkin untuk rebase root dari semua cabang menggunakan perintah ini? Sepertinya ini akan melepaskan cabang saat ini ke root baru dan semua cabang lainnya akan tetap pada root lama
woojoo666
@ woojoo666 Anda harus rebase cabang ke root baru. seperti biasa.
Berkus
@Atcold itu tidak berfungsi jika tidak ada root upstream
Kai
Peringatan: Saya salah berasumsi bahwa ini akan melakukan root pada cabang yang saya periksa, tetapi butuh beberapa saat untuk memuat semua commit, lalu rebase semuanya.
Leo
2
@ Leo apa komentar Anda? Saya tidak bisa melihat hubungan antara bagian pertama dan kedua - apa hubungannya dengan itu?
boycy
66

Untuk memperluas jawaban ecdpalma , Anda sekarang dapat menggunakan --rootopsi untuk memberi tahu rebasebahwa Anda ingin menulis ulang root / komit pertama:

git rebase --interactive --root

Kemudian komit root akan muncul dalam daftar rebase TODO, dan Anda dapat memilih untuk mengedit atau menulis ulang:

reword <root commit sha> <original message>
pick <other commit sha> <message>
...

Ini adalah penjelasan --rootdari dokumen Git rebase (penekanan pada saya):

Rebase semua komit yang dapat dijangkau <branch>, alih-alih membatasi mereka dengan <upstream>. Ini memungkinkan Anda untuk membuat ulang komit root pada cabang .

Komunitas
sumber
12

Hanya untuk memberikan alternatif bagi jawaban yang berperingkat lebih tinggi:

Jika Anda membuat repo, dan tahu di muka bahwa Anda akan rebasing di atas komit nyata "pertama" di masa depan, Anda dapat menghindari masalah ini sama sekali dengan membuat komit kosong eksplisit di awal:

git commit --allow-empty -m "Initial commit"

dan baru kemudian mulai melakukan komitmen "nyata". Maka Anda dapat dengan mudah rebase di atas yang melakukan cara standar, misalnyagit rebase -i HEAD^

jakub.g
sumber
4
Tidakkah ini berarti bahwa, agar ini berfungsi, Anda harus memiliki pandangan jauh ke depan (atau menjadi psikis) untuk membuat komitmen kosong tepat di awal proyek Anda ? Ini tampaknya sangat situasional , bagi saya, dan umumnya tidak praktis . Bagaimana menurut anda? Apa yang terjadi jika saya sudah membuat 100 commit, dan tiba-tiba saya perlu mengedit root commit. Akankah ini tetap bekerja, dalam hal itu, jika saya tidak membuat komit kosong pada awalnya?
2
Mengedit pesan dari commit root mungkin bukan sesuatu yang akan Anda lakukan setelah memiliki 100-an. Kadang-kadang saya kebetulan hanya ingin memiliki git repo, melakukan beberapa komit trashy, mengetahui bahwa begitu saya mencapai beberapa kondisi yang dapat digunakan, saya akan memeras mereka menjadi satu misalnya, dan menulis ulang pesannya. Bagaimanapun, sekarang saya berubah pikiran dan saya pikir hal yang paling berguna untuk komit pertama adalah meletakkan .gitattributesfile daripada melakukan komit kosong.
jakub.g
4

Anda bisa menggunakan git filter-branch:

cd test
git init

touch initial
git add -A
git commit -m "Initial commit"

touch a
git add -A
git commit -m "a"

touch b
git add -A
git commit -m "b"

git log

-->
8e6b49e... b
945e92a... a
72fc158... Initial commit

git filter-branch --msg-filter \
"sed \"s|^Initial commit|New initial commit|g\"" -- --all

git log
-->
c5988ea... b
e0331fd... a
51995f1... New initial commit
Alexander Groß
sumber
Saya menggunakan cabang-filter untuk mengubah pembuat / pengalih, dan -- --all opsi memang adalah kunci dalam hal ini untuk dapat juga menangani root commit.
sschuberth