IlmHamroh
JavaScript Full-stack/7-qism. Git va GitHub asoslari33/36-dars23 daqiqa
Mundarija (39)

GitHub branch himoyasi va rulesets: main'ni tasodifiy push'dan saqlash

Qisqacha: Ruleset — GitHub'dagi branch uchun qoidalar to'plami: "main'ga faqat Pull Request orqali", "force-push yo'q", "o'chirish yo'q". Qoida buzilsa, GitHub push'ni rad etadi va GH013: Repository rule violations found xabarini qaytaradi. Ruleset Settings → Rules → Rulesets sahifasida yaratiladi va public repolarda bepul. Eski usul — klassik branch himoyasi (branch protection rule) — ham ishlaydi, ikkalasi birga qo'llanadi.

Bu darsda

  • Ruleset nima ekanini va u klassik branch himoyasidan nimasi bilan farq qilishini tushuntira olasiz.
  • GitHub'da main uchun ruleset yaratasiz: maqsadli branch, holat (Active/Disabled), bypass ro'yxati.
  • Asosiy qoidalarni tanlay olasiz: o'chirish va force-push taqiqi, majburiy PR, review, chiziqli tarix, status check.
  • GH013 xatosini o'qiysiz va rad etilgan commitni yo'qotmasdan PR yo'liga o'tkazasiz.
  • Portfolio'ingizning main branchini himoyalaysiz.

Oldin bilishingiz kerak: Pull Request: yaratish, muhokama, merge, GitHub'da code review amaliyoti, Ajralgan tarix: pull --rebase va force-with-lease.

1. Nega bu kerak?

Pull Request darsida kelishib oldik: o'zgarish avval branch'da yoziladi, PR'da ko'riladi, keyin main ga qo'shiladi. Lekin bu — faqat kelishuv. Git hech kimni git push origin main yozishdan to'xtatmaydi.

Tasavvur qiling. «Bahor» saytida endi uch kishi ishlaydi: siz, Malika va stajyor Sardor. Kech soat 23:00 da Sardor menyu/ dagi narxni tuzatib, to'g'ridan-to'g'ri main ga yubordi. Bitta qavs yopilmay qolgan ekan. Sayt avtomatik yangilandi va menyu sahifasi buzildi. Ertalab mehmonlar narxlarni ko'ra olmadi.

Ikkinchi hafta yana bir voqea. Malika o'z tarixini rebase qildi va shoshib git push --force yozdi. Uning nusxasi eski edi — sizning kechagi uchta commitingiz main dan yo'qoldi. Ajralgan tarix darsida bunga qarshi --force-with-lease ni o'rgangan edik. Lekin u ham faqat yozgan odamning e'tiboriga bog'liq: charchagan odam baribir --force yozib yuboradi.

Bunday xatolarni "ehtiyot bo'linglar" degan gap to'xtatmaydi. Qoidani server tekshirishi kerak. GitHub'da buning vositasi bor — ruleset.

Hayotiy o'xshatish: bank kassasi. Kassir pulni qo'lda istalgancha bera olardi. Lekin bank tizimi har to'lovni tekshiradi: imzo yo'q — to'lov o'tmaydi. Kassir qanchalik tajribali bo'lmasin, qoida hamma uchun bir xil. Ruleset ham shunday: kim yozganidan qat'i nazar, qoidani buzgan push qabul qilinmaydi.

2. Ruleset va branch himoyasi

2.1 Ta'rif

Ruleset (qoidalar to'plami) — repodagi branch yoki taglarga qo'yiladigan nomli qoidalar ro'yxati. Masalan, "main himoyasi" nomli ruleset: main ni o'chirish mumkin emas, unga force-push mumkin emas, o'zgarish faqat PR orqali keladi.

GitHub qoidani push vaqtida tekshiradi. Siz git push yozasiz, commitlar serverga yetib boradi, GitHub ularni qoidalar bilan solishtiradi. Mos kelmasa — butun push rad etiladi va sizga sababi aytiladi. Repoda hech narsa o'zgarmaydi.

Bu himoya faqat terminal uchun emas. GitHub hujjatiga ko'ra, himoyalangan branch'da fayllarni brauzer orqali tahrirlab yoki yuklab bo'lmaydi. Birinchi deploy darsida portfolio fayllarini aynan shunday yuklagan edingiz. Endi bu yo'l ham yopiladi — o'zgarish faqat branch va PR orqali.

2.2 Ikki xil vosita

GitHub'da branchni himoyalashning ikki yo'li bor:

Klassik branch himoyasi Ruleset
Inglizcha nomi Branch protection rule Ruleset
Bitta branch'ga nechta Faqat bittasi ishlaydi Bir nechtasi birga
Vaqtincha o'chirish Faqat o'chirib tashlab Holatini Disabled qilib
Kim ko'ra oladi Admin O'qish huquqi bor hamma

Ruleset — yangiroq va moslashuvchan vosita. Bir nechta ruleset bitta branch'ga tushsa, qoidalar qo'shiladi. Bir qoida turlicha yozilgan bo'lsa, eng qattig'i ishlaydi. Masalan, bir rulesetda 1 ta, boshqasida 2 ta review talab qilinsa — 2 ta kerak bo'ladi. Klassik himoya ham shu hisobga qo'shiladi.

Ikkinchi muhim farq — adminlar. Klassik himoya, standart holatda, repo adminlariga tegmaydi: ular qoidani chetlab o'ta oladi. Buni yopish uchun alohida "Do not allow bypassing the above settings" katagi bor. Rulesetda esa aksincha: chetlab o'tish huquqi faqat bypass ro'yxatiga yozilganlarda. Ro'yxat bo'sh bo'lsa, repo egasi ham qoidaga bo'ysunadi.

Kursda ruleset ishlatamiz. Eski loyihalarda klassik himoyani ko'p uchratasiz — u Settings → Branches sahifasida, Add classic branch protection rule tugmasi bilan yaratiladi. Qoidalarning nomlari va ma'nosi deyarli bir xil.

2.3 Kimda ishlaydi va qancha turadi

GitHub hujjatiga ko'ra (2026-yil oktabr holati): ruleset va klassik himoya public repolarda bepul GitHub Free tarifida ishlaydi. Private repoda ular uchun pullik tarif kerak (Pro, Team yoki Enterprise). Portfolio repongiz login.github.io — public, demak bepul.

Bitta repoda 75 tagacha ruleset bo'lishi mumkin. Odatda 1–3 tasi yetadi.

Tekshirib ko'ring: Repoda ikkita ruleset main ga qaraydi. Birinchisi force-push'ni taqiqlaydi, ikkinchisi PR talab qiladi. main ga qaysi qoidalar ishlaydi?

Javob

Ikkalasi ham. Rulesetlar bir-birini almashtirmaydi — qoidalari yig'iladi. main ga endi force-push ham mumkin emas, PR'siz push ham. Klassik himoyada esa bitta branch'ga faqat bitta qoida ishlardi.

3. Ruleset yaratish

3.1 Sahifaga yo'l

Qadamlar GitHub hujjatidan (docs.github.com, "Creating rulesets for a repository"):

  1. Repo sahifasida Settings tabini bosing. Ko'rinmasa — ... menyusidan Settings ni tanlang.
  2. Chap paneldagi "Code and automation" bo'limida Rules → Rulesets ni bosing.
  3. New ruleset → New branch ruleset ni tanlang.

Menyuda New tag ruleset ham bor — u taglarni himoyalaydi: masalan, v* taglarini hech kim o'chira olmasin. Import a ruleset esa tayyor JSON faylidan ruleset yaratadi — bir xil qoidani ko'p repoga qo'yish uchun qulay.

3.2 Nom, holat va bypass

Ochilgan formada birinchi uchta maydon:

  • Ruleset name — nom. Biz main himoyasi deb yozdik. Nom faqat odamlar uchun — qisqa va tushunarli bo'lsin.
  • Enforcement status — holat. Active — qoida darhol ishlaydi. Disabled — ruleset saqlanadi, lekin ishlamaydi. Yangi forma standart holatda Disabled bo'ladi — Active ni o'zingiz tanlang. (Uchinchi holat — Evaluate: qoida faqat kuzatadi va hisobot yozadi. U faqat Enterprise tariflarida bor.)
  • Bypass list — qoidani chetlab o'ta oladiganlar. Add bypass tugmasi bilan rol (masalan Repository admin), jamoa yoki ilova qo'shiladi.

Maslahat: Bypass ro'yxatini bo'sh qoldiring. "Men egasiman, menga mumkin" — aynan kechasi 23:00 dagi xatoning boshlanishi. Qoida hamma uchun bir xil bo'lsa, unga ishonsa bo'ladi.

3.3 Qaysi branchlar: target

"Target branches" bo'limida Add a target tugmasi bor. Uchta yo'l:

  • Include default branch — standart branch (bizda main). Keyin branch nomi o'zgarsa ham, qoida yangisiga o'tadi.
  • Include all branches — hammasi.
  • Include by pattern — shablon bo'yicha. Masalan release/**/* — release/ bilan boshlanadigan hamma branch.

Shablondagi yulduzchalar .gitignore dagiga o'xshaydi: * — / gacha bo'lgan istalgan nom, ** — istalgan chuqurlikdagi papkalar. GitHub hujjati bu sintaksisni fnmatch deb ataydi — nomini bilish shart emas. Exclude by pattern bilan istisno ham qo'shish mumkin.

Portfolio uchun bitta target yetadi: Include default branch.

4. Qoidalar bittalab

"Branch protections" bo'limida qoidalar ro'yxati turadi. Har birining yonida katak. Ba'zilarini tanlaganingizda qo'shimcha sozlamalar ochiladi.

4.1 Ikki standart qoida

Yangi rulesetda ikkitasi oldindan belgilangan:

  • Restrict deletions — branchni o'chirish taqiqlanadi (bypass ro'yxatidagilardan tashqari).
  • Block force pushes — force-push taqiqlanadi. Ajralgan tarix darsidagi --force ham, --force-with-lease ham.

Ikkalasini ham qoldiring. Ular main tarixini o'chib ketishdan saqlaydi.

4.2 Require a pull request before merging

Eng muhim qoida: branch'ga o'zgarish faqat PR orqali keladi. GitHub hujjatida aytilishicha, PR tasdiqlangan bo'lishi shart emas — ochilgan bo'lishi kifoya. To'g'ridan-to'g'ri push rad etiladi.

Uni tanlaganingizda qo'shimcha sozlamalar ochiladi:

Sozlama Nima qiladi
Required approvals Merge'dan oldin nechta tasdiq (approve) kerak
Dismiss stale pull request approvals when new commits are pushed Yangi commit kelsa, eski tasdiq bekor bo'ladi
Require review from Code Owners Fayl "egasi" tasdiqlashi shart
Require approval of the most recent reviewable push Oxirgi push'ni boshqa odam tasdiqlashi kerak
Require conversation resolution before merging Hamma izoh "hal qilindi" bo'lishi kerak
Allowed merge methods Qaysi merge usullariga ruxsat: merge, squash, rebase

Code review darsidagi tasdiqlash aynan shu yerda majburiy bo'ladi. Jamoada odatda 1 ta tasdiq so'raladi.

Bir muhim nuqta: o'z PR'ingizni o'zingiz tasdiqlay olmaysiz. Yolg'iz ishlasangiz va "1 ta tasdiq" ni yoqsangiz, PR'ni hech kim merge qila olmaydi. Shuning uchun portfolio'da tasdiqlar sonini 0 qoldiramiz: PR majburiy, tasdiq — yo'q. Bu xatoning haqiqiy matnini keyingi darsda terminalda ko'rasiz.

"Code Owners" — fayllarga mas'ul odamlar ro'yxati, ya'ni Code review darsida yozgan CODEOWNERS faylingiz. Bu katak yoqilsa, ular faqat avtomatik chaqirilmaydi — ularning tasdig'isiz merge bo'lmaydi.

4.3 Require linear history

Chiziqli tarix (linear history) — main da merge commit bo'lmaydi. PR'ni faqat squash yoki rebase usuli bilan qo'shish mumkin. Bu usullarni Pull Request darsida ko'rgan edik.

gitGraph
  commit id: "3fbf72b Pages"
  branch feature/aloqa-telegram
  checkout feature/aloqa-telegram
  commit id: "ecffd19 Telegram"
  checkout main
  commit id: "a2a3d58 Telegram (#4)"

Nimaga qarang: squash usulida branch'dagi commit main ga yangi commit sifatida tushadi (a2a3d58), PR raqami (#4) bilan. main chizig'ida ayri yo'q — tarix bitta to'g'ri chiziq. Branch esa merge'dan keyin o'chiriladi.

Nega bu foydali? Chiziqli tarixda git log --oneline toza o'qiladi. Xato commitni revert qilish ham oson: har PR — bitta commit.

4.4 Qolgan qoidalar

Jadvalda yangi so'z bor: CI — har push'da kodni GitHub serverida avtomatik tekshiradigan tizim. Uni ikki darsdan keyin quramiz, hozir nomini bilish yetarli.

Qoida Qisqacha
Require status checks to pass Avtomatik tekshiruv (CI) o'tmasa, merge yo'q
Require signed commits Faqat imzolangan commitlar
Require deployments to succeed before merging Avval sinov serveriga deploy o'tishi kerak
Restrict creations / updates Branchni yaratish yoki yangilash faqat bypass bilan
Require merge queue PR'lar navbat bilan, birga sinalib qo'shiladi

Require status checks to pass — eng kuchli himoyalardan biri. U PR'dagi avtomatik tekshiruv (masalan, npm run check) muvaffaqiyatli bo'lishini talab qiladi. Bizda hali bunday tekshiruv yo'q. Uni GitHub Actions: birinchi CI workflow darsida yaratamiz va shu rulesetga qo'shamiz.

Shu qoidaning ichida Require branches to be up to date before merging katagi bor. U belgilansa ("strict" — qattiq rejim), PR branchi main ning eng oxirgi holatini o'z ichiga olishi shart. Belgilanmasa ("loose" — yumshoq rejim), eski asosdagi PR ham qo'shilaveradi.

Require merge queue — katta jamoalar uchun. GitHub hujjatiga ko'ra, u faqat tashkilotga (organization) tegishli repolarda ishlaydi. Shaxsiy repo uchun — yo'q.

4.5 Saqlash

Formaning pastidagi Create tugmasi. Holat Active bo'lsa, qoida shu zahoti ishlaydi. Keyin o'zgartirish uchun rulesetning nomini bosasiz va Save changes qilasiz.

Biz sinov reposida aynan shunday ruleset yaratdik. Target — default branch. Qoidalar to'rtta: o'chirish taqiqi, force-push taqiqi, chiziqli tarix va majburiy PR (0 ta tasdiq, izohlar hal qilinishi shart, faqat squash va rebase). GitHub uni ichida JSON shaklida saqlaydi — Import a ruleset aynan shu formatni o'qiydi:

json
{
  "name": "main himoyasi",
  "target": "branch",
  "enforcement": "active",
  "conditions": {
    "ref_name": { "include": ["~DEFAULT_BRANCH"], "exclude": [] }
  },
  "rules": [
    { "type": "deletion" },
    { "type": "non_fast_forward" },
    { "type": "required_linear_history" },
    {
      "type": "pull_request",
      "parameters": {
        "required_approving_review_count": 0,
        "dismiss_stale_reviews_on_push": false,
        "require_code_owner_review": false,
        "require_last_push_approval": false,
        "required_review_thread_resolution": true,
        "allowed_merge_methods": ["squash", "rebase"]
      }
    }
  ]
}

Bu faylni yozish shart emas — formadagi kataklar aynan shuni hosil qiladi. Lekin uni o'qiy olish foydali. ~DEFAULT_BRANCH — "standart branch" degan maxsus belgi. non_fast_forward — force-push taqiqining ichki nomi. Keyingi darsda bu JSON'ni terminaldan ham yaratamiz.

Tekshirib ko'ring: Siz portfolio ustida yolg'iz ishlaysiz. "Required approvals" ni 1 qilsangiz nima bo'ladi?

Javob

Hech bir PR merge bo'lmaydi. Tasdiqni muallifdan boshqa odam berishi kerak, siz esa yolg'izsiz. Yechim — tasdiqlar sonini 0 qoldirish: PR baribir majburiy, tarix tartibli, lekin o'zingizni bloklab qo'ymaysiz.

5. Push rad etildi: GH013

5.1 Qoidani buzib ko'ramiz

Ruleset yaratildi. Endi odatdagidek ishlaymiz — aloqa sahifasiga Telegram havolasini qo'shib, to'g'ridan-to'g'ri main ga yuboramiz. Chiqishlarda repo nomini login/login.github.io ga almashtirdik: biz vaqtinchalik sinov reposida ishladik, sizda o'z loginingiz turadi.

Sinov reposidagi portfolio tarixi juda qisqa: boshlang'ich commit va Pages workflow'i. Ikkinchisi u yerda qisqaroq nom bilan yozilgan — Deploy: Pages workflow'ini qo'sh. Sizda esa Remote darsidagi Deploy: sayt/ ni Pages'ga yuklaydigan workflow qo'sh va 07-qismdagi boshqa commitlaringiz turadi.

bash
git commit -m "Aloqa: Telegram havolasini qo'sh"
git push
text
[main ecffd19] Aloqa: Telegram havolasini qo'sh
 1 file changed, 4 insertions(+)
remote: error: GH013: Repository rule violations found for refs/heads/main.
remote: Review all repository rules at https://github.com/login/login.github.io/rules?ref=refs%2Fheads%2Fmain
remote:
remote: - Changes must be made through a pull request.
remote:
To https://github.com/login/login.github.io.git
 ! [remote rejected] main -> main (push declined due to repository rule violations)
error: failed to push some refs to 'https://github.com/login/login.github.io.git'

Commit lokal yaratildi. Push esa rad etildi. Qatorma-qator:

  • remote: bilan boshlanadigan qatorlar — GitHub serverining javobi. Remote darsidagi kabi.
  • GH013: Repository rule violations found for refs/heads/main — tarjimasi: "main branchi uchun repo qoidalari buzilgan". GH013 — GitHub'ning shu xato turi uchun kodi. Internetda qidirsangiz, aynan shu kod bilan qidiring.
  • Review all repository rules at ... — "barcha qoidalarni shu manzilda ko'ring". Repo manziliga /rules qo'shilgan sahifa — o'qish huquqi bor har kim ko'ra oladi.
  • Changes must be made through a pull request. — tarjimasi: "O'zgarishlar Pull Request orqali kiritilishi kerak". Buzilgan qoida — Require a pull request before merging.
  • ! [remote rejected] ... (push declined due to repository rule violations) — "server rad etdi: qoidalar buzilgani uchun push qabul qilinmadi".

E'tibor bering: bu [rejected] emas, [remote rejected]. Oddiy [rejected] ni Remote darsida ko'rgansiz — u "sizning nusxangiz eski" degani. [remote rejected] esa "server qabul qilmadi": commitlar yetib bordi, lekin qoida o'tkazmadi.

5.2 Commit qayerda qoldi?

bash
git status -sb
text
## main...origin/main [ahead 1]

ahead 1 — lokal main GitHub'dagidan bitta commit oldinda. Commit yo'qolmadi, u faqat kompyuteringizda. Endi uni to'g'ri yo'lga o'tkazamiz.

5.3 Commitni branch'ga ko'chirish

Reja: commit turgan joyda yangi branch ochamiz, main ni esa GitHub'dagi holatga qaytaramiz.

bash
git switch -c feature/aloqa-telegram
git branch -f main origin/main
git log --oneline --all
text
Switched to a new branch 'feature/aloqa-telegram'
branch 'main' set up to track 'origin/main'.
ecffd19 (HEAD -> feature/aloqa-telegram) Aloqa: Telegram havolasini qo'sh
3fbf72b (origin/main, origin/HEAD, main) Deploy: Pages workflow'ini qo'sh
59df546 Portfolio: 06-qism oxiridagi holat
  • git switch -c — yangi branch yaratib, unga o'tish (Branch nima). U ecffd19 ni ko'rsatadi — commit endi shu branch'da.
  • git branch -f main origin/main — main ko'rsatkichini majburan origin/main ga surish. -f — "force". Biz main da turmaganimiz uchun bu xavfsiz: ishchi papkaga tegmaydi.

Endi main va origin/main bir joyda (3fbf72b). Commit esa feature/aloqa-telegram da. Branchni yuboramiz:

bash
git push -u origin feature/aloqa-telegram
text
remote:
remote: Create a pull request for 'feature/aloqa-telegram' on GitHub by visiting:
remote:      https://github.com/login/login.github.io/pull/new/feature/aloqa-telegram
remote:
To https://github.com/login/login.github.io.git
 * [new branch]      feature/aloqa-telegram -> feature/aloqa-telegram
branch 'feature/aloqa-telegram' set up to track 'origin/feature/aloqa-telegram'.

Bu safar o'tdi. Ruleset faqat main ga qaraydi — boshqa branchlarga erkin push qilish mumkin. GitHub hatto PR ochish havolasini ham berdi.

5.4 PR va merge

Pull Request darsidagidek havolani ochib, PR yarating. PR sahifasining pastidagi merge oynasida (merge box) endi qoidalar ham ko'rinadi.

Merge tugmasi yonidagi strelkani bosing. Chiziqli tarix qoidasi tufayli Create a merge commit usuli ishlamaydi. Biz uni terminaldan sinab ko'rdik, GitHub javobi:

text
Merge commits are not allowed on this repository.

Tarjimasi: "Bu repoda merge commitlarga ruxsat yo'q". Squash and merge ni tanlang. Merge'dan keyin GitHub branchni o'chirishni taklif qiladi — o'chiring. Keyin kompyuterda:

bash
git switch main
git pull
git log --oneline
text
Switched to branch 'main'
Your branch is up to date with 'origin/main'.
From https://github.com/login/login.github.io
   3fbf72b..a2a3d58  main       -> origin/main
Updating 3fbf72b..a2a3d58
Fast-forward
 sayt/aloqa/index.html | 4 ++++
 1 file changed, 4 insertions(+)
a2a3d58 (HEAD -> main, origin/main, origin/HEAD) Aloqa: Telegram havolasini qo'sh (#4)
3fbf72b Deploy: Pages workflow'ini qo'sh
59df546 Portfolio: 06-qism oxiridagi holat

up to date ga aldanmang: Git origin/main ni oxirgi fetch dagi holatda eslaydi. git pull esa avval yangisini olib keladi — 3fbf72b..a2a3d58. main da yangi commit — a2a3d58, oxirida PR raqami (#4). Bu squash merge belgisi. Bizning sinov reposida bu to'rtinchi PR edi; sizda raqam ham, SHA ham boshqacha bo'ladi — squash commit merge qilingan vaqtdan hisoblanadi.

Lokal feature/aloqa-telegram branchi endi keraksiz:

bash
git branch -d feature/aloqa-telegram
text
warning: deleting branch 'feature/aloqa-telegram' that has been merged to
         'refs/remotes/origin/feature/aloqa-telegram', but not yet merged to HEAD
Deleted branch feature/aloqa-telegram (was ecffd19).

Branch o'chdi, lekin ogohlantirish bilan. Tarjimasi: "branch origin/feature/aloqa-telegram ga qo'shilgan, lekin HEAD'ga hali qo'shilmagan". Sababi — squash: main ga ecffd19 ning o'zi emas, uning nusxasi (a2a3d58) tushdi. Git buni bilmaydi.

Nega baribir o'chirdi? Git lokal xotiradagi origin/feature/aloqa-telegram ni ko'rdi va "commit u yerda saqlangan" deb ruxsat berdi. GitHub'da branch allaqachon o'chirilgan bo'lsa ham, bu xotira git fetch --prune gacha eski holatda turadi (Remote darsi). U ham bo'lmaganda, -d rad etardi va -D kerak bo'lardi (Branch nima darsidagi farq).

Butun yo'l bitta rasmda:

flowchart TD
  A["git push origin main"] --> B{"Ruleset<br/>tekshiradi"}
  B -- "qoida buzilgan" --> C["GH013<br/>remote rejected"]
  C --> D["git switch -c feature/..."]
  D --> E["git push -u origin<br/>feature/..."]
  E --> F["Pull Request"]
  F --> G{"Qoidalar<br/>bajarilganmi?"}
  G -- "ha" --> H["Squash and merge<br/>main yangilandi"]
  G -- "yo'q" --> F

Nimaga qarang: main ga yagona eshik — PR. To'g'ridan-to'g'ri yo'l (git push origin main) qizil chiziqqa olib keladi va siz baribir branch–PR yo'liga qaytasiz.

6. Force-push va o'chirish

6.1 Force-push

Endi ataylab ikkinchi qoidani buzamiz. Lokal main ni bitta commit orqaga qaytarib, ustiga boshqa commit qildik. Endi u GitHub'dagi main dan ayrilgan. Oddiy push:

bash
git push
text
To https://github.com/login/login.github.io.git
 ! [rejected]        main -> main (non-fast-forward)
error: failed to push some refs to 'https://github.com/login/login.github.io.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. If you want to integrate the remote changes,
hint: use 'git pull' before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

Bu — Git'ning o'z himoyasi, Ajralgan tarix darsidan tanish. Rulesetsiz repoda ham shunday bo'ladi. Ilgari bu yerda --force "yechim" edi. Endi:

bash
git push --force
text
remote: error: GH013: Repository rule violations found for refs/heads/main.
remote: Review all repository rules at https://github.com/login/login.github.io/rules?ref=refs%2Fheads%2Fmain
remote:
remote: - Cannot force-push to this branch
remote:
remote: - Changes must be made through a pull request.
remote:
To https://github.com/login/login.github.io.git
 ! [remote rejected] main -> main (push declined due to repository rule violations)
error: failed to push some refs to 'https://github.com/login/login.github.io.git'

Endi ikkita qoida buzilgan. Cannot force-push to this branch — tarjimasi: "Bu branch'ga force-push qilib bo'lmaydi". GitHub buzilgan hamma qoidani ro'yxat qilib beradi — bittasini tuzatib, ikkinchisiga urilmaysiz.

Lokal main ni qanday tuzatish kerak? Ayrilgan commit kerak bo'lsa — uni branch'ga oling (yuqoridagi switch -c usuli). Keraksiz bo'lsa — git reset --hard origin/main (reset va revert).

6.2 main ni o'chirish

bash
git push origin --delete main
text
To https://github.com/login/login.github.io.git
 ! [remote rejected] main (refusing to delete the current branch: refs/heads/main)
error: failed to push some refs to 'https://github.com/login/login.github.io.git'

Tarjimasi: "joriy branchni o'chirishdan bosh tortildi". Qiziq: bu yerda GH013 yo'q. main — reponing standart branchi, GitHub uni rulesetsiz ham o'chirtirmaydi. Restrict deletions qoidasi standart bo'lmagan branchlar uchun kerak bo'ladi — masalan, release/* shabloni bilan himoyalangan branchlar uchun.

Tekshirib ko'ring: [rejected] va [remote rejected] — ikkalasi ham push o'tmadi degani. Farqi nimada?

Javob

[rejected] — Git'ning o'zi push'ni boshlamasdan to'xtatdi: lokal tarix GitHub'dagidan orqada yoki ayrilgan. [remote rejected] — commitlar serverga yetib bordi, lekin server (GitHub ruleseti) ularni qabul qilmadi. Birinchisida git pull kerak, ikkinchisida — PR yo'li.

7. Hujumchi nigohi

Ruleset faqat adashgan odamdan emas, yomon niyatli odamdan ham saqlaydi. Tasavvur qiling: noutbukingizdagi GitHub tokeni o'g'irlandi (SSH kalit va autentifikatsiya darsidagi «Hujumchi nigohi»).

  • Rulesetsiz: hujumchi main ga zararli kod yuboradi. Sayt avtomatik yangilanadi — mehmonlarga uning sahifasi chiqadi. Yoki git push --force bilan butun tarixni o'chiradi.
  • Ruleset bilan: main ga to'g'ridan-to'g'ri push ham, force-push ham GH013 bilan qaytadi. Hujumchi PR ochishga majbur — PR esa hammaga ko'rinadi va izini qoldiradi.

Shuning uchun bypass ro'yxati bo'sh bo'lsin: unda turgan har bir akkaunt — hujumchi uchun ochiq eshik. Lekin to'liq kafolat yo'q: admin huquqli token rulesetni o'chirib qo'yishi ham mumkin. Ikkinchi qatlam — tokenlarga faqat kerakli ruxsatni berish (fine-grained token) va 2FA.

8. Ko'p uchraydigan xatolar

8.1 Ruleset yaratdim, lekin push o'tib ketyapti

Eng ko'p sabab — holat Disabled qolgan. Yangi forma standart holatda Disabled bo'ladi. Settings → Rules → Rulesets ro'yxatida rulesetni oching va Enforcement status ni Active qiling.

Ikkinchi sabab — target yo'q. "Target branches" bo'sh bo'lsa, ruleset hech qaysi branch'ga qo'llanmaydi. Uchinchisi — o'zingiz bypass ro'yxatidasiz.

8.2 "Merge commits are not allowed on this repository."

PR'ni Create a merge commit bilan qo'shmoqchi bo'ldingiz, chiziqli tarix esa yoqilgan. Tugma yonidagi strelkadan Squash and merge yoki Rebase and merge ni tanlang.

8.3 O'zimni bloklab qo'ydim

Yolg'iz loyihada "Required approvals: 1" yoqilgan — PR merge bo'lmaydi. Rulesetni oching, tasdiqlar sonini 0 qiling va Save changes. Bypass ro'yxatiga o'zingizni qo'shish — yomon yechim: qoida "hammaga, mendan tashqari" bo'lib qoladi.

8.4 Brauzerda fayl tahrirlay olmayapman

Himoyalangan branch'da GitHub saytida faylni tahrirlash va yuklash yopiladi (GitHub hujjatida shunday). Bu xato emas — himoya ishlayapti. Tahrirni branch'da qiling va PR oching.

8.5 GH013 ni ko'rib, --force yozish

Qo'rqib, git push --force bilan "zo'rlab" yuborishga urinish — foydasiz. Force-push ham qoida bilan yopilgan, xabarlar soni faqat ko'payadi. GH013 — "yo'l boshqa" degani: branch → PR.

9. Mashqlar

Javoblaringizni mashqlar reposida 07/33-branch-himoyasi/javoblar.md fayliga yozib, 07/33: branch himoyasi javoblarini qo'sh xabari bilan commit qiling.

1-mashq (oson): Qoidani toping

Har vaziyatga ruleset qoidasini (inglizcha nomi bilan) toping:

  1. Stajyor main ga to'g'ridan-to'g'ri push qildi.
  2. Malika git push --force bilan hamkasbining commitlarini o'chirdi.
  3. main tarixida "Merge pull request #12 ..." kabi merge commitlar ko'p, git log ni o'qish qiyin.
  4. Hech kim ko'rmagan kod main ga tushdi.
Yechim
  1. Require a pull request before merging — to'g'ridan-to'g'ri push rad etiladi.
  2. Block force pushes — force-push yopiladi.
  3. Require linear history — faqat squash yoki rebase merge.
  4. Require a pull request before merging + Required approvals: 1 — kamida bitta odam tasdiqlashi kerak. Faqat PR yetmaydi: GitHub hujjatiga ko'ra, PR ochilgan bo'lishi kifoya, tasdiq shart emas.

2-mashq (o'rta): Xabarni o'qing

Malika git push yozdi va shuni oldi:

text
remote: error: GH013: Repository rule violations found for refs/heads/main.
remote: - Cannot force-push to this branch
remote: - Changes must be made through a pull request.
 ! [remote rejected] main -> main (push declined due to repository rule violations)

Bo'sh joylarni to'ldiring. Push'ni Git emas, [:server] rad etdi — buni [remote rejected] dagi "remote" so'zi bildiradi. Ikkita qoida buzilgan: force-push taqiqi va majburiy [:PR]. Malika yozgan buyruqda ehtimol -- flagi bor edi.

Ishora: «Force-push va o'chirish» bo'limidagi ikki qoidali xabarni solishtiring.

Yechim

server, PR, force. Oddiy git push force-push qilmaydi. Shuning uchun Cannot force-push qatori Malika --force (yoki --force-with-lease) yozganini ko'rsatadi. To'g'ri yo'l — commitlarini yangi branch'ga olib, PR ochish.

3-mashq (qiyin): «Bahor» jamoasi uchun ruleset

«Bahor» reposida uch kishi ishlaydi: siz (admin), Malika va stajyor Sardor. Talablar:

  • main ga faqat PR orqali, kamida bitta tasdiq bilan.
  • Yangi commit kelsa, eski tasdiq kuchini yo'qotsin.
  • Tarix chiziqli bo'lsin.
  • release/ bilan boshlanadigan branchlarni hech kim o'chira olmasin va force-push qila olmasin, lekin ularga PR talab qilinmasin.

Nechta ruleset kerak? Har birida qaysi target va qaysi qoidalar? Bypass ro'yxati qanday bo'ladi?

Ishora: bitta rulesetning hamma qoidasi uning hamma targetiga qo'llanadi («Ruleset va branch himoyasi» bo'limi).

Yechim

Ikkita ruleset kerak, chunki main va release/* uchun qoidalar har xil.

1. main himoyasi — target: Include default branch.

  • Restrict deletions, Block force pushes.
  • Require a pull request before merging: Required approvals — 1, Dismiss stale pull request approvals when new commits are pushed — yoqilgan.
  • Require linear history.

2. reliz himoyasi — target: Include by pattern release/**/*.

  • Restrict deletions, Block force pushes. Boshqa hech narsa.

Bypass ro'yxati ikkalasida ham bo'sh — siz admin bo'lsangiz ham. Agar release/* ni bitta rulesetga qo'shsangiz, ularga ham PR va tasdiq talabi tushardi — shart buziladi.

Uch kishilik jamoada siz yozgan PR'ni Malika yoki Sardor tasdiqlaydi — "1 ta tasdiq" bloklamaydi.

4-mashq: Portfolio qadami — main himoyasi

Portfolio'ingiz Remote darsidan beri GitHub'da va har push'da Pages'ga chiqadi. Endi uning main branchini himoyalaymiz.

  1. login.github.io reposida Settings → Rules → Rulesets → New ruleset → New branch ruleset.
  2. Nom: main himoyasi. Holat: Active. Bypass ro'yxati — bo'sh.
  3. Target: Include default branch.
  4. Qoidalar: Restrict deletions va Block force pushes (standart), Require linear history, Require a pull request before merging.
  5. PR qoidasining sozlamalari: Required approvals — 0, Require conversation resolution before merging — yoqilgan, Allowed merge methods — Squash va Rebase.
  6. Create.
  7. Sinov: aloqa sahifasiga bitta qator qo'shing (masalan Telegram havolasi), commit qiling va git push — GH013 chiqishi kerak.
  8. Commitni feature/... branch'ga oling, main ni origin/main ga qaytaring, branchni yuboring, PR oching va Squash and merge qiling.
  9. git switch main, git pull, git log --oneline — oxirgi commitda (#N) bormi?

landing reposida ham xuddi shu rulesetni yarating.

Yechim

7-qadamdagi chiqish «Push rad etildi: GH013» bo'limidagidek bo'ladi. Faqat login o'rnida sizning loginingiz turadi.

8-qadam:

bash
git switch -c feature/aloqa-telegram
git branch -f main origin/main
git push -u origin feature/aloqa-telegram

PR'ni GitHub chiqargan havola orqali oching. Merge'dan keyin:

bash
git switch main
git pull
git branch -D feature/aloqa-telegram
git log --oneline

Oxirgi commit ... (#N) ko'rinishida bo'lsa (raqam sizda boshqacha bo'lishi mumkin) — hammasi to'g'ri.

landing uchun 1–6 qadamlar takrorlanadi. Vaqtni tejash usuli ham bor: portfolio rulesetini ochib, ... menyusidagi tarixdan (History) JSON'ni yuklab oling (Download). Keyin landing da New ruleset → Import a ruleset orqali shu faylni tanlang.

Bundan keyin portfolio'dagi har o'zgarish branch va PR orqali boradi. Keyingi darslarda shu yo'lga terminal vositasi (gh) va avtomatik tekshiruv qo'shiladi.

10. Real ishda

  • Deyarli har kompaniyada main himoyalangan: PR majburiy, kamida 1–2 tasdiq, CI o'tishi shart. Ishga kirganingizda birinchi push'ingiz GH013 bilan qaytsa — ajablanmang, bu normal.
  • Ochiq kodli loyihalarda ham shunday. Ko'p repolarning qoidalarini /rules sahifasida ko'rish mumkin — masalan, GitHub hujjatlari reposi github.com/github/docs/rules.
  • Tag himoyasi — reliz taglarini (v*) o'chirish va surishni taqiqlash. Tag va relizlar darsidagi "tag joyidan qimirlamaydi" va'dasini server darajasida kafolatlaydi.
  • Intervyuda: "main'ni qanday himoyalaysiz?", "Squash va merge commit farqi?", "Force-push'ni qachon ishlatish mumkin?" Javob: o'z feature branchingizda — ha (--force-with-lease bilan), main da — hech qachon.

Xulosa

  • Kelishuvni server tekshirishi kerak: ruleset — branch yoki tag uchun nomli qoidalar to'plami.
  • Yaratish: Settings → Rules → Rulesets → New branch ruleset; holat Active, target — default branch, bypass — bo'sh.
  • Asosiy qoidalar: o'chirish va force-push taqiqi, majburiy PR, chiziqli tarix; jamoada — tasdiqlar soni.
  • Yolg'iz loyihada tasdiqlar soni 0: o'z PR'ingizni o'zingiz tasdiqlay olmaysiz.
  • GH013 ... [remote rejected] — server qoidasi; yechim — commitni branch'ga olib, PR ochish.
  • Rulesetlar qo'shiladi va eng qattiq qoida ishlaydi; klassik branch himoyasi ham ular bilan birga ishlaydi.

Keyingi dars: GitHub CLI (gh) — PR, issue va rulesetlarni brauzerga chiqmasdan, terminaldan boshqarishni o'rganamiz.

Manbalar

  • GitHub Docs: "About rulesets", "Creating rulesets for a repository", "Available rules for rulesets", "Managing rulesets for a repository" — docs.github.com
  • GitHub Docs: "About protected branches", "Managing a branch protection rule" — docs.github.com
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
GitHub branch himoyasi va rulesets: main'ni tasodifiy push'dan saqlash — IlmHamroh