Git Commands We Should Know
Useful Git Commands
- Uninitialize Git repository
cd path/to/repo
rm -rf .git
- To see your initialized Git user locally
git config --list
- Drop all the changes
git stash -u && git stash drop
-
Stash your changes:
git stashThis command saves your local modifications and reverts the working directory to match the HEAD commit.
-
Pop the most recent stash:
git stash popThis command applies the changes from the most recent stash and removes it from the stash list.
-
Apply the most recent stash:
git stash applyThis command applies the changes from the most recent stash but keeps the stash in the stash list.
These commands will operate on the most recent stash without needing to specify stash@{0}.
-
Stash your changes with a message:
git stash push -m "my_stash_name" -
List your stashes to see the stash you just created:
git stash listYou will see an output similar to:
stash@{0}: On branch_name: my_stash_name -
Apply the stash:
git stash apply stash@{0}Replace
stash@{0}with the appropriate stash reference if it's not the most recent one. -
Or pop the stash (apply and remove from stash list):
git stash pop stash@{0}
Again, replace stash@{0} with the correct reference if needed.
Using apply will keep the stash in the list, while pop will remove it after applying.
- Create a new branch from the stash:
git stash branch <branch-name>
Replace <branch-name> with the desired name for your new branch. This command will create a new branch, apply the stashed changes, and drop the stash.
git checkout vs git switch
Both git switch and git checkout can be used to switch branches in Git, but git switch is a newer and more focused command introduced to simplify branch switching. Here are the differences and usage examples:
The git checkout command is versatile and can be used for various purposes, including switching branches, creating new branches, and checking out specific commits or files. However, its versatility can sometimes make it confusing.
- Switch to an existing branch:
git checkout branch-name
- Create and switch to a new branch:
git checkout -b new-branch-name
The git switch command is specifically designed for switching branches, making it more intuitive for this purpose. It does not support all the functionalities of git checkout.
- Switch to an existing branch:
git switch branch-name
- Create and switch to a new branch:
git switch -c new-branch-name
- Use
git switchfor a more straightforward and focused way to switch branches. - Use
git checkoutif you need its additional functionalities, such as checking out specific commits or files.
For most branch switching tasks, git switch is recommended for its simplicity and clarity.
The git log command is used to view the commit history of a Git repository. It shows a list of commits, including their hashes, author information, dates, and commit messages. Here are some common options and their differences:
- Basic
git log:
git log
This command shows the commit history in a simple format.
git log --oneline:
git log --oneline
This command shows the commit history in a condensed format, with each commit on a single line. It displays the commit hash and the commit message.
git log --graph:
git log --graph
This command shows the commit history as a graph, which is useful for visualizing branch and merge history.
git log --stat:
git log --stat
This command shows the commit history along with a summary of changes made in each commit (files changed, insertions, and deletions).
git log -p:
git log -p
This command shows the commit history along with the actual changes (diffs) made in each commit.
git log --author="Author Name":
git log --author="Author Name"
This command filters the commit history to show only commits made by a specific author.
git log --since="2022-01-01":
git log --since="2022-01-01"
This command filters the commit history to show only commits made since a specific date.
git log --until="2022-12-31":
git log --until="2022-12-31"
This command filters the commit history to show only commits made until a specific date.
git log --grep="keyword":
git log --grep="keyword"
This command filters the commit history to show only commits with messages containing a specific keyword.
-
Combining options:
git log --oneline --graph --decorate --allThis command combines multiple options to show a decorated graph of the commit history, with each commit on a single line, including all branches.
-
Compact graph view for recent commits:
git log --graph --oneline --decorate --all --max-count=15This is one of the most useful commands for quickly understanding a repository's recent history.
--graphdraws the branch and merge structure using ASCII lines.--onelineshows each commit in a short single-line format.--decorateshows branch names, tags, and remote references beside commits.--allincludes all branches, not just the current branch.--max-count=15limits the output to the latest 15 commits, so the view stays readable.
Use it when you want to quickly see where branches split, where they merged, and which commit belongs to which branch.
Related useful commands:
git log --graph --oneline --decorate --allShows the full decorated graph for all branches.
git log --graph --oneline --decorate --all --max-count=30Same graph view, but with the latest 30 commits.
git log --graph --oneline --decorate --branchesShows the graph for local branches only.
git log --graph --oneline --decorate --remotesShows the graph for remote-tracking branches.
git log --graph --oneline --decorate --all --author="Author Name"Shows the graph filtered by author.
git log --graph --oneline --decorate --all --since="2 weeks ago"Shows recent branch history from the last two weeks.
These options allow you to customize the output of git log to suit your needs and make it easier to navigate and understand the commit history.
Here are the basic Git commands to check the status of your repository, add changes to the staging area, and commit them:
- Check the status of your repository:
git status
This command will show you the current state of your working directory and staging area, including any changes that have been made, files that are staged for commit, and untracked files.
- Add changes to the staging area & unstaging
git add <file>
Replace <file> with the path to the file you want to stage. For example, to stage the index.html file:
git add src/index.html
To stage all changes in the repository, you can use:
git add .
To Unstage all files
git restore --staged .
Unstage the specific file
git restore --staged src/index.html
- Commit the staged changes:
git commit -m "Your commit message"
Replace "Your commit message" with a meaningful message describing the changes you made. For example:
git commit -m "Update index.html with systemjs-importmap and preload link"
- Switch to the specific commit in detached HEAD state:
git switch --detach <commit-hash>
Replace <commit-hash> with the hash of the commit you want to switch to. You can inspect the state of the repository at a specific commit without creating a new branch. This is useful for debugging or reviewing the code at a particular point in time.
In a detached HEAD state, you can make changes and commit them, but these commits will not belong to any branch. If you want to keep these changes, you should create a new branch:
- Create a new branch from the detached HEAD state:
git switch -c new-branch-name
Replace new-branch-name with the desired name for your new branch. This will create a new branch and move your changes to it.
git mergeis used to combine the changes from one branch into another. Depending on the branch history, Git may perform a fast-forward or create a merge commit.
git checkout main
git merge feature-branch
For a safer promotion flow where you want to ensure the target branch only moves forward without creating an unexpected merge commit, use:
git merge --ff-only feature-branch
--ff-only succeeds only when the current branch can be moved directly to the source branch commit. If the branches have diverged, Git stops instead of creating a merge commit.
- git rebase is a powerful Git command that allows you to move or combine a sequence of commits to a new base commit. It is often used to keep a linear commit history and to integrate changes from one branch into another.
git checkout feature-branch
git rebase main
- This command will rebase the feature-branch onto the main branch. It effectively takes the commits from feature-branch and re-applies them on top of the latest commit in main.
- During the rebase process, you might encounter conflicts. Git will pause the rebase and prompt you to resolve the conflicts.
- Identify conflicted files by
git status
- Resolve conflicts manually or accept incoming changes:
git checkout --theirs <file>
git add <file>
- Resolve conflicts manually or ignoring incoming changes/ keeping current changes:
git checkout --ours <file>
git add <file>
- Continue with the rebase:
git rebase --continue
This command tells Git to continue the rebase process after resolving the conflicts.
- Abort the rebase (if needed): If you want to stop the rebase process and return to the original state, you can use:
git rebase --abort
git merge --squashis used to combine the changes from one branch into another, but it does not create a merge commit. Instead, it squashes all the changes into a single commit.
git checkout main
git merge --squash feature-branch
- Pull changes from the remote
masterbranch to the currently checked-out branch
git pull origin master
git pull origin master does not switch you to master and update your local master branch automatically.
For example, if you are currently on feature/my-work, this command fetches origin/master and merges it into feature/my-work.
If your intention is to update your local master, first switch to it:
git switch master
git pull origin master
If you only want to download the latest remote information without changing your current branch, use:
git fetch origin
Or fetch only one remote branch:
git fetch origin master
- Check the differences between the working directory and the staging area:
git diff
- Check the differences between the staging area and the last commit:
git diff --staged
- Useful Git Commands for Remote URLs
-
Show current remote URLs:
git remote -vThis lists all remotes and their fetch/push URLs.
-
Set or change the remote URL:
git remote set-url <remote_name> <new_url>Example:
git remote set-url origin https://github.com/username/repo.git -
Add a new remote:
git remote add <remote_name> <url>Example:
git remote add upstream https://github.com/otheruser/repo.git -
Remove a remote:
git remote remove <remote_name>Example:
git remote remove upstream -
Rename a remote:
git remote rename <old_name> <new_name>Example:
git remote rename origin upstream -
Show detailed info about a remote:
git remote show <remote_name>Example:
git remote show origin
Breakdown of git pull origin master
-
Fetch Changes: The command first fetches the latest changes from the
masterbranch of the remote repository namedorigin. This updates your local copy of the remote branch.git fetch origin master -
Merge Changes: After fetching the changes, it merges the
masterbranch from the remote repository into your current branch. This integrates the changes from the remotemasterbranch into your working branch.git merge origin/master
Forking in Git: Contributing to Repositories You Don't Own
In Git (and especially on platforms like GitHub), forking is needed when you want to contribute to a repository you do not own or do not have write access to.
Why can't you just create a branch in someone else's repo?
- You cannot create branches directly in a repository unless you have write access (are a collaborator or member).
- Most open source projects do not give write access to everyone for security and quality reasons.
What does a fork do?
- Fork creates a copy of the original repository under your own GitHub account.
- In your fork, you have full control: you can create branches, make changes, and commit freely.
How does fork help you contribute?
- Fork the repository (creates your own copy).
- Clone your fork locally.
- Create a branch in your fork, make changes, and commit.
- Push the branch to your fork on GitHub.
- Open a Pull Request (PR) from your branch (in your fork) to the original repository’s branch (usually
masterormain).
How does merging work?
- The repository owner reviews your PR.
- If approved, they merge your changes into the original repo’s master/main branch.
Summary Table
| Without Fork | With Fork |
|---|---|
| No write access to other's repo | Full control in your fork |
| Can't create branches | Can create branches |
| Can't push changes | Can push changes |
| Can't open PRs from branches | Can open PRs from fork to original repo |
In short:
A fork lets you propose changes to someone else’s repository by giving you your own copy to work in, and then you use a pull request to ask the original repo to merge your changes.
Cloning Guide
- Clone only the remote primary HEAD (default: origin/master)
git clone <url> --single-branch
- Only specific branch
git clone <url> --branch <branch> --single-branch [<folder>]
git clone <url> --branch <branch>
-
Cloning repositories using degit
- main branch is default.
npx degit github:user/repo#branch-name <folder-name>
Git Merge, Rebase, and Squash: Differences Explained
Git Merge
git merge is used to combine the changes from one branch into another. It creates a new "merge commit" that records the history of both branches.
Example:
git checkout main
git merge feature-branch
- The changes from
feature-branchare merged intomain. - A merge commit is created if there are new commits on both branches.
Git Rebase
git rebase moves or combines a sequence of commits to a new base commit. It rewrites commit history by placing your branch’s commits on top of another branch.
Rebase Explained with an Analogy
Imagine you are writing a paragraph for a report. While you are writing, someone else updates the report with new lines.
git rebase lets you move your paragraph to the end of the latest version of the report, so it looks like you wrote it after those new lines.
Visual Example
-
Before rebase:
A → B (main branch)
A → B (main)
\
C → D (feature) -
Main branch gets new commits:
A → B → E → F (main)
\
C → D (your branch is outdated now) -
After rebase:
A → B → E → F → C' → D' (rebased feature branch)
Mermaid Diagram
Example:
git checkout feature-branch
git rebase main
- The commits from
feature-branchare reapplied on top of the latest commit inmain. - Results in a linear history, but can rewrite commit hashes.
Git Squash
Squashing means combining multiple commits into a single commit.
You can squash commits during an interactive rebase or with git merge --squash.
Example (interactive rebase):
git rebase -i HEAD~3
- The above command starts an interactive rebase for the last 3 commits on your current branch.
Example editor view:
pick 1234567 Commit message 1
pick 89abcde Commit message 2
pick fedcba9 Commit message 3
-
You can choose actions for each commit:
pick(keep as is)reword(change commit message)edit(change the commit itself)squash(combine with previous commit)drop(remove the commit)
-
In the editor, change
picktosquashorsfor the commits you want to squash. -
The selected commits will be combined into one.
Example (merge squash):
git checkout main
git merge --squash feature-branch
git commit -m "Squashed changes from feature-branch"
- All changes from
feature-branchare staged as a single commit onmain. - No merge commit is created; the branch history is not preserved.
Differences Table
| Command | Combines Changes | Commit History | Merge Commit | Linear History | Use Case |
|---|---|---|---|---|---|
git merge | Yes | Preserved | Yes | No | Standard branch integration |
git rebase | Yes | Rewritten | No | Yes | Clean, linear history |
git squash | Yes | Squashed | No | Yes | Combine multiple commits into one |
Summary
- Merge preserves branch history and creates a merge commit.
- Rebase rewrites history for a linear commit log and makes your changes appear after the latest updates.
- Squash combines multiple commits into one for a cleaner history.
Git Cherry-Pick
git cherry-pick lets you apply a specific commit (or a range of commits) from one branch onto your current branch — without merging the entire branch.
When to use it
- You fixed a bug on
mainand need that exact fix on an olderreleasebranch. - A teammate committed a useful change on their feature branch, and you need just that one commit — not everything else they did.
- You accidentally committed something to the wrong branch and want to bring it over cleanly.
Basic usage
git cherry-pick <commit-hash>
Replace <commit-hash> with the SHA of the commit you want (find it via git log --oneline).
Pick a range of commits
git cherry-pick <start-hash>^..<end-hash>
This picks all commits from <start-hash> through <end-hash> (inclusive) onto your current branch.
Handling conflicts
If a conflict occurs during cherry-pick, Git pauses and lets you resolve it:
# After resolving conflicts in the file(s):
git add <file>
git cherry-pick --continue
To abort and go back to the original state:
git cherry-pick --abort
Visual example
Before cherry-pick — feature-branch has commits E, F, G branching off main:
If you only want commit F on main:
git checkout main
git cherry-pick <hash-of-F>
After cherry-pick — only F' is copied onto main, leaving feature-branch untouched:
F' is a new commit with the same changes as F but a different hash.
Use git cherry-pick for surgical, targeted commits. For integrating an entire branch, prefer git merge or git rebase.
Revert Commands in Git
Git provides several ways to undo changes, depending on what you want to revert:
1. git revert
- Creates a new commit that undoes the changes made by a previous commit.
- Safe for shared/public branches because it doesn't rewrite history.
Example:
git revert <commit-hash>
This will open an editor for a commit message and create a new commit that reverses the changes of <commit-hash>.
- Push the revert commits to the remote
git push origin <your-branch-name>
Replace <your-branch-name> with the actual name of your branch (e.g., main, master, or a feature branch).
2. git reset
-
Moves the branch pointer and optionally changes the staging area and working directory.
-
--soft: Keeps changes staged.-
Useful if you want to undo commits but keep the changes staged for a new commit.
git reset --soft HEAD~2This moves the branch pointer back by 2 commits, but all changes from those commits remain staged.
-
-
--mixed(default): Keeps changes in working directory, unstaged. -
--hard: Discards all changes.
Example:
git reset --hard HEAD~1
This will move the branch pointer back by one commit and delete all changes from that commit.
- Force push the reset changes to the remote
git push --force origin <your-branch-name>
Replace <your-branch-name> with the actual name of your branch. The --force flag is necessary because you are rewriting history and the remote branch will not accept a non-fast-forward push otherwise
Use git reset --soft for safe undo, and git reset --hard only when you are sure you want to discard changes.
3. git checkout or git restore
- Used to restore files or commits to a previous state.
Restore a file to last committed state:
git restore <file>
Checkout a previous commit (detached HEAD):
git checkout <commit-hash>
Summary Table
| Command | History Changed? | Safe for Shared Branches | What It Does |
|---|---|---|---|
git revert | No | Yes | Creates a new commit to undo changes |
git reset --hard | Yes | No | Deletes commits & changes |
git restore <file> | No | Yes | Restores file to last commit |
Use git revert for undoing changes in public/shared branches.
Use git reset for local/private changes where history rewriting is safe.
How to Change the master Branch to main in Git
If you want to rename your local master branch to main and update your remote repository, follow these steps:
1. Rename the local branch
git branch -m master main
2. Fetch the latest branches from remote
git fetch origin
3. Set the upstream branch for main
git branch -u origin/main main
4. Update the remote HEAD reference
git remote set-head origin -a
5. Push the new branch and update remote (if needed)
If you have push access and need to update the remote branch name:
git push origin main
git push origin --delete master
Or, rename the branch on GitHub/Git server using the web interface.
Practical Daily Git Workflows and Safety Commands
This section collects practical commands that are especially useful when working with feature branches, deployment branches, and master/main.
Fetch the latest remote state safely
git fetch downloads remote commits and updates remote-tracking references such as origin/master without modifying your current working branch.
git fetch origin
Fetch one branch only:
git fetch origin master
Fetch all remotes:
git fetch --all
Fetch and remove stale remote-tracking branches that were deleted on the server:
git fetch --prune
or:
git fetch origin --prune
After fetching, compare your local branch with the remote branch:
git status
git log --oneline HEAD..origin/master
git log --oneline origin/master..HEAD
Interpretation:
HEAD..origin/mastershows commits that exist remotely but not locally.origin/master..HEADshows commits that exist locally but not remotely.
A compact branch overview:
git branch -vv
Show local and remote branches:
git branch -a
Show remote branches only:
git branch -r
Update the branch you actually intend to update
To update local master:
git switch master
git pull --ff-only origin master
To update a feature branch from its own remote branch:
git switch feature/my-feature
git pull --ff-only origin feature/my-feature
git pull --ff-only is useful on branches where you do not want Git to create an automatic merge commit during pull.
If the command fails because the branches diverged, inspect the history before choosing merge or rebase:
git log --graph --oneline --decorate --all --max-count=30
Merge one feature branch into another feature branch
Suppose:
feature/base-work
feature/next-work
and feature/next-work needs everything from feature/base-work.
Switch to the target branch first:
git switch feature/next-work
git fetch origin
git merge --ff-only feature/base-work
If --ff-only fails because both branches contain unique commits and you intentionally want to combine them:
git merge feature/base-work
Then push the target branch:
git push origin feature/next-work
Always remember:
git merge SOURCE_BRANCHmergesSOURCE_BRANCHinto the branch you currently have checked out.
Check your current branch before merging:
git branch --show-current
Merge a feature branch into master
A safe fast-forward workflow:
git switch master
git pull --ff-only origin master
git fetch origin
git merge --ff-only feature/my-feature
git push origin master
This is ideal when master has not diverged from the feature branch's base.
If the feature branch exists only on the remote and you do not need a local copy, you can merge the remote-tracking branch:
git switch master
git pull --ff-only origin master
git fetch origin
git merge --ff-only origin/feature/my-feature
git push origin master
Merge a feature branch into another deployment branch, then promote to master
A useful workflow when you maintain a deployment branch such as main-github:
# 1. Promote feature to deployment branch
git switch main-github
git pull --ff-only origin main-github
git merge --ff-only feature/my-feature
git push origin main-github
# 2. Verify deployment / CI
# 3. Promote the exact tested commit to master
git switch master
git pull --ff-only origin master
git merge --ff-only main-github
git push origin master
This keeps the code tested on the deployment branch identical to what is later promoted to master.
Why git merge --ff-only is useful
git merge --ff-only feature/my-feature
Use it when you expect the target branch to be directly behind the source branch.
It will:
- fast-forward when safe,
- avoid creating an unexpected merge commit,
- stop with an error when branches have diverged.
That failure is useful because it tells you to inspect the history instead of silently changing it.
Check whether a fast-forward is possible:
git merge-base --is-ancestor HEAD feature/my-feature
Exit code 0 means the current branch is an ancestor of the feature branch and can normally be fast-forwarded.
You can also compare branches:
git log --oneline master..feature/my-feature
git log --oneline feature/my-feature..master
Push the current branch
Push the current branch to its configured upstream:
git push
Push and set upstream the first time:
git push -u origin feature/my-feature
After -u, normal git pull and git push know which remote branch to use.
Show the configured upstream:
git rev-parse --abbrev-ref --symbolic-full-name @{u}
Verify local and remote commits match
Show the latest local commit:
git log --oneline -1
Show the latest commit for several local branches:
git log --oneline -1 master
git log --oneline -1 main-github
git log --oneline -1 feature/my-feature
Fetch first, then inspect remote-tracking branches:
git fetch origin
git log --oneline -1 origin/master
git log --oneline -1 origin/main-github
git log --oneline -1 origin/feature/my-feature
Compare commit hashes directly:
git rev-parse master
git rev-parse origin/master
If both hashes are identical, the local and remote branch tips match.
Check what will be merged before merging
Commits in the feature branch that are not yet in master:
git log --oneline master..feature/my-feature
File-level summary:
git diff --stat master...feature/my-feature
Full diff:
git diff master...feature/my-feature
Name only:
git diff --name-only master...feature/my-feature
Check for whitespace problems before commit or merge
Before committing:
git diff --check
For staged changes only:
git diff --cached --check
This is a quick and useful quality check before pushing code.
Create an empty commit to trigger CI/CD
Sometimes you need to rerun a CI/CD pipeline without changing any file:
git commit --allow-empty -m "Triggering CI build"
git push
A Conventional Commit style alternative is:
git commit --allow-empty -m "ci: trigger build"
git push
An empty commit changes the commit history but does not change project files.
Use it when:
- CI/CD did not run and you need another push event,
- a deployment needs to be retriggered,
- you want to verify pipeline configuration after changing repository-side settings or secrets.
Do not repeatedly create empty commits when the real issue is a failing build; fix the build error first.
Re-run CI without changing source code — when an empty commit is appropriate
Typical flow:
git switch main-github
git pull --ff-only origin main-github
git commit --allow-empty -m "ci: trigger GitHub Pages build"
git push origin main-github
Because the commit is created on main-github, pushing it triggers workflows configured for pushes to that branch.
Amend the latest commit
Change the most recent commit message:
git commit --amend -m "new commit message"
Add forgotten staged changes to the latest commit while keeping the same message:
git add <file>
git commit --amend --no-edit
Amending changes the commit hash. Avoid amending commits that other people may already be using unless you understand the history-rewrite implications.
Undo the most recent local commit but keep the changes
Keep changes staged:
git reset --soft HEAD~1
Keep changes but unstage them:
git reset HEAD~1
For a shared branch, prefer git revert instead of rewriting history.
Safely force-push rewritten history
If you intentionally rebased or amended a branch that you alone control, prefer:
git push --force-with-lease
over:
git push --force
--force-with-lease refuses to overwrite the remote branch if somebody else pushed unexpected commits since your last fetch.
Compare git pull, git pull --rebase, and git pull --ff-only
git pull
Fetches remote changes and then merges them into the current branch.
git pull --rebase
Fetches remote changes and reapplies your local commits on top of them. This keeps history linear but rewrites your local commit hashes.
git pull --ff-only
Fetches remote changes and updates the branch only when a fast-forward is possible. It refuses to create a merge commit.
A safe default for important shared branches such as master is often:
git pull --ff-only origin master
Inspect the exact current branch and repository state
Current branch:
git branch --show-current
Working tree status:
git status
Short status:
git status --short
Show the current commit hash:
git rev-parse HEAD
Show the repository root directory:
git rev-parse --show-toplevel
Show which branches contain a commit:
git branch --contains <commit-hash>
Include remote branches:
git branch -a --contains <commit-hash>
Find the common ancestor of two branches
git merge-base master feature/my-feature
This is useful when diagnosing branch divergence.
To check how far two branches differ:
git rev-list --left-right --count master...feature/my-feature
Example output:
2 5
means:
masterhas 2 commits not present in the feature branch,- the feature branch has 5 commits not present in
master.
Clean stale local references
Remove references to remote branches that no longer exist:
git fetch --prune
Delete a local feature branch after it has been merged:
git branch -d feature/my-feature
Force-delete an unmerged local branch only when you are certain:
git branch -D feature/my-feature
Delete a remote branch:
git push origin --delete feature/my-feature
Recover useful history with reflog
If you accidentally reset, rebase, or move a branch and need to find the previous commit:
git reflog
Then inspect or restore a known commit:
git show <commit-hash>
or create a recovery branch:
git switch -c recovery-branch <commit-hash>
git reflog is one of the most useful recovery tools when a commit seems to have disappeared locally.
Practical pre-push checklist
A useful sequence before pushing important changes:
git status
git diff
git diff --cached
git diff --check
git log --oneline --decorate -5
Then, when everything is correct:
git push
For a project with lint, tests, and build commands, run those project-specific checks before the push as well.
Quick reference: common branch promotion flows
| Goal | Commands |
|---|---|
Update local master | git switch master → git pull --ff-only origin master |
| Update local feature branch | git switch feature/x → git pull --ff-only origin feature/x |
| Feature → feature | switch to target feature → git merge --ff-only source-feature → push target |
Feature → master | switch to master → update master → git merge --ff-only feature/x → push |
| Feature → deployment branch | switch to deployment branch → update it → git merge --ff-only feature/x → push |
Deployment branch → master | switch to master → update it → git merge --ff-only deployment-branch → push |
| Trigger CI without file changes | git commit --allow-empty -m "ci: trigger build" → git push |
| Check whitespace | git diff --check |
| Download remote state only | git fetch origin |
| Remove stale remote refs | git fetch --prune |
| See branch graph | git log --graph --oneline --decorate --all --max-count=30 |
| Compare ahead/behind | git rev-list --left-right --count branch-a...branch-b |
| Recover lost local commit | git reflog |
Conventional Commit Format
Many teams follow the Conventional Commits specification to write consistent, readable commit messages. It also enables automation tools to generate changelogs and auto-bump version numbers.
Format
<type>(<optional scope>): <description>
Example:
git commit -m "feat(auth): add Google OAuth login"
git commit -m "fix(api): handle null response from payment service"
git commit -m "chore: update dependencies"
Common Types
| Type | Purpose |
|---|---|
feat | A new feature |
fix | A bug fix |
chore | Maintenance tasks (deps, config, tooling) |
docs | Documentation changes only |
style | Code formatting — no logic changes |
refactor | Code restructure — not a fix or feature |
test | Adding or fixing tests |
perf | Performance improvements |
ci | CI/CD pipeline changes |
revert | Reverting a previous commit |
With Emoji (Gitmoji)
Some teams use gitmoji instead of or alongside the text prefix:
| Emoji | Type | Meaning |
|---|---|---|
| ✨ | feat | New feature |
| 🐛 | fix | Bug fix |
| 🔧 | chore | Configuration / tooling |
| 📝 | docs | Documentation |
| ♻️ | refactor | Code refactor |
| 🚀 | perf | Performance improvement |
| ✅ | test | Tests |
| 👷 | ci | CI/CD changes |
| ⏪️ | revert | Revert a commit |
Both styles are equivalent — it's a team preference. Some projects combine them:
git commit -m "✨ feat: add dark mode toggle"
Tools like commitlint (with a git hook) can enforce the conventional commit format automatically across your team.
Commit Message Tense
Use the imperative (simple present) tense — even though the work is already done. This is the universal standard.
The reasoning: a commit message describes what the commit does when applied, not what you did. Think of it as a command:
"If you apply this commit, it will add dark mode toggle."
Git itself uses this convention in its own auto-generated messages (e.g. Merge branch 'main'). Major projects like the Linux kernel, React, and VS Code all follow imperative tense.
A helpful mental check: "If applied, this commit will ___."
| ✅ Correct (imperative) | ❌ Avoid |
|---|---|
add dark mode toggle | added dark mode toggle |
fix null pointer in auth | fixed null pointer in auth |
update login styles | updating login styles |
Commit Type for CSS / UI Style Changes
The style type sounds like it fits CSS changes, but it actually means code formatting (whitespace, semicolons, indentation) — not visual styling. For CSS or design changes, pick the type based on intent:
| Situation | Type |
|---|---|
| Adding new CSS for a new UI feature | feat |
| Fixing a broken or incorrect style | fix |
| Tweaking/refining existing appearance (not a bug) | refactor |
| Updating a CSS variable, theme, or design token | refactor or chore |
| Removing unused styles | chore |
Examples:
git commit -m "feat: add responsive styles for mobile nav"
git commit -m "fix: correct button alignment on Safari"
git commit -m "refactor: simplify card hover state CSS"
Some teams define a custom ui type specifically for visual/CSS changes since the built-in types can feel ambiguous here — but this is a team-level decision and not part of the official spec.
Resources
- 10 Git Commands Every Developer Should Know
- Git Branching Commands Explained with Examples
- git commands
- Git Branches: List, Create, Switch to, Merge, Push, & Delete
- git stash and git pull - Stack Overflow
- Git Merge vs. Rebase: Key Differences
- How to Create Diagrams as Code with Mermaid, GitHub, and Visual Studio Code
- Creating diagrams
- The Ultimate Git Command Cheatsheet
