Tracks changes in code over time.
Enables collaboration among multiple developers.
Helps revert or branch safely.
Local (e.g., RCS)
Centralized (e.g., SVN)
Distributed (e.g., Git)
A distributed version control system created by Linus Torvalds.
Every developer has a full copy of repo history.
Enables branching, merging, tagging, and rollback.
mkdir git-demo && cd git-demo git init git config --global user.name "Your Name" git config --global user.email "you@example.com" git config --list
echo "Hello world" > app.txt git add app.txt git commit -m "Initial commit"
Use git config --global only for personal identity; use repo-specific config (--local) for team projects.
git config --global
Configure your default branch name git config --global init.defaultBranch main.
git config --global init.defaultBranch main
Always verify your configuration: git config --list.
git config --list
When cloning, prefer SSH over HTTPS for secure access.
git status git log --oneline
git stash git stash list git stash pop
*.log node_modules/ .env
Make commits atomic — one logical change per commit.
Write meaningful commit messages:
Format: <type>(<scope>): <description> Example: fix(auth): handle null token error https://gist.github.com/qoomon/5dfcdf8eec66a051ecd85625518cfd13
command: git status
git status
git add
git commit
Regularly run git status to understand your state.
Understand .gitignore to prevent polluting the repo.
git branch feature/login git checkout feature/login git checkout -b feature/login
Merges different branches into one
git checkout main git merge feature/login
git merge --only-ff feature
git merge --no-ff feature
git merge
It is the default merging strategy of git.
A fast-forward merge happens when the branch you’re merging can be advanced directly to the tip of another branch — meaning there’s no divergent history.
mkdir ff-merge-demo cd ff-merge-demo git init echo "v1" > app.txt git add app.txt git commit -m "Initial commit"
git checkout -b feature-readme echo "This is README" > README.md git add README.md git commit -m "Add README file"
git checkout main git merge --ff-only feature-readme
git log --oneline --graph --decorate --all
There is no merge commit in history
By default, Git uses fast-forward (FF) merge if possible — meaning it simply moves the branch pointer forward without creating a new commit.
However, if you want to always create a merge commit, even when a fast-forward is possible, you use no-ff
Let’s create two branches like fast-forward merge but merge with different command
git merge --no-ff feature-branch -m "Merge feature-branch with --no-ff"
There will be merge commit in the history
A rebase merge is when you take the commits from a feature branch and replay them on top of another branch (usually main). This makes your commit history linear, unlike a normal merge that creates a merge commit.
main
mkdir rebase-merge-demo cd rebase-merge-demo git init
echo "Initial version" > app.txt git add app.txt git commit -m "Initial commit"
git checkout -b feature-login echo "Add login UI" >> app.txt git commit -am "Add login UI" echo "Add login validation" >> app.txt git commit -am "Add login validation"
git checkout main echo "Main branch update" >> app.txt git commit -am "Update from main branch"
git checkout feature-login git rebase main # Solve merge conflicts
git add app.txt git rebase --continue
git checkout main git merge feature-Login
A squash merge is a Git merge strategy that combines all commits from a branch into a single commit before adding them to the target branch.
mkdir squash-merge-demo cd squash-merge-demo git init
echo "Initial app setup" > app.txt git add app.txt git commit -m "Initial commit"
git checkout -b feature-login
echo "Add login page" >> app.txt git commit -am "Add login page" echo "Add login validation" >> app.txt git commit -am "Add login validation" echo "Fix login bug" >> app.txt git commit -am "Fix login bug"
git checkout main
git merge --squash feature-login git commit -m "Add login feature"
Protect main branches (main, develop) — restrict direct commits
Keep branch names descriptive: feature/login, fix/typo-readme, hotfix/security-patch
Avoid long-lived feature branches — merge frequently to reduce conflicts
A set of rules applied to Git branches to enforce safe development.
Prevents accidental changes to important branches like main or release.
Helps teams maintain code quality and workflow discipline.
One shared branch (e.g., main)
All developers push directly
Simple but risky
Branches:
main → stable
develop → ongoing work
develop
feature/* → new features
feature/*
release/* → prep for release
release/*
hotfix/* → quick fixes on main
hotfix/*
Protect production branches with rules (review required, CI checks).
Keep your main always deployable.
Enforce branch naming and PR templates via GitHub/GitLab rules
Git hooks are scripts that automatically run at specific points in the Git workflow, allowing you to automate tasks and enforce standards. They can be used for various actions, such as checking code quality before commits or sending notifications after pushes.
cd .git/hooks ls
mv pre-commit.sample pre-commit
Insert echo 'Hello World' in the script anywhere
echo 'Hello World'
Make a minor change and commit.
Observe that Hello World is displayed in the terminal output
Hello World
pre-commit
.pre-commit-config.yaml
Install pre-commit
pip install pre-commit
Create file .pre-commit-config.yaml with following contents
repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.6.0 hooks: - id: trailing-whitespace
Apply the config file
pre-commit install
Git tags are markers that point to specific commits in a Git repository's history, often used to signify important points like version releases.
git tag v1.0.0 git log --oneline git tag -d v1.0.0 # delete a tag
Create an empty repo on GitHub
Copy the URL
Add the URL as remote for the local git repo
git remote add origin <remote-url-name>
Push the local repo
git branch -M main git push -u origin main
Edit the global git config
git config –global -e
Include the following content in the global git config file
[includeIf "gitdir:/home/git-workship/project_1/**"] path = /home/git-workshop/project_1/.gitconfig [includeIf "gitdir:/hhome/git-workship/project_2/**"] path = /home/git-workshop/project_2/.gitconfig
[init] defaultBranch = main [core] editor = code --wait # opens vscode
[user] name = Jhon Doe email = jhon.doe@xyz.com signingkey = THIS_IS_MY_GPG_KEY [commit] gpgsign = true [tag] gpgsign = true
Build Validation means running automated checks (build, tests, linting, security scans, etc.) every time a Pull Request (PR) is created or updated — before the code is merged into the main branch.
Prevent broken code from being merged
Enforce team quality gates (tests, style, coverage)
Save review time — reviewers only see validated code
Automate feedback — developers know immediately if their PR fails
Step 1: Create a simple python app Step 2: Create a github workflow Step 3: Add a new feature branch and open PR Step 4: Observe build validation
mkdir build-validation-demo cd build-validation-demo git init echo "# Build Validation Demo" > README.md git add README.md git commit -m "Initial commit"
git remote add origin https://github.com/<your-username>/build-validation-demo.git git push -u origin main
mkdir app echo "def add(a, b): return a + b" > app/calculator.py
mkdir tests echo "from app.calculator import add def test_add(): assert add(2,3) == 5" > tests/test_calculator.py
echo 'pytest' > requirements.txt
git add . git commit -m "Add simple app and test" git push
mkdir -p .github/workflows nano .github/workflows/ci.yml
name: Build Validation on: pull_request: branches: [ main ] jobs: build: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: python-version: '3.11' - name: Install dependencies run: | pip install -r requirements.txt - name: Run tests run: | export PYTHONPATH=$PYTHONPATH:$(pwd) pytest -v
git push origin main
git checkout -b feature-bugfix echo "def multiply(a, b): return a * b" >> app/calculator.py git commit -am "Add multiply function" git push -u origin feature-bugfix
GitHub Actions will automatically run your CI workflow You’ll see a check like:
Build Validation — All checks have passed
If a test fails, you’ll see:
Build Validation — 1 failing test