Bagaimana cara menggunakan git merge --squash?

1209

Saya memiliki server Git jarak jauh, ini adalah skenario yang ingin saya lakukan:

  • Untuk setiap bug / fitur saya membuat cabang Git yang berbeda

  • Saya terus melakukan kode saya di cabang Git dengan pesan Git yang tidak resmi

  • Dalam repositori teratas kita harus melakukan satu komit untuk satu bug dengan pesan Git resmi

Jadi bagaimana saya bisa menggabungkan cabang saya ke cabang jarak jauh sehingga mereka mendapatkan hanya satu komit untuk semua check-in saya (saya bahkan ingin memberikan pesan komit untuk ini)?

SunnyShah
sumber
1
Saya tidak yakin apakah saya benar-benar mengerti Anda, tetapi Anda mungkin menginginkan "gurita bergabung".
MatrixFrog
27
Saya biasanya menggunakan git rebase -i untuk menciutkan semua komit saya menjadi satu komit dan menulis ulang pesan komit. Lalu saya kirim ke hulu.
Edward Falk
17
git merge --squashmelakukan semuanya pada baris perintah dalam satu tembakan dan Anda hanya berharap itu berfungsi. git rebase -imembawa editor dan memungkinkan Anda menyempurnakan rebase. Ini lebih lambat, tetapi Anda bisa melihat apa yang Anda lakukan. Juga, ada perbedaan antara rebase dan penggabungan yang sedikit terlalu terlibat untuk dibahas dalam komentar.
Edward Falk
4
masalah dengan semua jawaban ini adalah bahwa Anda harus berada di cabang master secara lokal dan menjalankan perintah gabungan - squash ... Saya ingin menjalankan gabungan - squash dari fitur cabang bukan cabang master..jadi itu ketika saya selesai, saya bisa mendorong cabang fitur ke remote dan mengirimkan PR, apakah itu mungkin?
Alexander Mills
2
@AlexanderMills, saya pikir Anda hanya perlu cabang fitur kedua (kloning dari cabang master). Lakukan merge --squashdari yang lama ke yang baru, lalu gabungkan cabang baru untuk dikuasai. Cabang lama menjadi usang.
Gyromite

Jawaban:

2002

Katakanlah cabang perbaikan bug Anda dipanggil bugfixdan Anda ingin menggabungkannya menjadi master:

git checkout master
git merge --squash bugfix
git commit

Ini akan mengambil semua komit dari bugfixcabang, squash mereka menjadi 1 komit, dan menggabungkannya dengan mastercabang Anda .


Penjelasan :

git checkout master

Beralih ke mastercabang Anda .

git merge --squash bugfix

Mengambil semua komit dari bugfixcabang dan menggabungkannya dengan cabang Anda saat ini.

git commit

Menciptakan satu komit dari perubahan yang digabungkan.

Dengan mengabaikan -mparameter, Anda dapat memodifikasi pesan konsep draf yang berisi setiap pesan dari komit terjepit Anda sebelum menyelesaikan komit Anda.

abyx
sumber
222
Jika Anda ingin menyimpan referensi ke pesan komit lama, Anda dapat menulis git commit(tanpa -mparam) dan Anda akan bisa memodifikasi pesan komit yang disusun yang berisi semua pesan komit yang Anda hancurkan.
Alex
12
Anda dapat mencapai hal yang sama dengan melakukan git commit --amend -m '...'nanti.
Janusz Lenar
19
Jika terjadi konflik penggabungan dan Anda menyelesaikan konflik ini, git committidak akan lagi menampilkan pesan komit bermanfaat yang berisi semua pesan komit yang Anda hancurkan. Jika demikian, coba git commit --file .git/SQUASH_MSG(via stackoverflow.com/a/11230783/923560 ).
Abdull
23
Perlu diingat bahwa squashing akan secara default menghubungkan komit ke squasher . Untuk mempertahankan penulis asli, Anda perlu menentukan secara eksplisit seperti:git commit -a --author="Author" --message="Issue title #id"
gaborous
5
git merge --squashmemungkinkan Anda untuk membuat komit tunggal di atas cabang saat ini yang efeknya sama dengan menggabungkan cabang lain. Tapi itu tidak akan menghasilkan catatan penggabungan, yang berarti permintaan tarik Anda karena hasilnya tidak akan berubah, namun tidak akan ditandai sebagai digabungkan! Jadi, Anda hanya perlu menghapus cabang yang harus dilakukan.
am0wa
129

Apa yang akhirnya bereskan bagi saya adalah komentar yang menunjukkan bahwa:

git checkout main
git merge --squash feature

setara dengan melakukan:

git checkout feature
git diff main > feature.patch
git checkout main
patch -p1 < feature.patch
git add .

Ketika saya ingin menggabungkan cabang fitur dengan 105 (!!) komit dan membuat semuanya tergencet menjadi satu, saya tidak mau git rebase -i origin/masterkarena saya perlu secara terpisah menyelesaikan konflik penggabungan untuk masing - masing komitmen menengah (atau setidaknya yang git tidak bisa mencari tahu sendiri). Menggunakan git merge --squashmemberi saya hasil yang saya inginkan, dari satu komit untuk menggabungkan seluruh cabang fitur. Dan, saya hanya perlu melakukan paling banyak satu resolusi konflik manual.

Dan Kohn
sumber
75
Saya sangat menyarankan melakukan penggabungan di cabang fitur pertama git merge master, dan hanya kemudian git merge --squash featuredi cabang master.
dotancohen
8
@dotancohen Maaf untuk mengeruk komentar lama :) Apa yang diperoleh dari penggabungan dalam cabang fitur sebelum melakukan git merge --squash featuredari cabang utama?
bitsmack
57
Anda ingin menggabungkan master ke cabang fitur terlebih dahulu, dan menangani semua perbaikan manual di cabang fitur Anda. Itu juga memungkinkan Anda menjalankan tes dan memastikan cabang fitur Anda berfungsi dengan benar. Kemudian, Anda dijamin dapat melakukan penggabungan otomatis cabang fitur Anda menjadi master.
Dan Kohn
4
@ John Saya sarankan Anda menambahkan penjelasan di komentar Anda di atas ke dalam jawaban Anda.
guntbert
3
@ bitmack: Anda akan menggabungkan master menjadi fitur terlebih dahulu. Ini memberi Anda kesempatan untuk menyelesaikan konflik pada fitur sebelum menggabungkan fitur menjadi master
Mike
97

Anda ingin bergabung dengan opsi squash. Itu jika Anda ingin melakukannya satu cabang sekaligus.

git merge --squash feature1

Jika Anda ingin menggabungkan semua cabang pada saat yang sama dengan komit tunggal, maka rebase pertama secara interaktif dan tekan setiap fitur kemudian gurita bergabung:

git checkout feature1
git rebase -i master

Squash menjadi satu komit kemudian ulangi untuk fitur lainnya.

git checkout master
git merge feature1 feature2 feature3 ...

Penggabungan terakhir itu adalah "penggabungan gurita" karena menggabungkan banyak cabang sekaligus.

Semoga ini membantu

Adam Dymitruk
sumber
3
Kenapa kamu rebasing?
Umair A.
12
@UmairAshraf ini adalah rebase interaktif yang memberi Anda opsi untuk melakukan squash di dalam cabang Anda.
andho
1
Rebasing adalah ide yang buruk. Jangan rebase komitmen yang sudah dipublikasikan
Sebi2020
1
@ Sebi2020 git merge --squash akan rebase komit Anda yang sudah diterbitkan dengan cara yang lebih buruk daripada rebase interaktif. Rebase interaktif (pada cabang fitur) membawa sedikit atau tidak ada efek samping.
xiix
1
@xiix Ini hanya berlaku jika Anda satu-satunya yang bekerja dengan cabang fitur. Ini bukan asumsi yang bisa Anda buat. Saya merekomendasikan untuk membaca halaman yang berkaitan dengan rebasing di Git-SCM . Itu menyatakan " Jangan rebase komit yang ada di luar repositori Anda dan orang-orang mungkin mendasarkannya pada mereka. " Dan jika Anda tidak tahu pasti apakah orang-orang sudah membuat karya berdasarkan komit yang diterbitkan (yang Anda tidak bisa tahu karena desentralisasi sifat git) kamu tidak harus melakukan itu.
Sebi2020
23

Jika sudah git merge bugfixaktif main, Anda dapat menekan komit gabungan menjadi satu dengan:

git reset --soft HEAD^1
git commit
qwertzguy
sumber
git reset --soft HEAD^1tampaknya membatalkan komit terakhir yang dilakukan sebelum penggabungan, setidaknya dalam kasus penggabungan menjadi maju cepat.
Jesper Matthiesen
@JesperMatthiesen jika ada fast-forward Anda tidak mendapatkan komit gabungan, maka Anda akan melakukannya git reset --soft HEAD^<number-of-commits-to-squash>.
qwertzguy
Ini membantu saya untuk memecah semua menjadi satu komit setelah penggabungan hilir.
killjoy
18

Gabungkan newFeaturecabang masterdengan komit khusus:

git merge --squash newFeature && git commit -m 'Your custom commit message';

Jika sebaliknya, Anda melakukannya

git merge --squash newFeature && git commit

Anda akan mendapatkan pesan komit yang akan menyertakan semua newFeaturekomitmen cabang, yang dapat Anda sesuaikan.

Saya jelaskan di sini: https://youtu.be/FQNAIacelT4

Vagelis Prokopiou
sumber
10

Saya tahu pertanyaan ini bukan tentang Github secara khusus, tetapi karena Github digunakan secara luas dan ini adalah jawaban yang saya cari, saya akan membagikannya di sini.

Github memiliki kemampuan untuk melakukan penggabungan squash, tergantung pada opsi penggabungan yang diaktifkan untuk repositori.

Jika penggabungan squash diaktifkan, opsi "Squash and merge" akan muncul di dropdown di bawah tombol "Gabung".

Cuplikan layar fitur "Squash and merge" Github

Harun
sumber
GitHub menggunakan email default yang terkait dengan akun Anda. Jika Anda memiliki beberapa alamat email, dan Anda harus menggunakan yang sekunder, Anda tidak bisa menggunakan GH UI.
Luca Guidi
4

Misalkan Anda bekerja di fitur / task1 dengan banyak komit.

  1. Buka cabang proyek Anda (proyek / my_project)

    git checkout project/my_project
    
  2. Buat cabang baru (fitur / task1_bugfix)

    git checkout -b feature/task1_bugfix
    
  3. Marge dengan --squashopsi

    git merge --squash feature/task1
    
  4. Buat komit tunggal

    git commit -am "add single comments"
    
  5. Dorong cabang Anda

    git push --set-upstream origin feature/task1_bugfix
    
Farid Haq
sumber
1

Untuk Git

Buat fitur baru

melalui Terminal / Shell:

git checkout origin/feature/<featurename>
git merge --squash origin/feature/<featurename>

Ini tidak melakukan itu, memungkinkan Anda untuk meninjaunya terlebih dahulu.

Kemudian komit, dan selesaikan fitur dari cabang baru ini, dan hapus / abaikan yang lama (yang sudah Anda gunakan).

Demian Berisford-Maynard
sumber
@Melebius Satu-satunya referensi untuk "SourceTree" ada dalam kalimat Anda, jika itu adalah tag atau pertanyaan sebelumnya: Tidak ada lagi.
Jordan Stefanelli
1
@JordanStefanelli SourceTree digunakan dalam versi asli dari jawaban ini . Terima kasih telah memberi tahu ini diperbaiki!
Melebius
1

jika Anda mendapatkan kesalahan: Melakukan tidak mungkin karena Anda memiliki file yang tidak dihapus.

git checkout master
git merge --squash bugfix
git add .
git commit -m "Message"

memperbaiki semua file Konflik

git add . 

Anda juga bisa menggunakan

git add [filename]
ResUta
sumber
0

Untuk menekan cabang lokal Anda sebelum mendorongnya:

  1. checkout cabang yang dimaksud untuk dikerjakan jika belum diperiksa.

  2. Temukan sha dari commit tertua yang ingin Anda pertahankan.

  3. Buat / checkout cabang baru (tmp1) dari komit itu.

    git checkout -b tmp1 <sha1-of-commit>

  4. Gabungkan cabang asli menjadi cabang baru yang tergencet.

    git merge --squash <original branch>

  5. Komit perubahan yang telah dibuat oleh gabungan, dengan pesan ringkasan komit.

    git commit -m <msg>

  6. Periksa cabang asli yang ingin Anda remas.

    git checkout <branch>

  7. Atur ulang ke komit asli yang ingin Anda pertahankan.

    git reset --soft <sha1>

  8. Rebase cabang ini berdasarkan cabang tmp1 baru.

    git rebase tmp1

  9. Itu saja - sekarang hapus cabang tmp1 sementara setelah Anda yakin semuanya baik-baik saja.

Jool
sumber
0

Anda dapat menggunakan alat yang saya buat untuk membuat proses ini lebih mudah: git-squash . Misalnya untuk menekan semua komit pada cabang fitur yang telah bercabang dari cabang utama, tulis:

git squash master
git push --force
sheerun
sumber