Asosiy kontentga o‘tish

Maqolalar

Darslik 13 daqiqa boshlang'ich 2 ko‘rish 0 yoqdi

git add nega kerak: fayl commitgacha uch bosqichdan o'tadi

#git #devops

Mundarija

Oldingi qismda Git'ni o'rnatdik va commitlar kim nomidan yozilishini sozlab oldik. Endi birinchi loyihamizni boshlaymiz.

Lekin bu yerda bitta savol tug'iladi: nega avval git add, keyin git commit qilamiz? Boshqa dasturlarda saqlash uchun bitta tugma yetadi-ku.

Buni tushunish uchun kichik tajriba qilamiz: bitta faylni o'zgartirib, uni bir vaqtning o'zida ikkita ro'yxatda turgan holatda ko'ramiz. Shundan keyin add nega alohida qadam ekanini aniqroq tushunamiz.

Fayl uch joydan o'tadi#

Git'da fayl commitgacha uchta bosqichdan o'tadi:

Sxema
  ishchi papka          staging              tarix
  (fayllaringiz)     (kutish zali)      (commit'lar)
        │                  │                  │
        │  ── git add ──►  │                  │
        │                  │  ── git commit ──►
        │                  │                  │
   tahrirlaysiz        tanlaysiz           yoziladi

Ishchi papka — kompyuteringizdagi haqiqiy fayllar. Faylni tahrirlaganingizda o'zgarish shu yerda paydo bo'ladi.

Staging — keyingi commit'ga kiritish uchun tanlab qo'yilgan o'zgarishlar. Git'dagi eng muhim tushunchalardan biri shu va boshida aynan shu joy biroz chalkash tuyuladi.

Tarix — commit qilingan va Git'da saqlanib qolgan holatlar.

Hozircha bular sizga nazariyadek tuyulishi mumkin. Keling, endi birgalikda amaliyotda sinab ko'ramiz.

Loyihani boshlaymiz#

Kunlik xarajatlarni yozib boradigan kichik dastur qilamiz. Dastur sodda bo'ladi, chunki bu yerda asosiy maqsad — Git qanday ishlashini amalda ko'rish.

Terminal
mkdir xarajat
cd xarajat
git init
Natija
Initialized empty Git repository in /Users/siz/xarajat/.git/

Shundan keyin papka ichida .git degan yashirin papka paydo bo'ladi. Ichiga qarab ko'ramiz:

Terminal
ls .git
Natija
HEAD        description info        refs
config      hooks       objects

Mana shu .git papkasi Git'ning asosiy xotirasi. Commitlar tarixi, sozlamalar va saqlangan holatlar shu yerda turadi. Uni o'chirsangiz, loyiha oddiy papkaga aylanadi va Git tarixi yo'qoladi.

Endi birinchi faylni yozamiz:

xarajat.py
"""Kunlik xarajatlarni yozib boradigan kichik dastur."""

XARAJATLAR = []


def qoshish(summa, izoh):
    XARAJATLAR.append({"summa": summa, "izoh": izoh})


def jami():
    return sum(x["summa"] for x in XARAJATLAR)


if __name__ == "__main__":
    qoshish(12000, "Non va sut")
    qoshish(45000, "Taksi")
    print(f"Jami: {jami():,} so'm")

Git nima deydi#

Ishni davom ettirishdan oldin hozir Git nimani ko'rayotganini tekshirib olamiz:

Terminal
git status
Natija
On branch main

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)
    xarajat.py

nothing added to commit but untracked files present (use "git add" to track)

Untracked — Git hali kuzatishni boshlamagan fayl degani. Git xarajat.py ni ko'rib turibdi, lekin uni hali o'z tarixiga qo'shmagan.

git status ning qisqa ko'rinishi ham bor. Kundalik ishlarda ko'pincha shu qulayroq:

Terminal
git status -s
Natija
?? xarajat.py

?? — Git bu faylni hali kuzatmayapti degani.

Birinchi qadam: add#

Endi faylni staging'ga qo'shamiz:

Terminal
git add xarajat.py
git status
Natija
On branch main

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
    new file:   xarajat.py

Endi sarlavha o'zgardi: Changes to be committed — ya'ni keyingi commit'ga kiradigan o'zgarishlar.

Demak, xarajat.py staging'ga tushdi.

Muhim joyi: fayl hali commit qilinmadi. Biz faqat uning hozirgi holatini keyingi commit'ga qo'shish uchun tanladik.

Endi eng muhim joyi#

Endi boshidagi savolga qaytamiz: nega add va commit alohida? Buni kichik tajriba bilan ko'ramiz.

Faylni yana bir marta o'zgartiramiz, lekin bu safar add qilmaymiz:

Terminal
echo "" >> xarajat.py
echo "# yangi qator" >> xarajat.py
git status -s
Natija
AM xarajat.py

Bu safar ikkita harf chiqdi. Aynan shu holat add nima uchun kerakligini ko'rsatadi.

Bitta faylning ikkita holati bor:

  • A (chapdagi harf) — faylning staging'ga qo'shilgan holati
  • M (o'ngdagi harf) — ishchi papkada fayl yana o'zgargan

To'liq holatni ko'rsak, bu yanada aniq ko'rinadi:

Terminal
git status
Natija
Changes to be committed:
    new file:   xarajat.py

Changes not staged for commit:
    modified:   xarajat.py

Bitta fayl bir vaqtning o'zida ikkita ro'yxatda turibdi.

Bu xato emas. git add qilganimizda Git faylning o'sha paytdagi holatini staging'ga oladi. Keyin faylni yana o'zgartirsak, staging'dagi holat o'zgarib ketmaydi.

Bu ikki holatning farqini alohida ko'rishimiz mumkin:

Terminal
git diff
Natija
+
+# yangi qator

git diff — staging'ga hali qo'shilmagan o'zgarishlarni ko'rsatadi. Ya'ni hozir faylda nima o'zgardi, lekin add qilinmadi?

Endi staging'dagi holatni ko'ramiz:

Terminal
git diff --staged
Natija
+"""Kunlik xarajatlarni yozib boradigan kichik dastur."""
+
+XARAJATLAR = []
...

git diff --staged esa staging'ga tushgan o'zgarishlarni ko'rsatadi. Ya'ni hozir commit qilsak, tarixga nima yoziladi?

Commit qilamiz va tekshiramiz#

Endi staging'dagi holatni commit qilamiz:

Terminal
git commit -m "Xarajat qo'shish va jami hisoblash"
Natija
[main (root-commit) d291ac2] Xarajat qo'shish va jami hisoblash
 1 file changed, 17 insertions(+)
 create mode 100644 xarajat.py

17 qator commit qilindi. Endi tekshirib ko'ramiz: # yangi qator ham commitga tushdimi?

Commit ichidagi faylning oxirgi uch qatorini ko'ramiz:

Terminal
git show HEAD:xarajat.py | tail -3
Natija
    qoshish(12000, "Non va sut")
    qoshish(45000, "Taksi")
    print(f"Jami: {jami():,} so'm")

# yangi qator yo'q. Chunki commitga ishchi papkadagi eng oxirgi holat emas, staging'ga add qilganimizdagi holat tushdi.

Lekin keyin yozgan o'zgarishimiz ham yo'qolmadi. U hali ham faylda turibdi:

Terminal
git status -s
Natija
 M xarajat.py

Bu safar M o'ng tomonda turibdi. Chap tomon bo'sh — staging'da o'zgarish yo'q. O'ng tomondagi M esa ishchi papkada hali commit qilinmagan o'zgarish borligini bildiradi.

git status -s da harfning joyi muhim: chapdagi ustun — staging, o'ngdagi ustun — ishchi papka.

Staging nega kerak?#

Endi git add nega alohida qadam ekanini ko'rdik.

Tasavvur qiling, bir necha soat ishladik. Bitta fayldagi yangi funksiya tayyor, boshqa fayldagi o'zgarish esa hali tugallanmagan. Ikkalasini bitta commitga qo'shsak, keyin tarixni o'qish qiyinlashadi.

Staging shu yerda yordam beradi: tayyor bo'lgan o'zgarishlarni add qilamiz, qolganlarini esa hozircha qoldiramiz. Commit faqat staging'ga tanlangan o'zgarishlarni oladi.

Demak, add ortiqcha qadam emas. U commitga aynan qaysi o'zgarishlarni kiritishni tanlash imkonini beradi.

Ikkinchi commit#

Avval tajriba uchun qo'shgan # yangi qator ni tozalab olamiz. Faylni ochib, o'sha qatorni va undan oldingi bo'sh qatorni o'chiring.

Keyin holatni tekshiramiz:

Terminal
git status -s

Agar hech narsa chiqmasa, demak ishchi papka commitdagi holat bilan bir xil.

Endi dasturga yana bitta funksiya qo'shamiz. Uni if __name__ == "__main__": blokidan oldin yozamiz — funksiyalar dastur ishga tushadigan qismdan yuqorida turgani tartibliroq bo'ladi:

xarajat.py
def eng_katta():
    """Eng qimmat xarajatni qaytaradi."""
    return max(XARAJATLAR, key=lambda x: x["summa"], default=None)

So'ng o'zgarishni staging'ga qo'shib, ikkinchi commitni qilamiz:

Terminal
git add xarajat.py
git commit -m "Eng qimmat xarajatni topish"

Tarixni o'qiymiz#

Endi ikkita commitimiz bor. Ularni git log orqali ko'ramiz:

Terminal
git log
Natija
commit b41bd9b2df239963b33687f1e9f7f75f0e65ea60
Author: Asadbek Solijonov <109437399+AsadbekSolijonov@users.noreply.github.com>
Date:   Fri Aug 21 22:09:37 2026 +0500

    Eng qimmat xarajatni topish

commit d291ac2e7b2d919f71b2cbe37433d1229f83dd7f
Author: Asadbek Solijonov <109437399+AsadbekSolijonov@users.noreply.github.com>
Date:   Fri Aug 21 21:52:02 2026 +0500

    Xarajat qo'shish va jami hisoblash

Oldingi qismda sozlagan ism va emailimiz shu yerda ko'rinadi. Har bir commitda uni kim qilgani, qachon qilingani va qanday izoh yozilgani saqlanadi.

Boshidagi uzun belgi esa commitning identifikatori. Git har bir commitga alohida hash beradi va kerak bo'lsa, aynan shu hash orqali o'sha commitga murojaat qilamiz.

Kundalik ishlarda tarixning qisqa ko'rinishi qulayroq:

Terminal
git log --oneline
Natija
b41bd9b Eng qimmat xarajatni topish
d291ac2 Xarajat qo'shish va jami hisoblash

Bu yerda commit hashining qisqa ko'rinishi va yonida commit izohi turibdi.

Bitta commitda nimalar o'zgarganini ko'rish uchun:

Terminal
git show --stat --oneline HEAD
Natija
b41bd9b Eng qimmat xarajatni topish
 xarajat.py | 5 +++++
 1 file changed, 5 insertions(+)

HEAD hozir turgan eng oxirgi commitni bildiradi. Natijadan ko'rinib turibdi: oxirgi commitda xarajat.py fayliga 5 ta qator qo'shilgan.

Xato qilsangiz: orqaga qaytarish#

Bu yerda ikkita holat bor va ularning yechimi ham boshqacha.

Birinchi holat: add qildik, lekin fikrimizdan qaytdik. Fayl staging'da turibdi:

Terminal
git status -s
Natija
M  xarajat.py

Endi uni staging'dan chiqaramiz:

Terminal
git restore --staged xarajat.py
git status -s
Natija
 M xarajat.py

Harf o'ng tomonga ko'chdi. O'zgarish yo'qolmadi — faqat staging'dan chiqdi va ishchi papkada qolib ketdi.

Ikkinchi holat: o'zgarishning o'zi kerak emas. Bu safar uni butunlay bekor qilamiz:

Terminal
git restore xarajat.py
git status -s

Hech narsa chiqmadi — demak ishchi papka oxirgi commitdagi holat bilan bir xil.

Bu buyruqda ehtiyot bo'lish kerak: git restore commit qilinmagan o'zgarishni butunlay o'chiradi. Git'ga tushmagan o'zgarishni keyin qaytarib bo'lmaydi.

Endi buzib ko'ring#

Tushunganingizni tekshirish uchun bir nechta joyni ataylab o'zgartirib ko'ramiz.

  1. Faylni o'zgartiring, add qiling, keyin yana o'zgartiring.

git status -s nima ko'rsatadi? git diff va git diff --staged bir xil natija beradimi?

  1. Ikkita fayl yarating, faqat bittasini add qiling va commit qiling.

Ikkinchi fayl commitga tushadimi? git status nima ko'rsatadi?

  1. git add qilib, keyin faylni butunlay o'chiring.

Commit qilsangiz nima bo'ladi? Fayl tarixda qoladimi?

  1. .git papkasini boshqa joyga ko'chiring va git status yozing.

Qanday xato chiqadi? Shu tajribadan keyin .git papkasining vazifasi yanada aniqroq bo'ladi.

Qilingan ishni tekshirib ko'ring#

Yuqoridagi ikkita commit shunchaki misol uchun yozilmagan. Ular mashq repozitoriysida turibdi va ularni o'zingiz ham ochib ko'rishingiz mumkin:

Terminal
git clone https://github.com/AsadbekSolijonov/git-darslik.git
cd git-darslik
git checkout qism-2
git log --oneline
Natija
b41bd9b Eng qimmat xarajatni topish
d291ac2 Xarajat qo'shish va jami hisoblash

Hashlar ham, commit izohlari ham maqoladagi bilan bir xil — chunki bular o'sha commitlarning o'zi. xarajat.py faylini ochib, ikkinchi commitda aynan nima qo'shilganini ham ko'rishingiz mumkin.

Agar Git detached HEAD haqida ogohlantirsa, bundan xavotir olmang. Bu hozir branchning oxirida emas, aniq bir commit holatida turganingizni bildiradi. git switch xarajat bilan loyihaning oxirgi holatiga qaytishingiz mumkin.

Siz yaratgan commitlarning hashleri boshqacha chiqishi normal. Hash faqat fayl mazmuniga emas, commit vaqti va muallif kabi ma'lumotlarga ham bog'liq. Shu sabab bir xil o'zgarishlarni qilsak ham, hashlar bir xil bo'lishi shart emas.

Shu qismning buyruqlari#

Buyruq Vazifasi
git init Papkani Git loyihasiga aylantirish
git status Hozirgi holat: nima o'zgargan, nima staging'da
git status -s Shu holatning qisqa ko'rinishi
git add <fayl> Faylni staging'ga qo'shish
git diff Staging'ga tushmagan o'zgarishlar
git diff --staged Staging'dagi o'zgarishlar
git commit -m "izoh" Staging'dagi holatni tarixga yozish
git log Commit tarixi
git log --oneline Tarixning qisqa ko'rinishi
git show HEAD:<fayl> Commitdagi faylni ochish
git restore --staged <fayl> Staging'dan chiqarish, o'zgarish esa qoladi
git restore <fayl> O'zgarishni butunlay bekor qilish ⚠️

Keyingi qismda#

Endi loyihamiz ham, commitlar tariximiz ham bor. Lekin hozircha bularning hammasi faqat kompyuterimizda turibdi. Agar kompyuter bilan muammo bo'lsa, loyiha tarixi ham birga yo'qolishi mumkin.

Keyingi qismda loyihani GitHub'ga chiqaramiz: SSH kalit yaratamiz, .gitignore bilan kerakmas va maxfiy fayllarni repoga tushirmaymiz, keyin birinchi push ni qilamiz. Shu jarayonda amalda tez-tez uchraydigan xatolarni ham birga ko'ramiz.

2 ko‘rish
Ulashish