git revert — commitni bekor qilish, reset dan farqi

~15 daq · Git · Git Tarixini Boshqarish

Muammodan boshlaylik

Juma, 17:00. Yangi to'lov moduli main ga qo'shildi va production ga deploy qilindi. 17:15 — mijozlar to'lov qila olmayapti. Xato tezda topilmaydi.

Kodni darhol oldingi holatga qaytarish kerak. Lekin:

  • git reset — push qilingan tarixni o'chiradi, hamkasblar tarixini buzadi (27-dars)
  • Qo'lda kodni tiklash — sekin va xatoga moyil

Yechim — git revert: tarixni o'chirmasdan, o'zgarishni bekor qiluvchi yangi commit yaratish.


Revert nima qiladi

git revert a3f9c2b

Git a3f9c2b commit idagi o'zgarishlarning teskarisini hisoblab, yangi commit yaratadi:

 Commit a3f9c2b:              Revert commit:
 +  payme.yarat(summa)        -  payme.yarat(summa)
 -  click.yarat(summa)        +  click.yarat(summa)
 Oldin:   ●────●────A────B    main

 Keyin:   ●────●────A────B────A̅    main
                               ↑
                     "Revert 'To'lov: Payme integratsiyasi'"

A hali ham tarixda. A̅ — uni bekor qiladi. Natijada kod A dan oldingi holatda (B ning o'zgarishlari saqlangan holda).

Muharrir ochiladi, standart xabar:

Revert "To'lov: Payme integratsiyasi"

This reverts commit a3f9c2b8e1d4f6a7b9c0d2e4f6a8b0c2d4e6f8a0.

Sababini qo'shish yaxshi amaliyot: "Production da to'lovlar o'tmayapti, #91".

git push                   # oddiy push — hech qanday force kerak emas

Reset va revert — farqi

 RESET (tarixni qayta yozadi):         REVERT (tarixga qo'shadi):
  ●──●──A──B   →   ●──●                 ●──●──A──B   →   ●──●──A──B──B̅
git reset git revert
Tarix Commitlarni olib tashlaydi Yangi commit qo'shadi
Push qilingan commitlar ❌ Xavfli (force kerak) ✅ Xavfsiz (oddiy push)
Hamkasblarga ta'siri Tarixlari buziladi Hech qanday — oddiy pull
"Nima bo'lgan" izi Yo'qoladi Saqlanadi: xato va bekor qilish ko'rinadi
Qachon Lokal, push qilinmagan Ommaviy branch lar, production

Qoida: push qilinganmi? → revert. Faqat lokalmi? → reset.


Bir nechta commit ni bekor qilish

git revert a3f9c2b e5f6a7b               # ikkita — har biri uchun alohida revert commit
git revert HEAD~3..HEAD                  # oxirgi 3 ta
git revert --no-commit HEAD~3..HEAD      # hammasini bitta revert commit ga
git commit -m "Revert: to'lov moduli o'zgarishlari (#91)"

--no-commit (-n) — o'zgarishlarni staging ga qo'yadi, commit qilmaydi: bir nechta revert ni bitta commit ga birlashtirish uchun.


Merge commit ni bekor qilish

Butun feature main ga merge commit bilan qo'shilgan (15-dars). Butun funksiyani bekor qilish:

git revert -m 1 9f8e7d6

Merge commit ning ikkita otasi bor. -m 1 — "birinchi otaga (main) nisbatan bekor qil", ya'ni feature branch dan kelgan hamma narsani olib tashla.

Bu --no-ff merge larning afzalligi (15-dars): butun funksiya — bitta revert. Squash merge da esa — bitta oddiy commit, -m siz revert.

[!WARNING] Merge commit revert qilingandan keyin, o'sha branch ni qayta merge qilsangiz — Git "bu commitlar allaqachon qo'shilgan" deb hisoblaydi va o'zgarishlar qaytmaydi. Funksiyani qaytarish uchun — revert ni revert qiling: git revert <revert-commit-hash>.


Revert conflict

Bekor qilinayotgan commit dan keyin o'sha qatorlar yana o'zgargan bo'lsa — conflict:

CONFLICT (content): Merge conflict in src/tolov.js
error: could not revert a3f9c2b... To'lov: Payme integratsiyasi

Hal qilish — 16-dars kabi:

# tahrirlash → git add src/tolov.js
git revert --continue
# yoki
git revert --abort

Production da tez qaytarish — ish oqimi

git switch main
git pull
git log --oneline -10            # muammoli commit ni topish
git revert a3f9c2b               # bekor qilish
npm test                         # tekshirish
git push                         # CI/CD avtomatik deploy qiladi

Sayt ishlaydi. Endi xotirjam, alohida branch da xatoni topib tuzatasiz va funksiyani qayta qo'shasiz.

[!TIP] Juma kechqurun xatoni tuzatishga urinmang — avval revert, sayt ishlasin. Tuzatish — dushanba kuni, xotirjam. "Roll back first, debug later" — production qoidasi.


Nima uchun shunday?

Nima uchun revert ataylab "xato + bekor qilish" ni tarixda qoldiradi — toza tarix yaxshiroq emasmi?

Chunki ommaviy tarix — jamoaviy kelishuv. Hamkasblaringizning lokal nusxalari, CI tizimi, deploy qilingan versiyalar, PR va issue havolalari — hammasi mavjud commit hash lariga tayanadi. Ularni o'chirish (reset + force) — bu kelishuvni bir tomonlama buzish. Revert esa tarixga faqat qo'shadi: hamma oddiy pull bilan sinxron bo'ladi, hech narsa buzilmaydi. Qo'shimcha foyda — halol hujjat: "bu funksiya 6-noyabrda chiqarildi, 15 daqiqadan keyin bekor qilindi, sabab — #91". Keyingi safar xuddi shu xatoga yo'l qo'ymaslik uchun aynan shunday tarix kerak.


Xulosa

Eslab qoling:

  • git revert <commit> — o'zgarishni bekor qiluvchi yangi commit
  • Tarix o'chirilmaydi; oddiy git push — force kerak emas
  • Push qilingan → revert; lokal → reset
  • Bir nechta: git revert A B yoki HEAD~3..HEAD; --no-commit — bittaga
  • Merge commit: git revert -m 1 <merge-hash>
  • Revert qilingan branch ni qayta qo'shish — revert ni revert qiling
  • Conflict: tahrirlash → git add → git revert --continue
  • Production da: avval revert, keyin xotirjam tuzatish

Keyingi dars

29-dars: git cherry-pick — boshqa branch dan bitta commit olish