Git
Conventional Commits
| Type |
Meaning |
Usage |
SemVer Impact |
Example |
| feat |
A new user-visible feature |
New endpoint, new UI component, CLI option, etc. |
Minor (or Major if breaking) |
feat(search): add fuzzy matching |
| fix |
A bug fix |
Correct wrong logic, null checks, crash fixes, etc. |
Patch |
fix(parser): handle CRLF line endings |
| docs |
Documentation only |
README, API docs, comments |
None |
docs(readme): add install steps for openSUSE |
| style |
No logic change, formatting |
whitespace, semicolons, formatter |
None |
style: run clang-format |
| refactor |
Code change that neither fixes a bug nor adds a feature |
rename, restructure, extract function |
None (unless breaking) |
refactor(ui): split dashboard into widgets |
| perf |
Performance improvements |
reduce allocations, optimize query |
Path (or minor if user-facing behavior) |
perf(scanner): cut token allocs by 49% |
| test |
Add / modify tests |
unit / integration/ regression tests |
None |
test: add case for empty CSV |
| build |
Build system changes |
make / cmake / gradle compiler flags |
None |
build(cmake): cache vcpkg artifacts |
| ci |
Continuoous integration |
GitHub Actions, Jenkins, pipelines |
None |
ci: add matrix for macOS |
| chore |
Housekeeping |
bump tooling, rename files, no src change |
None |
chore: update editorconfig |
| revert |
Revert a previous commit |
rollback with reference |
Reverts prior impact |
revert: feat(search) add fuzzy matching |
| deps |
Dependency updates |
bump libs, lockfiles |
None / Patch (security fixes often Patch) |
deps: bump lodash to 4.17.21 |
| security |
Security fixes |
vulns, hardening |
Path (Major if breaking) |
security: sanitize user input |
Branches
- In Git, a branch is simply a pointer (a reference) to a specific commit in the repo history.
It allows you to develop features, fix bugs, or experiment independently from the main codebase.
- When you create a new Git repository, Git starts with a default branch (it is usually the branch that holds your production-ready code), commonly named:
main (modern default)
master (legacy / default in old versions)
- A new branch starts at the current commit and lets you diverge from there:
git checkout -b feature/new-api
# or (modern syntax)
git switch -c feature/new-api
This creates a new branch named feature/new-api starting from wherever you currently are (HEAD), and switches you to it.
- HEAD is Git's special pointer to your current branch or commit.
When you checkout a branch, HEAD points to that branch.
When you're in a detached HEAD state (e.g., on a specific commit), HEAD points directly to the commit hash.
- After a feature is merged, you often want to delete the branch:
git branch -d feature/new-ui # Local
git push origin --delete feature/new-ui # Remote
- Push a new branch to GitHub:
git push -u origin feature/x
- Pull a remote branch:
git fetch then git checkout feature/x
- List Branches:
git branch # local
git branch -r # remote
git branch -a # all
- General format of git branch naming:
<type>/<short-description>
<type>/<issue-number>-<short-description>
- Links youor current local branch to the remote-tracking branch:
# assuming you're in the local branch "feature/generic",
# and you wish to link it with the "feature/generic" in the origin remote repo.
git branch --set-upstream-to=origin/feature/generic
- Push a local branch to the remote and set upstream.
git checkout -b <branch-name>
git push -u origin <branch-name>
The Three Stages of Git
- Introduction
- Git is a distributed version control system that tracks changes to files over time.
- Every file in your Git repository is always in one of three main stages:
- Working Directory: your actual files on disk
- Staging Area (Index): files prepared for commit
- Repository: committed snapshots stored in
.git/
- The Three Stages Overview
| Stage |
Description |
Example Files |
| Working Directory |
Files you are editing right now |
modified.txt |
| Staging Area (Index) |
Files marked for the next commit |
added.txt |
| Repository |
Committed snapshots stored permanently |
.git/objects |
- 1. Working Directory (Untracked or Modified State)
- This is where you create, edit, delete, and modify files.
- The working directory shows:
- untracked files: Git doesn't know about them.
- modified files: Git knows them but they were changed.
- deleted files: files removed but not staged yet.
git status
Untracked files:
newfile.txt
Changes not staged for commit:
modified: README.md
- The working directory contains files before they are staged.
- To move files to the next stage, you must stage them.
- 2. Staging Area (Index)
- The staging area is a temporary holding place for files you want to include in your next commit.
- You stage files manually using:
git add filename
git add .
- After staging, changes move from the working directory to the index:
git status
Changes to be committed:
new file: newfile.txt
modified: README.md
- Only staged files are included in the next commit.
- The staging area allows building commits intentionally and selectively.
- 3. Repository (Local Git Database)
- Once you commit, changes are saved permanently into the local Git repository at
.git/.
- Committed files become part of Git history.
- Use:
git commit -m "message"
- Commits move staged files into the repository:
git log --oneline
a4c71f1 Add README and initial setup
- Files in the repository are versioned and safe.
- Undoing or retrieving them is easy.
- The Full Git Workflow with Example
# 1. You modify two files
echo "hello" >> a.txt
rm b.txt
# 2. You stage only one file
git add a.txt
# 3. You commit staged changes
git commit -m "Add hello to a.txt"
- Only
a.txt enters the repository.
b.txt remains in the working directory as a deletion.
- Visual Representation of the Stages
Working Directory --(git add)--> Staging Area --(git commit)--> Repository
- Commands Related to Each Stage
| Stage |
Action |
Command |
| Working Directory |
See changes |
git status |
| Staging Area |
Add file to staging |
git add file |
| Staging Area |
Unstage a file |
git restore --staged file |
| Repository |
Commit staged changes |
git commit -m "message" |
| Repository |
View history |
git log |
- Undoing in Each Stage
- Undo changes in working directory
git restore file.txt
git restore --staged file.txt
- Undo the last commit (keep changes)
git reset --soft HEAD~1
- Undo the last commit (throw away changes)
git reset --hard HEAD~1
- Summary of the Three Stages
| Stage |
State |
Command to Move Forward |
| Working Directory |
Editing files |
git add |
| Staging Area |
Preparing commit |
git commit |
| Repository |
Stored history |
git push (optional) |
Git Add and Git Rm
- Introduction
git add and git rm are two fundamental commands used to manage which file changes are included in the next commit.
git add moves file changes from the Working Directory to the Staging Area.
git rm removes files from both the Working Directory and the Staging Area.
- Common git add Commands
git add .
- Stages all changes in the current directory and subdirectories.
git add -A
- Stage all changes in the repository (added, modified, deleted).
git add -p
- Patch mode: interactively choose hunks to stage.
- Useful for creating clean, logical commits.
git add "*.txt"
- Stages all
.txt files using glob patterns.
- Staging Modified and Deleted Files
rm old.txt
git add old.txt
- If a file is removed manually via
rm, git add stages the deletion.
- git rm: Remove Files from Git
git rm removes files from the Working Directory and the Staging Area
- Use it when you want to delete a file and record that deletion in your next commit.
git rm file.txt
- Deletes
file.txt from disk
- Stages the deletion
- Common git rm Options
git rm --cached file.txt
- Removes file from Git but keeps the physical file on disk.
- Used when you accidentally commit something you want to keep locally (e.g., logs, environment files).
git rm -r docs/
- Removes a directory recursively.
git rm -f file.txt
- Forces removal, even if the file has modifications.
- Useful when file differs from last commit and Git blocks removal.
- Workflow Examples
- Example 1: Add a new file
echo "hello" > a.txt
git add a.txt
git commit -m "Add a.txt"
- Example 2: Delete a file using git rm
git rm old.txt
git commit -m "Remove old.txt"
- Example 3: Remove from Git, keep file on disk
git rm --cached secrets.env
echo "secrets.env" >> .gitignore
git commit -m "Stop tracking secrets.env"
- Example 4: Unstage a file added by mistake
git add largefile.zip
git restore --staged largefile.zip
- Comparison Summary
| Command |
Purpose |
Modifies Disk? |
Modifies Index? |
git add file |
Stage file modifications |
No |
Yes |
git add -A |
Stage all changes |
No |
Yes |
git rm file |
Delete file, stage deletion |
Yes |
Yes |
git rm --cached file |
Remove from git, keep file |
No |
Yes |
Git Stash
- Introduction
git stash temporarily saves your uncommitted changes without creating a commit.
- Stashes are stored in a stack, and you can apply or inspect them later.
- Basic Usage: Saving Changes
git stash
- Moves modified and staged changes into a stash entry.
- Resets your working directory to a clean state.
git stash save "WIP: working on login feature"
- Adds a message to identify the stash entry.
- Saving Untracked Files
git stash -u
- Saves both tracked and untracked files.
git stash -a
- Saves all changes including ignored files.
- Listing Stashes
git stash list
stash@{0}: WIP on feature/login
stash@{1}: WIP: fixing UI
stash@{2}: WIP: initial setup
- Stashes are stored in a stack-like structure.
- Applying Stashes
git stash apply
- Applies the most recent stash but does not remove it from the stash list.
git stash apply stash@{2}
- Applies a specific stash entry.
- Applying and Removing a Stash (Pop)
git stash pop
- Applies the most recent stash and removes it from the list.
- Equivalent to: apply + remove
git stash pop stash@{1}
- Dropping a Stash Entry
git stash drop stash@{0}
- Deletes a stash entry permanently.
git stash clear
- Deletes all stash entries.
- Stashing Only Staged Changes
git stash --staged
- Saves only staged changes, leaving working directory untouched.
- Stashing Only Specific Files
git stash -m "WIP: styling" css/style.css
- Stashes only the provided file(s).
- Showing the Contents of a Stash
git stash show
- Shows which files were changed.
git stash show -p stash@{1}
- Shows the full diff patch.
- Creating a Branch from a Stash
git stash branch feature/login-fix stash@{0}
- Creates a new branch with changes applied.
- Useful if the stash contains large or important work.
- Automatically drops the stash after application.
- Handling Merge Conflicts During Pop/Apply
git stash pop
# conflict markers appear
- If conflicts appear:
- resolve them manually
- then stage resolved files
- and commit or continue working
stash pop will not delete the stash if conflicts occur.
- Common Stash Workflow Examples
- Example 1: Save work, switch branch, restore
git stash
git switch main
git pull
git switch feature/login
git stash pop
- Example 2: Stashing new files
git stash -u
- Example 3: Stash one file only
git stash push -m "partial fix" app.js
- Example 4: Create a branch from a stash
git stash branch hotfix stash@{1}
- Summary of git stash Commands
| Command |
Description |
git stash |
Save tracked modified files |
git stash -u |
Save tracked + untracked files |
git stash apply |
Apply stash without removing |
git stash pop |
Apply and remove stash |
git stash list |
Show all stash entries |
git stash show -p |
Show stash diff |
git stash drop |
Delete one stash entry |
git stash clear |
Delete all stashes |
git stash branch name stash@{n} |
Create branch with stashed changes applied |
Git Merge
- Introduction
git merge combines the history of one branch into another.
- Merging is non-destructive:
- it does not rewrite commit history
- it creates a new commit (merge commit) when needed
- Basic Merge Example
git switch main
git merge feature/login
- This merges the
feature/login branch into main.
- If no conflicts and histories diverged, Git creates a merge commit.
- Fast-Forward Merge
git merge feature/ui
- If
main has not diverged, Git simply moves the branch pointer forward.
- No merge commit is created.
# Before:
main --- A --- B
\
(feature)
# After fast-forward merge:
main --- A --- B (feature merged)
- Forcing a Merge Commit (No Fast-Forward)
git merge --no-ff feature/login
- This forces Git to create a merge commit even if fast-forward is possible.
- Useful for:
- Preserving branch history
- Code review traceability
- More readable merges
- Fast-Forward vs Merge Commit
| Type |
Git Behavior |
Usage |
| Fast-forward |
Moves branch pointer; no merge commit |
Simple linear history |
| Merge commit |
Creates a commit that joins histories |
Feature branch workflow |
- Checking Merge Status
git status
- Shows whether you are in the middle of a merge.
git log --oneline --graph --decorate
- Shows merge commits visually.
- Merge Conflicts
- A conflict occurs when two branches modify the same part of a file.
git merge feature/login
# CONFLICT (content): Merge conflict in src/app.js
- Conflict markers appear inside the file:
<<<<<<< HEAD
current branch code
=======
incoming branch code
>>>>>>> feature/login
- To resolve conflicts:
- edit the file
- remove conflict markers
- keep the correct version
- stage and commit
git add src/app.js
git commit
- Git automatically creates the merge commit.
- Aborting a Merge
git merge --abort
- Useful if merge goes wrong or conflicts are difficult to fix.
- Restores the repository to the state before merge began.
- Squash Merging
git merge --squash feature/api
git commit -m "Add API feature"
- Combines all feature branch commits into a single commit.
- Does not retain branch history.
- Does not create a merge commit.
- Merge vs Rebase (Conceptual)
| Operation |
Description |
History Style |
| Merge |
Joins two histories with a merge commit |
Non-linear |
| Rebase |
Replays your commits on top of another branch |
Linear |
- Merging keeps branch structure, rebasing rewrites history.
- Common Merge Workflow
- Example: Merge feature branch into main
git switch main
git pull
git merge feature/cart
git push
- Example: Bring latest main changes into feature branch
git switch feature/cart
git merge main
- Example: Merge without fast-forward
git merge --no-ff feature/cart
- Summary of Git Merge Options
| Command |
Description |
git merge branch |
Merge branch into current branch |
git merge --no-ff branch |
Force merge commit even if fast-forward is possible |
git merge --squash branch |
Merge changes as one commit (no merge commit) |
git merge --abort |
Cancel merge and restore previous state |
Git Fetch vs Git Pull
- Introduction
- Both
git fetch and git pull are used to get changes from a remote repository (e.g., GitHub) into your local repository.
- The key difference:
git fetch only downloads changes from remote; it does not modify your current branch.
git pull downloads changes and immediately integrates them into your current branch (via merge or rebase).
- How Git Stores Remote Changes
- When working with remotes, Git uses remote-tracking branches, such as:
origin/main
origin/feature/login
- Your local branch (e.g.
main) usually tracks a remote branch (e.g. origin/main).
git fetch updates these remote-tracking branches.
git pull updates them and tries to bring your current branch up to date as well.
- git fetch: Download Only
- Fetch changes from the default remote (
origin):
git fetch
- Fetch from a specific remote and branch:
git fetch origin main
- What happens after
git fetch:
- New commits are downloaded to your local
.git database.
- Remote-tracking branches like
origin/main are updated.
- Your current branch (e.g.
main) remains unchanged.
- You can now inspect the changes before merging:
git log HEAD..origin/main --oneline
git diff HEAD..origin/main
- Typical usage: safe way to see what others pushed without touching your working tree.
- git pull: Fetch + Integrate
git fetch
git merge origin/<your-branch>
git pull
- If your current branch tracks
origin/main:
- Git fetches new commits from
origin.
- Then merges
origin/main into your local main.
- This may create a merge commit or cause merge conflicts.
- You can also tell Git to rebase instead of merge:
git pull --rebase
git fetch
git rebase origin/<your-branch>
- Typical usage: quickly bring your branch up to date when you are comfortable with merge/rebase happening immediately.
- Step-by-Step Comparison
| Aspect |
git fetch |
git pull |
| Updates remote-tracking branches? |
Yes |
Yes |
| Updates current local branch? |
No |
Yes (merge or rebase) |
| Risk of merge conflicts right away? |
No (nothing merged yet) |
Yes (integration happens immediately) |
| Good for reviewing incoming changes? |
Excellent |
Possible, but history already changed |
| Typical use case |
Inspect, compare, then decide how to merge |
Fast update to latest remote state |
- Example: Using git fetch for Safe Updates
# 1. Download changes only
git fetch origin
# 2. See what changed on origin/main
git log HEAD..origin/main --oneline
# 3. Merge (or rebase) when you're ready
git merge origin/main
# or
git rebase origin/main
- Advantages:
- You stay in control of when and how history is integrated.
- You can avoid surprises or conflicts while you are in the middle of work.
- Example: Quick Update with git pull
# On branch main, tracking origin/main
git pull
- If there are no conflicts, your
main is now at the same commit as origin/main.
- For linear history lovers:
git pull --rebase
- This rewrites your local commits on top of the latest remote commits.
- When to Use Which?
- Prefer
git fetch when:
- You want to review incoming changes before integrating.
- You are in the middle of something and do not want merge conflicts now.
- You are debugging or inspecting remote history.
- Prefer
git pull when:
- You simply want your branch up to date with the remote.
- You are okay with Git performing merge or rebase automatically.
- You are in a clean working state (no uncommitted local changes).
- Common Aliases and Configs
- Some people configure Git to always rebase on pull:
git config --global pull.rebase true
- Or define aliases to remind themselves of the difference:
git config --global alias.fp "fetch --prune"
git config --global alias.pl "pull --rebase"
- Summary
| Command |
What it does |
Mental Model |
git fetch |
Download changes from remote, update origin/* branches, leave your current branch untouched. |
"Update my knowledge of the remote, but do not touch my work." |
git pull |
Fetch changes and immediately integrate them into the current branch by merge or rebase. |
"Download and merge now." |
Git Remote
- Introduction
- A
remote in Git is a reference (a named pointer) to another repository, usually hosted online (e.g., GitHub, GitLab, Bitbucket).
- Remotes let your local repository communicate by:
- fetching new commits
- pushing your commits
- tracking branches on the remote server
- The default remote is usually named
origin.
- Viewing Existing Remotes
git remote
git remote -v
- Shows remote names and their URLs (fetch + push URLs).
origin https://github.com/user/repo.git (fetch)
origin https://github.com/user/repo.git (push)
- Adding a Remote
- Add a remote repository named
origin:
git remote add origin https://github.com/user/repo.git
- Common use when:
- You cloned from local folder and want to connect it online.
- You want to work with multiple remotes.
- Removing a Remote
git remote remove origin
- Deletes the reference to the remote repository.
- This does not delete local branches or commits.
git remote rm origin
- Alias for the same action.
- Renaming a Remote
git remote rename origin upstream
- Useful when working with forked repositories:
- Changing the URL of a Remote
git remote set-url origin https://github.com/newuser/newrepo.git
- Required when:
- You renamed your GitHub repository.
- You changed HTTPS → SSH or vice versa.
git remote set-url origin git@github.com:user/repo.git
- Fetching From a Remote
git fetch
- Fetch from a specific remote:
git fetch origin
- This updates remote-tracking branches (e.g.
origin/main) but does NOT touch your local branches.
- Pushing to a Remote
git push origin main
- Pushes your local
main branch to origin/main.
git push -u origin feature/api
- Creates the branch on the remote and sets upstream tracking.
- Inspecting a Remote in Detail
git remote show origin
- This displays:
- Remote URL
- Tracked branches
- Local→remote branch relationships
- Push & fetch configuration
* remote origin
Fetch URL: https://github.com/user/repo.git
Push URL: https://github.com/user/repo.git
HEAD branch: main
Local branches configured for 'git pull':
main merges with remote main
- Working With Multiple Remotes
- You can have more than one remote:
origin: your GitHub repo
upstream: original project
backup: a mirrored backup
- Add upstream:
git remote add upstream https://github.com/original/project.git
- Fetch upstream’s changes:
git fetch upstream
- Merge upstream into your main branch:
git merge upstream/main
- Removing Orphaned Remote Branch References
- If a branch was deleted on the remote, your local
origin/branch reference remains until cleanup.
git fetch --prune
- This removes remote-tracking branches that no longer exist on the server.
- Summary Table
| Command |
Purpose |
git remote -v |
Show all remotes with their URLs. |
git remote add name url |
Add a new remote. |
git remote remove name |
Remove an existing remote. |
git remote rename old new |
Rename a remote. |
git remote set-url name url |
Change the URL of a remote. |
git remote show name |
Inspect remote details. |
git fetch name |
Download new commits from the remote. |
git push name branch |
Upload local commits to the remote. |
git fetch --prune |
Remove stale remote-tracking branches. |
Git Config
- Introduction
git config is the command used to view, edit, and manage Git configuration settings.
- These settings control Git’s behavior, identity, colors, default editor, merge tool, aliases, and much more.
- Git has 3 levels of configuration:
- System: applies to all users on the system (e.g.,
/etc/gitconfig)
- Global: applies to the current user (e.g.,
~/.gitconfig)
- Local: applies only to the current repository (
.git/config)
- Configuration levels override each other in this order:
- Viewing Configuration
git config --list
- Displays all configuration values Git sees (local + global + system).
git config --global --list
- Shows only global-level config.
git config --get user.name
- Shows a specific configuration value.
git config --show-origin user.email
- Shows where a setting came from (useful for debugging).
- Setting Up Identity
- These must be set before making commits:
git config --global user.name "Your Name"
git config --global user.email "username@example.com"
- The
--global flag writes to ~/.gitconfig.
git config user.name "Local Repo Name"
- Sets identity only for the current repository.
- Editing Configuration Files Directly
git config --global --edit
- Opens
~/.gitconfig in your default editor.
git config --local --edit
- Opens
.git/config in the current project.
- Configuring the Default Editor
git config --global core.editor "nvim"
- Sets the editor used for commit messages and merges.
git config --global core.editor "code --wait"
- VS Code example: waits until the window closes.
- Configuring Default Branch Name
git config --global init.defaultBranch main
- Ensures newly created repos use
main instead of master.
- Configuring Line Endings
git config --global core.autocrlf input
input – convert CRLF to LF on commit (recommended for macOS/Linux).
git config --global core.autocrlf true
true – checkout CRLF, commit LF (for Windows).
- Aliases: Custom Git Commands
- Aliases shorten long commands:
git config --global alias.st "status"
git config --global alias.co "checkout"
git config --global alias.br "branch"
git config --global alias.ci "commit"
git config --global alias.lg "log --oneline --graph --decorate --all"
git lg
- Configuring Merge & Diff Tools
- To use an external merge tool:
git config --global merge.tool vimdiff
git config --global mergetool.keepBackup false
- To set diff tool (example: VS Code):
git config --global diff.tool vscode
git config --global difftool.vscode.cmd "code --wait --diff $LOCAL $REMOTE"
- Configure Pull Behavior (Merge vs Rebase)
git config --global pull.rebase false
git config --global pull.rebase true
- Use rebase instead of merge for
git pull.
- Configuring Push Behavior
- Push only the current branch (recommended modern behavior):
git config --global push.default current
- Other options:
simple – safe default
upstream – push to the upstream branch
matching – push all matching branch names (dangerous)
- Enabling Colored Output
git config --global color.ui auto
- Makes Git output more readable with colors.
git config --global color.diff auto
git config --global color.status auto
git config --global color.branch auto
- Configuring Credential Caching
- Cache credentials temporarily:
git config --global credential.helper cache
git config --global credential.helper "cache --timeout=3600"
- Store credentials permanently (not recommended):
git config --global credential.helper store
- Configuring HTTPS vs SSH
git config --global url."ssh://git@github.com/".insteadOf "https://github.com/"
- Now any HTTPS GitHub URL automatically becomes SSH.
- Unsetting (Removing) a Config Value
git config --global --unset user.email
- Removes the value from the config file.
git config --unset-all alias.lg
- Removes all entries with that name.
- Summary
| Command |
Purpose |
git config --list |
View all effective config values. |
git config --global user.name |
Set username globally. |
git config --edit |
Edit config file using editor. |
git config --global alias.xxx |
Create a custom shorthand command. |
git config --global core.editor |
Set default editor. |
git config --global pull.rebase true |
Make git pull use rebase by default. |
git config --unset key |
Remove a config value. |
git config --show-origin key |
Show where config was defined. |