git add nega kerak: fayl commitgacha uch bosqichdan o'tadi
Mundarija
- Fayl uch joydan o'tadi
- Loyihani boshlaymiz
- Git nima deydi
- Birinchi qadam: add
- Endi eng muhim joyi
- Commit qilamiz va tekshiramiz
- Staging nega kerak?
- Ikkinchi commit
- Tarixni o'qiymiz
- Xato qilsangiz: orqaga qaytarish
- Endi buzib ko'ring
- Qilingan ishni tekshirib ko'ring
- Shu qismning buyruqlari
- Keyingi qismda
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:
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.
mkdir xarajat
cd xarajat
git init
Initialized empty Git repository in /Users/siz/xarajat/.git/
Shundan keyin papka ichida .git degan yashirin papka paydo bo'ladi. Ichiga qarab ko'ramiz:
ls .git
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:
"""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:
git status
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:
git status -s
?? xarajat.py
?? — Git bu faylni hali kuzatmayapti degani.
Birinchi qadam: add#
Endi faylni staging'ga qo'shamiz:
git add xarajat.py
git status
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:
echo "" >> xarajat.py
echo "# yangi qator" >> xarajat.py
git status -s
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 holatiM(o'ngdagi harf) — ishchi papkada fayl yana o'zgargan
To'liq holatni ko'rsak, bu yanada aniq ko'rinadi:
git status
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:
git diff
+
+# 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:
git diff --staged
+"""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:
git commit -m "Xarajat qo'shish va jami hisoblash"
[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:
git show HEAD:xarajat.py | tail -3
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:
git status -s
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:
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:
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:
git add xarajat.py
git commit -m "Eng qimmat xarajatni topish"
Tarixni o'qiymiz#
Endi ikkita commitimiz bor. Ularni git log orqali ko'ramiz:
git log
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:
git log --oneline
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:
git show --stat --oneline HEAD
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:
git status -s
M xarajat.py
Endi uni staging'dan chiqaramiz:
git restore --staged xarajat.py
git status -s
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:
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.
- Faylni o'zgartiring,
addqiling, keyin yana o'zgartiring.
git status -s nima ko'rsatadi? git diff va git diff --staged bir xil natija beradimi?
- Ikkita fayl yarating, faqat bittasini
addqiling va commit qiling.
Ikkinchi fayl commitga tushadimi? git status nima ko'rsatadi?
git addqilib, keyin faylni butunlay o'chiring.
Commit qilsangiz nima bo'ladi? Fayl tarixda qoladimi?
.gitpapkasini boshqa joyga ko'chiring vagit statusyozing.
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:
git clone https://github.com/AsadbekSolijonov/git-darslik.git
cd git-darslik
git checkout qism-2
git log --oneline
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.