Git is a distributed version control system used by developers and IT professionals to track changes, collaborate on code, and manage project history. This page is a practical command reference for Git 2.x, covering everything from initial setup to advanced workflows. Commands are grouped by task so you can find what you need quickly during daily use.
Setup and Configuration
| Command | What it does | Notes |
|---|
git --version | Show installed Git version | Confirm Git is installed and check version |
git config --global user.name "Your Name" | Set your name for all commits | Stored in ~/.gitconfig |
git config --global user.email "[email protected]" | Set your email for all commits | Must match your GitHub/GitLab account email |
git config --global core.editor nano | Set default text editor | Use vim, code --wait, or any editor |
git config --global init.defaultBranch main | Set default branch name for new repos | Replaces legacy master default |
git config --list | Display all current configuration | Add --global to show only global config |
git config --global alias.st status | Create a command alias | After this, git st runs git status |
git config --global pull.rebase false | Use merge (not rebase) on pull | Set to true to rebase on pull instead |
Starting a Repository
| Command | What it does | Notes |
|---|
git init | Initialise a new local repository | Creates a .git directory in the current folder |
git init --bare | Initialise a bare repository | Used for server-side repos; no working tree |
git clone URL | Clone a remote repository | Creates a folder named after the repo |
git clone URL foldername | Clone into a specific folder name | Overrides the default folder name |
git clone --depth 1 URL | Shallow clone — latest snapshot only | Faster; omits full history. Good for CI pipelines |
git clone --branch branchname URL | Clone and check out a specific branch | Also accepts tag names |
Staging and Committing
| Command | What it does | Notes |
|---|
git status | Show working tree and staging area status | Use frequently; shows what is staged, unstaged, untracked |
git add file | Stage a specific file | Supports glob patterns, e.g. git add *.js |
git add . | Stage all changes in current directory | Includes new, modified, and deleted files |
git add -p | Interactively stage chunks of changes | Lets you stage partial file changes — very useful for clean commits |
git diff | Show unstaged changes | Compares working directory to staging area |
git diff --staged | Show staged changes | Compares staging area to last commit |
git commit -m "message" | Commit staged changes with a message | Keep messages concise and in the imperative tense |
git commit -am "message" | Stage all tracked changes and commit | Skips git add — does not include new untracked files |
git commit --amend | Amend the last commit | Opens editor to change message and/or staged content |
git commit --amend --no-edit | Amend last commit without changing the message | Useful to add a forgotten file to the previous commit |
Branching
| Command | What it does | Notes |
|---|
git branch | List local branches | Current branch is highlighted with * |
git branch -a | List all branches including remote-tracking | Remote branches shown as remotes/origin/name |
git branch branchname | Create a new branch | Does not switch to it; use checkout -b or switch -c to create and switch |
git checkout branchname | Switch to an existing branch | Classic syntax; also used to check out files |
git checkout -b branchname | Create and switch to a new branch | Equivalent to git branch + git checkout |
git switch branchname | Switch to a branch (modern syntax) | Introduced in Git 2.23; preferred over checkout for switching |
git switch -c branchname | Create and switch to a new branch (modern syntax) | Modern equivalent of git checkout -b |
git branch -d branchname | Delete a branch (safe) | Only deletes if fully merged |
git branch -D branchname | Force-delete a branch | Deletes regardless of merge status |
git branch -m oldname newname | Rename a branch | Rename the current branch with git branch -m newname |
git merge branchname | Merge a branch into the current branch | Fast-forwards if possible |
git merge --no-ff branchname | Merge and always create a merge commit | Preserves branch history even when fast-forward is possible |
git rebase branchname | Rebase current branch onto another | Rewrites history — avoid on shared branches |
Remote Repositories
| Command | What it does | Notes |
|---|
git remote -v | List remotes with URLs | Shows fetch and push URLs |
git remote add origin URL | Add a remote named origin | origin is convention; any name can be used |
git remote remove name | Remove a remote | Does not delete the remote repository itself |
git remote rename old new | Rename a remote | e.g. git remote rename origin upstream |
git remote set-url origin URL | Change the URL of a remote | Useful when switching from HTTPS to SSH |
git fetch | Download changes from remote without merging | Safe — does not modify working tree |
git fetch --all | Fetch from all remotes | Useful in multi-remote setups |
git pull | Fetch and merge remote changes into current branch | Equivalent to git fetch + git merge |
git pull origin branchname | Pull a specific remote branch | Merges into your current branch |
git push | Push current branch to its tracked remote | Requires upstream to be set |
git push origin branchname | Push a specific branch to remote | Creates the branch on remote if it does not exist |
git push -u origin branchname | Push and set upstream tracking | After this, plain git push works for this branch |
git push --force-with-lease | Force push safely | Fails if the remote has commits you have not fetched — safer than --force |
git push origin --delete branchname | Delete a branch on the remote | Does not delete the local branch |
Viewing History
| Command | What it does | Notes |
|---|
git log | Show full commit history | Press q to exit the pager |
git log --oneline | Show condensed one-line history | Shows short hash and subject line |
git log --oneline --graph --all | Show branch graph for all branches | Add --decorate to include branch and tag labels |
git log -n 10 | Show only the last 10 commits | Replace 10 with any number |
git log --since="2 weeks ago" | Show commits from the past two weeks | Also accepts --until, dates, and relative strings |
git log --author="Name" | Filter commits by author | Partial name or email matches work |
git log -- filename | Show commits that changed a specific file | The -- separator is good practice |
git log -p | Show commits with their diffs | Verbose — combine with -n to limit output |
git show COMMIT | Show details and diff for a specific commit | Use short hash, full hash, or tag name |
git diff COMMIT1 COMMIT2 | Show differences between two commits | Use branch names or hashes |
git blame filename | Show who last changed each line of a file | Add -L 10,20 to limit to a line range |
git shortlog -sn | Summary of commits per contributor | -s suppresses messages, -n sorts by count |
Undoing Changes
Safe — does not rewrite history
| Command | What it does | Notes |
|---|
git restore file | Discard working directory changes to a file | Irreversible — changes are lost. Replaces old git checkout -- file |
git restore --staged file | Unstage a file | Keeps changes in working directory |
git revert COMMIT | Create a new commit that undoes a previous commit | Safe for shared branches — history is preserved |
git stash | Stash current uncommitted changes | Cleans working tree; changes can be restored later |
git stash pop | Restore most recent stash and remove it | Applies stash and drops it from the stash list |
git stash list | List all stashed entries | Entries shown as stash@{0}, stash@{1}, etc. |
git stash drop | Delete the most recent stash entry | Use git stash drop stash@{n} for a specific entry |
Destructive — rewrites history. Use with care on shared branches
| Command | What it does | Notes |
|---|
git reset --soft HEAD~1 | Undo last commit; keep changes staged | Commit is removed; all changes remain ready to recommit |
git reset --mixed HEAD~1 | Undo last commit; keep changes unstaged | Default mode if no flag is specified |
git reset --hard HEAD~1 | Undo last commit and discard all changes | Permanent data loss — cannot be undone without the reflog |
git reset --hard origin/main | Reset local branch to match remote exactly | Destroys all local commits and changes not on the remote |
git clean -fd | Delete all untracked files and directories | Run git clean -nfd first for a dry run |
Stashing
| Command | What it does | Notes |
|---|
git stash | Stash tracked changes | Add -u to also stash untracked files |
git stash save "message" | Stash with a descriptive label | Makes stash list easier to read |
git stash list | List all stash entries | Shows index, branch, and message |
git stash show stash@{0} | Show summary of a stash entry | Add -p for full diff |
git stash pop | Apply most recent stash and remove it | Equivalent to apply + drop |
git stash apply stash@{0} | Apply a specific stash without removing it | Stash entry remains in the list |
git stash drop stash@{0} | Delete a specific stash entry | Permanently removes it from the list |
git stash clear | Delete all stash entries | Irreversible |
git stash branch newbranch | Create a new branch from the stash | Applies stash and drops it if successful |
| Command | What it does | Notes |
|---|
git tag | List all tags | Add -l "v1.*" to filter by pattern |
git tag v1.0.0 | Create a lightweight tag at HEAD | Lightweight tags are just pointers; no metadata |
git tag -a v1.0.0 -m "message" | Create an annotated tag | Stores tagger name, date, and message — preferred for releases |
git tag -a v1.0.0 COMMIT | Tag a specific past commit | Replace COMMIT with the hash |
git push origin v1.0.0 | Push a single tag to remote | Tags are not pushed automatically with git push |
git push origin --tags | Push all local tags to remote | Pushes all tags not yet on the remote |
git tag -d v1.0.0 | Delete a tag locally | Does not affect the remote |
git push origin --delete v1.0.0 | Delete a tag from the remote | You must also delete locally with git tag -d |
Searching
| Command | What it does | Notes |
|---|
git grep "searchterm" | Search working tree for a string | Faster than grep on large repos; respects .gitignore |
git log --all --grep="message" | Search commit messages across all branches | Case-insensitive with -i |
git log -S "code string" | Find commits that added or removed a string | Known as the “pickaxe” search; useful for tracking when code appeared |
git bisect start | Begin a binary search for a bug-introducing commit | Then mark commits as git bisect bad or git bisect good COMMIT |
git bisect bad | Mark current commit as containing the bug | Git will check out a midpoint commit to test next |
git bisect good COMMIT | Mark a known-good commit | Provide the last commit you know was working |
Submodules
| Command | What it does | Notes |
|---|
git submodule add URL path | Add a repository as a submodule | Creates .gitmodules and stages changes |
git submodule init | Initialise submodules listed in .gitmodules | Run after cloning a repo with submodules |
git submodule update | Check out submodules at their recorded commit | Run after git submodule init |
git submodule update --init --recursive | Initialise and update all nested submodules | Single command for freshly cloned repos with submodules |
git submodule foreach git pull origin main | Run a command in every submodule | Any Git command can follow foreach |
git submodule status | Show the current state of all submodules | Prefix - means uninitialised, + means different from recorded commit |
.gitignore Quick Reference
A .gitignore file tells Git which files and directories to ignore. Place it in the repository root. Lines starting with # are comments. A trailing / matches directories only. A leading ! negates a pattern.
# Ignore a specific file
secrets.env
# Ignore a directory
node_modules/
.venv/
# Ignore all .log files
*.log
# Ignore all .log files except one
*.log
!important.log
# Ignore in any subdirectory
**/temp/
Common .gitignore entries
| Entry | What it ignores |
|---|
node_modules/ | Node.js dependencies directory |
.env | Environment variable files containing secrets |
.venv/ | Python virtual environment directory |
__pycache__/ | Python compiled bytecode cache |
*.pyc | Compiled Python files |
.DS_Store | macOS Finder metadata files |
Thumbs.db | Windows Explorer thumbnail cache |
*.log | Log files |
dist/ | Build output directory (JavaScript/Python) |
build/ | Compiled build output |
.idea/ | JetBrains IDE project files |
.vscode/ | Visual Studio Code workspace settings |
Git Aliases (Time Savers)
Add these aliases to your global Git configuration to speed up common workflows. Once set, the short form works in any repository.
git config --global alias.st status
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.lg "log --oneline --graph --all --decorate"
git config --global alias.undo "reset --soft HEAD~1"
git config --global alias.unstage "restore --staged"
After running the above, you can use git st, git co, git lg, git undo, and git unstage directly.
SSH Keys for GitHub/GitLab
SSH authentication is more secure than HTTPS with a password and avoids repeated credential prompts. Generate a key once per machine, add the public key to your account, then update your remotes to use SSH URLs.
# Generate an ED25519 key (recommended)
ssh-keygen -t ed25519 -C "[email protected]"
# Print the public key to copy into GitHub / GitLab
cat ~/.ssh/id_ed25519.pub
# Test connection to GitHub
ssh -T [email protected]
# Use SSH instead of HTTPS for an existing remote
git remote set-url origin [email protected]:user/repo.git
Useful One-Liners
# Show all branches sorted by most recent commit
git branch -a --sort=-committerdate
# Find which branch(es) contain a specific commit
git branch --contains COMMIT
# List files changed in the last commit
git diff-tree --no-commit-id -r --name-only HEAD
# Squash the last 3 commits into one
git reset --soft HEAD~3 && git commit -m "Squashed commit"
# Cherry-pick a single commit from another branch
git cherry-pick COMMIT
# Preview what would be pushed to the remote
git log origin/main..HEAD --oneline
# Export a file at a specific commit to a new file
git show COMMIT:path/to/file > output.txt
# Stop tracking a file without deleting it locally
git rm --cached filename