Git Version Control

Git cheatsheet — undo commits, stash, rebase, merge, resolve conflicts, push, pull. Every command with real examples. The only Git reference you need.

9 min read

What it is

Git is a distributed version control system for tracking changes in source code during software development, enabling collaboration and rollback capabilities.

Installation

Linux

sudo apt update
sudo apt install git

or

sudo yum install git

macOS

Using Homebrew:

brew install git

Or download from the official Git website: https://git-scm.com/downloads

Windows

Download the installer from the official Git website: https://git-scm.com/downloads

Core Concepts

  • Repository (Repo): A collection of files and their history. Can be local (on your machine) or remote (on a server like GitHub, GitLab, Bitbucket).
  • Working Directory: The directory on your file system where your project files reside.
  • Staging Area (Index): An intermediate area where you prepare changes to be committed. You add specific changes to the staging area before committing them.
  • Commit: A snapshot of your project at a specific point in time. Each commit has a unique identifier (SHA-1 hash) and a commit message describing the changes.
  • Branch: An independent line of development. Branches allow you to work on new features or fixes without affecting the main codebase. main (or master) is typically the primary branch.
  • HEAD: A pointer to the currently checked-out commit or branch.
  • Remote: A repository hosted on a different server, usually for collaboration. origin is the conventional name for the default remote repository.
  • Fetch: Downloads commits, files, and refs from a remote repository into your local repo, but does not merge them into your local working branch.
  • Pull: Fetches from and integrates with another repository or a local branch. It’s a git fetch followed by a git merge.
  • Push: Updates your remote repository with commits from your local repository.

Commands / Usage

Initializing and Configuring a Repository

  • git init Initialize an empty Git repository in the current directory.
    git init
    
  • git init <directory> Initialize an empty Git repository in a specified directory.
    git init my-new-project
    
  • git clone <repository_url> Clone a remote repository to your local machine.
    git clone https://github.com/user/repo.git
    
  • git config --global user.name "Your Name" Set your Git username for all repositories on your system.
    git config --global user.name "Alice Wonderland"
    
  • git config --global user.email "youremail@example.com" Set your Git email address for all repositories on your system.
    git config --global user.email "alice@example.com"
    
  • git config --list View your Git configuration settings.
    git config --list
    

Making Changes and Committing

  • git status Show the status of your working directory and staging area.
    git status
    
  • git add <file> Add a specific file to the staging area.
    git add README.md
    
  • git add . Add all changes in the current directory and subdirectories to the staging area.
    git add .
    
  • git add -u Stage modified and deleted files, but not new files.
    git add -u
    
  • git commit -m "Commit message" Commit staged changes with a descriptive message.
    git commit -m "Add initial README file"
    
  • git commit -am "Commit message" Stage all tracked modified files and commit them with a message (skips git add).
    git commit -am "Update project configuration"
    
  • git commit --amend Amend the last commit, allowing you to add forgotten changes or modify the commit message.
    git commit --amend
    
    (This will open your editor to modify the message and staged changes).
  • git restore <file> Discard changes in the working directory for a specific file (restores to the last commit).
    git restore index.html
    
  • git restore --staged <file> Unstage a file (remove it from the staging area).
    git restore --staged main.py
    

Viewing History

  • git log Show the commit history.
    git log
    
  • git log --oneline Show commit history in a compact, one-line format.
    git log --oneline
    
  • git log --graph --oneline --all Show a graphical representation of commit history across all branches.
    git log --graph --oneline --all
    
  • git diff Show changes between the working directory and the staging area.
    git diff
    
  • git diff --staged Show changes between the staging area and the last commit.
    git diff --staged
    
  • git diff <commit> Show changes between the working directory and a specific commit.
    git diff HEAD~1
    
  • git diff <commit1> <commit2> Show changes between two specific commits.
    git diff abc1234 def5678
    

Working with Branches

  • git branch List all local branches.
    git branch
    
  • git branch <branch_name> Create a new branch.
    git branch feature-login
    
  • git checkout <branch_name> Switch to a different branch.
    git checkout feature-login
    
  • git checkout -b <branch_name> Create a new branch and switch to it immediately.
    git checkout -b bugfix-navbar
    
  • git merge <branch_name> Merge changes from another branch into your current branch.
    git merge feature-login
    
  • git branch -d <branch_name> Delete a local branch (only if it has been fully merged).
    git branch -d feature-login
    
  • git branch -D <branch_name> Force delete a local branch (even if not merged).
    git branch -D experimental-feature
    
  • git branch -m <old_branch_name> <new_branch_name> Rename a branch.
    git branch -m main master
    

Working with Remotes

  • git remote -v List all remote repositories configured for your local repository.
    git remote -v
    
  • git remote add <remote_name> <repository_url> Add a new remote repository.
    git remote add origin https://github.com/user/repo.git
    
  • git fetch <remote_name> Download commits and objects from a remote repository.
    git fetch origin
    
  • git pull <remote_name> <branch_name> Fetch from and integrate with a remote branch.
    git pull origin main
    
  • git push <remote_name> <branch_name> Push your local branch commits to a remote repository.
    git push origin main
    
  • git push -u <remote_name> <branch_name> Push your local branch and set the upstream tracking branch.
    git push -u origin feature-login
    
  • git push <remote_name> --delete <branch_name> Delete a branch on the remote repository.
    git push origin --delete feature-login
    

Undoing Changes

  • git reset <commit> Reset the current branch to a specified commit. Be cautious with this command as it can discard history. --soft: Moves HEAD to the commit, staging area and working directory are unchanged. --mixed: Moves HEAD to the commit, staging area is reset, working directory is unchanged. (This is the default). --hard: Moves HEAD to the commit, resets staging area and working directory to match the commit. This discards all subsequent changes.
    git reset --hard HEAD~1 # Discard the last commit and its changes
    git reset --soft HEAD~2 # Move HEAD back two commits, keep changes staged
    
  • git revert <commit> Create a new commit that undoes the changes introduced by a specified commit. This is safer for shared history.
    git revert abc1234
    
  • git clean -n See what untracked files would be removed.
    git clean -n
    
  • git clean -f Remove untracked files from the working directory.
    git clean -f
    
  • git clean -fd Remove untracked files and directories from the working directory.
    git clean -fd
    

Stashing Changes

  • git stash Save your uncommitted local changes (both staged and unstaged) so you can switch branches or work on something else.
    git stash
    
  • git stash list List all stashes.
    git stash list
    
  • git stash apply [stash@{n}] Re-apply the changes from a stash (the stash remains in the list).
    git stash apply stash@{2}
    
  • git stash pop [stash@{n}] Re-apply the changes from a stash and remove it from the stash list.
    git stash pop
    
  • git stash drop [stash@{n}] Remove a stash from the list.
    git stash drop stash@{1}
    
  • git stash clear Remove all stashes.
    git stash clear
    

Tagging Releases

  • git tag List all tags.
    git tag
    
  • git tag <tag_name> Create a lightweight tag at the current commit.
    git tag v1.0.0
    
  • git tag -a <tag_name> -m "Tag message" Create an annotated tag with a message.
    git tag -a v1.0.1 -m "Release version 1.0.1"
    
  • git tag -d <tag_name> Delete a tag.
    git tag -d v1.0.0
    
  • git push origin <tag_name> Push a specific tag to the remote.
    git push origin v1.0.1
    
  • git push origin --tags Push all local tags to the remote.
    git push origin --tags
    

Common Patterns

  • Creating a new branch, making changes, committing, and pushing:
    git checkout -b new-feature
    # ... make changes ...
    git add .
    git commit -m "Implement new feature X"
    git push -u origin new-feature
    
  • Pulling changes from remote and merging into current branch:
    git checkout main
    git pull origin main
    
  • Rebasing a branch onto the latest main:
    git checkout my-feature-branch
    git fetch origin main
    git rebase origin/main
    # Resolve any conflicts if they occur
    git push --force-with-lease origin my-feature-branch # Use force-with-lease after rebasing
    
  • Discarding all local changes:
    git reset --hard HEAD
    git clean -fd
    
  • Viewing changes introduced in the last commit:
    git show HEAD
    
  • Viewing changes for a specific file across all commits:
    git log -p -- <file_path>
    
    Example:
    git log -p -- src/app.js
    
  • Stashing changes and applying them later:
    git stash push -m "Work on login form" # Add a message to the stash
    # ... do other work ...
    git stash pop
    
  • Finding which commit introduced a bug (Binary Search):
    git bisect start
    git bisect bad HEAD # Mark current commit as bad
    git bisect good <commit_hash_before_bug> # Mark an older commit as good
    # Git will checkout a commit in the middle. Test it.
    git bisect good # If the bug is NOT present
    git bisect bad # If the bug IS present
    # Repeat until Git pinpoints the commit
    git bisect reset # Exit bisect mode
    

Gotchas

  • git pull vs git fetch: git pull fetches and merges, potentially creating merge commits. git fetch only downloads changes, giving you a chance to review before merging.
  • git reset --hard is destructive: It discards committed changes. Be extremely careful, especially on shared branches. Prefer git revert for undoing published history.
  • Force pushing (git push --force): Overwrites the history on the remote. This can cause problems for collaborators. Use git push --force-with-lease which is safer as it checks if the remote branch has been updated by someone else since your last fetch.
  • Committing sensitive information: Never commit passwords, API keys, or other secrets directly into Git. Use .gitignore or environment variables.
  • Large files: Git is not optimized for large binary files. Consider using Git LFS (Large File Storage).
  • Branch naming conventions: While Git allows almost any name, using consistent naming (e.g., feature/, bugfix/, hotfix/) improves clarity.
  • Merge Conflicts: When Git cannot automatically combine changes from different branches, it flags a merge conflict. You must manually edit the conflicted files to resolve them, then git add and git commit to complete the merge.
  • Stale origin/main: If you work on a branch and others push to main, your local origin/main pointer will be outdated. Always git fetch before rebasing or merging main into your branch.