
What lies inside Git?

655a20f99af32926cbf6d8fab092506ddd70e49cMainly:
Each object is identifiable by its SHA-1 hash.
cat .git/refs/heads/main
# 7c66409021358486e63d2d40c9b07e2c35e8124d
cat .git/refs/remotes/origin/dev
# c29dc332ac3eebebffc5726e16d0e91df170103f
cat .git/refs/tags/v2.6.3
# d49de0ec577052db3e47e2baf5aff0be738637acTip: In PowerShell, you can use gc (alias for Get-Content) instead of the cat command.
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 for a real projectpybrickz/.git β COMMIT_EDITMSG last commit message edited in the local repository β config local configuration, applies only to this repository β description don't worry about it β FETCH_HEAD remembers what was last fetched from the remote repository β HEAD pointer to the current branch/commit β index binary list of paths and SHA-1 hashes, view content with `git ls-files --stage` β ORIG_HEAD previous state of HEAD, set by commands with potentially dangerous behavior β packed-refs packed references (heads, tags) ββββhooks [β¦] ββββinfo [β¦] ββββlogs [β¦] ββββobjects [β¦] ββββrefs [β¦]
.git/objectspybrickz/.git β [β¦] ββββhooks [β¦] ββββinfo [β¦] ββββlogs [β¦] ββββobjects objects - blobs, trees, commits β ββββ00 β β 57f7cf16175d94fa850ad30918dffcd4cd850c β ββββ01 β β 4daec1e8a05a71852209c4caf9750bfe4717b1 ... β ββββfe β β 1c754ef352dece245b5f7a0d7047b048d7b1d9 β β 8a73f88812537678fde89e91c19c87623ff47c β ββββff β β 7e837bf1dc59b8835767fdcf789e308528498a β ββββinfo [β¦] β ββββpack [β¦] ββββrefs [β¦]
.git/refspybrickz/.git
β [β¦]
ββββhooks [β¦]
ββββinfo [β¦]
ββββlogs [β¦]
ββββobjects [β¦]
ββββrefs references - branches, remote branches, tags
ββββheads [β¦]
ββββremotes [β¦]
ββββtags [β¦]
.git/refs/headspybrickz/.git
β [β¦]
ββββhooks [β¦]
ββββinfo [β¦]
ββββlogs [β¦]
ββββobjects [β¦]
ββββrefs
ββββheads
β dev
β main
β staging
β ββββbugfix
β β bugfix-1 branch created via `git branch bugfix/bugfix-1`
β β bugfix-2 branch created via `git branch bugfix/bugfix-2`
β ββββfeature
β feature-A branch created via `git branch feature/feature-A`
β feature-B branch created via `git branch feature/feature-B`
ββββremotes [β¦]
ββββtags [β¦]
.git/refs/remotespybrickz/.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/tagspybrickz/.git
β [β¦]
ββββhooks [β¦]
ββββinfo [β¦]
ββββlogs [β¦]
ββββobjects [β¦]
ββββrefs
ββββheads [β¦]
ββββremotes [β¦]
ββββtags
v1.0.0
v1.0.1
...
v2.6.4
v2.7.0
.git/HEADHEAD is a pointer to the current branch or commitDETACHED HEAD is a situation where HEAD points to a commit that is not the head of a branch.git directory, find the file with the hash that the slovak branch points to.git rev-parse slovak command.git cat-file -p command multiple times, find out what content is in the hello.py file on the slovak branch.
-p.After cloning the repository, all the objects that Git uses are located in the .git/objects directory, but some of them may be packed in the pack directory.
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.revManual unpacking of objects is possible using the git unpack-objects command. However, if we use this command on the files from the previous example, nothing will happen. This is because Git will not unpack objects that are already in the repository. Therefore, before unpacking the objects, it is necessary to move them to another part of the repository.
# Move the files with packed objects to a temporary directory
mkdir temp; mv .git/objects/pack/* temp
# Unpack the objects
cat temp/*.pack | git unpack-objects
# Delete the temporary directory
rm -rf tempManual unpacking of objects is not necessary outside of experimentation.
In Git, there are two main ways to integrate changes from one branch into another: merge and rebase.
mergemain and feature) and their latest common ancestormergerebasefeature branch onto the main branch means moving the start of the feature branch to the end of the main branchfeature will be recreated on the main branchrebaserebase?git rebase on public or collaborative branches (especially main)rebase?mergegit 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
# ... resolve the conflict ...
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) - conflictgit log --oneline --graph --allMerge:
* 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 --onelineMerge (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-rebasezoo-merge repository:
origin/krokodil and origin/gorila branches into the local main branch using the git merge command.(continued on the next slide)
zoo-rebase repository:
gorila branch and rebase it onto the main branch using git rebase. Resolve any conflicts that arise.main branch and git merge the gorila branch into it.krokodil branch and rebase if onto the main branch using git rebase -i. Mark the middle commit as fixup. Resolve conflicts.main branch and git merge the krokodil branch into it.git log command to compare the state of both repositories.git merge --squash creates a single commit on the target branch.
Usage:
* 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
* f3492de (main) Squash french * d23ef42 Squash slovak * 54b75b3 Add docstring for default | * 437cd19 (slovak) Add docstring for slovak | * 5a92065 Fix slovak | * c1344d5 Add slovak |/ | * 0962e07 (french) Add docstring for french | * 7571e67 Add french |/ * de2c4ac Add hello.py * 944ce4e Initial commit
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
f3492de (main) Squash french d23ef42 Squash slovak 54b75b3 Add docstring for default de2c4ac Add hello.py 944ce4e Initial commit
After performing a squash merge, you should always delete the feature branch.
git revertgit revert HEAD # remove changes made in the last commit
git revert HEAD~1 # remove changes made in the second to last commit
git revert d49de0 # remove changes made in the commit with hash d49de0git revert creates a new version and does not change the repository history.
git resetgit reset --hard changes the repository history and can cause file loss.
reset vs revert vs checkout| Command | Context | Usage |
|---|---|---|
git reset |
Commit | Discard commits in a private branch or discard uncommitted changes |
git reset |
File | Remove a file from the staging area (from the index) |
git checkout |
Commit | Switch between branches or view old versions |
git checkout |
File | Discard changes in the working directory |
git revert |
Commit | Revert commits in a public branch |
git revert |
File | (N/A) |
git revert --no-commit $bad_commit # revert the commit, but do not save changes
git reset HEAD . # unstage the changes
git add --patch . # stage the changes that should be *reverted*
git commit # create a commit to revert those changes
git checkout -- . # discard changes that should not be revertedNote: The changes we add using the git add --patch command are the changes we want to revert, not the changes we want to keep.
Moving the last 3 commits from main to a new branch feature:
If the old commit has already been pushed to the remote, after using git commit --amend you need to push with git push --force or --force-with-lease.
If the old commit has already been pushed to the remote, after using git commit --amend you need to push with git push --force or --force-with-lease.
In Git, there are many different workflows that differ in how they use branching. In this chapter, we will show some of the most commonly used workflows and their advantages and disadvantages.
The Git Workflows Warehouse project contains a catalog of 50 workflows and also a useful list of resources.
main), no other branches are usedAdvantages:
Disadvantages:
Centralized workflow (Atlassian)
feature branches, which are then merged into the main branchAdvantages:
mainDisadvantages:
Git feature branch workflow (Atlassian)
feature branches are short-lived and frequently merged into the main branch (even several times a day)Advantages:
Disadvantages:
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, release, and hotfix branchesmain - production branchdevelop - development branchfeature - development of new featuresrelease - preparation for releasehotfix - fixing bugs in the production versionA successful Git branching model (Vincent Driessen)
Advantages:
Disadvantages:
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 mainrelease branch is created from developFeature branches are created from developfeature is complete it is merged into the develop branchrelease branch is done it is merged into develop and mainhotfix branch is created from mainhotfix is complete it is merged to both develop and main
Examples:
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 |