Pertanyaan Bagaimana saya bisa menggabungkan dua commit menjadi satu jika saya sudah mulai rebase?


Saya mencoba menggabungkan 2 commit menjadi 1, jadi saya mengikutinya "Memeras melakukan dengan rebase" dari git siap.

Saya berlari

git rebase --interactive HEAD~2

Dalam editor yang dihasilkan, saya berubah pick untuk squash lalu simpan-berhenti, tetapi rebase gagal dengan kesalahan tersebut

Tidak dapat 'squash' tanpa komitmen sebelumnya

Sekarang pohon kerja saya telah mencapai keadaan ini, saya mengalami kesulitan memulihkan. Perintah git rebase --interactive HEAD~2 gagal dengan

Rebase interaktif sudah dimulai

dan git rebase --continue gagal dengan

Tidak dapat 'squash' tanpa komitmen sebelumnya


989
2018-04-01 20:56


asal


Jawaban:


Ringkasan

Pesan kesalahan

Tidak dapat 'squash' tanpa komitmen sebelumnya

berarti Anda mungkin mencoba "menekan ke bawah". Git selalu membuat komitmen baru ke commit lama atau "ke atas" seperti yang dilihat pada daftar todo rebase interaktif, yaitu menjadi komit pada baris sebelumnya. Mengubah perintah pada baris pertama daftar todo Anda squash akan selalu menghasilkan kesalahan ini karena tidak ada apa-apa bagi komitmen pertama untuk melakukan squash.

The Fix

Pertama kembali ke tempat Anda memulai

$ git rebase --abort

Katakan sejarah Anda

$ git log --pretty=oneline
a931ac7c808e2471b22b5bd20f0cad046b1c5d0d c
b76d157d507e819d7511132bdb5a80dd421d854f b
df239176e1a2ffac927d8b496ea00d5488481db5 a

Yaitu, a adalah komit pertama, lalu b, dan akhirnya c. Setelah melakukan c, kami memutuskan untuk melakukan squash b dan c:

(Catatan: Menjalankan git log menyalurkan outputnya ke pager, less secara default di sebagian besar platform. Untuk keluar dari pager dan kembali ke command prompt Anda, tekan q kunci.)

Lari git rebase --interactive HEAD~2 memberi Anda editor

pick b76d157 b
pick a931ac7 c

# Rebase df23917..a931ac7 onto df23917
#
# Commands:
#  p, pick = use commit
#  r, reword = use commit, but edit the commit message
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit
#  f, fixup = like "squash", but discard this commit's log message
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#

(Perhatikan bahwa daftar todo ini dalam urutan terbalik dibandingkan dengan output dari git log.)

Mengubah b pick untuk squash akan menghasilkan kesalahan yang Anda lihat, tetapi jika sebaliknya Anda menekan c ke b (commit yang lebih baru ke yang lebih tua atau "memencet ke atas") dengan mengubah daftar agenda ke

pick   b76d157 b
squash a931ac7 c

dan menyimpan-berhenti editor Anda, Anda akan mendapatkan editor lain yang isinya

# This is a combination of 2 commits.
# The first commit's message is:

b

# This is the 2nd commit message:

c

Ketika Anda menyimpan dan keluar, konten dari file yang diedit menjadi komit dari commit gabungan baru:

$ git log --pretty=oneline
18fd73d3ce748f2a58d1b566c03dd9dafe0b6b4f b and c
df239176e1a2ffac927d8b496ea00d5488481db5 a

Catatan Tentang Riwayat Menulis Ulang

Interaktif menulis ulang sejarah penulisan ulang. Mencoba untuk mendorong ke remote yang berisi riwayat lama akan gagal karena ini bukan fast-forward.

Jika cabang yang Anda rebal adalah cabang topik atau fitur di mana Anda bekerja sendiri, bukan masalah besar. Mendorong ke repositori lain akan membutuhkan --force pilihan, atau alternatifnya Anda mungkin bisa, tergantung pada izin repositori jauh, untuk terlebih dahulu menghapus cabang lama dan kemudian mendorong versi yang telah di-render. Contoh dari perintah-perintah yang berpotensi menghancurkan pekerjaan berada di luar lingkup jawaban ini.

Tulis ulang sejarah yang sudah dipublikasikan pada cabang di mana Anda bekerja dengan orang lain tanpa sangat alasan bagus seperti membocorkan kata sandi atau detail sensitif lainnya memaksa bekerja ke kolaborator Anda dan bersifat antisosial dan akan mengganggu pengembang lainnya. Itu "Memulihkan Dari Rebase Hulu" di git rebase dokumentasi menjelaskan, dengan penekanan tambahan.

Rebase (atau bentuk lain dari penulisan ulang) cabang yang orang lain kerjakan adalah ide yang buruk: siapa pun di bagian hilirnya dipaksa untuk memperbaiki riwayat mereka secara manual. Bagian ini menjelaskan cara memperbaiki dari sudut pandang hilir. Namun, perbaikan yang sebenarnya adalah menghindari rebase hulu sejak awal. ...


1533
2018-04-02 19:04



Jika ada beberapa commit, Anda bisa menggunakannya git rebase -i untuk menekan dua komit menjadi satu.

Jika hanya ada dua commit yang ingin Anda gabungkan, dan mereka adalah "dua yang paling baru", perintah berikut dapat digunakan untuk menggabungkan dua commit menjadi satu:

git reset --soft "HEAD^"
git commit --amend

335
2017-07-11 05:31



Pertama Anda harus memeriksa berapa banyak commit yang Anda miliki:

git log

Ada dua status:

Salah satunya adalah bahwa ada hanya dua komit:

Sebagai contoh:

commit A
commit B

(Dalam hal ini, Anda tidak dapat menggunakan git rebase untuk melakukannya) yang harus Anda lakukan berikut ini.

$ git reset --soft HEAD^1

$ git commit --amend

Lain adalah bahwa ada lebih dari dua komit; Anda ingin menggabungkan komit C dan D.

Sebagai contoh:

commit A
commit B
commit C
commit D

(dalam kondisi ini, Anda dapat menggunakan git rebase)

git rebase -i B

Dan daripada menggunakan "squash" untuk melakukannya. Sisanya menipis sangat mudah. Jika Anda masih belum tahu, silakan baca http://zerodie.github.io/blog/2012/01/19/git-rebase-i/ 


50
2018-05-27 19:01



Rebase: Anda Tidak Akan Membutuhkannya:

Cara yang lebih sederhana untuk skenario yang paling sering.

Umumnya:

Sebenarnya jika semua yang Anda inginkan adalah adil cukup menggabungkan beberapa commit terbaru menjadi satu  tetapi tidak perlu drop, reword dan karya rebase lainnya.

Anda cukup lakukan:

git reset --soft "HEAD~n"
  • Asumsi ~n adalah jumlah commit yang lunak tanpa komitmen (mis. ~1, ~2, ...)

Kemudian, gunakan perintah berikut untuk mengubah pesan commit.

git commit --amend

yang cukup sama dengan jarak jauh squash dan satu pick.

Dan ini bekerja untuk n commit tetapi tidak hanya dua commit seperti jawaban di atas diminta.


49
2018-04-26 09:15



Dengan asumsi Anda berada di cabang topik Anda sendiri. Jika Anda ingin menggabungkan 2 commit terakhir menjadi satu dan terlihat seperti pahlawan, lakukan commit sebelum Anda membuat dua commit terakhir.

git checkout -b temp_branch HEAD^2

Kemudian squash melakukan cabang lain di cabang baru ini:

git merge branch_with_two_commits --squash

Itu akan membawa perubahan tetapi tidak melakukannya. Jadi, lakukan saja dan selesai.

git commit -m "my message"

Sekarang Anda dapat menggabungkan kembali cabang topik baru ini ke dalam cabang utama Anda.


26
2017-10-23 23:44



Anda dapat membatalkan rebase dengan

git rebase --abort

dan ketika Anda menjalankan perintah rebase interaktif lagi 'squash; commit harus berada di bawah pick commit dalam daftar


22
2018-04-01 20:59



Saya sering menggunakannya git reset - dicampur untuk mengembalikan versi dasar sebelum beberapa commit yang ingin Anda gabungkan, maka saya membuat commit baru, dengan cara itu dapat membiarkan commit Anda terbaru, pastikan versi Anda HEAD setelah Anda mendorong ke server.

commit ac72a4308ba70cc42aace47509a5e
Author: <me@me.com>
Date:   Tue Jun 11 10:23:07 2013 +0500

    Added algorithms for Cosine-similarity

commit 77df2a40e53136c7a2d58fd847372
Author: <me@me.com>
Date:   Tue Jun 11 13:02:14 2013 -0700

    Set stage for similar objects

commit 249cf9392da197573a17c8426c282
Author: Ralph <ralph@me.com>
Date:   Thu Jun 13 16:44:12 2013 -0700

    Fixed a bug in space world automation

Jika saya ingin menggabungkan dua komit menjadi satu, pertama saya gunakan:

git reset --mixed 249cf9392da197573a17c8426c282

"249cf9392da197573a17c8426c282" adalah versi ketiga, juga adalah versi dasar Anda sebelum Anda bergabung, setelah itu, saya membuat commit baru:

git add .
git commit -m 'some commit message'

Itu semua, harapan adalah cara lain untuk semua orang.

FYI, dari git reset --help:

 --mixed
     Resets the index but not the working tree (i.e., the changed files are
     preserved but not marked for commit) and reports what has not been
     updated. This is the default action.

13
2017-09-09 02:48



$ git rebase --abort

Jalankan kode ini kapan saja jika Anda ingin membatalkan git rebase

$ git rebase -i HEAD~2

Untuk menerapkan kembali dua commit terakhir. Perintah di atas akan membuka editor kode

  • [ Komitmen terakhir akan berada di bagian bawah ]. Ubah yang terakhir berkomitmen untuk squash (s). Karena labu akan berbaur dengan komit sebelumnya.
  • Kemudian tekan tombol esc dan ketik: wq untuk menyimpan dan menutup

Setelah: wq Anda akan berada dalam mode rebase aktif

Catatan: Anda akan mendapatkan editor lain jika tidak ada pesan peringatan / kesalahan, Jika ada kesalahan atau peringatan editor lain tidak akan muncul, Anda dapat membatalkan dengan runnning $ git rebase --abort jika Anda melihat kesalahan atau peringatan lain, lanjutkan saja dengan menjalankan $ git rebase --continue

Anda akan melihat 2 pesan commit Anda. Pilih satu atau tulis pesan commit Anda sendiri, simpan dan keluar [: wq]

Catatan 2: Anda mungkin perlu memaksakan perubahan Anda ke repositori jarak jauh jika menjalankan perintah rebase

$ git push -f

$ git push -f origin master


10
2018-02-20 21:49



Jika cabang tuanmu git log terlihat seperti berikut:

commit ac72a4308ba70cc42aace47509a5e
Author: <me@me.com>
Date:   Tue Jun 11 10:23:07 2013 +0500

    Added algorithms for Cosine-similarity

commit 77df2a40e53136c7a2d58fd847372
Author: <me@me.com>
Date:   Tue Jun 11 13:02:14 2013 -0700

    Set stage for similar objects

commit 249cf9392da197573a17c8426c282
Author: Ralph <ralph@me.com>
Date:   Thu Jun 13 16:44:12 2013 -0700

    Fixed a bug in space world automation

dan Anda ingin menggabungkan dua komitmen teratas hanya melakukan langkah mudah berikut:

  1. Pertama berada di sisi aman checkout kedua terakhir melakukan di cabang terpisah. Anda dapat menamai cabang apa saja. git checkout 77df2a40e53136c7a2d58fd847372 -b merged-commits
  2. Sekarang, pilih saja perubahan Anda dari commit terakhir ke dalam cabang baru ini sebagai: git cherry-pick -n -x ac72a4308ba70cc42aace47509a5e. (Selesaikan konflik jika ada)
  3. Jadi sekarang, perubahan Anda di commit terakhir ada di commit terakhir kedua Anda. Tetapi Anda masih harus melakukan, jadi pertama-tama tambahkan perubahan yang baru saja Anda pilih dan kemudian jalankan git commit --amend.

Itu dia. Anda dapat mendorong versi gabungan ini di cabang "gabungan-commit" jika Anda suka.

Juga, Anda dapat membuang dua komit back-to-back di cabang master Anda sekarang. Perbarui cabang master Anda seperti:

git checkout master
git reset --hard origin/master (CAUTION: This command will remove any local changes to your master branch)
git pull

1
2018-06-16 15:57



Karena saya menggunakan git cherry-pick untuk hampir segalanya, bagi saya itu alami untuk melakukannya bahkan di sini.

Mengingat yang saya miliki branchX check out dan ada dua komit di ujungnya, yang saya ingin membuat satu komit menggabungkan konten mereka, saya melakukan ini:

git checkout HEAD^ // Checkout the privious commit
git cherry-pick --no-commit branchX // Cherry pick the content of the second commit
git commit --amend // Create a new commit with their combined content

Jika saya ingin memperbarui branchX juga (dan saya kira ini adalah sisi bawah dari metode ini) Saya juga harus:

git checkout branchX
git reset --hard <the_new_commit>

1
2017-11-26 10:52



Jika Anda ingin menggabungkan dua commit terbaru dan cukup menggunakan pesan commit yang lama, Anda dapat mengotomatiskan proses yang digunakan expect.

Saya berasumsi:

  • Anda menggunakan vi sebagai editor Anda
  • Komitimu masing-masing satu baris

Saya diuji dengan git version 2.14.3 (Apple Git-98).


#!/usr/bin/env expect
spawn git rebase -i HEAD~2

# down, delete word, insert 's' (for squash), Escape, save and quit
send "jdwis \033:wq\r"

expect "# This is a"

# down 4, delete 3 lines, save and quit
send "4j3d\r:wq\r"

interact

0
2018-02-06 04:45