GIT/DOCS·KA
Git-ის სრული ცნობარი — ბრძანებების ვიზუალიზაცია, ნაბიჯ-ნაბიჯ პროცესები, ცოცხალი დემოები. ყველაფერი ქართულად, ერთ გვერდზე, terminal-სავით.
⚙ საბაზისო ბრძანებები
ეს ბრძანებები ყოველდღიურად გამოიყენება და ქმნის Git-ის სამუშაო ბაზისს. ეს არის წინაპირობა ყველა მომავალი თემისთვის.
ფაილის სახელის შეცვლა Git-ის მეშვეობით
როდესაც ფაილს ოპერაციული სისტემით (Explorer-ით ან Finder-ით) გადავარქმევთ სახელს, Git მას აღიქვამს როგორც ერთი ფაილის წაშლას და ახალის შექმნას. ამის თავიდან ასაცილებლად, შეგვიძლია გამოვიყენოთ git mv:
git mv old.txt new.txt
ყველა ცვლილების დამატება Stage-ში
ფლაგი -A ემსახურება ყველა ცვლილების — ახალი, შეცვლილი და წაშლილი ფაილების — სრულად ასახვას Staging Area-ში. ეს განსაკუთრებით მნიშვნელოვანია მაშინ, როცა ფაილები ოპერაციული სისტემიდან დაგვიშლია ან გადავარქმევია სახელი.
git add -A
გამოყენება git status ბრძანებისა Staging-ის წინ — გვიჩვენებს რომელი ფაილები შეიცვალა და რომელი დამატებულია სტეიჯში.
📝 Commit — ცვლილებების დამახსოვრება
Commit არის Git-ის "ფოტო" - კონკრეტული მომენტის სრული მდგომარეობა, რომელიც შეიცავს იმ ცვლილებებს, რომლებიც Staging Area-ში შევიდა.
📋 Commit-ის სრული პროცესი:
-
ცვლილება Working Directory-შიფაილის შექმნა, შეცვლა ან წაშლა — ცვლილება ცოცხალია მხოლოდ შენს კომპიუტერში.
-
Stage-ში დამატება (
git add)Git-ს ვეუბნებით — "ეს ცვლილება მინდა შემდეგ commit-ში მოხვდეს". -
Commit (
git commit -m)Stage-ში არსებული ყველაფერი ფიქსირდება ისტორიაში უნიკალური hash-ით. -
Push (არასავალდებულო)commit-ი ლოკალურია სანამ remote-ზე არ ავიტვირთება.
სწრაფი commit (add + commit ერთად)
როდესაც ფაილი უკვე არის tracked (Git-ისთვის ცნობილი) და გვინდა ცვლილებების სწრაფად დაფიქსირება, შეგვიძლია -am ფლაგი გამოვიყენოთ:
# ფაილის დამატება და დამახსოვრება ერთი ბრძანებით
git commit -am "ჩემი ცვლილებების მესიჯი"
-am არ მუშაობს ახალი (untracked) ფაილებისთვის. ისინი ჯერ git add-ით უნდა დავამატოთ.
ბოლო commit-ის შესწორება
თუ ბოლო commit-ის მესიჯში შეცდომა იყო, ან რაიმე ფაილი დაგავიწყდა, --amend საშუალებას გვაძლევს მის შესწორებას ახალი commit-ის შექმნის გარეშე:
git commit --amend
--amend ცვლის commit-ის hash-ს. თუ უკვე გავაკეთეთ push, ნუ გამოიყენებთ ამას — სხვა დეველოპერებს ისტორია დაერევათ.
📜 Log — ისტორიის ნახვა
Log გვიჩვენებს commit-ების ისტორიას — ვინ, როდის, რა გააკეთა.
დროის ლიმიტი
ფლაგი --since მიიღებს ნებისმიერ ფორმატის თარიღს — "yesterday", "3 days ago", "2 weeks ago", კონკრეტული თარიღი:
git log --since="3 days ago" --oneline
კონკრეტული ფაილის ისტორია
git log -- filename --oneline
--oneline— თითო commit ერთ ხაზზე--graph— ASCII გრაფიკული ხე--all— ყველა ტოტის ჩათვლით--author="სახელი"— კონკრეტული ავტორის commit-ები-n 10— მხოლოდ ბოლო 10
🔍 Show — დეტალური ინფორმაცია
Show ობიექტის სრულ შინაარსს გვაჩვენებს — commit, tag, blob ან tree.
git show somehash
გამოიტანს commit-ის სრულ მესიჯს, ავტორს, თარიღს და diff-ს — რა ფაილები შეიცვალა და როგორ.
⚖️ Diff — განსხვავების ნახვა
Diff აჩვენებს განსხვავებას ორ მდგომარეობას შორის — ფაილების, ტოტების ან commit-ების.
2 ტოტს შორის განსხვავება
git diff branch1 branch2
ვიზუალური diff tool
git difftool branch1 branch2
🌿 Branch — ტოტები
ტოტი არის "პარალელური სამყარო" — შეგვიძლია ექსპერიმენტი გავაკეთოთ ცალკე ხაზში, მთავარი კოდის დაზიანების გარეშე.
ყველა ტოტის ნახვა
ფლაგი -a გვაჩვენებს როგორც ლოკალურ, ისე remote ტოტებს ერთად:
git branch -a
ახალი ტოტის შექმნა
git branch newbranch
ტოტზე გადასვლა
git checkout newbranch
ერთდროულად შეიქმნას და გადავიდეს ახალ ტოტზე: git checkout -b newbranch
ტოტის სახელის შეცვლა
git branch -m old_branch_name new_branch_name
ტოტის წაშლა
git branch -d old_branch_name
-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 ცალკე რჩება
🔀 Merge — ტოტების შერწყმა
სიტყვა "merge" ერთ-ერთი მნიშვნელობით ნიშნავს შთანთქმას ან ჩაყლაპვას. შეგვიძლია წარმოვიდგინოთ, როგორ ყლაპავს მიმდინარე ტოტი მითითებულს.
ნაბიჯ-ნაბიჯ Merge:
-
გადავერთოთ მიმღებ ტოტზეთუ ფიჩერ ტოტი გვინდა master-ში გავაერთიანოთ, ჯერ master-ზე ვართ.
-
ვუშვებთ
git merge other_branchGit ცდილობს ცვლილებების ავტომატურ შერწყმას. -
კონფლიქტების შემთხვევაშითუ ერთი და იგივე ხაზი ორივე ტოტში შეიცვალა — Git გვთხოვს გადავწყვიტოთ.
-
Merge commit-იწარმატებული merge-ის შემდეგ იქმნება ახალი "merge commit", თუ
--no-ffან კონფლიქტი იყო.
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, რომელიც აერთიანებს ორ ხაზს
კონფლიქტების გადაწყვეტა
git mergetool
გახსნის კონფიგურირებულ merge-tool-ს (VS Code, Beyond Compare, P4Merge და სხვა) — სადაც ვიზუალურად შეგვიძლია გადავწყვიტოთ კონფლიქტი.
📡 Fetch — მონაცემების მოტანა
Fetch მოაქვს მეტა-მონაცემები remote repository-დან, მაგრამ არ აკეთებს merge-ს. ეს არის უსაფრთხო გზა იმის ნახვისა, რა ცვლილებები მოხდა სხვა დეველოპერებთან.
🔍 Fetch vs Pull განსხვავება:
-
git fetch— მხოლოდ ჩამოწერაRemote-ის მდგომარეობა ჩამოგვაქვს, მაგრამ ლოკალურ ტოტს არ ცვლის. -
ცვლილებების ნახვა
git log HEAD..origin/master— გვიჩვენებს რა ცვლილებებია remote-ზე, რომელიც ჯერ ჩვენ არ გვაქვს. -
თვით merge ცალკე
git merge origin/master— როცა მზად ვართ. -
git pull= fetch + mergePull ერთდროულად აკეთებს ორივეს — სწრაფი, მაგრამ ნაკლებად კონტროლირებადი.
git fetch origin master --all
📋 Restore — ფაილის აღდგენა
Restore კოპიკავს კონკრეტული წყაროს მდგომარეობას მიმდინარე სამუშაო ფაილში. ნაყოფიერია, როდესაც გვინდა ერთი ფაილი დავაბრუნოთ წინა მდგომარეობაში.
# აკოპირებს 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
💎 Stash — დროებითი დამალვა
სიტყვა "stash" ნიშნავს დამალვას, დაფარულ საგანძურს. გამოიყენება მაშინ, როდესაც გვაქვს დაუმთავრებელი ცვლილებები, მაგრამ სასწრაფოდ უნდა გადავერთოთ სხვა ტოტზე.
🎒 Stash-ის გამოყენების სცენარი:
-
ვმუშაობთ feature ტოტზეგვაქვს დაუმთავრებელი ცვლილებები — commit-ის გაკეთება არ გვინდა.
-
სასწრაფო bug master-ზეგვჭირდება სასწრაფო გადასვლა master-ზე, მაგრამ უცომიტო ცვლილებები ხელს უშლის.
-
git stash save "ჩემი ცვლილებები"ცვლილებები "ემალება" — Working Directory სუფთა ხდება. -
გადავერთოთ master-ზე და ვასწორებთ bug-სსუფთა გარემოში ვხუთავთ პრობლემას.
-
ვბრუნდებით feature-ზე და
git stash popჩვენი დამალული ცვლილებები ბრუნდება უცვლელი სახით.
დროებით დამალვა (კომენტარით)
git stash save "comment message"
Untracked ფაილების ჩათვლით
ფლაგი -u ემსახურება untracked ფაილების stash-ში მოქცევას:
git stash -u save "comment message"
დამალულის სიის ჩვენება
git stash list
კონკრეტული საგანძურის ნახვა
git stash show stash@{n}
საგანძურის დაბრუნება
git stash apply stash@{1} # დააბრუნე, მაგრამ სტეშში დარჩეს
git stash drop stash@{1} # კონკრეტული წაშლა
git stash pop # ბოლო სტეშის დაბრუნება + წაშლა
სტეშიდან ახალი ტოტის შექმნა
git stash branch new_branch_name
ყველა საგანძურის წაშლა
git stash clear
🏷️ 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)
ტეგის შექმნა
git tag tagname # მსუბუქი ტეგი
git tag -a v1.0.0 # ანოტირებული ტეგი (რეკომენდირებული)
ტეგების ჩამონათვალი და ნახვა
git tag --list
git show tagname
git show --delete tagname
ტეგის მინიჭება კონკრეტული ქომითისთვის
git tag -a tagname sha_of_commit
ტეგის გადატანა სხვა ქომითისთვის
git tag -a tagname -f sha_of_commit
ტეგის Push GitHub-ზე
ჩვეულებრივი git push ტეგებს არ აიტვირთავს — საჭიროა ცალკე ბრძანება. რაც თავის მხრივ ქმნის zip ფაილის გადმოწერის საშუალებას GitHub-ის Releases გვერდიდან:
git push origin tagname # კონკრეტული ტეგი
git push origin master --tags # ყველა ტეგი ერთად
ტეგების წაშლა GitHub-დან
ფორმულა — "push nothing to this tag name". რჩება ლოკალურად, მაგრამ იშლება GitHub-დან:
git push origin :tagname
⚡ Alias — სწრაფი მალსახმობები
Alias-ი საშუალებას გვაძლევს გრძელი ბრძანებები მოკლე "სახელი"-ზე გადავცვალოთ. გასარკვევი — ყველაფერი ფაილში ~/.gitconfig.
გლობალური alias-ის მისამართი
გლობალური ალიასები ინახება ამ მისამართზე:
cd ~/.gitconfig
გლობალური alias-ის შექმნა
git config --global alias.somealias "somename --param1 --param2 --param3"
პოპულარული alias-ების მაგალითი
# მოკლე 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 — და სრული სტატუსი თვალწინ გვაქვს. დაზოგავთ ბევრ დროს ყოველდღიურ მუშაობაში.
🔄 Reset vs Revert vs Restore
სამივე ბრძანება აღდგენისთვის გამოიყენება, მაგრამ სხვადასხვა სიტუაციაში. მნიშვნელოვანია ვიცოდეთ — როდის რომელი.
გამოიყენება მანამდე, სანამ push-ს გავაკეთებთ. გადააადგილებს HEAD-ს უკან.
გამოიყენება push-ის შემდეგ. ქმნის ახალ commit-ს ძველი ცვლილების გასაუქმებლად.
აკოპირებს source-ის მდგომარეობას მიმდინარე სამუშაო ფაილში. ცალკეული ფაილისთვის.
Reset-ი გამოიყენება მანამდე, სანამ არ გავაკეთებთ push-ს, ხოლო push-ის გაკეთების მერე ვიყენებთ Revert-ს. Restore-ი აკოპირებს source-ის მდგომარეობას მიმდინარე სამუშაო ფაილში.
🔁 Revert — უსაფრთხო გაუქმება
Revert ქმნის ახალ commit-ს, რომელიც აუქმებს ძველის ცვლილებებს. ისტორია უცვლელი რჩება — ეს განსაკუთრებით მნიშვნელოვანია გუნდურ მუშაობაში.
🔄 Revert-ის ლოგიკა:
-
ვპოულობთ პრობლემურ commit-სვიყენებთ
git log-ს რომ ვიპოვოთ commit-ის hash. -
ვუშვებთ
git revert <hash>Git ავტომატურად ქმნის ახალ commit-ს რომელიც პირიქით აკეთებს იმას, რასაც ძველი აკეთებდა. -
commit-ის მესიჯიგვიხსნება ედიტორი — შეგვიძლია მესიჯი დავარედაქტიროთ.
-
Push უსაფრთხოდისტორია უცვლელია — სხვა დეველოპერებს არ ერევათ ცვლილებები.
# ქმნის ახალ 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-ს ცვლილებებს
⚡ Reset — ნაბიჯ-ნაბიჯ ვიზუალიზაცია
git reset ცვლის HEAD პოინტერს. სამი ტიპი არსებობს: --soft, --mixed (ნაგულისხმევი) და --hard. ცალ-ცალკე გავიაროთ ყველა.
| ტიპი | Working Dir | Stage Area | აღწერა |
|---|---|---|---|
--soft |
❌ რჩება შეუცვლელი | ❌ რჩება შეუცვლელი | მოძრაობს მხოლოდ HEAD პოინტერი |
--mixed (default) |
❌ რჩება შეუცვლელი | ✅ იცვლება | იშლება მხოლოდ Staging Area |
--hard |
✅ იცვლება | ✅ იცვლება | იშლება Staging Area-ც და Working Directory-ც |
გამოყენების მაგალითები
1. ყველა დაუქომითებელი ცვლილების წაშლა
# შლის ყველა დაუქომითებელ ცვლილებას
git reset --hard
2. ბოლო 2 commit-ის გაუქმება
# შლის ბოლო 2 commit-ს
git reset HEAD~2 --hard
git reset --hard წაშლის ცვლილებებს სამუდამოდ. დაუბრუნებელია, თუ git reflog-ით არ აღვადგენთ. გამოიყენეთ მხოლოდ მაშინ, როდესაც დარწმუნებული ხართ.
🔄 Rebase — ტოტის საწყისის შეცვლა
Rebase "გადაიტანს" ჩვენი ტოტის commit-ებს სხვა ბაზაზე. შედეგად ვიღებთ წრფივ, სუფთა ისტორიას merge commit-ების გარეშე.
🔁 Rebase ნაბიჯ-ნაბიჯ:
-
გადავერთოთ ფიჩერ ტოტზე
git checkout otherbranch -
ვუშვებთ
git rebase masterGit იღებს ჩვენი ტოტის commit-ებს და "ცვლის" მათ master-ის უახლეს მდგომარეობაზე. -
კონფლიქტი?გადავწყვიტოთ, შემდეგ
git addდაgit rebase --continue. -
თავიდან აცილებათუ რამე გვინდა გავაუქმოთ —
git rebase --abortაბრუნებს ყველაფერს.
git checkout otherbranch
git rebase master
თავიდან აცილება / გაგრძელება
git rebase --abort # კონფლიქტში — ყველაფერი თავდაპირველად დავაბრუნოთ
git rebase --continue # კონფლიქტის გადაწყვეტის შემდეგ
Pull rebase-ით
Pull-ის ნაცვლად, რომელიც ქმნის merge commit-ს, შეგვიძლია გამოვიყენოთ rebase ვერსია — სუფთა ისტორიისთვის:
git pull --rebase origin master
არასოდეს გააკეთო 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-ების გარეშე
🍒 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 ნაბიჯ-ნაბიჯ:
-
ვიპოვოთ commit-ის hash
git log feature-xyzდა დავიმახსოვროთ რომელიც გვჭირდება. -
გადავერთოთ მიმღებ ტოტზე
git checkout main -
ვუშვებთ
git cherry-pick <hash>Git ქმნის ახალ commit-ს იმავე ცვლილებებით, მაგრამ ახალი hash-ით. -
კონფლიქტის შემთხვევაშიგადავწყვიტოთ, შემდეგ
git cherry-pick --continue. ან--abortგასაუქმებლად.
git checkout main
git cherry-pick <commit-hash>
🌲 Worktree — რამდენიმე სამუშაო ფოლდერი ერთი repo-დან
Worktree საშუალებას გვაძლევს ერთი და იგივე git repository-დან გავხსნათ რამდენიმე ცალკე სამუშაო ფოლდერი — თითო მათგანი სხვადასხვა ტოტზე. აღარ არის საჭირო stash, branch switching ან მთელი repo-ს კლონირება.
ვმუშაობ feature ტოტზე. სასწრაფო bug მოვიდა. stash-ის ნაცვლად, ვქმნი ცალკე worktree-ს main-ზე, ვასწორებ bug-ს იქ — ჩემი მიმდინარე ფოლდერი ხელუხლებელი რჩება.
🌲 Worktree ნაბიჯ-ნაბიჯ:
-
ვქმნით ახალ worktree-ს ცალკე ფოლდერში
git worktree add ../hotfix main— შეიქმნება../hotfixფოლდერი, შიგნით main ტოტი. -
გადავდივართ იქ და ვმუშაობთჩვენი მთავარი ფოლდერი უცვლელი რჩება — შეგვიძლია იქაც პარალელურად ვიმუშაოთ.
-
ვაკეთებთ commit-ს და push-სისტორია იზიარება — ერთი .git ფოლდერი, რამდენიმე სამუშაო ფოლდერი.
-
ვშლით worktree-ს როცა აღარ გვჭირდება
git worktree remove ../hotfix— ფოლდერი იშლება, ისტორია რჩება repo-ში.
ყველა მთავარი ბრძანება
# ახალი 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
ცვლილებები იმალება, მხოლოდ ერთი ფოლდერი გვაქვს. ცვლილებებზე ვერ ვაკეთებთ commit-ს მალულ მდგომარეობაში.
რამდენიმე ფოლდერი, ერთი .git. პარალელური მუშაობა, არანაირი stash, არანაირი context-switch.
სრული ასლი დისკზე — ბევრი ადგილი, ცალკე ისტორია. სხვადასხვა remote-დან რომ მოგვაქვს ის შემთხვევაა.
დიდ პროექტებში, სადაც build-ი გრძელია — შეგვიძლია ერთი worktree-ში ვაშენოთ main, მეორეში — feature. Build cache ცალკე რჩება, არ გადაიწერება ტოტის გადართვისას.
🔄 Switch — checkout-ის თანამედროვე ჩამნაცვლებელი
Git 2.23-ში გამოჩნდა ორი ახალი ბრძანება: git switch და git restore. მათი მიზანია — ძველი git checkout ბრძანების ორი მნიშვნელობა (ტოტის გადართვა და ფაილის აღდგენა) ცალცალკე გავამარტოვოთ.
git checkout ერთდროულად აკეთებდა ბევრ რამეს: ტოტს ცვლიდა, ფაილს აღადგენდა, commit-ს ამოწმებდა. ამან დააბნია მომხმარებლები. switch + restore ცხადად გამოყოფს თითოეულ ფუნქციას.
switch-ის ძირითადი ბრძანებები
# არსებულ ტოტზე გადასვლა
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 უფრო ნათელია.
⏰ Reflog — Git-ის დროის მანქანა
Reflog ინახავს HEAD-ის ყოველ მოძრაობას ბოლო ~30-90 დღის განმავლობაში. ეს გვეხმარება დავიბრუნოთ git reset --hard-ის შემდეგ "სამუდამოდ" დაკარგული commit-ები.
თუ git reset --hard გავაკეთე და მინდა უკან დაბრუნება, reflog ჩემი ერთადერთი მაშველია. Git-ის ისტორია წაშლილია, მაგრამ reflog ახსოვს სად იყო HEAD წინა მდგომარეობებში.
ძირითადი ბრძანებები
# ვიხილოთ HEAD-ის ისტორია
git reflog
# კონკრეტული ტოტის reflog
git reflog show main
# დროითი ფილტრი
git reflog --since="2 hours ago"
დაკარგული commit-ის აღდგენა
-
ვუშვებთ
git reflogნახავთ სიას:HEAD@{0},HEAD@{1}... — თითოეული მდგომარეობა. -
ვპოულობთ "დაკარგულ" მდგომარეობასმაგ.:
HEAD@{5}: commit: ჩემი მნიშვნელოვანი ცვლილება -
ვაბრუნებთ ან ცალკე ტოტზე ვიღებთ
git reset --hard HEAD@{5}ანgit checkout -b recovered HEAD@{5}
# reflog-დან აღდგენა
git reset --hard HEAD@{5}
# უსაფრთხო ვარიანტი — ცალკე ტოტი
git checkout -b recovered HEAD@{5}
ნაგულისხმევად 90 დღეში ხდება გასუფთავება (gc.reflogExpire). თუ უკვე გავიდა ბევრი დრო — შეიძლება ვეღარ აღვადგინოთ.
🔍 Bisect — Bug-ის ბინარული ძიება
Bisect არის ალგორითმი, რომელიც ბინარული ძიებით ყოფს commit-ების ისტორიას შუაზე და გვეხმარება ვიპოვოთ ის კონკრეტული commit, რომელმაც bug შემოიტანა. 1000 commit-ში — მაქსიმუმ 10 ნაბიჯში.
log₂(1000) ≈ 10. ანუ 1024 commit-ში მხოლოდ 10 ცდას სჭირდება bug-ის ლოკაციის დადგენა. ეს არის O(log n) ნაცვლად ხელით გასინჯვის O(n).
Bisect ნაბიჯ-ნაბიჯ
-
ვიწყებთ ძიებას
git bisect start -
ვაცხადებთ მიმდინარე (bug-იან) commit-ს ცუდად
git bisect bad— ანუ "აქ უკვე არსებობს bug". -
ვაცხადებთ ძველ (კარგ) commit-ს კარგად
git bisect good v1.0.0— "აქ ჯერ არ იყო bug". -
Git გვაჩვენებს შუა commit-სჩვენ ვტესტავთ — bug არის თუ არა? ვცხადებთ
git bisect goodანgit bisect bad. -
ვიმეორებთ მინი ცდასGit ცდის სანახევრო შუას, შემდეგ მისი შუას... სანამ მოძებნის zerk-ს commit-ს.
-
ვამთავრებთ
git bisect reset— დავუბრუნდეთ ჩვეულებრივ HEAD-ს.
სრული მაგალითი
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 თვითონ შეასრულებს ყველა ნაბიჯს:
git bisect start HEAD v1.0.0
git bisect run npm test
# Git ავტომატურად იპოვის bug-იან commit-ს! 🎯
📂 Sparse Checkout — ნაწილობრივი repo
დიდ monorepo-ებში (Google, Microsoft სტილი) ხშირად არ გვჭირდება ყველა ფაილი. Sparse checkout ეხმარება ჩამოვწეროთ მხოლოდ ის ფოლდერები, რომელზეც ვმუშაობთ. დანარჩენი ლოკალურად არ ჩანს.
2020 წელს გამოიცა git sparse-checkout ბრძანება, რომელიც ბევრად მარტივად აყენებს ამ კონფიგურაციას. ძველი core.sparseCheckout = true manual setup აღარ სჭირდება.
გამოყენება
# ვრთავთ 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 — დისკზე მინიმუმი, სიჩქარე მაქსიმუმი:
# 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-ი მყისიერია.
🪝 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/ ფოლდერში. შევქმნათ მარტივი:
#!/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-ში — გუნდის ყველა წევრი ერთ კონფიგს იყენებს:
npm install --save-dev husky
npx husky init
# ახლა ფაილი .husky/pre-commit ემსახურება ყველას
echo "npm test" > .husky/pre-commit
- lint-staged — მხოლოდ staged ფაილებს ალინტავს (სწრაფი)
- commitlint — Conventional Commits-ის შემოწმება
- pre-commit framework (Python) — multi-language hook manager
🕵️ Blame — რომელ ხაზს ვინ დაწერა
Blame აჩვენებს თითო ხაზის გვერდიდან ბოლო commit-ს — ვინ შეცვალა, როდის და რომელ commit-ში. სახელის მიუხედავად, ეს არის ყველაზე ნაყოფიერი ბრძანება ისტორიის გასაგებად — არა ვინმეს დასადანაშაულებლად.
# სრული 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-ებს არ აჩვენებს
GitLens (VS Code), JetBrains IDE და Sublime Merge ავტომატურად აჩვენებენ blame-ს ხაზის გვერდით — ბრძანების გაშვების გარეშე. რეალურ დროში ვხედავთ ვინმე ცოცხლობდა ამ ხაზს.
🛠️ Maintenance — Repo-ს ფონური ოპტიმიზაცია
Git 2.30+ (2021) დაამატა git maintenance — ბრძანება, რომელიც ფონურად აოპტიმიზებს repo-ს: ხდება gc, ახალდება commit-graph, prefetch-ი remote-დან. დიდი repo-ის სამუშაო სიჩქარე ბევრად უმჯობესდება.
ჩართვა და მართვა
# ჩართვა — ავტომატურად დადგება 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. შემდეგ კი დაელოდე — შესრულდება ფონურად, არ შეგიშლის ხელს.