david@MacBook-Pro: ~/git-docs git docs 100×40
--:--:--

GIT/DOCS·KA

Git-ის სრული ცნობარი — ბრძანებების ვიზუალიზაცია, ნაბიჯ-ნაბიჯ პროცესები, ცოცხალი დემოები. ყველაფერი ქართულად, ერთ გვერდზე, terminal-სავით.

live v1.0.0 25 sec ka-GE CRT mode
// 01 — BASICS 🟢 მარტივი

საბაზისო ბრძანებები

ეს ბრძანებები ყოველდღიურად გამოიყენება და ქმნის Git-ის სამუშაო ბაზისს. ეს არის წინაპირობა ყველა მომავალი თემისთვის.

ფაილის სახელის შეცვლა Git-ის მეშვეობით

როდესაც ფაილს ოპერაციული სისტემით (Explorer-ით ან Finder-ით) გადავარქმევთ სახელს, Git მას აღიქვამს როგორც ერთი ფაილის წაშლას და ახალის შექმნას. ამის თავიდან ასაცილებლად, შეგვიძლია გამოვიყენოთ git mv:

terminal
git mv old.txt new.txt

ყველა ცვლილების დამატება Stage-ში

ფლაგი -A ემსახურება ყველა ცვლილების — ახალი, შეცვლილი და წაშლილი ფაილების — სრულად ასახვას Staging Area-ში. ეს განსაკუთრებით მნიშვნელოვანია მაშინ, როცა ფაილები ოპერაციული სისტემიდან დაგვიშლია ან გადავარქმევია სახელი.

terminal
git add -A
💡 რჩევა

გამოყენება git status ბრძანებისა Staging-ის წინ — გვიჩვენებს რომელი ფაილები შეიცვალა და რომელი დამატებულია სტეიჯში.

// 02 — COMMIT 🟢 მარტივი

📝 Commit — ცვლილებების დამახსოვრება

Commit არის Git-ის "ფოტო" - კონკრეტული მომენტის სრული მდგომარეობა, რომელიც შეიცავს იმ ცვლილებებს, რომლებიც Staging Area-ში შევიდა.

📋 Commit-ის სრული პროცესი:

  1. ცვლილება Working Directory-ში
    ფაილის შექმნა, შეცვლა ან წაშლა — ცვლილება ცოცხალია მხოლოდ შენს კომპიუტერში.
  2. Stage-ში დამატება (git add)
    Git-ს ვეუბნებით — "ეს ცვლილება მინდა შემდეგ commit-ში მოხვდეს".
  3. Commit (git commit -m)
    Stage-ში არსებული ყველაფერი ფიქსირდება ისტორიაში უნიკალური hash-ით.
  4. Push (არასავალდებულო)
    commit-ი ლოკალურია სანამ remote-ზე არ ავიტვირთება.

სწრაფი commit (add + commit ერთად)

როდესაც ფაილი უკვე არის tracked (Git-ისთვის ცნობილი) და გვინდა ცვლილებების სწრაფად დაფიქსირება, შეგვიძლია -am ფლაგი გამოვიყენოთ:

terminal
# ფაილის დამატება და დამახსოვრება ერთი ბრძანებით
git commit -am "ჩემი ცვლილებების მესიჯი"
⚠️ ყურადღება

-am არ მუშაობს ახალი (untracked) ფაილებისთვის. ისინი ჯერ git add-ით უნდა დავამატოთ.

ბოლო commit-ის შესწორება

თუ ბოლო commit-ის მესიჯში შეცდომა იყო, ან რაიმე ფაილი დაგავიწყდა, --amend საშუალებას გვაძლევს მის შესწორებას ახალი commit-ის შექმნის გარეშე:

terminal
git commit --amend
⚠️ მნიშვნელოვანი

--amend ცვლის commit-ის hash-ს. თუ უკვე გავაკეთეთ push, ნუ გამოიყენებთ ამას — სხვა დეველოპერებს ისტორია დაერევათ.

// 03 — LOG 🟢 მარტივი

📜 Log — ისტორიის ნახვა

Log გვიჩვენებს commit-ების ისტორიას — ვინ, როდის, რა გააკეთა.

დროის ლიმიტი

ფლაგი --since მიიღებს ნებისმიერ ფორმატის თარიღს — "yesterday", "3 days ago", "2 weeks ago", კონკრეტული თარიღი:

terminal
git log --since="3 days ago" --oneline

კონკრეტული ფაილის ისტორია

terminal
git log -- filename --oneline
🎨 სასარგებლო ფლაგები
  • --oneline — თითო commit ერთ ხაზზე
  • --graph — ASCII გრაფიკული ხე
  • --all — ყველა ტოტის ჩათვლით
  • --author="სახელი" — კონკრეტული ავტორის commit-ები
  • -n 10 — მხოლოდ ბოლო 10
// 04 — SHOW 🟢 მარტივი

🔍 Show — დეტალური ინფორმაცია

Show ობიექტის სრულ შინაარსს გვაჩვენებს — commit, tag, blob ან tree.

terminal
git show somehash

გამოიტანს commit-ის სრულ მესიჯს, ავტორს, თარიღს და diff-ს — რა ფაილები შეიცვალა და როგორ.

// 05 — DIFF 🟢 მარტივი

⚖️ Diff — განსხვავების ნახვა

Diff აჩვენებს განსხვავებას ორ მდგომარეობას შორის — ფაილების, ტოტების ან commit-ების.

2 ტოტს შორის განსხვავება

terminal
git diff branch1 branch2

ვიზუალური diff tool

terminal
git difftool branch1 branch2
// 06 — BRANCH 🟢 მარტივი

🌿 Branch — ტოტები

ტოტი არის "პარალელური სამყარო" — შეგვიძლია ექსპერიმენტი გავაკეთოთ ცალკე ხაზში, მთავარი კოდის დაზიანების გარეშე.

ყველა ტოტის ნახვა

ფლაგი -a გვაჩვენებს როგორც ლოკალურ, ისე remote ტოტებს ერთად:

terminal
git branch -a

ახალი ტოტის შექმნა

terminal
git branch newbranch

ტოტზე გადასვლა

terminal
git checkout newbranch
💡 მოკლე ხერხი

ერთდროულად შეიქმნას და გადავიდეს ახალ ტოტზე: git checkout -b newbranch

ტოტის სახელის შეცვლა

terminal
git branch -m old_branch_name new_branch_name

ტოტის წაშლა

terminal
git branch -d old_branch_name
⚠️ ფლაგი -d vs -D

-d წაშლის ტოტს მხოლოდ მაშინ, თუ ის უკვე merge-ულია. -D (დიდი ასოთი) ძალით წაშლის — ცვლილებები შეიძლება დაიკარგოს.

ტოტების ვიზუალიზაცია

gitGraph
  commit id: "A"
  commit id: "B"
  branch feature
  checkout feature
  commit id: "C"
  commit id: "D" tag: "HEAD"
  checkout main
  commit id: "E"
        
📖 დიაგრამის ახსნა
  • A, B — საწყისი commit-ები main ტოტზე
  • C, D — ფიჩერული მუშაობა feature ტოტზე
  • E — main გრძელდება, feature ცალკე რჩება
// 07 — MERGE 🟡 საშუალო

🔀 Merge — ტოტების შერწყმა

სიტყვა "merge" ერთ-ერთი მნიშვნელობით ნიშნავს შთანთქმას ან ჩაყლაპვას. შეგვიძლია წარმოვიდგინოთ, როგორ ყლაპავს მიმდინარე ტოტი მითითებულს.

ნაბიჯ-ნაბიჯ Merge:

  1. გადავერთოთ მიმღებ ტოტზე
    თუ ფიჩერ ტოტი გვინდა master-ში გავაერთიანოთ, ჯერ master-ზე ვართ.
  2. ვუშვებთ git merge other_branch
    Git ცდილობს ცვლილებების ავტომატურ შერწყმას.
  3. კონფლიქტების შემთხვევაში
    თუ ერთი და იგივე ხაზი ორივე ტოტში შეიცვალა — Git გვთხოვს გადავწყვიტოთ.
  4. Merge commit-ი
    წარმატებული merge-ის შემდეგ იქმნება ახალი "merge commit", თუ --no-ff ან კონფლიქტი იყო.
terminal
git checkout master
git merge other_branch

Merge-ის ორი ძირითადი ტიპი

--fast-forward (default)

როდესაც master-ზე არ მომხდარა ცვლილებები და ისე ერთიანდება, თითქოს არც ყოფილა განტოტვა. ისტორია წრფივი რჩება.

gitGraph
  commit id: "A"
  commit id: "B"
  branch feature
  checkout feature
  commit id: "C"
  commit id: "D"
  checkout main
  merge feature id: "fast-forward"
        

🔀 --no-ff

ისე ერთიანდება, თითქოს ყოფილა განტოტვა. ქმნის ცალკე merge commit-ს — ისტორიაში ჩანს, რომ იყო ფიჩერი.

gitGraph
  commit id: "A"
  commit id: "B"
  branch feature
  checkout feature
  commit id: "C"
  commit id: "D"
  checkout main
  commit id: "E"
  merge feature id: "M" tag: "no-ff"
        
📖 დიაგრამის ახსნა
  • A, B — საწყისი commit-ები main-ზე
  • C, D — feature ტოტის ცვლილებები
  • E — main გაგრძელდა feature-ის შექმნის შემდეგ
  • M — merge commit, რომელიც აერთიანებს ორ ხაზს

კონფლიქტების გადაწყვეტა

terminal
git mergetool

გახსნის კონფიგურირებულ merge-tool-ს (VS Code, Beyond Compare, P4Merge და სხვა) — სადაც ვიზუალურად შეგვიძლია გადავწყვიტოთ კონფლიქტი.

// 08 — FETCH 🟡 საშუალო

📡 Fetch — მონაცემების მოტანა

Fetch მოაქვს მეტა-მონაცემები remote repository-დან, მაგრამ არ აკეთებს merge-ს. ეს არის უსაფრთხო გზა იმის ნახვისა, რა ცვლილებები მოხდა სხვა დეველოპერებთან.

🔍 Fetch vs Pull განსხვავება:

  1. git fetch — მხოლოდ ჩამოწერა
    Remote-ის მდგომარეობა ჩამოგვაქვს, მაგრამ ლოკალურ ტოტს არ ცვლის.
  2. ცვლილებების ნახვა
    git log HEAD..origin/master — გვიჩვენებს რა ცვლილებებია remote-ზე, რომელიც ჯერ ჩვენ არ გვაქვს.
  3. თვით merge ცალკე
    git merge origin/master — როცა მზად ვართ.
  4. git pull = fetch + merge
    Pull ერთდროულად აკეთებს ორივეს — სწრაფი, მაგრამ ნაკლებად კონტროლირებადი.
terminal
git fetch origin master --all
// 09 — RESTORE 🟡 საშუალო

📋 Restore — ფაილის აღდგენა

Restore კოპიკავს კონკრეტული წყაროს მდგომარეობას მიმდინარე სამუშაო ფაილში. ნაყოფიერია, როდესაც გვინდა ერთი ფაილი დავაბრუნოთ წინა მდგომარეობაში.

terminal
# აკოპირებს source-ის მდგომარეობას მიმდინარე სამუშაო ფაილში
git restore filename --source=<Branchname or HEAD~n>
📌 პრაქტიკული მაგალითები

1. ფაილი დავაბრუნოთ HEAD-ის მდგომარეობაში (განვაუქმოთ შეცვლა):

git restore index.html

2. ფაილი ავიღოთ master-ის ბოლო მდგომარეობიდან:

git restore index.html --source=master

3. 3 commit წინანდელი ვერსია:

git restore index.html --source=HEAD~3
// 10 — STASH 🟡 საშუალო

💎 Stash — დროებითი დამალვა

სიტყვა "stash" ნიშნავს დამალვას, დაფარულ საგანძურს. გამოიყენება მაშინ, როდესაც გვაქვს დაუმთავრებელი ცვლილებები, მაგრამ სასწრაფოდ უნდა გადავერთოთ სხვა ტოტზე.

🎒 Stash-ის გამოყენების სცენარი:

  1. ვმუშაობთ feature ტოტზე
    გვაქვს დაუმთავრებელი ცვლილებები — commit-ის გაკეთება არ გვინდა.
  2. სასწრაფო bug master-ზე
    გვჭირდება სასწრაფო გადასვლა master-ზე, მაგრამ უცომიტო ცვლილებები ხელს უშლის.
  3. git stash save "ჩემი ცვლილებები"
    ცვლილებები "ემალება" — Working Directory სუფთა ხდება.
  4. გადავერთოთ master-ზე და ვასწორებთ bug-ს
    სუფთა გარემოში ვხუთავთ პრობლემას.
  5. ვბრუნდებით feature-ზე და git stash pop
    ჩვენი დამალული ცვლილებები ბრუნდება უცვლელი სახით.

დროებით დამალვა (კომენტარით)

terminal
git stash save "comment message"

Untracked ფაილების ჩათვლით

ფლაგი -u ემსახურება untracked ფაილების stash-ში მოქცევას:

terminal
git stash -u save "comment message"

დამალულის სიის ჩვენება

terminal
git stash list

კონკრეტული საგანძურის ნახვა

terminal
git stash show stash@{n}

საგანძურის დაბრუნება

terminal
git stash apply stash@{1}    # დააბრუნე, მაგრამ სტეშში დარჩეს
git stash drop stash@{1}     # კონკრეტული წაშლა
git stash pop                 # ბოლო სტეშის დაბრუნება + წაშლა

სტეშიდან ახალი ტოტის შექმნა

terminal
git stash branch new_branch_name

ყველა საგანძურის წაშლა

terminal
git stash clear
// 11 — TAGS 🟡 საშუალო

🏷️ Tags — რელიზების მონიშვნა

Tag არის "სამუდამო ნიშანი" კონკრეტულ commit-ზე. გამოიყენება ვერსიების მონიშვნისთვის (v1.0.0, v2.0.0).

ვერსიონირების სქემა (Semantic Versioning)

v1.2.3 ფორმატი:

  • 1 — Major release number (დიდი ცვლილებები, არ არის უკან-თავსებადი)
  • 2 — Minor release number (ახალი ფიჩერები, უკან-თავსებადი)
  • 3 — Maintenance release number (bugfixes only)

ტეგის შექმნა

terminal
git tag tagname              # მსუბუქი ტეგი
git tag -a v1.0.0            # ანოტირებული ტეგი (რეკომენდირებული)

ტეგების ჩამონათვალი და ნახვა

terminal
git tag --list
git show tagname
git show --delete tagname

ტეგის მინიჭება კონკრეტული ქომითისთვის

terminal
git tag -a tagname sha_of_commit

ტეგის გადატანა სხვა ქომითისთვის

terminal
git tag -a tagname -f sha_of_commit

ტეგის Push GitHub-ზე

ჩვეულებრივი git push ტეგებს არ აიტვირთავს — საჭიროა ცალკე ბრძანება. რაც თავის მხრივ ქმნის zip ფაილის გადმოწერის საშუალებას GitHub-ის Releases გვერდიდან:

terminal
git push origin tagname              # კონკრეტული ტეგი
git push origin master --tags        # ყველა ტეგი ერთად

ტეგების წაშლა GitHub-დან

ფორმულა — "push nothing to this tag name". რჩება ლოკალურად, მაგრამ იშლება GitHub-დან:

terminal
git push origin :tagname
// 12 — ALIAS 🟡 საშუალო

Alias — სწრაფი მალსახმობები

Alias-ი საშუალებას გვაძლევს გრძელი ბრძანებები მოკლე "სახელი"-ზე გადავცვალოთ. გასარკვევი — ყველაფერი ფაილში ~/.gitconfig.

გლობალური alias-ის მისამართი

გლობალური ალიასები ინახება ამ მისამართზე:

terminal
cd ~/.gitconfig

გლობალური alias-ის შექმნა

terminal
git config --global alias.somealias "somename --param1 --param2 --param3"

პოპულარული alias-ების მაგალითი

~/.gitconfig
# მოკლე log გრაფით
git config --global alias.lg "log --oneline --graph --all --decorate"

# სტეტუსის სწრაფი ნახვა
git config --global alias.s "status -sb"

# ბოლო commit-ი
git config --global alias.last "log -1 HEAD"

# ცვლილებების მოკლე ჩვენება
git config --global alias.d "diff --stat"
✨ შემდეგ უბრალოდ

ვწერთ git lg — და ვიღებთ ლამაზ გრაფიკს. git s — და სრული სტატუსი თვალწინ გვაქვს. დაზოგავთ ბევრ დროს ყოველდღიურ მუშაობაში.

// 13 — RECOVERY METHODS 🔴 რთული

🔄 Reset vs Revert vs Restore

სამივე ბრძანება აღდგენისთვის გამოიყენება, მაგრამ სხვადასხვა სიტუაციაში. მნიშვნელოვანია ვიცოდეთ — როდის რომელი.

⚡ Reset

გამოიყენება მანამდე, სანამ push-ს გავაკეთებთ. გადააადგილებს HEAD-ს უკან.

⚠️ საფრთხიანია — ცვლის ისტორიას
🔁 Revert

გამოიყენება push-ის შემდეგ. ქმნის ახალ commit-ს ძველი ცვლილების გასაუქმებლად.

✅ უსაფრთხოა — ისტორია უცვლელია
📋 Restore

აკოპირებს source-ის მდგომარეობას მიმდინარე სამუშაო ფაილში. ცალკეული ფაილისთვის.

📁 ფაილის დონეზე მუშაობს
🎯 მთავარი წესი

Reset-ი გამოიყენება მანამდე, სანამ არ გავაკეთებთ push-ს, ხოლო push-ის გაკეთების მერე ვიყენებთ Revert-ს. Restore-ი აკოპირებს source-ის მდგომარეობას მიმდინარე სამუშაო ფაილში.

// 14 — REVERT 🔴 რთული

🔁 Revert — უსაფრთხო გაუქმება

Revert ქმნის ახალ commit-ს, რომელიც აუქმებს ძველის ცვლილებებს. ისტორია უცვლელი რჩება — ეს განსაკუთრებით მნიშვნელოვანია გუნდურ მუშაობაში.

🔄 Revert-ის ლოგიკა:

  1. ვპოულობთ პრობლემურ commit-ს
    ვიყენებთ git log-ს რომ ვიპოვოთ commit-ის hash.
  2. ვუშვებთ git revert <hash>
    Git ავტომატურად ქმნის ახალ commit-ს რომელიც პირიქით აკეთებს იმას, რასაც ძველი აკეთებდა.
  3. commit-ის მესიჯი
    გვიხსნება ედიტორი — შეგვიძლია მესიჯი დავარედაქტიროთ.
  4. Push უსაფრთხოდ
    ისტორია უცვლელია — სხვა დეველოპერებს არ ერევათ ცვლილებები.
terminal
# ქმნის ახალ Commit-ს ძველის გასაუქმებლად
# hash-ად უნდა მივუთითოთ ის hash-ი რომლის გაუქმებაც გვინდა
# გამოიყენება ერთი კონკრეტული commit-ის გასაუქმებლად
git revert <hash>

ვიზუალიზაცია

gitGraph
  commit id: "A"
  commit id: "B" type: REVERSE
  commit id: "C"
  commit id: "B'" tag: "HEAD"
        
📖 დიაგრამის ახსნა
  • A — საწყისი commit
  • B — პრობლემური ფიჩერი (გადახაზული — გასაუქმებელი)
  • C — სხვა ცვლილება (უცვლელი რჩება)
  • B' — ახალი commit, რომელიც აუქმებს B-ს ცვლილებებს
// 15 — RESET DEEP DIVE 🔴 რთული

Reset — ნაბიჯ-ნაბიჯ ვიზუალიზაცია

git reset ცვლის HEAD პოინტერს. სამი ტიპი არსებობს: --soft, --mixed (ნაგულისხმევი) და --hard. ცალ-ცალკე გავიაროთ ყველა.

ტიპი Working Dir Stage Area აღწერა
--soft ❌ რჩება შეუცვლელი ❌ რჩება შეუცვლელი მოძრაობს მხოლოდ HEAD პოინტერი
--mixed (default) ❌ რჩება შეუცვლელი ✅ იცვლება იშლება მხოლოდ Staging Area
--hard ✅ იცვლება ✅ იცვლება იშლება Staging Area-ც და Working Directory-ც
ინტერაქტიული Reset ვიზუალიზაცია
📂 Working Directory
file.js (ცვლილებით)
readme.md (ცვლილებით)
🎯 Staging Area
file.js
readme.md
📦 Repository (HEAD)
● a3f2c1 — feature added
▼ HEAD ▼
● b4e8d2 — fix bug
● c1d9a3 — initial
აირჩიეთ Reset-ის ტიპი ზემოთ და დააჭირეთ "ნაბიჯის გაშვება". ნახეთ რა ხდება Working Directory-სა და Staging Area-სთან.

გამოყენების მაგალითები

1. ყველა დაუქომითებელი ცვლილების წაშლა

terminal
# შლის ყველა დაუქომითებელ ცვლილებას
git reset --hard

2. ბოლო 2 commit-ის გაუქმება

terminal
# შლის ბოლო 2 commit-ს
git reset HEAD~2 --hard
🚨 უკიდურესი სიფრთხილე

git reset --hard წაშლის ცვლილებებს სამუდამოდ. დაუბრუნებელია, თუ git reflog-ით არ აღვადგენთ. გამოიყენეთ მხოლოდ მაშინ, როდესაც დარწმუნებული ხართ.

// 16 — REBASE 🔴 რთული

🔄 Rebase — ტოტის საწყისის შეცვლა

Rebase "გადაიტანს" ჩვენი ტოტის commit-ებს სხვა ბაზაზე. შედეგად ვიღებთ წრფივ, სუფთა ისტორიას merge commit-ების გარეშე.

🔁 Rebase ნაბიჯ-ნაბიჯ:

  1. გადავერთოთ ფიჩერ ტოტზე
    git checkout otherbranch
  2. ვუშვებთ git rebase master
    Git იღებს ჩვენი ტოტის commit-ებს და "ცვლის" მათ master-ის უახლეს მდგომარეობაზე.
  3. კონფლიქტი?
    გადავწყვიტოთ, შემდეგ git add და git rebase --continue.
  4. თავიდან აცილება
    თუ რამე გვინდა გავაუქმოთ — git rebase --abort აბრუნებს ყველაფერს.
terminal
git checkout otherbranch
git rebase master

თავიდან აცილება / გაგრძელება

terminal
git rebase --abort     # კონფლიქტში — ყველაფერი თავდაპირველად დავაბრუნოთ
git rebase --continue  # კონფლიქტის გადაწყვეტის შემდეგ

Pull rebase-ით

Pull-ის ნაცვლად, რომელიც ქმნის merge commit-ს, შეგვიძლია გამოვიყენოთ rebase ვერსია — სუფთა ისტორიისთვის:

terminal
git pull --rebase origin master
⚠️ Rebase-ის ოქროს წესი

არასოდეს გააკეთო rebase ისეთ ტოტზე, რომელიც უკვე გაზიარებულია სხვებთან. Rebase ცვლის commit-ების hash-ებს, რაც სხვებისთვის გამოიწვევს ისტორიის "გადარევას".

Merge vs Rebase ვიზუალურად

🔀 Merge — შენახულია მთელი ისტორია

gitGraph
  commit id: "A"
  commit id: "B"
  branch feature
  checkout feature
  commit id: "C"
  commit id: "D"
  checkout main
  commit id: "E"
  merge feature id: "M"
        

🔄 Rebase — წრფივი ისტორია

commit-ები C და D "გადაიგზავნა" E-ის შემდეგ, თითქოს თავიდანვე იქ იყო:

gitGraph
  commit id: "A"
  commit id: "B"
  commit id: "E"
  commit id: "C'" tag: "rebased"
  commit id: "D'" tag: "HEAD"
        
📖 დიაგრამის ახსნა
  • A, B, E — main-ის ისტორია უცვლელი
  • C', D' — feature-ის ცვლილებები ახალი hash-ებით, E-ს შემდეგ მიწერილი
  • შედეგი — წრფივი ხაზი merge commit-ების გარეშე
// 17 — CHERRY-PICK 🔴 რთული

🍒 Cherry-pick — ერთი commit-ის "არჩევა"

ერთი კონკრეტული commit-ის დაკოპირება სხვა ტოტზე. სიტყვა "cherry-pick" ნიშნავს ბაღიდან საუკეთესო ალუბლის შერჩევას — ანუ ცალკე commit-ის ამოღებას სხვა commit-ების გარეშე.

⚠️ ყურადღება

მაღალი ალბათობით შეიძლება გამოიწვიოს კონფლიქტები, განსაკუთრებით თუ commit დიდი ცვლილებებს შეიცავს ან ისეთ კოდში, რომელიც უკვე შეცვლილია სამიზნე ტოტში.

ვიზუალური მაგალითი

ქვემოთ მოცემულ ვიზუალიზაციაში ვაკოპირებთ C commit-ს feature-xyz-დან main-ზე:

gitGraph
  commit id: "A"
  commit id: "B"
  branch feature-xyz
  checkout feature-xyz
  commit id: "C"
  commit id: "D"
  checkout main
  commit id: "E"
  cherry-pick id: "C" tag: "🍒"
        
📖 დიაგრამის ახსნა
  • A, B — საწყისი commit-ები main-ზე
  • C — საუკეთესო ფიჩერი (ეს გვინდა main-ზე გადავიტანოთ)
  • D — სხვა ცვლილება feature-ზე (არ გვაინტერესებს)
  • E — main გაგრძელდა
  • 🍒 C — დაკოპირებული C, ახალი hash-ით main-ზე

🍒 Cherry-pick ნაბიჯ-ნაბიჯ:

  1. ვიპოვოთ commit-ის hash
    git log feature-xyz და დავიმახსოვროთ რომელიც გვჭირდება.
  2. გადავერთოთ მიმღებ ტოტზე
    git checkout main
  3. ვუშვებთ git cherry-pick <hash>
    Git ქმნის ახალ commit-ს იმავე ცვლილებებით, მაგრამ ახალი hash-ით.
  4. კონფლიქტის შემთხვევაში
    გადავწყვიტოთ, შემდეგ git cherry-pick --continue. ან --abort გასაუქმებლად.
terminal
git checkout main
git cherry-pick <commit-hash>
// 18 — WORKTREE 🟣 თანამედროვე NEW

🌲 Worktree — რამდენიმე სამუშაო ფოლდერი ერთი repo-დან

Worktree საშუალებას გვაძლევს ერთი და იგივე git repository-დან გავხსნათ რამდენიმე ცალკე სამუშაო ფოლდერი — თითო მათგანი სხვადასხვა ტოტზე. აღარ არის საჭირო stash, branch switching ან მთელი repo-ს კლონირება.

💡 ყველაზე ხშირი სცენარი

ვმუშაობ feature ტოტზე. სასწრაფო bug მოვიდა. stash-ის ნაცვლად, ვქმნი ცალკე worktree-ს main-ზე, ვასწორებ bug-ს იქ — ჩემი მიმდინარე ფოლდერი ხელუხლებელი რჩება.

🌲 Worktree ნაბიჯ-ნაბიჯ:

  1. ვქმნით ახალ worktree-ს ცალკე ფოლდერში
    git worktree add ../hotfix main — შეიქმნება ../hotfix ფოლდერი, შიგნით main ტოტი.
  2. გადავდივართ იქ და ვმუშაობთ
    ჩვენი მთავარი ფოლდერი უცვლელი რჩება — შეგვიძლია იქაც პარალელურად ვიმუშაოთ.
  3. ვაკეთებთ commit-ს და push-ს
    ისტორია იზიარება — ერთი .git ფოლდერი, რამდენიმე სამუშაო ფოლდერი.
  4. ვშლით worktree-ს როცა აღარ გვჭირდება
    git worktree remove ../hotfix — ფოლდერი იშლება, ისტორია რჩება repo-ში.

ყველა მთავარი ბრძანება

terminal
# ახალი worktree ცალკე ფოლდერში არსებული ტოტიდან
git worktree add ../hotfix main

# ახალი worktree + ახალი ტოტი ერთდროულად
git worktree add -b new-feature ../new-feature

# ყველა worktree-ის ჩამონათვალი
git worktree list

# worktree-ის წაშლა (უცვლელად დატოვებს ტოტს)
git worktree remove ../hotfix

# გასუფთავება — წაშლის "ობოლ" worktree-ის ჩანაწერებს
git worktree prune

Worktree vs Stash vs Clone

📦 Stash

ცვლილებები იმალება, მხოლოდ ერთი ფოლდერი გვაქვს. ცვლილებებზე ვერ ვაკეთებთ commit-ს მალულ მდგომარეობაში.

🌲 Worktree

რამდენიმე ფოლდერი, ერთი .git. პარალელური მუშაობა, არანაირი stash, არანაირი context-switch.

🔁 Clone

სრული ასლი დისკზე — ბევრი ადგილი, ცალკე ისტორია. სხვადასხვა remote-დან რომ მოგვაქვს ის შემთხვევაა.

✨ რეალური სცენარი

დიდ პროექტებში, სადაც build-ი გრძელია — შეგვიძლია ერთი worktree-ში ვაშენოთ main, მეორეში — feature. Build cache ცალკე რჩება, არ გადაიწერება ტოტის გადართვისას.

// 19 — SWITCH (MODERN) 🟣 თანამედროვე

🔄 Switch — checkout-ის თანამედროვე ჩამნაცვლებელი

Git 2.23-ში გამოჩნდა ორი ახალი ბრძანება: git switch და git restore. მათი მიზანია — ძველი git checkout ბრძანების ორი მნიშვნელობა (ტოტის გადართვა და ფაილის აღდგენა) ცალცალკე გავამარტოვოთ.

⚠️ რატომ შეიქმნა?

git checkout ერთდროულად აკეთებდა ბევრ რამეს: ტოტს ცვლიდა, ფაილს აღადგენდა, commit-ს ამოწმებდა. ამან დააბნია მომხმარებლები. switch + restore ცხადად გამოყოფს თითოეულ ფუნქციას.

switch-ის ძირითადი ბრძანებები

terminal
# არსებულ ტოტზე გადასვლა
git switch main

# ახალი ტოტის შექმნა და გადასვლა (-c = create)
git switch -c new-feature

# remote ტოტზე გადასვლა (ლოკალურად შექმნით)
git switch --track origin/feature

# წინა ტოტზე დაბრუნება
git switch -

# detached HEAD რეჟიმი (კონკრეტულ commit-ზე)
git switch --detach <commit-hash>

Old vs New ცხრილი

ძველი (checkout) ახალი (switch / restore) რას აკეთებს
git checkout main git switch main ტოტზე გადასვლა
git checkout -b new git switch -c new ახალი ტოტი + გადასვლა
git checkout file.js git restore file.js ფაილის აღდგენა
git checkout HEAD~3 file.js git restore --source=HEAD~3 file.js ფაილი წინა ვერსიიდან
💡 უნდა გადავერთო?

checkout ჯერ არ წაშლილა — მუშაობს და მომავალში არ გაქრება. მაგრამ ახალი კოდის და ახალი მომხმარებლებისთვის switch / restore უფრო ნათელია.

// 20 — REFLOG 🟣 თანამედროვე

Reflog — Git-ის დროის მანქანა

Reflog ინახავს HEAD-ის ყოველ მოძრაობას ბოლო ~30-90 დღის განმავლობაში. ეს გვეხმარება დავიბრუნოთ git reset --hard-ის შემდეგ "სამუდამოდ" დაკარგული commit-ები.

🛟 მე უკვე "დავკარგე" commit-ები — როგორ გადავიდე უკან?

თუ git reset --hard გავაკეთე და მინდა უკან დაბრუნება, reflog ჩემი ერთადერთი მაშველია. Git-ის ისტორია წაშლილია, მაგრამ reflog ახსოვს სად იყო HEAD წინა მდგომარეობებში.

ძირითადი ბრძანებები

terminal
# ვიხილოთ HEAD-ის ისტორია
git reflog

# კონკრეტული ტოტის reflog
git reflog show main

# დროითი ფილტრი
git reflog --since="2 hours ago"

დაკარგული commit-ის აღდგენა

  1. ვუშვებთ git reflog
    ნახავთ სიას: HEAD@{0}, HEAD@{1}... — თითოეული მდგომარეობა.
  2. ვპოულობთ "დაკარგულ" მდგომარეობას
    მაგ.: HEAD@{5}: commit: ჩემი მნიშვნელოვანი ცვლილება
  3. ვაბრუნებთ ან ცალკე ტოტზე ვიღებთ
    git reset --hard HEAD@{5} ან git checkout -b recovered HEAD@{5}
terminal
# reflog-დან აღდგენა
git reset --hard HEAD@{5}

# უსაფრთხო ვარიანტი — ცალკე ტოტი
git checkout -b recovered HEAD@{5}
⏳ Reflog მუდმივი არ არის

ნაგულისხმევად 90 დღეში ხდება გასუფთავება (gc.reflogExpire). თუ უკვე გავიდა ბევრი დრო — შეიძლება ვეღარ აღვადგინოთ.

// 21 — BISECT 🟣 თანამედროვე

🔍 Bisect — Bug-ის ბინარული ძიება

Bisect არის ალგორითმი, რომელიც ბინარული ძიებით ყოფს commit-ების ისტორიას შუაზე და გვეხმარება ვიპოვოთ ის კონკრეტული commit, რომელმაც bug შემოიტანა. 1000 commit-ში — მაქსიმუმ 10 ნაბიჯში.

🧮 მათემატიკა

log₂(1000) ≈ 10. ანუ 1024 commit-ში მხოლოდ 10 ცდას სჭირდება bug-ის ლოკაციის დადგენა. ეს არის O(log n) ნაცვლად ხელით გასინჯვის O(n).

Bisect ნაბიჯ-ნაბიჯ

  1. ვიწყებთ ძიებას
    git bisect start
  2. ვაცხადებთ მიმდინარე (bug-იან) commit-ს ცუდად
    git bisect bad — ანუ "აქ უკვე არსებობს bug".
  3. ვაცხადებთ ძველ (კარგ) commit-ს კარგად
    git bisect good v1.0.0 — "აქ ჯერ არ იყო bug".
  4. Git გვაჩვენებს შუა commit-ს
    ჩვენ ვტესტავთ — bug არის თუ არა? ვცხადებთ git bisect good ან git bisect bad.
  5. ვიმეორებთ მინი ცდას
    Git ცდის სანახევრო შუას, შემდეგ მისი შუას... სანამ მოძებნის zerk-ს commit-ს.
  6. ვამთავრებთ
    git bisect reset — დავუბრუნდეთ ჩვეულებრივ HEAD-ს.

სრული მაგალითი

terminal
git bisect start
git bisect bad                  # ახლა bug-ი არის
git bisect good v1.0.0          # v1.0.0-ში ჯერ არ იყო

# Git გადაგვიყვანს შუა commit-ზე
# ვტესტავთ აპლიკაციას, შემდეგ:
git bisect good                 # ან git bisect bad

# ... ვიმეორებთ ...

# საბოლოოდ Git გვეუბნება:
# "abc1234 is the first bad commit"

git bisect reset                # უკან ვბრუნდებით

ავტომატური bisect (ულტრა-ძლიერი)

თუ გვაქვს ტესტი, რომელიც აბრუნებს non-zero exit code bug-ის შემთხვევაში — Git თვითონ შეასრულებს ყველა ნაბიჯს:

terminal
git bisect start HEAD v1.0.0
git bisect run npm test
# Git ავტომატურად იპოვის bug-იან commit-ს! 🎯
// 22 — SPARSE CHECKOUT 🟣 თანამედროვე

📂 Sparse Checkout — ნაწილობრივი repo

დიდ monorepo-ებში (Google, Microsoft სტილი) ხშირად არ გვჭირდება ყველა ფაილი. Sparse checkout ეხმარება ჩამოვწეროთ მხოლოდ ის ფოლდერები, რომელზეც ვმუშაობთ. დანარჩენი ლოკალურად არ ჩანს.

🚀 Git 2.25+ — ახალი API

2020 წელს გამოიცა git sparse-checkout ბრძანება, რომელიც ბევრად მარტივად აყენებს ამ კონფიგურაციას. ძველი core.sparseCheckout = true manual setup აღარ სჭირდება.

გამოყენება

terminal
# ვრთავთ sparse checkout-ს (cone mode — დანერგვის ახალი მეთოდი)
git sparse-checkout init --cone

# ვირჩევთ მხოლოდ კონკრეტულ ფოლდერებს
git sparse-checkout set frontend/web shared/utils

# ნახვა — რა ფოლდერებს ვრთავთ
git sparse-checkout list

# ვამატებთ კიდევ ერთ ფოლდერს
git sparse-checkout add backend/api

# ვთიშავთ — ყველა ფაილი ბრუნდება
git sparse-checkout disable

Partial clone-თან ერთად (ნამდვილი ძალა)

დიდი repo-სთვის: ჯერ partial clone-ი, შემდეგ sparse checkout — დისკზე მინიმუმი, სიჩქარე მაქსიმუმი:

terminal
# Blob-ები ჩამოგვაქვს მხოლოდ მაშინ, როცა გვჭირდება
git clone --filter=blob:none --no-checkout <url>
cd repo
git sparse-checkout init --cone
git sparse-checkout set frontend
git checkout main
📊 რეალური შედეგი

100GB-იანი monorepo შეიძლება გადაიქცეს 2GB-ად. Build-ი ხდება უფრო სწრაფი, IDE-ი არ ხუნდება, git status-ი მყისიერია.

// 23 — HOOKS 🟣 თანამედროვე

🪝 Hooks — ავტომატიზაცია Git-ის მოვლენებზე

Hook არის სკრიპტი, რომელსაც Git ავტომატურად უშვებს კონკრეტული მოვლენის წინ ან შემდეგ — commit-ის წინ, push-ის წინ, merge-ის შემდეგ. ეს ემსახურება კოდის ხარისხის შენარჩუნებას, ტესტების გაშვებას, ფორმატირებას.

ყველაზე გამოყენებადი hooks

Hook როდის მუშაობს გავრცელებული მიზანი
pre-commit commit-ის წინ Lint, format, ტესტი
commit-msg commit-მესიჯის შემდეგ Conventional Commits ფორმატის შემოწმება
pre-push push-ის წინ სრული ტესტ-სუიტი, build
post-merge merge-ის შემდეგ npm install, deps განახლება
prepare-commit-msg ედიტორის გახსნამდე JIRA ticket ID-ის ავტომატური ჩასმა

ხელით — pre-commit hook

Hook-ები ცხოვრობენ .git/hooks/ ფოლდერში. შევქმნათ მარტივი:

.git/hooks/pre-commit
#!/bin/sh
# არ დართო commit თუ ლინტი ჩავარდა
npm run lint
if [ $? -ne 0 ]; then
  echo "❌ Lint errors detected. Commit aborted."
  exit 1
fi

დარწმუნდი, რომ ფაილი executable-ია: chmod +x .git/hooks/pre-commit

თანამედროვე გზა — Husky

.git/hooks/ ცალკეული მომხმარებლისთვის ლოკალურია, არ იზიარება გუნდთან. Husky არის Node.js ბიბლიოთეკა, რომელიც hook-ებს ინახავს repo-ში — გუნდის ყველა წევრი ერთ კონფიგს იყენებს:

terminal
npm install --save-dev husky
npx husky init

# ახლა ფაილი .husky/pre-commit ემსახურება ყველას
echo "npm test" > .husky/pre-commit
⚡ პოპულარული tools
  • lint-staged — მხოლოდ staged ფაილებს ალინტავს (სწრაფი)
  • commitlint — Conventional Commits-ის შემოწმება
  • pre-commit framework (Python) — multi-language hook manager
// 24 — BLAME 🟣 თანამედროვე

🕵️ Blame — რომელ ხაზს ვინ დაწერა

Blame აჩვენებს თითო ხაზის გვერდიდან ბოლო commit-ს — ვინ შეცვალა, როდის და რომელ commit-ში. სახელის მიუხედავად, ეს არის ყველაზე ნაყოფიერი ბრძანება ისტორიის გასაგებად — არა ვინმეს დასადანაშაულებლად.

terminal
# სრული blame
git blame index.html

# კონკრეტული ხაზების დიაპაზონი (50-დან 100-მდე)
git blame -L 50,100 index.html

# ფუნქციის blame სახელით
git blame -L :myFunction:src/utils.js

# whitespace ცვლილებების უგულებელყოფა
git blame -w index.html

# გადახლართული ფაილების ისტორია — სანამ ფაილი არ გადარქმეულა
git blame -C -C -C index.html

გამოსაყენებელი ფლაგები

  • -w — უგულებელყოფს whitespace ცვლილებებს (ფორმატირების commit-ები იფარება)
  • -M — აღმოაჩენს ფაილის შიგნით კოდის გადატანას
  • -C — აღმოაჩენს კოდის გადატანას სხვა ფაილიდან (-CC, -CCC უფრო აგრესიული)
  • --since="1 year ago" — ძველ blame-ებს არ აჩვენებს
💡 IDE ინტეგრაცია

GitLens (VS Code), JetBrains IDE და Sublime Merge ავტომატურად აჩვენებენ blame-ს ხაზის გვერდით — ბრძანების გაშვების გარეშე. რეალურ დროში ვხედავთ ვინმე ცოცხლობდა ამ ხაზს.

// 25 — MAINTENANCE 🟣 თანამედროვე NEW

🛠️ Maintenance — Repo-ს ფონური ოპტიმიზაცია

Git 2.30+ (2021) დაამატა git maintenance — ბრძანება, რომელიც ფონურად აოპტიმიზებს repo-ს: ხდება gc, ახალდება commit-graph, prefetch-ი remote-დან. დიდი repo-ის სამუშაო სიჩქარე ბევრად უმჯობესდება.

ჩართვა და მართვა

terminal
# ჩართვა — ავტომატურად დადგება cron job (Linux/Mac) ან launchd
git maintenance start

# მიმდინარე სტატუსი
git maintenance register

# ხელით გაშვება ყველა ოპტიმიზაცია
git maintenance run --task=gc --task=commit-graph --task=prefetch

# გათიშვა
git maintenance stop

რა სრულდება ფონურად?

Task რას აკეთებს როგორ ეხმარება
gc Garbage collection — შლის "ობოლ" ობიექტებს დისკი თავისუფლდება
commit-graph commit-ების გრაფი წინასწარ ინდექსდება git log, git blame 10× სწრაფად
prefetch Remote-დან წინასწარ ჩამოგვაქვს ცვლილებები fetch უფრო სწრაფი
loose-objects ცალკეული ფაილების packing დისკზე ნაკლები ფაილი
incremental-repack Pack-ფაილების ინკრემენტული გაუმჯობესება სწრაფი ოპერაციები
📈 რეალური წარმოდგენა

Microsoft-ის Windows repo (~300GB!) იყო ერთ-ერთი მთავარი მოტივატორი ამ ფიჩერის შესაქმნელად. მათ git status-ი 10 წამიდან 200ms-მდე ჩამოვიდა commit-graph-ისა და maintenance-ის მეშვეობით.

💡 დღევანდელი რეკომენდაცია

ნებისმიერ პროექტში, სადაც git status ან git log ნელია, ჯერ ჩართე: git maintenance start. შემდეგ კი დაელოდე — შესრულდება ფონურად, არ შეგიშლის ხელს.