Menggabungkan dua commit pertama dari repositori Git?

197

Misalkan Anda memiliki riwayat yang mengandung tiga komit A, B dan C :

A-B-C

Saya ingin menggabungkan dua komit A dan B menjadi satu komit AB :

AB-C

Saya mencoba

git rebase -i A

yang membuka editor saya dengan konten berikut:

pick e97a17b B
pick asd314f C

Saya mengubah ini menjadi

squash e97a17b B
pick asd314f C

Kemudian Git 1.6.0.4 mengatakan:

Cannot 'squash' without a previous commit

Apakah ada cara atau ini tidak mungkin?

Kristen
sumber

Jawaban:

168

Gunakan git rebase -i --root pada Git versi 1.7.12 .

Dalam file rebase interaktif, ubah baris kedua dari komit B menjadi squash dan biarkan baris lain di pilih :

pick f4202da A
squash bea708e B
pick a8c6abc C

Ini akan menggabungkan dua komit A dan B menjadi satu komit AB .

Ditemukan dalam jawaban ini .

Kostmo
sumber
126

Anda mencoba:

git rebase -i A

Dimungkinkan untuk memulai seperti itu jika Anda melanjutkan dengan editdaripada squash:

edit e97a17b B
pick asd314f C

lalu lari

git reset --soft HEAD^
git commit --amend
git rebase --continue

Selesai

David Lichteblau
sumber
4
Jika Anda melakukan ini untuk diam-diam memperbaiki inti github, Anda harus menambahkan -m "inisial" ke komit. ;-)
Bruno Bronosky
1
git rebase --abortuntuk memulai kembali dan melakukannya dengan cara yang benar (tidak menekan komit pertama di editor)
oma
66

A adalah komit awal, tetapi sekarang Anda inginkan B menjadi komit awal. komit git adalah seluruh pohon, bukan beda bahkan jika mereka biasanya digambarkan dan dilihat dalam hal perbedaan yang mereka perkenalkan.

Resep ini berfungsi bahkan jika ada banyak komit antara A dan B, dan B dan C.

# Go back to the last commit that we want
# to form the initial commit (detach HEAD)
git checkout <sha1_for_B>

# reset the branch pointer to the initial commit,
# but leaving the index and working tree intact.
git reset --soft <sha1_for_A>

# amend the initial tree using the tree from 'B'
git commit --amend

# temporarily tag this new initial commit
# (or you could remember the new commit sha1 manually)
git tag tmp

# go back to the original branch (assume master for this example)
git checkout master

# Replay all the commits after B onto the new initial commit
git rebase --onto tmp <sha1_for_B>

# remove the temporary tag
git tag -d tmp
CB Bailey
sumber
1
ini memicu rebase interaktif besar-besaran ketika saya melakukangit rebase --onto tmp <sha1_for_B>
Alex
Mengingat saya memiliki repo baru dengan hanya dua komitmen (yang ingin saya gabungkan menjadi satu), ini bekerja dengan baik untuk saya. Terima kasih @CB Bailey
RominRonin
10

Dalam hal rebase interaktif, Anda harus melakukannya sebelum A sehingga daftar akan menjadi:

pick A
pick B
pick C

untuk menjadi:

pick A
squash B
pick C

Jika A adalah komit awal, Anda harus memiliki komit awal yang berbeda sebelum A. Git berpikir dalam perbedaan, itu akan bekerja pada perbedaan antara (A dan B) dan (B dan C). Karenanya squash tidak berfungsi dalam contoh Anda.

Loki
sumber
9

Dalam kasus yang Anda memiliki ratusan atau ribuan komit, menggunakan jawaban kostmo ini dari

git rebase -i --root

bisa jadi tidak praktis dan lambat, hanya karena banyaknya komitmen yang harus diproses skrip rebase dua kali , satu kali untuk menghasilkan daftar editor rebase interaktif (di mana Anda memilih tindakan apa yang akan diambil untuk setiap komit), dan satu kali untuk benar-benar mengeksekusi penerapan kembali komitmen.

Berikut adalah solusi alternatif yang akan menghindari biaya waktu pembuatan daftar editor rebase interaktif dengan tidak menggunakan rebase interaktif di tempat pertama. Dengan cara ini, ini mirip dengan solusi Charles Bailey . Anda cukup membuat cabang yatim dari komit kedua, dan kemudian rebase semua komitmen turunan di atasnya:

git checkout --orphan orphan <second-commit-sha>
git commit -m "Enter a commit message for the new root commit"
git rebase --onto orphan <second-commit-sha> master

Dokumentasi

Komunitas
sumber
0

Perintah git untuk pasukan: git rebase -i KEPALA ~ [jumlah komit]

Katakanlah Anda memiliki di bawah riwayat git commit:


pick 5152061 feat: Menambahkan dukungan untuk menyimpan gambar. (A)
pilih 39c5a04 Fix: perbaikan bug. (B)
pilih perbaikan 839c6b3: konflik diselesaikan. (C)

Sekarang Anda ingin memencet A dan B ke AB, lakukan langkah-langkah di bawah ini:


pick 5152061 feat: Menambahkan dukungan untuk menyimpan gambar. (A)
s 39c5a04 Fix: perbaikan bug. (B)
pilih perbaikan 839c6b3: konflik diselesaikan. (C)

Catatan: untuk squashing commit kita bisa menggunakan squash atau s. Hasil akhirnya adalah:
pilih 5152061 feat: Menambahkan dukungan untuk menyimpan gambar. (AB)
pilih perbaikan 839c6b3: konflik diselesaikan. (C)

Sumit
sumber
-1

Anda harus melakukan sedikit keajaiban baris perintah.

git checkout -b a A
git checkout B <files>
git commit --amend
git checkout master
git rebase a

Itu akan meninggalkan Anda dengan cabang yang memiliki AB dan C sebagai commit.

Bombe
sumber
Karena commit awal lama dan baru tidak memiliki leluhur yang sama, Anda mungkin mendapatkan beberapa konflik yang tidak perlu ketika git mencoba menerapkan seluruh sejarah master ke dalam, walaupun mereka memiliki pohon yang sama. Dengan menggunakan opsi --onto untuk git rebase, Anda dapat memberi tahu git tempat yang tepat untuk mulai mendaftar.
CB Bailey