Čo sa skrýva vo vnútri Gitu?
655a20f99af32926cbf6d8fab092506ddd70e49c
Ide najmä o:
Každý objekt je identifikovateľný s pomocou svojho SHA-1 hashu.
cat .git/refs/heads/main
# 7c66409021358486e63d2d40c9b07e2c35e8124d
cat .git/refs/remotes/origin/dev
# c29dc332ac3eebebffc5726e16d0e91df170103f
cat .git/refs/tags/v2.6.3
# d49de0ec577052db3e47e2baf5aff0be738637ac
Tip: v powershelli môžeš namiesto príkazu cat
použiť gc
(alias pre Get-Content
)
Porcelain:
commit
, log
, merge
, pull
, push
, status
, …Plumbing:
cat-file
, commit-tree
, hash-object
, ls-files
, merge-base
, rev-parse
, ….git
tree.git
├── HEAD ref: refs/heads/main
├── index
├── objects
│ └── 59 blob [test.txt] 'version 1'
│ └── 4dc0e39bc4468ee19c67e65d37b97eb963b68b
│
│
│
│
│
│
│
│
│
│
│
│
│
│
│
│
└── refs
├── heads
|
└── tags
.git ├── HEAD ref: refs/heads/main ├── index ├── objects │ ├── 59 blob [test.txt] 'version 1' │ │ └── 4dc0e39bc4468ee19c67e65d37b97eb963b68b │ ├── 67 tree [blob 594d] │ │ └── 4d4d31b97233152f3be1825cc9e765fa2b2859 │ └── f8 commit [tree 674d] "First" │ └── 0a04ee3dfbeb5eb666ade615abc617c1ea20e3 │ │ │ │ │ │ │ │ │ │ │ │ └── refs ├── heads | └── main f80a... └── tags
.git ├── HEAD ref: refs/heads/main ├── index ├── objects │ ├── 59 blob [test.txt] 'version 1' │ │ └── 4dc0e39bc4468ee19c67e65d37b97eb963b68b │ ├── 67 tree [blob 594d] │ │ └── 4d4d31b97233152f3be1825cc9e765fa2b2859 │ ├── f8 commit [tree 674d] "First" │ │ └── 0a04ee3dfbeb5eb666ade615abc617c1ea20e3 │ ├── f0 blob [test.txt] 'version 2' │ │ └── d983103c610431663d84b3012d1b172f2f52ea │ ├── 37 tree [tree 674d, blob f0d9] │ │ └── 87931e43c8baf51f3ffafc44f6394651a505ca │ └── 53 commit [tree 3787, par. f80a] "Second" │ └── 9f7e662b0fa2ceb0df1dc9332179b06e5cdaec │ │ │ │ │ │ └── refs ├── heads | └── main 539f... └── tags
.git ├── HEAD ref: refs/heads/main ├── index ├── objects │ ├── 59 blob [test.txt] 'version 1' │ │ └── 4dc0e39bc4468ee19c67e65d37b97eb963b68b │ ├── 67 tree [blob 594d] │ │ └── 4d4d31b97233152f3be1825cc9e765fa2b2859 │ ├── f8 commit [tree 674d] "First" │ │ └── 0a04ee3dfbeb5eb666ade615abc617c1ea20e3 │ ├── f0 blob [test.txt] 'version 2' │ │ └── d983103c610431663d84b3012d1b172f2f52ea │ ├── 37 tree [tree 674d, blob f0d9] │ │ └── 87931e43c8baf51f3ffafc44f6394651a505ca │ ├── 53 commit [tree 3787, par. f80a] "Second" │ │ └── 9f7e662b0fa2ceb0df1dc9332179b06e5cdaec │ ├── dc blob [new.txt] 'new' │ │ └── 334bff12fb7d7404c79935fa3ba535c3bb28d0 │ ├── b0 tree [tree 674d, blob f0d9, blob dc33] │ │ └── ea95a512bad604278bcc96e8b8e726b462e010 │ └── 62 commit [tree b0ea, par. 539f] "Third" │ └── e37a96f8f09d0421644817dea320108ceac481 └── refs ├── heads | └── main 62e3... └── tags
.git
pre reálny projektpybrickz/.git │ COMMIT_EDITMSG posledný popis záznamu upravený v lokálnom repozitári │ config lokálna konfigurácia, aplikuje sa iba na tento repozitár │ description don't worry about it │ FETCH_HEAD pamätá si, čo bolo naposledy stiahnuté zo vzdialeného repozitára │ HEAD ukazovateľ na aktuálnu vetvu/commit │ index binárny zoznam ciest a SHA-1 hashov, obsah zobraz cez `git ls-files --stage` │ ORIG_HEAD predchádzajúci stav HEAD, nastavený príkazmi s potenciálne nebezpečným správaním │ packed-refs zabalené referencie (heads, tags) ├───hooks […] ├───info […] ├───logs […] ├───objects […] └───refs […]
.git/objects
pybrickz/.git │ […] ├───hooks […] ├───info […] ├───logs […] ├───objects objekty - bloby, stromy (trees), commity │ ├───00 │ │ 57f7cf16175d94fa850ad30918dffcd4cd850c │ ├───01 │ │ 4daec1e8a05a71852209c4caf9750bfe4717b1 ... │ ├───fe │ │ 1c754ef352dece245b5f7a0d7047b048d7b1d9 │ │ 8a73f88812537678fde89e91c19c87623ff47c │ ├───ff │ │ 7e837bf1dc59b8835767fdcf789e308528498a │ ├───info […] │ └───pack […] └───refs […]
.git/refs
pybrickz/.git │ […] ├───hooks […] ├───info […] ├───logs […] ├───objects […] └───refs referencie - vetvy, vzdialené vetvy, tagy ├───heads […] ├───remotes […] └───tags […]
.git/refs/heads
pybrickz/.git │ […] ├───hooks […] ├───info […] ├───logs […] ├───objects […] └───refs ├───heads │ dev │ main │ staging │ ├───bugfix │ │ bugfix-1 vetva vytvorená cez `git branch bugfix/bugfix-1` │ │ bugfix-2 vetva vytvorená cez `git branch bugfix/bugfix-2` │ └───feature │ feature-A vetva vytvorená cez `git branch feature/feature-A` │ feature-B vetva vytvorená cez `git branch feature/feature-B` ├───remotes […] └───tags […]
.git/refs/remotes
pybrickz/.git │ […] ├───hooks […] ├───info […] ├───logs […] ├───objects […] └───refs ├───heads […] ├───remotes │ ├───gh │ │ main │ └───origin │ │ dev │ │ HEAD │ │ main │ ├───bugfix │ │ bugfix-2 │ └───feature │ my-awesome-feature-A └───tags […]
.git/refs/tags
pybrickz/.git │ […] ├───hooks […] ├───info […] ├───logs […] ├───objects […] └───refs ├───heads […] ├───remotes […] └───tags v1.0.0 v1.0.1 ... v2.6.4 v2.7.0
.git/HEAD
HEAD
je ukazovateľ na aktuálnu vetvu alebo commitDETACHED HEAD
je situácia keď HEAD ukazuje na commit ktorý nie je hlavou vetvy.git
nájdi súbor s hashom na ktorý ukazuje vetva slovak
.git rev-parse slovak
.git cat-file -p
zisti aký obsah sa nacháda v súbore hello.py
na vetve slovak
.
-p
použi hash z predošlého kroku.Po naklonovaní repozitára sa v priečinku .git/objects
nachádzajú všetky objekty, ktoré Git používa, niektoré z nich však môžu byť zabalené v priečinku pack
.
git clone https://github.com/bbrrck/hello.git
cd hello
ls .git/objects
# .git/objects/info
# .git/objects/pack
ls .git/objects/pack
# .git/objects/pack/pack-48cae0e3bd98461308f23caeb2cfcc3df0b34da8.idx
# .git/objects/pack/pack-48cae0e3bd98461308f23caeb2cfcc3df0b34da8.pack
# .git/objects/pack/pack-48cae0e3bd98461308f23caeb2cfcc3df0b34da8.rev
Manuálne rozbalenie objektov je možné pomocou príkazu git unpack-objects. Ak však tento príkaz použijeme na súbory z predošlého príkladu, nič sa nestane. Je to preto, lebo Git nerozbalí objekty ktoré sa už nachádzajú v repozitári. Pred rozbalením objektov je preto potrebné ich najprv presunúť do inej časti repozitára.
# Presuň súbory so zabalenými objektami do dočasného priečinku
mkdir temp; mv .git/objects/pack/* temp
# Rozbaľ objekty
cat temp/*.pack | git unpack-objects
# Vymaž dočasný priečinok
rm -rf temp
Mimo experimentovania manuálne rozbaľovanie objektov nie je potrebné.
V Gite existujú dva hlavné spôsoby, ako integrovať zmeny z jednej vetvy do druhej: merge
a rebase
.
merge
main
a feature
) a ich najnovším spoločným predkommerge
rebase
feature
na vetvu main
znamená presunutie začiatku vetvy feature
na koniec vetvy main
feature
budú znova vytvorené na vetve main
rebase
rebase
?git rebase
na verejných alebo kolaboratívnych vetvách (najmä main
)rebase
?merge
git clone https://github.com/bbrrck/hello.git hello-merge; cd hello-merge
git merge origin/french
# Auto-merging hello.py
git merge origin/slovak
# CONFLICT (content): Merge conflict in hello.py
# ... vyrieš konflikt ...
git add .
git commit
# [main cef4a72] Merge remote-tracking branch 'origin/slovak'
rebase
(french)git clone https://github.com/bbrrck/hello.git hello-rebase; cd hello-rebase
git checkout french
git rebase main
# Successfully rebased and updated refs/heads/french.
git checkout main
git merge french
# Updating 0297280..5f6f019
# Fast-forward
# hello.py | 11 ++++++++++-
# 1 file changed, 10 insertions(+), 1 deletion(-)
rebase
(slovak) - konfliktgit log --oneline --graph --all
Merge:
* cef4a72 (main) Merge branch 'slovak' |\ | * 163a9c3 (slovak) Add docstring for slovak | * bd67d8d Fix slovak | * 75fcf88 Add slovak * | bc3f86b Merge branch 'french' |\ \ | * | a31caf9 (french) Add docstring for french | * | 6d348f3 Add french | |/ * / 0297280 Add docstring for default |/ * 4b4a8ad Add hello.py * 60d4d94 Initial commit
Rebase:
* ab2fda1 (main, slovak) Add docstring for slovak * 806b97a Add slovak * 5f6f019 (french) Add docstring for french * ea40a3b Add french * 0297280 Add docstring for default | * 163a9c3 Add docstring for slovak | * bd67d8d Fix slovak | * 75fcf88 Add slovak |/ | * a31caf9 Add docstring for french | * 6d348f3 Add french |/ * 4b4a8ad Add hello.py * 60d4d94 Initial commit
git log main --oneline
Merge (10):
cef4a72 (main) Merge branch 'slovak' bc3f86b Merge branch 'french' 0297280 Add docstring for default 163a9c3 (slovak) Add docstring for slovak bd67d8d Fix slovak 75fcf88 Add slovak a31caf9 (french) Add docstring for french 6d348f3 Add french 4b4a8ad Add hello.py 60d4d94 Initial commit
Rebase (7):
ab2fda1 (main, slovak) Add docstring for slovak 806b97a Add slovak 5f6f019 (french) Add docstring for french ea40a3b Add french 0297280 Add docstring for default 4b4a8ad Add hello.py 60d4d94 Initial commit
git clone https://github.com/bbrrck/zoo.git zoo-merge
git clone https://github.com/bbrrck/zoo.git zoo-rebase
zoo-merge
:
git merge
vetvy origin/krokodil
a origin/gorila
do lokálnej vetvy main
.(pokračovanie na ďalšom slajde)
zoo-rebase
:
gorila
a zlúč na ňu cez príkaz git rebase
vetvu main
. Vyrieš vzniknuté konflikty.main
a zlúč na ňu cez príkaz git merge
vetvu gorila
.krokodil
a zlúč na ňu cez príkaz git rebase -i
vetvu main
. Prostredný commit označ ako fixup
. Vyrieš vzniknuté konflikty.main
a zlúč na ňu cez príkaz git merge
vetvu krokodil
.git log
porovnaj stav oboch repozitárov.git revert
git revert HEAD # odstráň zmeny vykonané v poslednom commite
git revert HEAD~1 # odstráň zmeny vykonané v predposlednom commite
git revert d49de0 # odstráň zmeny vykonané v commite s hashom d49de0
Príkaz git revert
vytvorí novú verziu, a nemení históriu repozitára.
git reset
Príkaz git reset
mení históriu repozitára a môže spôsobiť stratu súborov.
reset
vs revert
vs checkout
Príkaz | Kontext | Použitie |
---|---|---|
git reset |
Commit | Zahoď commity v súkromnej vetve alebo zahoď necommitnuté zmeny |
git reset |
Súbor | Odstráň súbor z prípravnej zóny (z indexu) |
git checkout |
Commit | Presun medzi vetvami alebo prezeranie starých verzií |
git checkout |
Súbor | Zahoď zmeny v pracovnom adresári |
git revert |
Commit | Vráť commity vo verejnej vetve |
git revert |
Súbor | (N/A) |
git revert -n $bad_commit # vráť commit späť, ale neukladaj zmeny
git reset HEAD . # zruš pridanie zmien
git add --patch . # pridaj požadované zmeny
git commit # vytvor commit z týchto zmien
git checkout -- . # odstráň ostatné zmeny
Pozn.: Zmeny, ktoré pridávame pomocou príkazu git add --patch
, sú zmeny, ktoré chceme vrátiť späť, nie zmeny, ktoré chceme ponechať.
Presunutie posledných 3 commitov z main
na novú vetvu feature
:
Ak už bol starý commit pushnutý na remote, po použití git commit --amend
je potrebné pushnúť cez git push --force
alebo --force-with-lease
.
Ak už bol starý commit pushnutý na remote, po použití git commit --amend
je potrebné pushnúť cez git push --force
alebo --force-with-lease
.
V Gite existuje mnoho rôznych workflowov, ktoré sa líšia v tom, ako používajú vetvenie (branching). V tejto kapitole si ukážeme niekoľko najpoužívanejších workflowov a ich výhody a nevýhody.
Projekt Git Workflows Warehouse obsahuje katalóg 50-tich workflowov a tiež užitočný zoznam zdrojov.
main
), žiadne ďalšie vetvy sa nepoužívajúVýhody:
Nevýhody:
Centralized workflow (Atlassian)
feature
vetvách, ktoré sa následne zlučujú do main
vetvyVýhody:
main
Nevýhody:
Git feature branch workflow (Atlassian)
feature
vetvy sú krátke a často mergované do main
vetvy (aj niekoľkokrát denne)Výhody:
Nevýhody:
Feature-based deployment can be beneficial for teams that value the isolation of features and are willing to manage the complexities of merging these features back into the mainline. On the other hand, trunk-based deployment is suited for organizations that prioritize rapid integration and releases and have the infrastructure to manage continuous integrations and feature flags.
In recent years, with the rise of DevOps and agile methodologies, there’s been a clear trend towards more frequent integrations and releases. This trend has made trunk-based development, with its emphasis on rapid integration and release, increasingly popular among many tech giants and startups alike. However, as with all methodologies, it’s essential to evaluate the specific needs and capabilities of an organization before adopting a deployment strategy.
Feature-Based Deployment vs. Trunk-Based Deployment by John Nochowitz
develop
a release
, a hotfix
vetvymain
- produkčná vetvadevelop
- vývojová vetvafeature
- vývoj nových funkciírelease
- príprava na vydaniehotfix
- oprava chýb v produkčnej verziiA successful Git branching model (Vincent Driessen)
Výhody:
Nevýhody:
Gitflow is a legacy Git workflow that was originally a disruptive and novel strategy for managing Git branches. Gitflow has fallen in popularity in favor of trunk-based workflows, which are now considered best practices for modern continuous software development and DevOps practices. Gitflow also can be challenging to use with CI/CD.
Gitflow workflow (Atlassian)
The overall flow of Gitflow is:
develop
branch is created from main
release
branch is created from develop
Feature
branches are created from develop
feature
is complete it is merged into the develop
branchrelease
branch is done it is merged into develop
and main
hotfix
branch is created from main
hotfix
is complete it is merged to both develop
and main
Príklady:
Making a Pull Request (Atlassian)
ssh-keygen # use default settings
ssh-keygen -t rsa -C "[email protected]" # compatible with most git providers
ssh-keygen -t ed25519 -C "[email protected]" # compatible with GitHub
git gc
)en | sk |
---|---|
branch | vetva |
clone | naklonovanie repozitára |
commit | záznam |
commit message | popis záznamu |
conflict | konflikt medzi verziami |
conflict resolution | riešenie konfliktov |
diff | rozdiel medzi verziami |
merge | zlúčenie vetiev |
en | sk |
---|---|
pull | stiahnutie vzdialených zmien |
push | odoslanie lokálnych zmien |
repository | repozitár, úložisko |
remote | vzdialený repozitár |
snapshot | snímka |
staging area | prípravná oblasť (tiež index) |
status | stav repozitára |
version | verzia |