Git Commands

Git is a distributed version control system designed to manage and track changes to files—primarily source code—across time. Git's approach is to maintain a full local repository, complete with a complete history of every revision, in each working directory. This decentralized structure offers significant robustness, flexibility, and powerful features for branching, merging, and collaboration.

Below is a comprehensive look at many common Git commands, their usages, and their implications. This detailed explanation aims to help both newcomers and experienced developers understand Git's underlying concepts and use it effectively. Each section will provide the context, syntax, and common patterns for using the commands.


Basic Concepts and Terminology

Repository (Repo):
A data structure used by Git to store metadata and the entire history of commits. A repository can be local (on your machine) or remote (like on GitHub, GitLab, or Bitbucket).

Working Directory:
The directory in which you have a checked-out version of the project's files. Changes you make to files occur here first.

Staging Area (Index):
An intermediate area where changes get listed before committing. You add changes to the staging area with git add.

Commit:
A snapshot of your project at a given point in time. Once created with git commit, it's recorded in the repository's history.

Branch:
A pointer to a snapshot (commit) in the repository's history that can grow and evolve independently of other branches.

Remote:
A common repository that is hosted on a server or a service like GitHub. Teams push their work to and pull updates from this remote repository.


Configuration and Setup

git config

Usage:

git config [–global | –local] key value

Purpose:
Sets configuration values. –global applies settings user-wide (e.g., sets your name and email), while without the –global flag, it only applies to the current repository.

Examples:

# Set your user name and email globally
git config –global user.name "Your Name"
git config –global user.email "your.email@example.com"

# Check config values
git config –list

Common Configurations:

  • user.name: Your displayed username in commit logs.
  • user.email: The email address associated with commits you create.
  • core.editor: The default editor Git uses for commit messages and other prompts.
  • core.autocrlf: Handles line-ending conversions, useful for cross-platform teams.

Initializing and Cloning Repositories

git init

Usage:

git init [directory]

Purpose:
Creates a new Git repository. If directory is provided, Git creates a repository inside that directory; otherwise, it initializes the current directory as a repository. A .git folder is created, storing all repository data.

Example:

git init my-new-project

git clone

Usage:

git clone [repository_url] [local_directory]

Purpose:
Copies an existing remote repository (or local repository) and downloads all commits, branches, and tags. You get a working copy connected to the remote by default.

Examples:

git clone https://github.com/user/repo.git
git clone git@github.com:user/repo.git my-local-repo

Inspecting Repository State

git status

Usage:

git status

Purpose:
Shows the current state of your working directory and staging area. It displays changes that are untracked, changes that are staged for commit, and changes that have not been staged yet.

Example Output:

  • Files modified but not staged.
  • Files staged and ready to commit.
  • Untracked files (never added before).

git diff

Usage:

git diff [options] [<commit> <commit>] [–] [<path>…]

Purpose:
Compares changes between:

  • Your working directory and the staging area,
  • The staging area and the last commit,
  • Or between two commits.

Common Usage Patterns:

# Differences between working directory and staging area
git diff

# Differences between staging area and last commit
git diff –staged

# Differences between two commits
git diff commit1 commit2

git log

Usage:

git log [options]

Purpose:
Shows the commit history. By default, lists commits in reverse chronological order (most recent first). Can be customized heavily with options.

Common Options:

  • –oneline: Show each commit on a single line.
  • –graph: Show a graphical representation of the commit history.
  • –stat: Show statistics of changes (lines added/removed).
  • -p: Show the patch (actual changes) for each commit.

Examples:

git log
git log –oneline –graph –decorate –all
git log -p

Staging and Committing Changes

git add

Usage:

git add [pathspec]

Purpose:
Adds changes from the working directory to the staging area. Until you git add a changed file, that change will not be included in the next commit.

Examples:

# Stage a single file
git add file.txt

# Stage all changes in the current directory
git add .

# Stage specific directories or patterns
git add src/ *.md

git commit

Usage:

git commit -m "Commit message" git commit (to open an editor)

Purpose:
Records a snapshot of the staged changes into the repository's history as a new commit.

Common Options:

  • -m "message": Add a commit message inline.
  • –amend: Modify the most recent commit (only if you haven't pushed it yet).
  • –no-edit: Combine with –amend to keep the old message.

Examples:

git commit -m "Fix bug in user login"
git commit –amend -m "Update commit message"

Branching and Merging

git branch

Usage:

git branch [branch_name] git branch -d [branch_name]

Purpose:
Lists, creates, or deletes branches.

Examples:

# List all branches
git branch

# Create a new branch
git branch feature-branch

# Delete a branch (must be fully merged or use -D)
git branch -d feature-branch

git checkout

Usage:

git checkout [branch_name] git checkout [commit_hash] — [filename]

Purpose:
Switches to a specified branch or updates files in the working directory to match a specific commit. Before Git 2.23, git checkout was used to switch branches. Now, git switch is often recommended for changing branches, and git restore for discarding changes.

Examples:

# Switch to a branch
git checkout main

# Create and switch to a new branch
git checkout -b new-feature

# Discard changes to a file
git checkout — file.txt

# Move working directory to a certain commit (detached HEAD)
git checkout abc1234

git switch (Introduced in newer Git versions)

Usage:

git switch [branch_name] git switch -c [branch_name]

Purpose:
A cleaner command to switch branches without the confusion caused by git checkout.

Examples:

# Switch to an existing branch
git switch main

# Create and switch to a new branch
git switch -c feature-branch

git merge

Usage:

git merge [branch_name]

Purpose:
Combines changes from one branch into the current branch. Git attempts an automatic merge; if conflicts arise, you must resolve them, then commit the merge.

Examples:

# Merge feature-branch into the current branch
git merge feature-branch

Rebasing and Rewriting History

git rebase

Usage:

git rebase [base_branch] git rebase -i [commit_hash or branch_name]

Purpose:
Moves or replays commits on top of another base commit, effectively rewriting the commit history. Often used to maintain a clean, linear project history.

Common Scenarios:

  • Regular Rebase: Sync your feature branch with the main branch by rebasing your changes on top of the latest main.
  • Interactive Rebase (-i): Squash, reorder, or edit commit messages before merging.

Examples:

# Rebase your current branch on main
git rebase main

# Interactive rebase the last 4 commits
git rebase -i HEAD~4

Important Note:
Rewriting history that others have already pulled can cause confusion. Use rebase carefully, and generally avoid rebasing public branches.


Fetching, Pulling, and Pushing

git remote

Usage:

git remote -v git remote add [name] [url] git remote remove [name]

Purpose:
Manages a list of remote repositories. Use it to add, list, or remove remotes.

Examples:

# List remotes
git remote -v

# Add a remote
git remote add origin https://github.com/user/repo.git

# Remove a remote
git remote remove origin

git fetch

Usage:

git fetch [remote] [branch]

Purpose:
Downloads changes (commits, branches, tags) from the remote repository but does not integrate them into your local branches. Useful for checking what changes are available before merging or rebasing.

Examples:

# Fetch all branches from origin
git fetch origin

# Fetch a single branch
git fetch origin main

git pull

Usage:

git pull [remote] [branch]

Purpose:
Fetches and then integrates (merges) changes from a remote branch into your current branch. It is essentially a git fetch followed by a git merge.

Examples:

git pull
git pull origin main

Recommendation:
Some developers prefer git fetch then git merge (or git rebase) manually to have more control over the integration step, rather than using git pull directly.

git push

Usage:

git push [remote] [branch]

Purpose:
Uploads your local commits to the remote repository branch.

Common Options:

  • –set-upstream: Establishes a tracking relationship with the remote branch so future git push commands can omit arguments.
  • –force or -f: Overwrites remote history if necessary; use with caution.

Examples:

# Push current branch to origin
git push origin main

# Set upstream and push
git push -u origin feature-branch

Stashing Changes

git stash

Usage:

git stash [push] git stash pop git stash list git stash drop

Purpose:
Temporarily shelve changes you've made to your working copy without committing them, allowing you to switch branches or pull in changes without losing your current work.

Examples:

# Stash all changes
git stash

# Stash changes with a message
git stash push -m "WIP: working on login form"

# List stashes
git stash list

# Apply and remove the most recent stash
git stash pop

# Apply (but do not remove) the most recent stash
git stash apply

# Drop a stash
git stash drop

Tagging

git tag

Usage:

git tag [tag_name] [commit_hash] git tag -a [tag_name] -m "Message"

Purpose:
Create references to specific points in Git history, often used to mark release versions.

Examples:

# Create a lightweight tag on the current commit
git tag v1.0.0

# Create an annotated tag with a message
git tag -a v1.0.1 -m "Release v1.0.1"

# Tag a past commit
git tag v0.9.0 abc1234

Pushing Tags:

# Push a single tag
git push origin v1.0.0

# Push all tags
git push origin –tags

Advanced Tools

git cherry-pick

Usage:

git cherry-pick [commit_hash]

Purpose:
Apply changes from a single commit (or a set of commits) from one branch onto your current branch. This allows selective integration of changes without merging the entire branch.

Example:

git cherry-pick abc1234

git revert

Usage:

git revert [commit_hash]

Purpose:
Creates a new commit that undoes the changes from a specified commit. Unlike git reset, git revert is safe for public branches because it doesn't rewrite history.

Example:

git revert abc1234

git reset

Usage:

git reset [–soft | –mixed | –hard] [commit]

Purpose:
Moves the current branch HEAD to a specific commit. It can also modify the staging area and/or the working directory depending on the mode.

Modes:

  • –soft: Move HEAD but leave changes in the staging area and working directory.
  • –mixed (default): Move HEAD and reset the staging area, leave working directory changes untouched.
  • –hard: Move HEAD, reset staging area and working directory to the specified commit, discarding changes permanently.

Example:

# Move HEAD to a previous commit but keep work in staging area
git reset –soft HEAD~1

# Move HEAD one commit back and clear staging area
git reset HEAD~1

# Permanently discard changes and move HEAD back
git reset –hard HEAD~1

Warning:
git reset –hard is destructive. Changes that were not committed are lost.


Viewing and Managing References

git reflog

Usage:

git reflog

Purpose:
Shows a log of all the references (HEAD moves, branch changes) that happened in the repository. This is helpful for recovering commits you may have lost due to resets, rebases, etc.

Example:

git reflog

Practical Tips

  1. Clean Working Tree Before Switching Branches:
    Use git stash or commit your changes to avoid conflicts.
  2. Use Branches Liberally:
    Branches are cheap and encourage experimenting without endangering the main codebase.
  3. Commit Often, with Meaningful Messages:
    Frequent commits with descriptive messages help track changes and revert easily if needed.
  4. Pull Often, or Rebase Frequently, When Working with a Team:
    Stay synced with the remote repository to minimize complex merges.
  5. Check Status and Diff Before Committing:
    Always know what you're committing and why.

In Summary:
The Git commands listed above form the core workflow for software development teams. Mastering these commands involves understanding what each step does to the repository state, and how best to maintain a clear, maintainable commit history. Over time, you'll gain the intuition to choose between merges and rebases, when to reset or revert, and how to use tags and branches effectively to manage your project's growth.