git reset
adalah tentang bergerak HEAD
, dan umumnya ref cabang .
Pertanyaan: bagaimana dengan pohon dan indeks kerja?
Ketika dipekerjakan dengan --soft
, bergerak HEAD
, paling sering memperbarui ref cabang, dan hanyaHEAD
.
Ini berbeda commit --amend
dengan:
- itu tidak membuat komit baru.
- itu sebenarnya dapat memindahkan HEAD ke komit apa pun (karena
commit --amend
hanya tentang tidak memindahkan HEAD, sambil mengizinkan untuk mengulang komit saat ini)
Baru saja menemukan contoh penggabungan ini:
- gabungan klasik
- gabungan subtree
semua menjadi satu (gurita, karena ada lebih dari dua cabang digabung) melakukan penggabungan.
Tomas "dulu." Carnecky menjelaskan dalam artikelnya "Subtree Octopus merge" :
- Strategi penggabungan subtree dapat digunakan jika Anda ingin menggabungkan satu proyek menjadi subdirektori dari proyek lain, dan selanjutnya menjaga agar proyek tetap terbaru. Ini adalah alternatif untuk git submodules.
- Strategi penggabungan gurita dapat digunakan untuk menggabungkan tiga atau lebih cabang. Strategi normal hanya dapat menggabungkan dua cabang dan jika Anda mencoba untuk menggabungkan lebih dari itu, git secara otomatis kembali ke strategi gurita.
Masalahnya adalah Anda hanya dapat memilih satu strategi. Tapi saya ingin menggabungkan keduanya untuk mendapatkan sejarah bersih di mana seluruh repositori diperbarui secara atom ke versi baru.
Saya punya proyek super, sebut saja projectA
, dan sub proyek projectB
,, yang saya gabungkan menjadi subdirektori dari projectA
.
(Itulah bagian menggabungkan subtree)
Saya juga mempertahankan beberapa komitmen lokal.
ProjectA
secara teratur diperbarui, projectB
memiliki versi baru setiap beberapa hari atau minggu dan biasanya tergantung pada versi tertentu projectA
.
Ketika saya memutuskan untuk memperbarui kedua proyek, saya tidak hanya menarik dari projectA
dan projectB
karena itu akan membuat dua komitmen untuk apa yang seharusnya menjadi pembaruan atom dari seluruh proyek .
Sebagai gantinya, saya membuat satu komit gabungan yang menggabungkan projectA
, projectB
dan komit lokal saya .
Bagian yang sulit di sini adalah bahwa ini adalah gabungan gurita (tiga kepala), tetapi projectB
perlu digabungkan dengan strategi subtree . Jadi inilah yang saya lakukan:
# Merge projectA with the default strategy:
git merge projectA/master
# Merge projectB with the subtree strategy:
git merge -s subtree projectB/master
Di sini penulis menggunakan reset --hard
, dan kemudian read-tree
untuk mengembalikan apa yang telah dilakukan oleh dua penggabungan pertama ke pohon kerja dan indeks, tetapi di situlah reset --soft
dapat membantu:
Bagaimana saya mengulangi dua penggabungan , yang telah bekerja, yaitu pohon kerja dan indeks saya adalah baik-baik saja, tetapi tanpa harus merekam kedua komitmen tersebut
# Move the HEAD, and just the HEAD, two commits back!
git reset --soft HEAD@{2}
Sekarang, kita dapat melanjutkan solusi Tomas:
# Pretend that we just did an octopus merge with three heads:
echo $(git rev-parse projectA/master) > .git/MERGE_HEAD
echo $(git rev-parse projectB/master) >> .git/MERGE_HEAD
# And finally do the commit:
git commit
Jadi, setiap kali:
- Anda puas dengan apa yang Anda dapatkan (dalam hal pohon dan indeks kerja)
- Anda tidak puas dengan semua komitmen yang membawa Anda ke sana:
git reset --soft
adalah jawabannya.
git reset --soft
: stackoverflow.com/questions/6869705/…Use Case - Gabungkan serangkaian commit lokal
"Ups. Tiga komitmen itu bisa jadi hanya satu."
Jadi, batalkan komit 3 terakhir (atau apa pun) berkomitmen (tanpa mempengaruhi indeks atau direktori kerja). Kemudian komit semua perubahan sebagai satu.
Misalnya
Sekarang semua perubahan Anda dipertahankan dan siap untuk dilakukan sebagai satu.
Jawaban singkat untuk pertanyaan Anda
Apakah kedua perintah ini benar-benar sama (
reset --soft
vscommit --amend
)?Adakah alasan untuk menggunakan satu atau yang lain dalam istilah praktis?
commit --amend
untuk menambah / rm file dari komit terakhir atau untuk mengubah pesannya.reset --soft <commit>
untuk menggabungkan beberapa komit berurutan menjadi yang baru.Dan yang lebih penting, apakah ada kegunaan lain
reset --soft
selain mengubah komit?sumber
reset --soft
selain dari mengubah komit - Tidak"git reset
) baik ketika Anda (a) ingin menulis ulang sejarah, (b) tidak peduli dengan komitmen lama (sehingga Anda dapat menghindari kerepotan rebase interaktif), dan (c) memiliki lebih dari satu komitmen untuk berubah (jika tidak,commit --amend
lebih sederhana).Saya menggunakannya untuk mengubah lebih dari sekedar komit terakhir .
Katakanlah saya membuat kesalahan dalam komit A dan kemudian membuat komit B. Sekarang saya hanya dapat mengubah B. Jadi saya lakukan
git reset --soft HEAD^^
, saya memperbaiki dan komit ulang A dan kemudian komit kembali B.Tentu saja, itu tidak terlalu nyaman untuk komit besar ... tetapi Anda tidak boleh melakukan komit besar ;-)
sumber
git commit --fixup HEAD^^
git rebase --autosquash HEAD~X
berfungsi dengan baik juga.git rebase --interactive HEAD^^
di mana Anda memilih untuk mengedit komit A dan B. Dengan cara ini menyimpan pesan komit dari A dan B, jika diperlukan Anda masih dapat memodifikasinya juga.git reset A
, buat dan tambahkan perubahangit commit --amend
,,git cherry-pick <B-commit-hash>
.Penggunaan potensial lainnya adalah sebagai alternatif untuk menyembunyikan (yang beberapa orang tidak suka, lihat misalnya https://codingkilledthecat.wordpress.com/2012/04/27/git-stash-pop-considered-harmful/ ).
Sebagai contoh, jika saya sedang mengerjakan cabang dan perlu memperbaiki sesuatu dengan segera pada master, saya bisa melakukan:
kemudian checkout master dan lakukan perbaikan. Setelah selesai, saya kembali ke cabang saya dan melakukannya
untuk terus bekerja di tempat saya tinggalkan.
sumber
--soft
sebenarnya tidak perlu di sini, kecuali Anda benar-benar peduli tentang perubahan akan segera dipentaskan. Saya sekarang hanya menggunakangit reset HEAD~
ketika melakukan ini. Jika saya memiliki beberapa perubahan yang dipentaskan ketika saya perlu berganti cabang, dan ingin tetap seperti itu, maka saya lakukangit commit -m "staged changes"
, kemudiangit commit -am "unstaged changes"
, kemudiangit reset HEAD~
diikuti olehgit reset --soft HEAD~
untuk sepenuhnya memulihkan kondisi kerja. Meskipun, sejujurnya saya melakukan kedua hal ini jauh lebih sedikit sekarang yang saya tahu tentanggit-worktree
:)Anda dapat menggunakan
git reset --soft
untuk mengubah versi yang ingin Anda miliki sebagai induk untuk perubahan yang Anda miliki di indeks dan pohon kerja Anda. Kasus-kasus di mana ini berguna jarang terjadi. Kadang-kadang Anda mungkin memutuskan bahwa perubahan yang Anda miliki di pohon kerja Anda harus menjadi milik cabang yang berbeda. Atau Anda dapat menggunakan ini sebagai cara sederhana untuk memecah beberapa commit menjadi satu (mirip dengan squash / fold).Lihat jawaban ini oleh VonC untuk contoh praktis: Hancurkan dua komit pertama di Git?
sumber
git reset --soft anotherBranch
dan kemudian komit di sana? Tetapi Anda tidak benar-benar mengubah cabang ckeckout, jadi apakah Anda akan berkomitmen ke Cabang atau ke Cabang lain ?Salah satu kemungkinan penggunaan adalah ketika Anda ingin melanjutkan pekerjaan Anda pada mesin yang berbeda. Ini akan bekerja seperti ini:
Periksa cabang baru dengan nama simpanan,
Dorong cabang simpanan Anda ke atas,
Beralih ke mesin Anda yang lain.
Tarik simpanan dan cabang yang ada,
Anda harus berada di cabang yang ada sekarang. Gabungkan perubahan dari cabang simpanan,
Setel ulang cabang Anda yang ada menjadi 1 sebelum penggabungan,
Hapus cabang simpanan Anda,
Hapus juga cabang simpanan Anda dari asal,
Terus bekerja dengan perubahan Anda seolah-olah Anda telah menyimpannya secara normal.
Saya pikir, di masa depan, GitHub dan rekan. harus menawarkan fungsionalitas "simpanan jauh" ini dalam beberapa langkah lebih sedikit.
sumber
Salah satu penggunaan praktis adalah jika Anda telah berkomitmen pada repo lokal Anda (mis. Git commit -m) maka Anda dapat membalikkan komit terakhir dengan melakukan reset git --soft HEAD ~ 1
Juga untuk pengetahuan Anda, jika Anda telah melakukan perubahan Anda sudah (yaitu dengan git add.) Maka Anda dapat membalikkan pementasan dengan melakukan git reset - dicampur KEPALA atau saya sudah umum juga baru saja digunakan
git reset
terakhir, git reset --hard menghapus semuanya termasuk perubahan lokal Anda. Kepala ~ setelah memberi tahu Anda berapa banyak komit untuk pergi dari atas.
sumber
git reset --soft HEAD ~1
memberi saya,fatal: Cannot do soft reset with paths.
saya pikir kita perlu menghapus ruang setelah KEPALA sehinggagit reset --soft HEAD~1
Alasan bagus untuk menggunakan '
git reset --soft <sha1>
' adalah untuk bergerakHEAD
dalam repo telanjang.Jika Anda mencoba menggunakan opsi
--mixed
atau--hard
, Anda akan mendapatkan kesalahan karena Anda mencoba untuk memodifikasi dan bekerja pohon dan / atau indeks yang tidak ada.Catatan: Anda harus melakukan ini langsung dari repo telanjang.
Catatan Lagi: Anda perlu memastikan cabang yang ingin Anda atur ulang di bare repo adalah cabang aktif. Jika tidak, ikuti jawaban VonC tentang cara memperbarui cabang aktif dalam repo kosong ketika Anda memiliki akses langsung ke repo.
sumber
SourceTree adalah git GUI yang memiliki antarmuka yang cukup nyaman untuk pementasan bit yang Anda inginkan. Itu tidak memiliki sesuatu yang mirip untuk mengubah revisi yang tepat.
Jadi
git reset --soft HEAD~1
jauh lebih bermanfaat daripadacommit --amend
dalam skenario ini. Saya dapat membatalkan komit, mendapatkan semua perubahan kembali ke area pementasan, dan melanjutkan tweak bit yang dipentaskan menggunakan SourceTree.Sungguh, menurut saya itu
commit --amend
adalah perintah yang lebih berlebihan dari keduanya, tetapi git adalah git dan tidak menghindar dari perintah serupa yang melakukan hal yang sedikit berbeda.sumber
Walaupun saya benar-benar menyukai jawaban di utas ini, saya menggunakan
git reset --soft
skenario yang sedikit berbeda, namun tetap sangat praktis.Saya menggunakan IDE untuk pengembangan yang memiliki alat diff yang baik untuk menampilkan perubahan (bertahap dan tidak bertahap) setelah komit terakhir saya. Sekarang, sebagian besar tugas saya melibatkan banyak komitmen. Sebagai contoh, katakanlah saya membuat 5 komitmen untuk menyelesaikan tugas tertentu. Saya menggunakan alat diff di IDE selama setiap komit tambahan dari 1-5 untuk melihat perubahan saya dari komit terakhir. Saya merasa ini cara yang sangat membantu untuk meninjau perubahan saya sebelum melakukan.
Tetapi pada akhir tugas saya, ketika saya ingin melihat semua perubahan saya bersama-sama (dari sebelum komit 1), untuk melakukan review kode diri sebelum membuat permintaan tarik, saya hanya akan melihat perubahan dari komit saya sebelumnya (setelah komit 4) dan tidak berubah dari semua komitmen dari tugas saya saat ini.
Jadi saya gunakan
git reset --soft HEAD~4
untuk kembali 4 komitmen. Ini memungkinkan saya melihat semua perubahan bersama. Ketika saya yakin akan perubahan saya, saya bisa melakukannyagit reset HEAD@{1}
dan mendorongnya ke jarak jauh dengan percaya diri.sumber
git add --patch
dangit commit
berulang kali untuk membangun seri komit yang telah Anda buat jika Anda tahu apa yang Anda lakukan selama ini. Komit pertama Anda seperti catatan di meja Anda atau draf memo pertama, mereka ada di sana untuk mengatur pemikiran Anda, bukan untuk publikasi.git reset @{1}
untuk memulihkan seri draf pertama Anda, Anda dapat membangun seri untuk publikasi darigit add -p
dangit commit
.Kasus penggunaan lain adalah ketika Anda ingin mengganti cabang lain dengan Anda dalam permintaan tarik, misalnya, katakanlah Anda memiliki perangkat lunak dengan fitur A, B, C dalam pengembangan.
Anda mengembangkan dengan versi berikutnya dan Anda:
Fitur yang dihapus B
Fitur yang ditambahkan D
Dalam prosesnya, kembangkan hotfix baru saja ditambahkan untuk fitur B.
Anda dapat menggabungkan pengembangan menjadi yang berikutnya, tetapi itu kadang-kadang bisa berantakan, tetapi Anda juga dapat menggunakan
git reset --soft origin/develop
dan membuat komit dengan perubahan Anda dan cabang dapat digabung tanpa konflik dan menyimpan perubahan Anda.Ternyata itu
git reset --soft
adalah perintah yang berguna. Saya pribadi banyak menggunakannya untuk menekan komit yang tidak memiliki "pekerjaan selesai" seperti "WIP" jadi ketika saya membuka permintaan tarik, semua komit saya bisa dimengerti.sumber