Bagaimana saya bisa membatalkan komit terakhir di repositori git bare?

94

Mempertimbangkan bahwa ada beberapa perintah git yang tidak masuk akal dalam repositori telanjang (karena repositori telanjang tidak menggunakan indeks dan tidak memiliki direktori kerja),

git reset --hard HEAD^ 

bukanlah solusi untuk membatalkan perubahan terakhir dalam repositori semacam itu.

Mencari melalui Internet, yang dapat saya temukan terkait dengan topik ini adalah ini , di mana saya disajikan tiga cara untuk melakukan ini:
1. "perbarui referensi secara manual (yang melibatkan pipa ledeng)";
2. " git push -fdari repositori non-telanjang";
3. " git branch -f this $that".

Solusi mana yang menurut Anda lebih tepat atau cara lain apa yang dapat dilakukan untuk melakukannya? Sayangnya, dokumentasi yang saya temukan tentang repositori git bare cukup buruk.

Lavinia-Gabriela Dobrovolschi
sumber
8
@ Lavinia-Garbriela Dobrovol Jangan gunakan hal-hal rumit di bawah ini. Anda mencoba untuk memindahkan HEAD ke komit yang berbeda dan untuk itulah git reset dimaksudkan, bahkan dalam repo kosong. Sesuai jawaban saya di bawah ini, gunakan: git reset --soft <commit> Dengan --soft, Anda tidak mencoba mengubah pohon kerja dan indeks yang tidak ada, jadi git memungkinkan Anda melakukan reset tanpa masalah.
Hazok

Jawaban:

133

Anda bisa menggunakan git update-refperintah. Untuk menghapus komit terakhir, Anda akan menggunakan:

$ git update-ref HEAD HEAD^

Atau jika Anda tidak berada di cabang tempat Anda tidak dapat menghapus komit terakhir:

$ git update-ref refs/heads/branch-name branch-name^

Anda juga bisa memberikan sha1 jika Anda ingin:

$ git update-ref refs/heads/branch-name a12d48e2

Lihat dokumentasi perintah git-update-ref .

Sylvain Defresne
sumber
@ Lavinia-Gabriela Dobrovolschi: benar, saya tidak terbiasa dengan sintaks yang tepat.
VonC
@VonC Anda dapat menentukan <ref> in git update-ref <ref> <newvalue>menjadi cabang yang benar, seperti "refs / heads / master" alih-alih HEAD, misalnya. Saya harap saya tidak salah paham dengan pertanyaan Anda.
Lavinia-Gabriela Dobrovolschi
@Sylvain: +1 hasil edit yang bagus. @ Lavinia-Gabriela Dobrovolschi terima kasih atas ketepatannya. Itu jauh lebih praktis (jika Anda memiliki akses langsung ke server jarak jauh, saya kira).
VonC
3
Contoh-contoh tersebut menyesatkan sehubungan dengan branch-nameargumen. Saat menggunakan update-refdengan "cabang" Anda benar-benar harus menentukan nama referensi lengkap cabang (yaitu, diawali refs/heads/dengan nama cabang pendek yang normal). Jika Anda hanya menggunakan nama pendek, Anda akan membuat / memperbarui, $GIT_DIR/branch-namebukan $GIT_DIR/refs/heads/branch-name. Adanya keduanya branch-namedan refs/heads/branch-nameakan menyebabkan peringatan “refname… is ambiguous”.
Chris Johnsen
Jawaban ini jauh lebih rumit dari apa yang Zach usulkan. Dan solusinya bekerja dengan baik.
Krystian
32

Jika Anda menggunakan yang berikut ini dalam repo telanjang:

git reset --soft <commit>

maka Anda tidak mengalami masalah yang Anda gunakan --harddan --mixedopsi dalam repo telanjang karena Anda tidak mencoba mengubah sesuatu yang tidak dimiliki repo telanjang (yaitu pohon kerja dan indeks). Dalam kasus Anda secara khusus, Anda ingin menggunakan (dari repo telanjang):

git reset --soft HEAD^

Untuk mengganti cabang pada repo jarak jauh lakukan:

git symbolic-ref HEAD refs/heads/<branch_name>

Untuk melihat penggunaan cabang yang dipilih saat ini:

git symbolic-ref HEAD

https://mirrors.edge.kernel.org/pub/software/scm/git/docs/git-symbolic-ref.html

Hazok
sumber
3
Bagaimana Anda memilih cabang yang ingin Anda pindahkan? Contoh Anda berfungsi dengan baik pada master tetapi git checkout other_branchtidak bekerja secara telanjang.
Gauthier
1
Hmmm ... Saya ingin tahu siapa yang menolak saya dalam hal ini. Pertanyaannya tidak menanyakan bagaimana cara mengganti cabang pada repo jarak jauh, melainkan bagaimana mengatur ulang pada repo telanjang. Untuk mengubah cabang default di repo jarak jauh, gunakan git symbolic-ref HEAD refs / heads / <branch_name>.
Hazok
7

The git push -fharus bekerja dengan baik:
jika Anda clone bahwa repo telanjang, menghapus komit terakhir ( git reset --hard HEAD^seperti yang Anda sebutkan, tetapi dalam repo non-telanjang lokal) dan mendorong kembali ( -f):

  • Anda tidak mengubah SHA1 apa pun untuk commit lain sebelum yang Anda hapus.
  • Anda yakin Anda mendorong kembali konten yang tepat dari repo telanjang dikurangi komit ekstra (karena Anda baru saja mengkloningnya terlebih dahulu).
VonC
sumber
@ VonC Hi Von, saya telah melihat Anda menjawab banyak tentang Git jadi ingin bertanya kepada Anda ... Saya penasaran, mengapa git reset --soft <sha1>seperti yang ditunjukkan pada jawaban saya di bawah ini tidak menjadi latihan yang disarankan untuk memindahkan HEAD pada repo kosong?
Hazok
Saya kira alasan lain yang saya tanyakan adalah bahwa menggunakan soft reset untuk repo telanjang bukanlah informasi yang tersedia dan banyak forum tampaknya memiliki solusi yang tidak perlu rumit ketika tampaknya soft reset adalah praktik terbaik karena jumlah pengetikan yang paling sedikit dan sedikit peluang untuk kesalahan.
Hazok
2
@ Zach: a reset --softharus berfungsi jika dilakukan langsung pada repo kosong. Saya menduga ini jarang dilakukan karena repo telanjang umumnya merupakan repo upstream (yaitu repo tempat Anda mendorong data), dan sebagian besar waktu, Anda tidak memiliki akses lokal langsung ke sana. Tetapi jika Anda melakukannya, maka ini tentunya contoh bagus lainnya dari reset --softpenggunaan " " (seperti dalam stackoverflow.com/questions/5203535/… ) Jadi +1 untuk jawaban Anda.
VonC
2

Anda juga dapat menggunakan notasi git refspec dan melakukan sesuatu seperti ini:

git push -f origin +<commit you want to revert to>:<destination_head | branch_name>

Ini memaksa pembaruan cabang tujuan (sebagaimana dilambangkan dengan ref) ke komit sumber sebagaimana dilambangkan dengan +<object ref>bagian.

alup
sumber
2
kecuali jika ada acl di cabang - yang biasanya terjadi jika Anda "perlu melakukannya di repo telanjang itu sendiri" ...
David Schmitt