A comprehensive, practical reference for beginners, intermediate, and advanced Git users. Designed for swiftener.com. 1. Git Overview Git is a distributed vers…
A comprehensive, practical reference for beginners, intermediate, and advanced Git users. Designed for swiftener.com.
1. Git Overview
Git is a distributed version control system created by Linus Torvalds in 2005. It tracks changes to files, enables collaboration, supports non-linear development through branching, and keeps a complete history of a project.
Key characteristics:
- Distributed: Every clone is a full repository with complete history.
- Fast: Most operations are local.
- Integrity: Content is identified by SHA-1 (or SHA-256 in newer setups) hashes.
- Branching model: Lightweight branches encourage frequent branching and merging.
- Snapshots, not diffs: Git stores snapshots of the entire project at each commit.
Git is free, open-source, and the de-facto standard for software development.
2. Git Terminology and Core Concepts
| Term |
Definition |
| Repository (repo) |
The database of all commits, branches, tags, and configuration. Contained in the .git directory. |
| Working tree / Working directory |
The directory containing the files you edit. |
| Staging area / Index |
Intermediate area where changes are prepared before committing. |
| Commit |
A snapshot of the staged changes, with metadata (author, message, parent(s), timestamp). |
| Branch |
A movable pointer to a commit. Default branch is usually main or master. |
| HEAD |
Pointer to the current branch (or commit in detached state). |
| Remote |
A named reference to another repository (e.g., origin). |
| Upstream |
The remote branch that a local branch tracks. |
| Fast-forward |
Moving a branch pointer forward when there is a linear history. |
| Three-way merge |
Merge that uses the common ancestor plus the tips of two branches. |
| Conflict |
Overlapping changes that Git cannot automatically resolve. |
| Ref |
A pointer to a commit (branches, tags, HEAD, etc.). |
| Object |
Blob (file content), tree (directory), commit, or tag stored in the object database. |
| SHA-1 / Hash |
Unique identifier for every object (40-character hex string). |
| Detached HEAD |
HEAD points directly to a commit instead of a branch. |
| Reflog |
Local log of where HEAD and branch tips have been. |
| Stash |
Temporary storage for uncommitted changes. |
| Tag |
Named pointer to a commit, usually for releases. |
| Bare repository |
Repository without a working tree (used for servers). |
3. Installing Git
Linux (Debian/Ubuntu)
sudo apt update
sudo apt install git
Linux (Fedora/RHEL)
sudo dnf install git
macOS
# Using Homebrew (recommended)
brew install git
# Or download from https://git-scm.com
Windows
- Download the official installer from https://git-scm.com
- Or use winget:
winget install Git.Git
- Or Chocolatey:
choco install git
After installation, open a new terminal and verify.
4. Checking the Git Version
git --version
Example output: git version 2.45.2
5. Initial Git Configuration
Git stores configuration in three levels (see next section). Minimum recommended setup after install:
git config --global user.name "Your Name"
git config --global user.email "you@example.com"
git config --global init.defaultBranch main
git config --global core.editor "code --wait" # or vim, nano, etc.
git config --global pull.rebase false # or true / merges
6. Global, Local, and System Configuration
| Level |
Scope |
File location |
Command flag |
| System |
All users on the machine |
/etc/gitconfig (Linux/macOS) or C:\Program Files\Git\etc\gitconfig |
--system |
| Global |
Current user |
~/.gitconfig or ~/.config/git/config |
--global |
| Local |
Current repository |
.git/config |
--local (default) |
View configuration:
git config --list # all levels, last one wins
git config --global --list
git config --local --list
git config --show-origin --list # show which file each value comes from
Get a single value:
git config user.name
git config --global user.email
Unset a value:
git config --global --unset user.email
7. User Identity Configuration
git config --global user.name "Jane Developer"
git config --global user.email "jane@example.com"
For a specific repository only:
git config user.name "Jane (Work)"
git config user.email "jane@company.com"
Git uses this identity for commit and tag author/committer fields.
8. Useful Aliases
Add to ~/.gitconfig or via command:
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.last 'log -1 HEAD'
git config --global alias.lg "log --oneline --graph --decorate --all"
git config --global alias.unstage 'reset HEAD --'
git config --global alias.amend 'commit --amend --no-edit'
git config --global alias.undo 'reset --soft HEAD~1'
git config --global alias.visual '!gitk'
Usage after defining:
git st
git lg
git amend
9. Creating Repositories
Create a new local repository
mkdir my-project
cd my-project
git init
Creates a .git directory. The default branch is whatever init.defaultBranch is set to (usually main).
Create and switch to a specific branch immediately
git init -b main
Initialize in an existing directory
cd existing-project
git init
10. Cloning Repositories
git clone <url>
git clone <url> <directory-name>
git clone --branch <branch> <url>
git clone --depth 1 <url> # shallow clone
git clone --recurse-submodules <url>
Examples:
git clone https://github.com/example/project.git
git clone git@github.com:example/project.git my-local-name
git clone --branch develop https://github.com/example/project.git
Cloning creates a remote named origin pointing to the source URL and checks out the default branch.
11. Git Directory Structure
Typical .git layout (simplified):
.git/
├── HEAD # current branch or commit
├── config # local configuration
├── description # for gitweb
├── hooks/ # client-side and server-side hooks
├── index # staging area
├── logs/ # reflogs
├── objects/ # all content (blobs, trees, commits, tags)
│ ├── pack/ # packed objects
│ └── info/
├── refs/
│ ├── heads/ # local branches
│ ├── tags/ # tags
│ └── remotes/ # remote-tracking branches
└── packed-refs
Never manually edit files inside .git unless you know exactly what you are doing.
12. Working Tree, Staging Area, and Repository
Git has three main areas:
- Working tree – files you see and edit.
- Staging area (index) – snapshot of changes prepared for the next commit.
- Repository (
.git) – permanent history of commits.
Workflow:
- Edit files in the working tree.
- Stage desired changes (
git add).
- Commit the staged snapshot (
git commit).
Working Tree → Staging Area → Repository
(edit) (git add) (git commit)
13. Checking Repository Status
git status
git status -s # short format
git status -sb # short + branch info
git status --ignored # include ignored files
Short status codes:
?? untracked
A added
M modified
D deleted
R renamed
C copied
U unmerged (conflict)
14. Adding Files
git add <file>
git add <directory>
git add . # all changes in current directory and below
git add -A # all changes in the entire working tree
git add -u # only tracked files (no new untracked)
git add -p # interactive patch mode (stage hunks)
git add -i # interactive mode
git add --intent-to-add <file> # record path but not content (useful for empty files)
Examples:
git add README.md
git add src/
git add -p app.js # stage selected hunks
15. Committing Changes
git commit -m "Short message"
git commit # opens editor for longer message
git commit -a -m "Message" # stage all tracked modifications and commit
git commit --amend # modify the last commit
git commit --amend --no-edit # amend without changing message
git commit --allow-empty -m "Empty commit for CI"
Only staged changes are committed.
16. Writing Good Commit Messages
Recommended format (Conventional Commits inspired):
<type>(optional scope): <short summary in imperative mood>
[optional body – explain what and why]
[optional footer – breaking changes, issue refs]
Examples of good messages:
feat(auth): add JWT refresh token support
fix: prevent null pointer when user has no avatar
docs: update installation instructions for Windows
refactor(api): extract validation into separate module
chore: bump dependencies
Rules of thumb:
- Use the imperative mood (“Add feature” not “Added feature”).
- Keep the first line ≤ 50–72 characters.
- Separate subject from body with a blank line.
- Explain why, not just what.
- Reference issues:
Closes #123 or Fixes #456.
17. Viewing Commit History
git log
git log --oneline
git log --graph --oneline --decorate --all
git log -n 5
git log --author="Jane"
git log --since="2 weeks ago"
git log --until="2025-01-01"
git log --grep="bugfix"
git log -p # show patches
git log --stat
git log --name-only
git log --name-status
git log <file>
git log --follow <file> # follow renames
Useful aliases often include:
git log --oneline --graph --decorate --all
18. Viewing and Comparing Changes
git diff # unstaged changes
git diff --staged # staged changes (same as --cached)
git diff HEAD # all uncommitted changes
git diff branch1 branch2
git diff commit1 commit2
git diff --name-only
git diff --stat
git diff --word-diff
git show <commit> # show a specific commit
git show HEAD
git show HEAD~3
19. Git Diff
git diff compares:
- Working tree vs staging area (default)
- Staging area vs last commit (
--staged)
- Any two commits/trees/blobs
Common options:
git diff --color-words
git diff -w # ignore whitespace
git diff --ignore-space-change
git diff --stat
git diff --numstat
git diff --name-status
git diff branchA...branchB # changes reachable from either but not both (symmetric difference)
20. Ignoring Files with .gitignore
Create a .gitignore file in the repository root (or any subdirectory).
Common patterns:
# Dependencies
node_modules/
vendor/
# Build outputs
dist/
build/
*.o
*.exe
# IDE / OS
.DS_Store
.idea/
*.swp
Thumbs.db
# Environment
.env
.env.local
# Logs
*.log
Rules:
- Blank lines and lines starting with
# are ignored.
* matches anything except /.
** matches across directories.
/ at the start anchors to the directory of the .gitignore.
! negates a pattern.
- Trailing
/ matches directories only.
Check why a file is ignored:
git check-ignore -v path/to/file
Force-add an ignored file:
git add -f ignored-file.txt
21. Git Attributes
.gitattributes controls how Git treats files (line endings, diff drivers, merge strategies, LFS, etc.).
Example:
*.txt text
*.jpg binary
*.psd binary
*.sh text eol=lf
*.bat text eol=crlf
*.md diff=markdown
secret.txt filter=crypt
Common uses:
- Force LF or CRLF
- Mark binary files so Git does not attempt textual diff/merge
- Custom diff or merge drivers
- Git LFS tracking
22. Removing and Renaming Files
git rm <file> # remove from working tree and stage deletion
git rm --cached <file> # untrack but keep the file on disk
git rm -r <directory>
git mv <old> <new> # rename/move and stage
After git rm or git mv, commit the change.
23. Tracking and Untracking Files
- Track:
git add <file> then commit.
- Untrack (keep file):
git rm --cached <file> then commit.
- Stop tracking permanently: add the path to
.gitignore and remove from the index.
To remove a previously committed file from history (advanced, rewrites history):
git filter-repo --path secret.txt --invert-paths
# or older: git filter-branch / BFG Repo-Cleaner
24. Branches
A branch is a lightweight movable pointer to a commit. Creating a branch is nearly instantaneous.
List branches:
git branch # local
git branch -r # remote-tracking
git branch -a # all
git branch -v # with last commit
git branch --merged
git branch --no-merged
25. Creating, Switching, Renaming, and Deleting Branches
git branch <name> # create
git switch <name> # switch (modern)
git checkout <name> # older equivalent
git switch -c <name> # create and switch
git checkout -b <name> # older equivalent
git branch -m <old> <new> # rename
git branch -d <name> # delete (safe, refuses unmerged)
git branch -D <name> # force delete
git push origin --delete <name> # delete remote branch
Modern recommendation: prefer git switch and git restore over the overloaded git checkout.
26. Merging Branches
git switch main
git merge feature-branch
Git performs a fast-forward if possible; otherwise a three-way merge and creates a merge commit.
27. Fast-Forward and Three-Way Merges
- Fast-forward: The target branch pointer simply moves forward. No merge commit.
- Three-way merge: Git finds the common ancestor and merges the two divergent tips. Produces a merge commit with two parents.
Force a merge commit even when fast-forward is possible:
git merge --no-ff feature-branch
28. Merge Conflicts
When the same lines are changed differently on both sides, Git marks the conflict:
<<<<<<< HEAD
current change
=======
incoming change
>>>>>>> feature-branch
Status shows unmerged paths. Resolve by editing the files, then:
git add <resolved-file>
git commit # completes the merge
Abort a merge:
git merge --abort
29. Resolving Conflicts
- Open conflicted files.
- Decide which changes to keep (or combine).
- Remove conflict markers.
git add the resolved files.
git commit (or continue rebase/cherry-pick).
Tools that help:
git mergetool
Configure a visual tool (e.g., VS Code, Beyond Compare, Meld).
30. Rebasing
Rebase moves a sequence of commits onto a new base:
git switch feature
git rebase main
This rewrites the feature branch commits so they appear after the tip of main.
Warning: Never rebase commits that have already been pushed and shared with others unless you coordinate carefully (history rewrite).
31. Interactive Rebasing
git rebase -i HEAD~5
git rebase -i main
In the editor you can:
pick – keep
reword – change message
edit – stop to amend
squash / fix – combine commits
drop – remove
- reorder lines
Useful for cleaning history before merging.
32. Cherry-Picking
Apply a specific commit onto the current branch:
git cherry-pick <commit-hash>
git cherry-pick <hash1> <hash2>
git cherry-pick --no-commit <hash> # apply changes but do not commit
Conflicts are possible; resolve as with merge/rebase.
33. Stashing
Temporarily save uncommitted changes:
git stash
git stash push -m "Work in progress on login"
git stash list
git stash show
git stash show -p
git stash apply # apply and keep stash
git stash pop # apply and remove stash
git stash drop stash@{0}
git stash clear
git stash branch new-branch-name stash@{0} # create branch from stash
Stash includes staged and unstaged changes by default. Use --include-untracked or -u for untracked files.
34. Tags
Tags mark specific points in history (usually releases).
git tag
git tag -l "v1.*"
35. Annotated and Lightweight Tags
Lightweight (just a pointer):
git tag v1.0.0
Annotated (recommended for releases – contains message, tagger, date, optional signature):
git tag -a v1.0.0 -m "Release version 1.0.0"
git tag -a v1.0.0 -s -m "Signed release" # GPG-signed
Push tags:
git push origin v1.0.0
git push origin --tags
git push origin --follow-tags
Delete:
git tag -d v1.0.0
git push origin --delete v1.0.0
36. Remote Repositories
Remotes are named URLs of other repositories.
git remote
git remote -v
git remote show origin
37. Adding, Changing, and Removing Remotes
git remote add origin https://github.com/user/repo.git
git remote add upstream https://github.com/original/repo.git
git remote set-url origin git@github.com:user/repo.git
git remote rename origin old-origin
git remote remove upstream
38. Fetching
Download objects and refs from a remote without merging:
git fetch
git fetch origin
git fetch --all
git fetch origin main
git fetch --prune # remove remote-tracking branches that no longer exist
39. Pulling
Fetch + integrate (merge or rebase):
git pull
git pull origin main
git pull --rebase
git pull --ff-only
Configure default behavior:
git config pull.rebase false # merge (default in many setups)
git config pull.rebase true # rebase
git config pull.ff only # only fast-forward
40. Pushing
git push
git push origin main
git push -u origin main # set upstream
git push --force-with-lease # safer force
git push --force # dangerous – overwrites remote
git push --tags
git push origin --delete branch-name
Never use --force on shared branches without coordination.
41. Tracking Branches
A local branch can track a remote-tracking branch.
git branch -vv # show tracking info
git switch -c feature origin/feature # create local tracking branch
42. Upstream Branches
Set or change upstream:
git branch --set-upstream-to=origin/main
git branch -u origin/main
git push -u origin feature
After setting, git pull and git push need no extra arguments.
43. GitHub / GitLab / Bitbucket Workflows
Typical hosted-platform workflow:
- Clone or fork the repository.
- Create a feature branch.
- Commit changes.
- Push the branch.
- Open a Pull Request / Merge Request.
- Review, address feedback, merge.
- Delete the feature branch.
44. Fork-Based Workflows
- Fork the upstream repository on the hosting platform.
- Clone your fork.
- Add the original repository as
upstream:git remote add upstream https://github.com/original/repo.git
- Keep your fork updated:
git fetch upstream
git switch main
git merge upstream/main
- Push feature branches to your fork and open PRs against upstream.
45. Pull Requests
Pull Requests (PRs) / Merge Requests are platform features, not pure Git. They propose merging one branch into another, enable discussion, CI checks, and code review.
Best practices:
- Keep PRs focused and reasonably sized.
- Write a clear description.
- Link related issues.
- Respond to review comments.
- Prefer rebase or squash when the platform offers it for a clean history.
46. Feature-Branch Workflows
- Start from an up-to-date main:
git switch main
git pull
git switch -c feature/login
- Work, commit, push.
- Open PR.
- After merge, delete the local and remote feature branch.
47. Git Flow and Alternative Branching Strategies
Git Flow (classic):
main – production
develop – integration
feature/*, release/*, hotfix/*
GitHub Flow (simpler):
main is always deployable
- Short-lived feature branches
- PR → merge → deploy
Trunk-Based Development:
- Very short-lived branches or direct commits to main
- Feature flags for incomplete work
- High automation and CI
Choose the strategy that matches team size and release cadence.
48. HEAD, HEAD~, HEAD^, and Commit References
| Reference |
Meaning |
HEAD |
Current commit |
HEAD~1 or HEAD~ |
First parent of HEAD |
HEAD~3 |
Three commits before HEAD |
HEAD^ |
First parent (same as ~1 for non-merge) |
HEAD^2 |
Second parent of a merge commit |
HEAD@{2} |
Reflog entry |
main |
Tip of main |
main~2 |
Two commits before main |
abc1234 |
Abbreviated hash |
v1.0.0 |
Tag |
origin/main |
Remote-tracking branch |
49. Detached HEAD State
Occurs when you check out a commit, tag, or remote branch directly instead of a local branch:
git switch --detach v1.2.0
# or
git checkout abc1234
You can make commits, but they are not on any branch and may become unreachable.
To keep the work:
git switch -c new-branch-name
Return to a branch:
git switch main
50. Reflog
Local history of HEAD and branch movements:
git reflog
git reflog show main
git reflog expire --expire=now --all
git reflog delete HEAD@{2}
Reflog entries expire (default 90 days for unreachable, 30 days for reachable). Essential for recovery.
51. Recovering Lost Commits
- Find the commit with
git reflog or git fsck --lost-found.
- Create a branch pointing to it:
git branch recovered-commit abc1234
- Or reset a branch to it (careful):
git reset --hard abc1234
52. Reset
Moves the current branch pointer (and optionally updates index and working tree).
git reset --soft HEAD~1 # move branch, keep staging and working tree
git reset --mixed HEAD~1 # move branch + reset staging (default)
git reset --hard HEAD~1 # move branch + reset staging + working tree (DESTRUCTIVE)
git reset <commit>
git reset HEAD <file> # unstage a file
Warning: --hard discards uncommitted changes permanently (unless recoverable via reflog in some cases).
53. Revert
Creates a new commit that undoes the changes of a previous commit. Safe for published history.
git revert <commit>
git revert HEAD
git revert -m 1 <merge-commit> # revert a merge, keeping first parent
git revert --no-commit <commit1> <commit2>
54. Restore
Modern command for restoring files (Git 2.23+):
git restore <file> # discard working tree changes
git restore --staged <file> # unstage
git restore --source=HEAD~1 <file> # restore from a specific commit
git restore --staged --worktree <file>
55. Checkout
Historically overloaded. Prefer switch and restore for clarity.
git checkout <branch> # switch branch
git checkout -b <new-branch>
git checkout -- <file> # discard changes (old style)
git checkout <commit> -- <file> # restore file from commit
56. Reset vs Revert vs Restore vs Checkout
| Command |
Purpose |
Affects history? |
Safe for shared branches? |
reset |
Move branch pointer, optionally clean index/worktree |
Yes (rewrites) |
No (if pushed) |
revert |
New commit that undoes changes |
No (adds) |
Yes |
restore |
Restore files in worktree or index |
No |
Yes |
checkout (file) |
Restore file (legacy) |
No |
Yes |
checkout / switch (branch) |
Change HEAD |
No |
Yes |
57. Amend Commits
git commit --amend
git commit --amend -m "New message"
git commit --amend --no-edit
git commit --amend --author="New Name <email>"
Warning: Amending rewrites the commit. Do not amend commits that have already been pushed unless you force-push with coordination.
58. Squashing Commits
Via interactive rebase:
git rebase -i HEAD~4
# change "pick" to "squash" or "fix" for commits to combine
Or soft reset + new commit:
git reset --soft HEAD~3
git commit -m "Single clean commit"
59. Rewriting History
Tools that rewrite history:
git commit --amend
git rebase / git rebase -i
git filter-repo (recommended replacement for filter-branch)
git filter-branch (legacy)
- BFG Repo-Cleaner
After rewriting published history you must force-push:
git push --force-with-lease
Always communicate with collaborators before rewriting shared history.
60. Bisect
Binary search to find the commit that introduced a bug:
git bisect start
git bisect bad # current version is bad
git bisect good v1.2.0 # known good version
# Git checks out a midpoint; test it
git bisect good # or bad
# repeat until Git identifies the first bad commit
git bisect reset
Automate with a script:
git bisect run ./test-script.sh
61. Blame
Show who last modified each line:
git blame <file>
git blame -L 10,20 <file>
git blame -w <file> # ignore whitespace
git blame --since=1.month <file>
62. Grep
Search file contents in the repository:
git grep "TODO"
git grep -n "functionName"
git grep -i "error" -- "*.js"
git grep -E "pattern1|pattern2"
63. Log Filtering and Searching
git log --author="Jane"
git log --grep="fix"
git log -S "functionName" # pickaxe – commits that change occurrence count
git log -G "regex"
git log --since="2024-01-01" --until="2024-06-01"
git log -- path/to/file
git log --all --full-history -- path/to/deleted-file
64. Useful Log Formatting
git log --pretty=oneline
git log --pretty=format:"%h %an %ar %s"
git log --pretty=format:"%C(yellow)%h%Creset %s %C(cyan)<%an>%Creset"
git log --date=short
git log --date=relative
Common placeholders: %H full hash, %h short, %an author name, %ae email, %ad date, %s subject, %b body, %d ref names.
65. Searching Repository History
- Content changes:
git log -S / -G
- Message:
git log --grep
- Author:
git log --author
- File existence:
git log --all --full-history -- <path>
- Deleted content recovery: combine with
git show <commit>:<path>
66. Git Hooks
Scripts in .git/hooks/ that run at specific points.
Client-side examples:
pre-commit – run linters/tests
commit-msg – validate message format
pre-push – extra checks
Server-side:
pre-receive, update, post-receive
Hooks are not versioned by default. Use tools like Husky, pre-commit framework, or a shared hooks directory with core.hooksPath.
Example simple pre-commit:
#!/bin/sh
npm test
Make executable: chmod +x .git/hooks/pre-commit
67. Git Submodules
Embed another repository inside your repository at a specific commit.
git submodule add https://github.com/example/lib.git libs/lib
git submodule init
git submodule update
git submodule update --init --recursive
git clone --recurse-submodules <url>
Update a submodule to a newer commit, then commit the change in the parent.
Working with submodules has complexity; many teams prefer monorepos, subtrees, or package managers instead.
68. Git Worktrees
Multiple working trees attached to the same repository:
git worktree add ../feature-branch feature-branch
git worktree list
git worktree remove ../feature-branch
git worktree prune
Useful for working on several branches simultaneously without stashing or cloning.
69. Git LFS (Large File Storage)
Stores large files outside the normal Git object database.
git lfs install
git lfs track "*.psd"
git lfs track "*.zip"
git add .gitattributes
git add large-file.psd
git commit -m "Add design assets"
Push/pull works transparently once LFS is installed on the client.
70. Sparse Checkout
Check out only part of a repository:
git sparse-checkout init --cone
git sparse-checkout set src/ docs/
git sparse-checkout add more/path
git sparse-checkout disable
Useful for monorepos when you only need a subset of directories.
71. Shallow Clones
Clone with limited history:
git clone --depth 1 <url>
git clone --depth 50 <url>
git fetch --depth 100
git fetch --unshallow # convert to full clone
Saves time and space; some operations (full blame, some rebases) may be limited.
72. Partial Clones
More advanced filtering (Git 2.19+):
git clone --filter=blob:none <url> # no blobs until needed
git clone --filter=tree:0 <url>
git clone --filter=blob:limit=1m <url>
Combined with sparse-checkout for very large repositories.
73. Signed Commits and Tags
Prove authenticity of commits and tags.
git commit -S -m "Signed commit"
git tag -s v1.0.0 -m "Signed tag"
git log --show-signature
git verify-commit HEAD
git verify-tag v1.0.0
74. GPG / SSH Signing
GPG:
git config --global user.signingkey <key-id>
git config --global commit.gpgsign true
git config --global tag.gpgSign true
SSH (Git 2.34+):
git config --global gpg.format ssh
git config --global user.signingkey ~/.ssh/id_ed25519.pub
git config --global commit.gpgsign true
Add the public key to your GitHub/GitLab account for verification.
75. SSH Authentication
- Generate key:
ssh-keygen -t ed25519 -C "you@example.com"
- Start agent and add key:
ssh-add ~/.ssh/id_ed25519
- Add public key to GitHub/GitLab/Bitbucket.
- Test:
ssh -T git@github.com
- Use SSH URLs:
git@github.com:user/repo.git
76. HTTPS Authentication
Uses username + password or, more commonly, a personal access token (PAT) as the password.
Credential helpers store tokens so you are not prompted every time.
77. Personal Access Tokens
Platforms no longer accept account passwords for Git over HTTPS. Create a PAT with appropriate scopes (repo, workflow, etc.) and use it as the password when prompted, or store it via a credential helper.
78. Credential Management
git config --global credential.helper cache # temporary
git config --global credential.helper store # plaintext file
git config --global credential.helper manager # Windows
git config --global credential.helper osxkeychain # macOS
On Linux, libsecret or a custom helper is common.
Clear stored credentials when needed via the platform or helper-specific tools.
79. Git Environment Variables
| Variable |
Purpose |
GIT_DIR |
Path to the .git directory |
GIT_WORK_TREE |
Path to the working tree |
GIT_AUTHOR_NAME / GIT_AUTHOR_EMAIL |
Override author |
GIT_COMMITTER_NAME / GIT_COMMITTER_EMAIL |
Override committer |
GIT_SSH_COMMAND |
Custom SSH command |
GIT_TRACE |
Enable tracing |
GIT_CURL_VERBOSE |
Verbose HTTP |
GIT_EDITOR |
Editor for commit messages |
GIT_PAGER |
Pager (less, cat, etc.) |
80. Git Configuration Files
- System:
/etc/gitconfig
- Global:
~/.gitconfig or $XDG_CONFIG_HOME/git/config
- Local:
.git/config
- Worktree-specific (rare):
.git/config.worktree
Conditional includes (useful for work vs personal):
[includeIf "gitdir:~/work/"]
path = ~/.gitconfig-work
81. Git Maintenance and Garbage Collection
git gc
git gc --aggressive
git prune
git fsck
git maintenance run
git maintenance start # background maintenance (Git 2.30+)
git gc packs objects, removes unreachable objects, and optimizes the repository.
82. Repository Optimization
- Run
git gc periodically on large or long-lived repos.
- Use
git repack -ad
- Avoid committing large binaries (use LFS or external storage).
- Keep history linear when possible.
- Use shallow or partial clones for CI.
83. Large Repositories
Strategies:
- Git LFS for binaries
- Sparse checkout
- Partial clone / promisor remotes
- Shallow clones in CI
- Split monorepo into multiple repos if necessary
git filter-repo to remove large files from history
84. Monorepos
Single repository containing multiple projects.
Challenges: clone size, CI performance, access control.
Mitigations: sparse-checkout, partial clone, path-based CODEOWNERS, powerful CI caching, monorepo-aware tools (Bazel, Nx, etc.).
85. Subtrees
Alternative to submodules for embedding another project:
git subtree add --prefix=libs/lib https://github.com/example/lib.git main --squash
git subtree pull --prefix=libs/lib https://github.com/example/lib.git main --squash
git subtree push --prefix=libs/lib https://github.com/example/lib.git main
History is merged into the parent repository.
86. Archives
Create an archive of a commit or tree:
git archive --format=zip --output=release.zip HEAD
git archive --format=tar.gz --prefix=project/ v1.0.0 > project-1.0.0.tar.gz
87. Bundles
Package objects and refs into a single file for transfer without a server:
git bundle create repo.bundle main
git bundle create repo.bundle --all
git bundle verify repo.bundle
git clone repo.bundle -b main my-clone
Useful for offline or air-gapped environments.
88. Patching
git format-patch -1 HEAD
git format-patch main..feature
git format-patch -o patches/ main
Produces numbered .patch files.
89. Applying Patches
git apply patch-file.patch
git am patch-file.patch # apply mailbox-style patches and commit
git am --abort
git am --continue
90. Three-Way Patch Application
git apply can use three-way merge when the patch was generated with sufficient context and the base blob is available:
git apply --3way patch-file.patch
git am -3 does the same for mailbox patches.
91. Common Collaboration Workflows
- Centralized: everyone pushes to the same main branch (simple, needs discipline).
- Feature branch + PR: most common.
- Fork + PR: open-source and external contributors.
- Git Flow: release-oriented teams.
- Trunk-based: high-velocity teams with strong CI.
92. Common Git Mistakes
- Committing secrets → use tools like
git-secrets, scan history, rotate credentials.
- Committing to the wrong branch → cherry-pick or reset.
- Force-pushing shared branches → coordinate, prefer
--force-with-lease.
- Large binary commits → LFS or remove from history.
- Ignoring
.gitignore rules → git check-ignore, force-add only when necessary.
- Detached HEAD commits that disappear → create a branch immediately.
93. Troubleshooting
| Problem |
Approach |
| “Your branch is behind” |
git pull or git pull --rebase |
| Merge conflicts |
Resolve files, git add, continue |
| Detached HEAD |
git switch -c new-branch or return to a branch |
| Authentication failed |
Check SSH keys, PATs, credential helper |
| Large file rejected |
Use LFS or remove the file |
| “Non-fast-forward” |
Fetch + merge/rebase, or force-with-lease after review |
| Corrupted repo |
git fsck, restore from backup/reflog |
94. Recovering from Accidental Commits
- Uncommitted changes:
git restore / git checkout --
- Last commit (not pushed):
git reset --soft HEAD~1
- Last commit message only:
git commit --amend
- Pushed commit:
git revert
95. Recovering Deleted Branches
git reflog
# find the tip commit of the deleted branch
git branch recovered-branch abc1234
Or:
git switch -c recovered-branch abc1234
96. Recovering from Accidental Reset
git reflog
git reset --hard HEAD@{2} # or the appropriate entry
Act quickly; reflog entries eventually expire.
97. Undoing Pushed Changes
Preferred safe method:
git revert <commit>
git push
If absolute rewrite is required and coordinated:
git reset --hard <good-commit>
git push --force-with-lease
98. Handling Merge and Rebase Problems
- Abort:
git merge --abort / git rebase --abort
- Continue after resolving:
git add then git merge --continue / git rebase --continue
- Skip a commit during rebase:
git rebase --skip
99. Handling Divergent Branches
git pull --rebase
# or
git fetch
git rebase origin/main
# or merge
git merge origin/main
100. Handling Non-Fast-Forward Errors
The remote has commits you lack. Integrate them first:
git fetch origin
git merge origin/main
# or
git rebase origin/main
git push
Only force-push when you intentionally rewrote history and have permission.
101. Handling Rejected Pushes
Common causes:
- Non-fast-forward (see above)
- Branch protection rules
- Missing rights
- Hook rejection (pre-receive)
Read the remote error message carefully.
102. Handling Authentication Errors
- SSH: test with
ssh -T git@github.com, check key loaded in agent, correct remote URL.
- HTTPS: verify PAT validity and scopes, clear old credentials, re-authenticate.
- 2FA: always use PAT or SSH, never account password.
103. Handling Detached HEAD
git switch main # discard temporary commits
# or keep them
git switch -c temporary-work
104. Handling Large Files
- Before commit: add to
.gitignore or use Git LFS.
- After commit (not pushed):
git rm --cached, amend or soft reset.
- After push:
git filter-repo or BFG, then force-push, and notify collaborators to re-clone or reset.
105. Handling Line-Ending Problems
Configure once:
# Windows
git config --global core.autocrlf true
# macOS / Linux
git config --global core.autocrlf input
Or use .gitattributes:
* text=auto
*.sh text eol=lf
*.bat text eol=crlf
Normalize an existing repository carefully with a dedicated commit.
106. Windows, Linux, and macOS Considerations
- Line endings: biggest difference (see above).
- Case sensitivity: Linux is case-sensitive; Windows/macOS usually not. Avoid files that differ only by case.
- Executable bit: preserved on Unix, simulated on Windows.
- Path length: Windows historically limited; modern Git for Windows supports long paths.
- Credential helpers and SSH agents differ by platform.
- Shell: Git Bash, PowerShell, WSL, or native terminals.
107. Git Command Cheat Sheets by Task
(See dedicated quick-reference sections below.)
108. Everyday Git Workflow
git switch main
git pull
git switch -c feature/my-feature
# edit files
git status
git add -p
git commit -m "feat: implement my feature"
git push -u origin feature/my-feature
# open PR, address review
git switch main
git pull
git branch -d feature/my-feature
git push origin --delete feature/my-feature
109. Advanced Git Command Reference
git replace – object replacement
git notes – add notes without changing commit hash
git interpret-trailers
git range-diff
git multi-pack-index
git commit-graph
git sparse-checkout
git maintenance
git cat-file, git hash-object, git ls-files, git rev-parse (plumbing)
110. Destructive-Command Safety Guide
High risk (can lose work or rewrite published history):
git reset --hard
git clean -fd
git push --force / --force-with-lease (still dangerous on shared branches)
git filter-repo / filter-branch
git rebase of published commits
git branch -D
git tag -d + force-push of tags
git stash drop / clear
Safer alternatives:
- Prefer
git revert over history rewrite for shared commits.
- Use
--force-with-lease instead of --force.
- Create a backup branch before risky operations:
git branch backup-main.
- Consult
git reflog before giving up.
111. Git Best Practices
- Commit early and often with clear messages.
- Keep commits focused.
- Pull/rebase before starting new work.
- Never commit secrets or large binaries.
- Use feature branches and pull requests.
- Protect the main branch.
- Sign important tags and commits when required.
- Keep
.gitignore up to date.
- Review
git status and git diff before committing.
- Prefer
switch/restore over classic checkout for clarity.
112. Recommended Commit Workflow
git status / git diff
- Stage intentionally (
git add -p when useful)
- Write a precise commit message
git log -1 to verify
- Push when ready
113. Recommended Branching Practices
- Short-lived feature branches.
- Descriptive names:
feature/user-auth, fix/login-crash, chore/upgrade-deps.
- Delete branches after merge.
- Keep main/master releasable.
- Use branch protection rules on the hosting platform.
114. Security Considerations
- Never commit credentials, API keys, or private keys.
- Rotate any secrets that were committed.
- Use signed commits/tags for release integrity.
- Restrict force-push and deletion on protected branches.
- Review third-party actions/workflows carefully.
- Keep Git itself updated.
115. Performance Tips
- Use shallow/partial clones in CI.
- Enable
git maintenance.
- Avoid huge binary files in history.
- Use sparse-checkout for monorepos.
- Periodically run
git gc.
- Prefer SSH or HTTPS with persistent connections.
- Upgrade to a recent Git version (many performance improvements).
116. Quick-Reference Command Tables
Most-Used Git Commands
| Command |
Purpose |
git status |
Show working tree status |
git add <file> |
Stage changes |
git commit -m "msg" |
Commit staged changes |
git push |
Upload commits |
git pull |
Download and integrate |
git switch <branch> |
Switch branch |
git switch -c <branch> |
Create and switch |
git log --oneline |
Compact history |
git diff |
Show unstaged changes |
git stash |
Temporarily save work |
Git Commands by Task
| Task |
Commands |
| Start project |
git init, git clone |
| Save work |
git add, git commit |
| Share work |
git push, git pull, git fetch |
| Branch |
git switch -c, git branch, git merge, git rebase |
| Undo |
git restore, git reset, git revert, git stash |
| Inspect |
git status, git log, git diff, git show, git blame |
| Tag |
git tag, git push --tags |
| Clean |
git clean, git gc |
Git Branching Commands
git branch
git switch -c feature
git switch main
git merge feature
git rebase main
git branch -d feature
git push origin --delete feature
Git Remote Commands
git remote -v
git remote add origin <url>
git fetch
git pull
git push -u origin main
git remote set-url origin <new-url>
Git Undo / Recovery Commands
git restore <file>
git restore --staged <file>
git reset --soft HEAD~1
git reset --hard HEAD~1 # destructive
git revert HEAD
git reflog
git branch recovered <hash>
Git History Commands
git log --oneline --graph --all
git log -p
git log -S "term"
git show <commit>
git blame <file>
Git Inspection / Debugging Commands
git status -sb
git diff --stat
git bisect start
git fsck
git cat-file -t <hash>
git ls-files
Git Configuration Commands
git config --global user.name "Name"
git config --global user.email "email"
git config --list --show-origin
git config --global alias.lg "log --oneline --graph --decorate"
Git Stash Commands
git stash push -m "message"
git stash list
git stash pop
git stash apply
git stash drop
Git Tag Commands
git tag -a v1.0.0 -m "Release"
git tag
git push origin v1.0.0
git tag -d v1.0.0
Git Advanced Commands
git rebase -i HEAD~n
git cherry-pick <hash>
git worktree add ../other branch
git submodule update --init
git lfs track "*.bin"
git sparse-checkout set src/
git filter-repo ...
Dangerous / Destructive Commands
| Command |
Risk |
git reset --hard |
Discards uncommitted work |
git clean -fd |
Deletes untracked files |
git push --force |
Overwrites remote history |
git branch -D |
Force-deletes branch |
git rebase of published commits |
Rewrites shared history |
git filter-repo |
Rewrites entire history |
Always create a backup branch first when experimenting.
117. Common Command Combinations
# Update and create feature
git switch main && git pull && git switch -c feature/x
# Stage interactively and commit
git add -p && git commit -m "msg"
# Soft undo last commit, keep changes
git reset --soft HEAD~1
# Safe force push
git push --force-with-lease
# Pretty history
git log --oneline --graph --decorate --all -20
# Clean untracked files (dry-run first)
git clean -fdn && git clean -fd
118. Practical Real-World Examples
Starting a new project
mkdir awesome-app && cd awesome-app
git init -b main
echo "# Awesome App" > README.md
git add README.md
git commit -m "Initial commit"
git remote add origin git@github.com:user/awesome-app.git
git push -u origin main
Cloning an existing project
git clone git@github.com:user/awesome-app.git
cd awesome-app
Making and committing changes
# edit files
git status
git add -p
git commit -m "feat: add user login form"
Creating a feature branch
git switch main
git pull
git switch -c feature/payment-integration
Merging a feature branch
git switch main
git pull
git merge --no-ff feature/payment-integration
git push
Resolving a merge conflict
# after git merge or pull that conflicts
# edit conflicted files, remove markers
git add resolved-file.js
git commit
Rebasing a branch
git switch feature/x
git fetch origin
git rebase origin/main
# resolve conflicts if any, then
git push --force-with-lease
Updating a local repository
git fetch --all --prune
git switch main
git merge origin/main
Working with multiple remotes
git remote add upstream https://github.com/original/repo.git
git fetch upstream
git merge upstream/main
Undoing an uncommitted change
git restore path/to/file
# or older
git checkout -- path/to/file
Undoing a commit (not pushed)
git reset --soft HEAD~1
Undoing a pushed commit safely
git revert HEAD
git push
Recovering a deleted commit
git reflog
git branch restore-point abc1234
Recovering a deleted branch
git reflog
git switch -c old-feature-branch abc1234
Finding which commit introduced a bug
git bisect start
git bisect bad
git bisect good v1.0.0
# test, mark good/bad until found
git bisect reset
Temporarily saving unfinished work
git stash push -m "WIP: login form"
git switch main
# ... later
git switch feature/login
git stash pop
Moving changes between branches
git stash
git switch other-branch
git stash pop
# or cherry-pick specific commits
Tagging a release
git tag -a v2.1.0 -m "Release 2.1.0"
git push origin v2.1.0
Working with GitHub (typical PR flow)
git switch -c feature/x
# work + commit
git push -u origin feature/x
# open PR on GitHub, merge via UI
git switch main
git pull
git branch -d feature/x
Contributing to an open-source project
# fork on GitHub, then
git clone git@github.com:yourname/project.git
cd project
git remote add upstream https://github.com/original/project.git
git fetch upstream
git switch -c fix/typo upstream/main
# fix, commit
git push -u origin fix/typo
# open PR against upstream
119. Beginner-to-Advanced Learning Path
- Basics: install, config, init/clone, status, add, commit, log, diff.
- Branching: create, switch, merge, resolve simple conflicts.
- Remotes: push, pull, fetch, tracking branches.
- Collaboration: feature branches, pull requests, basic rebase.
- Undo & recovery: restore, reset (soft/mixed), revert, reflog.
- History rewriting: interactive rebase, amend, squash (on private branches).
- Advanced inspection: bisect, blame, pickaxe search, worktrees.
- Scaling: LFS, sparse-checkout, partial clones, submodules/subtrees, maintenance.
- Automation & integrity: hooks, signed commits, CI integration.
- Mastery: plumbing commands, filter-repo, custom workflows, performance tuning.
Practice on real projects and deliberately recover from mistakes in a safe repository.
120. Glossary of Git Terminology
| Term |
Meaning |
| Ancestor |
A commit reachable by following parent links. |
| Blob |
Object storing file content. |
| Branch |
Movable reference to a commit. |
| Checkout |
Update working tree/HEAD to a commit or branch (legacy term). |
| Cherry-pick |
Apply the changes of a specific commit. |
| Clone |
Full copy of a repository. |
| Commit |
Snapshot + metadata. |
| Conflict |
Overlapping changes Git cannot auto-merge. |
| Detached HEAD |
HEAD points directly at a commit. |
| Fast-forward |
Linear advance of a branch pointer. |
| Fetch |
Download objects/refs without merging. |
| Hash / SHA |
Unique object identifier. |
| HEAD |
Pointer to the current commit/branch. |
| Index / Staging area |
Snapshot prepared for the next commit. |
| Merge |
Combine histories. |
| Object database |
Content-addressable storage inside .git/objects. |
| Origin |
Conventional name for the primary remote. |
| Plumbing |
Low-level Git commands. |
| Porcelain |
High-level user-facing commands. |
| Rebase |
Replay commits on top of another base. |
| Ref |
Name that points to a commit (branch, tag, etc.). |
| Reflog |
Local history of ref updates. |
| Remote |
Named repository URL. |
| Remote-tracking branch |
Local ref reflecting a remote branch (origin/main). |
| Staging area |
Same as index. |
| Stash |
Temporary storage of modifications. |
| Tag |
Named, usually immutable, reference to a commit. |
| Tree |
Object representing a directory. |
| Upstream |
The branch a local branch pulls from / pushes to. |
| Working tree |
The checked-out files you edit. |
This cheat sheet covers Git as of modern 2.x releases. Commands and defaults can vary slightly by version and platform. Always consult git help <command> or the official documentation for the most authoritative details.