Git Cheat Sheet

Git Concepts & Terminology Cheat Sheet

Fundamental Concepts

  • repository: A data structure where Git stores all the project files, including their entire history.
  • bare repository: A repository that does not have a working tree. It’s typically used as a central remote repository.
  • local repository: The repository on your computer where you work on your project.
  • remote repository: A version of the repository hosted on the internet or a network, allowing collaboration.
  • working tree: The directory on your file system that contains the actual files you’re working on.
  • index / staging area: A layer between the working tree and the repository. It’s where you prepare a set of changes before committing them.
  • tracked files: Files that Git knows about and are part of the repository’s history.
  • untracked files: Files in the working tree that Git doesn’t know about and aren’t part of the repository’s history.
  • commit: A snapshot of the repository at a specific point in time. It includes a unique hash, a message, and metadata.
  • staged: Changes that have been added to the staging area, ready to be committed.
  • un-staged: Changes that have been made in the working tree but have not yet been added to the staging area.

Core Commands & Operations

  • init: A command to create a new, empty Git repository.
  • clone: A command to create a copy of a remote repository on your local machine.
  • add: A command to move changes from the working tree to the staging area.
  • commit: A command to save the changes from the staging area into the repository as a new commit.
  • push: A command to send your local commits to a remote repository.
  • pull: A command to fetch changes from a remote repository and automatically merge them into your current branch.
  • fetch: A command to download commits, files, and refs from a remote repository into your local repository without merging them.
  • merge: A command to combine a sequence of commits into a single unified history.
  • rebase: A command to move a sequence of commits to a new base commit, rewriting history.
  • stash: A command to temporarily save changes in your working tree that are not yet ready to be committed, allowing you to switch branches or perform other tasks.
  • cherry-pick: A command to apply the changes from a single commit to your current branch.
  • patch: A file format that represents the changes between two versions of a file or a set of files. It can be applied to update a codebase.

Branches & Pointers

  • branch: A lightweight, movable pointer to a commit. It allows for parallel development.
  • origin: A conventional name for the default remote repository that you cloned from.
  • HEAD: A pointer that refers to the last commit on the current branch. It’s your current location in the repository’s history.
  • tag: A permanent pointer to a specific commit, often used to mark releases or milestones.

Advanced Concepts & Files

  • gitignore: A text file that specifies intentionally untracked files that Git should ignore.
  • hook: Scripts that Git executes at certain points in its operation, such as before a commit or after a push.
  • history: The complete set of commits and their relationships, forming the timeline of a project.
  • logs: A command to view the history of commits in the repository.
  • reflog: A log that records updates to the tips of branches and other references in the local repository. It can be used to recover lost commits.
  • cherry-pick: A command to apply the changes from a single commit to your current branch.
  • patch: A file format that represents the changes between two versions of a file or a set of files. It can be applied to update a codebase.

Merging Specifics

  • fast-forward merge: A merge that occurs when the current branch is a direct ancestor of the branch being merged. Git simply moves the HEAD pointer forward.
  • three-way merge: A merge that is required when the histories of the two branches have diverged. Git uses a common ancestor and the latest commits from both branches to create a new merge commit.
  • rebase: A command to move a sequence of commits to a new base commit, rewriting history. It can be a way to create a linear history.
  • squash: The action of combining multiple commits into a single new commit.
  • conflict: Occurs when two branches have changed the same part of a file, and Git cannot automatically merge them. A user must manually resolve the differences.

Repository States & Objects

  • BLOB: Binary Large Object. The object type that Git uses to store the contents of a file.
  • TREE: The object type that Git uses to store the directory structure and the references to files (BLOBs) and subdirectories (other TREEs).
  • COMMIT: The object type that stores the commit message, author, committer, and a pointer to a TREE object representing the repository’s state.
  • TAG: The object type for a lightweight or annotated tag. An annotated tag stores extra metadata.
  • detached HEAD: A state where the HEAD is pointing directly to a commit, not a branch. This can happen when you check out a specific commit or tag.

Additional Terminology

  • alias: A shortcut you can create for a longer Git command.
  • fork: Creating a full copy of a repository on a service like GitHub, which you can then modify and propose changes back to the original.
  • submodule: A way to include another repository as a subdirectory in your own repository. This is useful for managing dependencies.
  • upstream: The branch on the remote repository that your local branch is set to track.
  • downstream: The branch on your local repository that tracks an upstream branch.
  • origin/master: A common convention for referring to the master branch on the remote repository named ‘origin’.
  • diff: The difference between two files, two commits, or a file and its staged version. The git diff command is used to show these differences.

Git Commands Cheat Sheet

git init

git init is a command used to create a new, empty Git repository. It’s the first step in starting a new project with version control.

Basic Usage

git init

  • What it does: It transforms the current directory into a Git repository by creating a hidden .git subdirectory. This directory contains all the necessary files for tracking your project’s history, branches, and commits.
  • Where to run it: You should run this command inside the project directory you want to version control.
  • Result: You will see a message confirming the initialization of an empty Git repository. Your project files are not yet tracked; you’ve just set up the infrastructure.

How to use it

  1. Navigate to your project’s root directory in the terminal.
  2. Run the command git init.
  3. Confirm that a .git folder has been created. You may need to enable viewing hidden files to see it.

Example:

# Assuming your project is in a folder called 'my_awesome_project'
cd my_awesome_project
git init

Options & Flags

  • --bare: Creates a bare repository, which is a repository without a working directory. This is typically used for a central, shared repository on a server. You cannot edit files or commit directly to a bare repository.
  • --initial-branch=<name>: Specifies the name of the initial branch created in the new repository. The default is usually master or main.

Example with options:

# Creates a new bare repository in the "project.git" directory
git init --bare project.git
# Creates a new repository with the initial branch named 'develop'
git init --initial-branch=develop

git clone

git clone is a command used to create a copy of an existing Git repository. It’s the standard way to get a local copy of a project that’s hosted on a remote server like GitHub, GitLab, or Bitbucket.

Basic Usage

git clone <repository_url>

  • What it does: This command downloads the entire repository, including all files, branches, and the complete commit history. It also automatically sets up a new local repository and a remote connection, typically named origin, that points back to the original repository.
  • Result: A new directory will be created in your current location with the same name as the repository. Inside this directory, you’ll find the project files and the hidden .git folder.

Example:

# Clones a public repository from GitHub
git clone https://github.com/git/git.git

Common Options & Flags

  • –branch <name>: Clones a specific branch instead of the default branch (e.g., main or master).Example: git clone –branch develop <repository_url>
  • –depth <number>: Creates a shallow clone with a history truncated to the specified number of commits. This is useful for large repositories where you only need the most recent history.Example: git clone –depth 1 <repository_url>
  • –bare: Creates a bare repository with no working directory. This is useful for creating a central, shared repository on a server.Example: git clone –bare <repository_url>
  • <directory>: Specifies a different directory name for the cloned repository instead of using the default repository name.Example: git clone <repository_url> my-new-project-folder

git clone vs. Other Commands

  • git clone vs. git pull:
    • git clone is a one-time operation for getting a project for the first time. It downloads the entire repository and creates a local working copy.
    • git pull is used to update an existing local repository with the latest changes from the remote. It’s a combination of git fetch (downloading new changes) and git merge (integrating those changes).
  • git clone vs. git init:
    • git clone copies an existing repository from a remote location.
    • git init creates a new, empty local repository from scratch.

git branch

git branch is a powerful and versatile command for managing branches in your Git repository. Its primary functions are to list, create, delete, and rename branches.

Basic Usage

  • git branch: Lists all local branches in your repository. The currently active branch will be marked with an asterisk (*) and often highlighted in a different color.
  • git branch <new-branch-name>: Creates a new branch with the specified name. It does not automatically switch you to this new branch. The new branch is created as a pointer to the current commit of the branch you’re on.
  • git branch --initial-branch=<name>: Creates a new, empty repository with the initial branch set to the specified name. This is an advanced usage, typically combined with git init.

Options & Flags

  • -a (--all): Lists both local and remote-tracking branches. Remote branches are prefixed with the remote’s name (e.g., remotes/origin/main).
  • -r (--remotes): Lists only the remote-tracking branches.
  • -v (--verbose): Displays more information about each branch, including the SHA-1 hash and the commit message of the last commit on that branch.
  • -d <branch-name> (--delete): Deletes a local branch. This is a “safe” operation that prevents you from deleting a branch that has unmerged changes.
  • -D <branch-name>: A force-delete command. It will delete the specified branch regardless of its merge status. Use this with caution, as it can lead to losing work.
  • -m <old-name> <new-name> (--move): Renames a local branch. If you are currently on the branch you want to rename, you can omit the <old-name>.
  • --merged: Lists only the branches that have been fully merged into your current branch. This is useful for cleanup.
  • --no-merged: Lists branches that have not been merged into your current branch. This helps you find branches with un-integrated work.

Combined Commands & Workflows

While git branch is for managing branches, other commands are needed to work with them:

  • Create and switch to a new branch: A common workflow is to create a branch and immediately start working on it.
    • git checkout -b <new-branch-name>: This is a shortcut that combines git branch <new-branch-name> and git checkout <new-branch-name>.
  • Rename and push:
    1. git branch -m <new-name> (rename local branch)
    2. git push origin -u <new-name> (push the renamed branch to the remote, and set it as the upstream tracking branch)
    3. git push origin --delete <old-name> (delete the old branch from the remote)
  • Deleting a remote branch:
    • git push <remote> --delete <branch-name>: Deletes a branch on the remote repository. This is a common practice after a feature branch has been merged and is no longer needed.

git status

git status is a command that displays the state of your working directory and staging area. It shows which files have been modified, staged, and untracked since your last commit, but it doesn’t show any information about the project’s commit history.

Understanding the Output

The output of git status is typically divided into a few key sections.

  1. On branch…: This first line tells you which branch you’re currently working on. It may also tell you if your local branch is “ahead” or “behind” the remote branch, indicating whether you need to push or pull.
  2. Changes to be committed: This section lists files that have been staged with git add and are ready to be included in the next commit. These are also known as staged changes.
  3. Changes not staged for commit: This section shows files that have been modified in your working directory but have not yet been added to the staging area with git add. These are also known as unstaged changes.
  4. Untracked files: This section lists files that are in your working directory but are not yet tracked by Git. These are typically new files that you have not added to the repository’s history.

Common States of a File

When you run git status, a file can be in one of the following states:

  • Untracked: The file is new and has not been added to Git’s tracking system.
  • Modified: The file has been changed since the last commit.
  • Staged: The modified file has been added to the staging area with git add and is ready for the next commit.
  • Unmodified: The file has not been changed since the last commit. git status won’t show these files.

Common Options & Flags

  • -s or --short: This provides a more concise, single-line output that is useful for scripting or when you just want a quick overview. It uses a two-column format: the left column indicates the status in the staging area, and the right column indicates the status in the working directory.
    • M file.txt: The file is modified in the working directory but not staged.
    • A file.txt: The file has been added to the staging area.
    • AM file.txt: The file has been added and committed, but also modified again in the working directory.
  • --ignored: This shows the files that are being ignored by Git, as specified in your .gitignore file.
  • -v or --verbose: This shows a more detailed output, including the textual changes (diffs) of the modified files, similar to the output of git diff.

git add

git add is a fundamental command that moves changes from your working directory into the staging area (also known as the index). This prepares your changes to be included in the next commit. Think of it as telling Git, “I’m ready to save these changes.”

Basic Usage

  • git add <file-name>: Stages a specific file. This is the most common way to use the command.Example: git add index.html stages only the changes made to the index.html file.
  • git add .: Stages all changes in the current directory, including new files and modifications. This is a powerful shortcut, but use it with caution to avoid staging unwanted files.
  • git add -A or git add --all: Stages all changes in the entire repository, regardless of your current location within the repository. This is similar to git add . but operates from the repository’s root.

Key Options & Flags

  • -p or –patch: This is a powerful option that lets you interactively stage parts of a changed file. Git will walk you through the “hunks” (chunks of code) and ask you if you want to stage each one individually. This is excellent for creating clean, focused commits.Example: git add -p my-feature-file.js
  • -u or –update: Stages only modified and deleted files that are already being tracked by Git. It does not stage new, untracked files. This is a good way to stage changes without accidentally including new files you might be working on.Example: git add -u

git add vs. git commit

  • git add prepares changes. It moves them from the working directory to the staging area. Your changes are not yet saved to the repository’s history.
  • git commit saves the staged changes. It creates a permanent snapshot of the staged changes and records them in the repository’s history with a unique ID and a message.

You must run git add before every git commit to include new or modified files in that commit.

Common Workflows

  1. Stage a single file:git add style.cssgit commit -m “Add basic styling”
  2. Stage all changes in the current directory:git add .git commit -m “Update homepage and add new assets”
  3. Stage a modified file and ignore a new one:git add -ugit commit -m “Fix bug in main script”

git commit

git commit is the command that saves your staged changes to the Git repository. Each commit is a unique snapshot of your project at a specific point in time, marked by a unique ID (a SHA-1 hash) and a commit message.

Basic Usage

git commit

  • What it does: This command creates a new commit containing all the files you have added to the staging area with git add. It will then open a text editor for you to write a commit message.
  • Result: A new commit is created in your local repository’s history, and the staging area is cleared.

Committing with a Message

git commit -m "Your commit message here"

  • What it does: This is the most common way to commit. The -m flag allows you to provide a commit message directly in the command line without opening a separate text editor.
  • Best practice: A good commit message is short (50 characters or less) and describes the changes you’ve made. It should complete the sentence “This commit will…”

Key Options & Flags

  • -a or --all: This is a shortcut that automatically stages all modified and deleted files that are already being tracked by Git, and then performs the commit. It does not stage new, untracked files.
    • Example: git commit -a -m "Update some files"
  • --amend: This command allows you to change your last commit. It’s used to add new changes to the previous commit or to correct a mistake in the commit message. The new commit will replace the old one, but it will have a different SHA-1 hash.
    • Example:
      1. git add new-file.txt (stage a new file you forgot to add)
      2. git commit --amend -m "Add feature X and new file" (amend the previous commit)
  • --no-verify: This option bypasses pre-commit hooks. Hooks are scripts that run automatically before a commit, for tasks like linting code or running tests.
    • Example: git commit --no-verify -m "Skip linting for now"

git commit vs. Other Commands

  • git commit vs. git add: You must first use git add to move changes to the staging area before you can use git commit to save them to the repository.
  • git commit vs. git push:
    • git commit saves a snapshot of your project to your local repository.
    • git push uploads those local commits to a remote repository, making them available to other collaborators.

git diff

git diff is a command that shows the difference between two states of your repository. It is a powerful tool for inspecting what has changed, whether it’s in your working directory, the staging area, or between commits.

Basic Usage

  • git diff: Shows unstaged changes—the difference between your working directory and the staging area. It displays the modifications you’ve made to tracked files that you haven’t yet run git add on.
  • git diff --staged or git diff --cached: Shows staged changes—the difference between the staging area and the last commit. This lets you review what you’ve added with git add before you run git commit.

Comparing Different States

  • Between two commits:git diff <commit1> <commit2>This shows the differences between the two specified commits. You can use commit hashes, branch names, or tags. For example, git diff HEAD HEAD^ compares your last commit with the one before it.
  • Between a branch and your current state:git diff <branch-name>This shows the differences between your current working directory and the tip of the specified branch. This is useful for seeing what changes you have locally that are not yet on another branch.
  • Between two branches:git diff <branch1> <branch2>This shows the difference between the latest commits on two different branches.

Key Options & Flags

  • --name-only: Shows only the names of the files that have changed, without displaying the actual line-by-line differences. This is useful for getting a quick overview.
  • --stat: Shows a summary of the changes, including a list of the modified files and the number of lines added and removed for each.
  • --color-words: Shows the differences by highlighting changed words instead of entire lines. This can be very helpful for reviewing a lot of text, as it makes subtle changes easier to spot.
  • <file-path>: When added to any git diff command, this limits the output to show changes only for the specified file. For example, git diff --staged index.html will only show the staged changes for that specific file.

git log

git log is a command used to view the commit history of a Git repository. It is a powerful tool for exploring the timeline of a project, understanding who made what changes, and when.

Basic Usage

  • git log: Displays the commit history starting from the most recent commit. Each entry shows the commit ID (SHA-1 hash), author, date, and commit message.
    • Result: The command opens a pager (like less) to display the log. You can use arrow keys to scroll, q to quit, and / to search.

Common Options & Flags

  • --oneline: Shows each commit on a single line. This provides a compact and easy-to-read summary, displaying a shortened commit hash and the commit message.
    • Example: git log --oneline
  • --graph: Renders a text-based graph of the branch and merge history. This is particularly useful when combined with other flags.
    • Example: git log --oneline --graph
  • --decorate: Shows all the branch and tag names that point to the commits in the log. This is often used with --oneline to see where branches are pointing.
    • Example: git log --oneline --decorate
  • -p or --patch: Shows the full diff (the changes) for each commit in the log. This is useful for reviewing the exact modifications made in each commit.
  • -n <number>: Limits the number of commits shown to the specified number.
    • Example: git log -n 5 will show the last 5 commits.
  • --author="<author-name>": Filters the log to show only commits by a specific author.
    • Example: git log --author="John Doe"
  • --since="<date>" or --until="<date>": Filters commits by date. You can use various date formats like "2 weeks ago", "2025-09-06", or "yesterday".
    • Example: git log --since="2 weeks ago"

Viewing Specific Commits or Files

  • git log <file-path>: Shows the commit history for a specific file. This helps you track all the changes made to that file over time.
    • Example: git log src/app.js
  • git log <commit-hash>..<commit-hash>: Shows the commits between two specific points in the history.
    • Example: git log 82b8811..HEAD shows all commits from the specified hash to the current commit.
  • git log --merges: Shows only merge commits, which can be helpful for understanding the branch integration history.

git tag

git tag is a command used to create, list, and delete tags. Tags are essentially permanent, static pointers to specific commits. They are most commonly used to mark release points in a project’s history, such as v1.0.0 or v2.0-beta. Unlike branches, tags don’t move.

Basic Usage

  • git tag: Lists all tags in your local repository.
  • git tag <tag-name>: Creates a new lightweight tag on the current commit. Lightweight tags are just pointers to a commit.
    • Example: git tag v1.0.0

Annotated Tags vs. Lightweight Tags

Git offers two types of tags, and it is a best practice to use annotated tags for releases.

FeatureAnnotated TagLightweight Tag
Commandgit tag -a <tag-name>git tag <tag-name>
InformationStores the tagger’s name, email, date, and a message.Just a name and a pointer to a commit.
StorageStored as a full object in the Git database.Stored as a simple pointer (a reference).
Use CaseRecommended for project releases.For temporary or private use.

To create an annotated tag, you use the -a flag:

  • git tag -a <tag-name> -m "Tag message"
  • Example: git tag -a v1.0.0 -m "Initial public release"

Advanced Use Cases

  • Tag a specific past commit: To tag a commit other than your current one, specify its hash at the end of the command.
    • Example: git tag -a v0.9.0 9f1b2c4
  • Share tags with a remote repository: Tags are not automatically pushed with your commits. You must explicitly push them.
    • Push a single tag: git push <remote-name> <tag-name> (e.g., git push origin v1.0.0)
    • Push all tags: git push <remote-name> --tags
  • Delete a tag:
    • Delete a local tag: git tag -d <tag-name> (e.g., git tag -d v1.0.0)
    • Delete a remote tag: git push <remote-name> --delete <tag-name> (e.g., git push origin --delete v1.0.0)

Key Takeaway

git tag is crucial for marking significant milestones in your project’s lifecycle. While branches are for active development, tags provide a static, permanent reference point to a version, making it easy for users and collaborators to check out a stable release.

git mv

git mv is a command used to move or rename a file or directory that is already tracked by Git. It is a convenience command that combines the file system’s move/rename operation with staging the changes for a commit.

Basic Usage

git mv <source> <destination>

  • What it does: This command renames the file or directory from the <source> path to the <destination> path.
  • Result: It performs two actions in one step:
    1. It renames the file on your file system.
    2. It stages the change for you, so you don’t need to manually use git add afterward.

Example:

# Rename the file 'old-name.txt' to 'new-name.txt'
git mv old-name.txt new-name.txt
# Now, run git status to see the change is already staged
git status
# Commit the change
git commit -m "Rename old-name.txt to new-name.txt"

Why Not Just Use mv?

While you can use the standard mv command to move files, doing so requires an extra step.

If you use mv directly, Git will see it as two separate events: a deleted file (the original file) and an untracked file (the new file). You would then have to manually git add the new file and git rm the old one.

git mv automates this process, ensuring that Git understands the file was moved and not deleted and recreated.

Common Options & Flags

  • -f or --force: Forces the move or rename, even if the destination file already exists.
  • -n or --dry-run: Shows what the command would do without actually performing the move. This is helpful for avoiding mistakes.
  • -v or --verbose: Shows the names of the files being moved.

Example with options:

# Force the move and overwrite 'file-B.txt' if it exists
git mv -f file-A.txt file-B.txt
# See what would happen without making the change
git mv --dry-run file.txt new-location/

git rm

git rm is a command used to remove files from your Git repository. It performs two actions in one step: it deletes the file from your file system and stages the deletion for the next commit.

Basic Usage

  • git rm <file-name>: Deletes the specified file from both your working directory and the staging area. The file will be removed in your next commit.
    • Example: git rm outdated-report.txt

Key Options & Flags

  • --cached: This is a very useful option that allows you to remove a file from the staging area and the repository’s tracking, but keep the file in your working directory. The file will appear as an untracked file after the command is run. This is helpful for when you accidentally staged a file that should be ignored, such as a log file or a password.
    • Example: git rm --cached sensitive-data.txt
  • -f or --force: Forces the removal of a file that has been modified. Git will normally not let you remove a modified file to prevent you from losing work. The force option overrides this safety check.
  • -r or --recursive: Used to remove a directory and all of its contents.
    • Example: git rm -r logs/

Common Workflows

  1. Removing a file:
    • git rm unused-file.js
    • git commit -m "Remove unused JavaScript file"
  2. Removing a directory:
    • git rm -r assets/images
    • git commit -m "Remove assets directory"
  3. Removing a file from the repository but keeping it locally:
    • git rm --cached config.yml
    • git commit -m "Stop tracking config.yml, but keep it locally"
    • echo "config.yml" >> .gitignore (add the file to .gitignore to prevent it from being accidentally tracked again)

Why Not Just Use rm?

If you use the standard rm command, the file will be deleted from your file system, but Git won’t know about the deletion. When you run git status, the file will be listed as “deleted,” but you’ll still have to manually stage the deletion using git add -A or git commit -a. git rm simplifies this by doing both steps for you.

git checkout

git checkout is a versatile command used to switch branches or restore files. It lets you navigate between different states of your project’s history. It is a fundamental command for working with branches.

Basic Usage

  • git checkout <branch-name>: Switches your working directory to the specified branch. This command updates your files to match the state of the target branch’s last commit. If you have uncommitted changes, Git will prevent you from switching to avoid losing your work unless the changes won’t be overwritten on the new branch.
    • Example: git checkout main
  • git checkout -b <new-branch-name>: Creates a new branch and immediately switches to it. This is a common and convenient shortcut for starting a new feature or bug fix.
    • Example: git checkout -b feature/new-login

Restoring Files

  • git checkout -- <file-name>: Discards uncommitted changes in your working directory and restores the specified file to its state from the last commit. This is useful for undoing a mistake without using more complex commands.
    • Example: git checkout -- index.html will revert index.html to its last committed version.
  • git checkout <commit-hash> -- <file-name>: Restores a specific file to its state from a particular commit. This lets you bring back a file from earlier in your project’s history without changing your current branch.
    • Example: git checkout 9f1b2c4 -- scripts/app.js

Checking Out Commits or Tags (Detached HEAD)

  • git checkout <commit-hash> or git checkout <tag-name>: This checks out a specific commit or tag. This will put you in a detached HEAD state.
  • Detached HEAD: This means you are directly on a commit, not on a branch. You can view files and make changes, but any new commits you create will not belong to a branch. It is a good practice to create a new branch from this point if you plan to make new commits.
    • Example: git checkout v1.0.0
    • To get out of the detached HEAD state, simply check out an existing branch: git checkout main

git checkout vs. git switch and git restore

In newer versions of Git (2.23+), the functionality of git checkout has been split into two new commands to simplify and clarify their purpose:

  • git switch: Used exclusively for switching branches.
    • git switch <branch-name>
    • git switch -c <new-branch-name> (to create and switch)
  • git restore: Used exclusively for restoring files.
    • git restore <file-name> (to restore from the last commit)
    • git restore --staged <file-name> (to un-stage a file)

While git checkout still works for all these functions, git switch and git restore are the recommended commands for new users to avoid confusion.

git switch

git switch is a command used to change branches. Introduced in Git 2.23, its purpose is to provide a dedicated, safer alternative to the multipurpose git checkout command for branch-related operations.

Basic Usage

  • git switch <branch-name>: Switches your working directory to the specified branch. The command will fail if you have uncommitted changes that would be overwritten.
    • Example: git switch main
  • git switch -c <new-branch-name>: Creates a new branch and immediately switches to it. This is a common and convenient shortcut for starting a new feature or bug fix. It is the modern equivalent of git checkout -b.
    • Example: git switch -c feature/new-login-page

Key Options & Flags

  • -C <new-branch-name>: This option is a shortcut to create a new branch and force the switch, even if there are uncommitted changes that would be overwritten. Any uncommitted changes are carried over to the new branch. This is the modern equivalent of git checkout -B.
  • --orphan <new-branch-name>: Creates a new branch with a completely empty history. This is useful for creating a new branch to hold documentation or for creating a first-time commit in a new repository.
    • Example: git switch --orphan docs
  • - (hyphen): Switches to the last branch you were on. This is a quick way to toggle between two branches.
    • Example: git switch -

Why Use git switch?

The primary advantage of git switch is that it makes your intent clearer and prevents common mistakes.

  • Clarity: Its name clearly indicates that its sole purpose is to “switch” branches.
  • Safety: It has stricter checks for uncommitted changes, making it safer than git checkout. It won’t let you switch if a simple switch would overwrite a file, prompting you to either commit or stash your changes first.
  • Separation of Concerns: It separates the branch-switching functionality from the file-restoring functionality, which is now handled by the git restore command. This separation makes both commands easier to learn and remember.

git fetch

git fetch is a command used to download commits, files, and refs from a remote repository into your local repository. It is a non-destructive operation, meaning it won’t change your working directory or local branches. It simply downloads the new information for you to review later.

Basic Usage

  • git fetch <remote>: Downloads all the latest changes from the specified remote repository (e.g., origin). The downloaded changes are stored in a special remote-tracking branch (e.g., origin/main).
    • Example: git fetch origin
  • git fetch <remote> <branch-name>: Downloads only a specific branch from the remote.
    • Example: git fetch origin feature-A

How It Works

  1. Contact Remote: Git connects to the specified remote repository (e.g., origin).
  2. Download Updates: It downloads all new commits and references that you don’t have in your local repository.
  3. Update Remote-Tracking Branches: It updates your local remote-tracking branches (e.g., origin/main) to reflect the state of the remote repository.

The key thing to remember is that git fetch does not automatically merge or integrate the changes into your local branches.

Common Workflows

  1. Check for updates without merging:
    • git fetch origin
    • git log main..origin/main (This command shows you all the new commits that are on the remote origin/main branch but not yet on your local main branch.)
  2. Pulling a specific branch:
    • git fetch origin
    • git checkout main
    • git merge origin/main (This is the manual equivalent of a git pull).

git pull

git pull is a command used to update your local repository with the latest changes from a remote repository. It is a two-step operation that combines git fetch (downloading new changes) with git merge (integrating those changes into your current branch).

Basic Usage

  • git pull: Fetches changes from the remote repository and automatically merges them into your current branch.
    • Result: Your local branch is updated to match the state of the remote branch. The command will provide a summary of the files that were merged.

How It Works

  1. git fetch: Git first contacts the remote repository (by default, origin) and downloads all the new commits and references that you don’t have. These changes are stored in a remote-tracking branch (e.g., origin/main).
  2. git merge: Git then merges the downloaded changes from the remote-tracking branch into your current local branch.

Common Options & Flags

  • --rebase: This is a powerful option that uses rebase instead of merge to integrate the changes. Instead of creating a merge commit, it rewrites your local commits to be on top of the remote’s latest commit, creating a linear history. This is often preferred in a team setting for keeping the commit history clean.
    • Example: git pull --rebase
  • --all: Fetches all remote-tracking branches and their changes, then merges all the fetched remote-tracking branches with their respective local branches.
  • --prune: Before fetching, removes any remote-tracking branches that no longer exist on the remote repository.

git pull vs. git fetch

git pull is essentially a convenience command. It is the combination of two commands, git fetch and git merge, and therefore can have unintended side effects.

Commandgit fetchgit pull
Primary ActionDownloads changes from remote.Downloads and merges changes from remote.
Working DirectoryDoes not alter your working directory or local branches.Updates your working directory and local branches.
SafetyNon-destructive.Can be destructive if conflicts occur.
Use CaseTo inspect remote changes before integrating them.To quickly update your local branch to the latest version.

A common best practice is to use git fetch first to inspect the changes, and then git merge or git rebase manually to integrate them, giving you more control over the process.

git push

git push is a command used to upload your local commits to a remote repository. It’s how you share your work with others and update the shared project.

Basic Usage

  • git push <remote> <branch-name>: This is the fundamental command to upload commits from your local branch to a specific remote branch. The <remote> is usually origin, and the <branch-name> is the name of the branch you want to push.
    • Example: git push origin main
  • git push: When you’ve already set up an upstream branch (a remote branch your local branch tracks), you can use this simple command. Git automatically knows where to push.

How It Works

  1. Check for New Commits: Git scans your local branch for any commits that are not present in the remote repository.
  2. Upload Commits: It uploads these new commits to the remote repository.
  3. Update Remote Branch: The remote branch’s pointer is moved forward to the new latest commit you just pushed, making your changes visible to others.

Key Options & Flags

  • -u or --set-upstream: This is a very useful flag for the first time you push a new branch. It not only pushes the branch but also sets up a tracking relationship between your local branch and the remote one. After this, you can just use git push without specifying the remote and branch.
    • Example: git push -u origin feature/new-login
  • --force or -f: This command is used to force a push, overwriting the remote branch’s history with your local history. This is a dangerous command and should be used with extreme caution, as it can cause you to lose your collaborators’ work. It’s most commonly used after a git rebase where you’ve rewritten history.
    • Example: git push --force origin main
  • --all: Pushes all of your local branches to the remote repository.
  • --tags: Pushes all of your local tags to the remote. Tags are not pushed by default, so you must use this flag to share them.
  • --delete <branch-name>: This is used to delete a branch on the remote repository.
    • Example: git push origin --delete feature/old-feature

git remote

git remote is a command used to manage the connections to other repositories, often referred to as “remotes.” It lets you view, add, and remove these connections, which are essential for sharing your work.

Basic Usage

  • git remote: Lists the short names of all the remote repositories you have configured. The default remote is typically named origin.
  • git remote -v or --verbose: Lists the remote repositories along with the URLs for fetching and pushing. This is the most common way to check your remote connections.
    • Example: git remote -v
    • Output:origin https://github.com/user/repo.git (fetch) origin https://github.com/user/repo.git (push)

Adding a Remote

git remote add <name> <url>

  • What it does: This command adds a new remote connection to your local repository.
  • <name>: A short, easy-to-remember name for the remote. origin is the default name for the remote from which you cloned.
  • <url>: The URL of the remote repository. This can be an HTTP or SSH address.
    • Example: git remote add upstream https://github.com/project/main.git (Often used when you’ve forked a repository and want to keep track of the original project).

Removing and Renaming Remotes

  • git remote remove <name>: Removes the specified remote connection from your local repository.
    • Example: git remote remove upstream
  • git remote rename <old-name> <new-name>: Renames a remote. This is useful for improving clarity or consistency in your remote names.
    • Example: git remote rename origin main_project_repo

Inspecting a Remote

git remote show <name>

  • What it does: This command provides detailed information about a specific remote.
  • Result: It displays the remote’s URL, the head branch, and which branches are tracked locally and remotely. It also shows which local branches will be pushed and pulled from that remote.
    • Example: git remote show origin
    • Output:* remote origin Fetch URL: https://github.com/user/repo.git Push URL: https://github.com/user/repo.git HEAD branch: main Remote branches: main tracked feature/login tracked Local branches configured for 'git pull': main merges with remote main Local branches configured for 'git push': main pushes to main (fast-forwardable)

git merge

git merge is a command used to integrate changes from one branch into another. It combines a sequence of commits into a single unified history, creating a merge commit by default. This is how you bring new features or bug fixes from a feature branch into a main branch.

Basic Usage

  1. Switch to the target branch: Navigate to the branch you want to merge changes into.
    • git checkout main
  2. Run the merge command: Merge the source branch into the target branch.
    • git merge <source-branch-name>
    • Example: git merge feature/new-feature

How It Works (Three-Way Merge)

When the histories of the two branches have diverged, Git performs a three-way merge.

  1. Finds a Common Ancestor: Git identifies the last common commit shared by both branches.
  2. Compares: It compares the source-branch with the common ancestor and the target-branch with the common ancestor.
  3. Combines: It then combines the changes from both branches and creates a new merge commit. This new commit has two parent commits: the tip of the target-branch and the tip of the source-branch.

Fast-Forward Merge

A fast-forward merge occurs when the target branch is a direct ancestor of the source branch. In this case, there are no divergent changes, and Git simply moves the target branch’s pointer forward to the tip of the source branch without creating a new merge commit. This results in a linear history.

  • Example:
    • git checkout main
    • git merge feature-branch
    • If main is an ancestor of feature-branch, main‘s pointer will just move forward.

Handling Merge Conflicts

A merge conflict happens when two branches have made different changes to the same part of a file. Git cannot automatically decide which change to keep, so it pauses the merge and asks for your input.

  • How to resolve:
    1. Run git status to see which files have conflicts.
    2. Open the conflicted file in a text editor. Git adds special markers (<<<<<<<, =======, >>>>>>>) to show you the conflicting sections.
    3. Manually edit the file to resolve the conflict, choosing which changes to keep.
    4. Save the file.
    5. Run git add <conflicted-file> to stage the resolved file.
    6. Run git commit to complete the merge.

Key Options & Flags

  • --no-ff: This option forces Git to create a merge commit, even if a fast-forward merge would be possible. This is useful for preserving a record of the branch’s existence in your history.
  • --abort: Aborts the current merge, returning you to the state before you ran the git merge command. This is helpful if you decide you don’t want to continue the merge.
  • --squash: Combines all commits from the source branch into a single new commit on the target branch. It does not create a merge commit. This is useful for creating a clean, single-commit history for a feature.

git cherry-pick

git cherry-pick is a command used to apply the changes introduced by one or more existing commits from one branch to another. This is useful when you need to bring a specific commit (e.g., a bug fix) from one branch to another without merging the entire branch.

Basic Usage

  1. Switch to the target branch: Navigate to the branch where you want the commit to be applied.
    • git checkout main
  2. Cherry-pick the commit: Run the command with the commit’s hash.
    • git cherry-pick <commit-hash>
    • Example: git cherry-pick 9f1b2c4

How It Works

When you cherry-pick a commit, Git:

  1. Identifies the changes in the specified commit.
  2. Creates a new commit on your current branch that contains the exact same changes.
  3. The new commit will have a different hash, but the content will be the same as the original commit.

This process is similar to git revert in that it creates a new commit rather than rewriting history. This makes it a safe operation to use on shared branches.

Cherry-Picking Multiple Commits

You can cherry-pick multiple commits at once by listing their hashes in order.

  • git cherry-pick <commit-hash1> <commit-hash2> <commit-hash3>

You can also cherry-pick a range of commits using a double-dot (..) or a caret (^).

  • Inclusive range: git cherry-pick <start-commit>..<end-commit>
    • Example: git cherry-pick 9f1b2c4..a2f98e7 (Picks all commits between the two hashes, including a2f98e7.)
  • Exclusive range: git cherry-pick <start-commit>^..<end-commit>
    • Example: git cherry-pick 9f1b2c4^..a2f98e7 (Picks all commits between the two hashes, excluding 9f1b2c4 but including a2f98e7.)

Common Options & Flags

  • --edit: This option allows you to edit the commit message of the new cherry-picked commit before it is created.
  • --no-commit: Applies the changes to your working directory and staging area without creating a new commit. This is useful if you want to make further modifications or combine multiple cherry-picked commits into one.
  • --abort: Aborts the cherry-pick operation and returns your branch to the state it was in before you started.
  • --quit: Exits the cherry-pick sequence but leaves your working directory and staging area as they were.

git cherry-pick vs. git merge

Featuregit cherry-pickgit merge
ScopeApplies a single commit or a small, selected number of commits.Integrates an entire branch and all its commits.
HistoryCreates a new, duplicate commit with a new ID.Creates a single merge commit that joins two histories.
Use CasePatching a bug fix to a different branch without a full merge.Integrating an entire feature branch into another branch.

git reset

git reset is a powerful and potentially dangerous command used to undo changes in your repository. It lets you move a branch’s HEAD pointer to a different commit, effectively rewriting history. This command is often used to un-stage files or to discard recent commits.

The Three Modes of git reset

git reset operates in three main modes, each affecting a different part of your repository. Understanding these modes is crucial for using the command correctly.

ModeCommandWhat It Does
--softgit reset --soft <commit-hash>Moves the HEAD pointer to the specified commit but keeps all changes in the staging area. The working directory is untouched. This is useful for undoing a commit while keeping all the changes staged and ready to be re-committed.
--mixedgit reset --mixed <commit-hash>Moves the HEAD pointer to the specified commit and un-stages all changes. The changes are still in your working directory, but you’ll have to git add them again to stage them. This is the default mode.
--hardgit reset --hard <commit-hash>Moves the HEAD pointer to the specified commit and discards all changes in both the staging area and the working directory. This is a destructive command that will permanently delete your work. Use with extreme caution.

Basic Use Cases

  • Un-staging a file: You can un-stage a file without changing your commit history.
    • git reset HEAD <file-name>: This is a common and safe way to move a staged file back to your working directory. It is the same as git reset --mixed HEAD <file-name>.
  • Undoing the last commit (soft): This is useful if you want to fix a typo in your commit message or add a few more files.
    • git reset --soft HEAD~1: Moves the HEAD pointer back by one commit. Your files are now staged, and you can make a new, corrected commit.
  • Undoing the last commit (mixed): This is the default behavior if you don’t specify a mode.
    • git reset HEAD~1: Moves the HEAD pointer back by one commit and un-stages the changes. Your files are still in your working directory, but you have to git add and git commit them again.
  • Undoing the last commit (hard): This is the most destructive option.
    • git reset --hard HEAD~1: Permanently deletes the last commit and all the changes associated with it. Your working directory is now identical to the state of the repository before that commit.

Important Safety Note

git reset rewrites the history of your local repository. If you use it on commits that have already been pushed to a shared remote repository, it can cause problems for your collaborators. To prevent this, it is highly recommended to only use git reset on commits that have not yet been pushed. If you must use git reset on a shared branch, you will need to use git push --force to update the remote, which should only be done with great care and communication with your team.

git restore

git restore is a command used to undo changes in your working directory or staging area. Introduced in Git 2.23, it was designed to make the process of restoring files simpler and safer than using the multi-purpose git checkout command.

Basic Usage

  • git restore <file-name>: This command discards uncommitted changes in your working directory and restores the specified file to its state from the last commit. This is a quick and easy way to “un-do” a file modification.
    • Example: git restore main.css will revert main.css back to its version in your last commit.
  • git restore .: Restores all files in your current working directory to their last committed state. This is a quick way to discard all recent changes.

Undoing Staged Changes

  • git restore --staged <file-name>: This command un-stages a file. It moves the changes from the staging area back to the working directory, where they will appear as modified but not ready to be committed. This is the modern equivalent of git reset HEAD <file-name>.
    • Example: git restore --staged index.html will move changes to index.html from the staging area to the working directory.

Restoring from a Specific Commit

  • git restore --source=<commit-hash> <file-name>: Restores a file to its state from a specific past commit. This allows you to bring back an older version of a file without having to check out the entire repository at that point in time.
    • Example: git restore --source=9f1b2c4 app.js will revert app.js to the version it was at in the commit with the hash 9f1b2c4.

Important Safety Notes

  • Working directory changes: git restore <file-name> is destructive! It will permanently overwrite any uncommitted changes in your working directory for that file. There is no git undo for this. Make sure you truly want to discard those changes before running the command.
  • No commit history changes: git restore only affects the working directory and staging area; it does not change your commit history. For that, you would need to use git reset, git revert, or git rebase.

git revert

git revert is a command used to undo an existing commit. It is a safe, non-destructive way to undo changes because it doesn’t rewrite history. Instead, it creates a new commit that reverses the changes introduced by the target commit, leaving the original commit and all subsequent history intact.

Basic Usage

git revert <commit-hash>

  • What it does: Git creates a new commit that contains the exact opposite changes of the commit you specified. This new “revert” commit effectively undoes the changes from the original commit.
  • Result: The original commit remains in the history, and a new commit is added to the log to show that the changes were undone. This is crucial for shared branches where you cannot rewrite history.
    • Example: git revert 9f1b2c4

How It Works

Imagine you made a commit with a new feature, but it introduced a bug. You can use git revert to undo that commit.

  1. Find the commit to revert: Use git log to find the hash of the commit you want to undo.
  2. Revert: Run git revert <commit-hash>. Git will apply the changes in reverse and open your text editor to write a commit message for the revert.
  3. New commit: A new commit is created and added to the history, making your repository’s state identical to what it was before the buggy commit.

The key difference between git revert and git reset is their impact on the project’s history.

Featuregit revertgit reset
ImpactCreates a new commit to undo changes.Rewrites history by moving the HEAD pointer.
SafetySafe for shared branches.Dangerous for shared branches; can cause conflicts for others.
Use CaseUndoing changes that have already been pushed.Undoing local changes or cleaning up a local branch’s history.

Common Options & Flags

  • -n or --no-commit: This option applies the reverse changes to your working directory and staging area but does not create a commit. This is useful if you want to make further modifications before committing the revert.
    • Example: git revert --no-commit 9f1b2c4
  • --edit: The default behavior is to open the editor to write the commit message. This flag is used for explicitly stating this intent.
  • --abort: Stops the revert process if there are conflicts. This is helpful if you want to cancel the operation and return to your previous state.

git revert is the preferred and safest way to undo changes on a shared branch, as it maintains a clear, traceable history for all collaborators.

git show

git show is a command used to display information about a specific Git object, most commonly a commit, tag, or tree. Its primary use is to inspect the contents and changes introduced by a single commit.

Basic Usage

  • git show <commit>: Displays the metadata (author, date, message) and the diff (the changes) of a specific commit. If you don’t provide a commit hash, it defaults to showing the last commit (HEAD).
    • Example: git show
    • Example: git show 82b8811

Common Options & Flags

  • --name-only: Shows only the names of the files that were changed in the commit, without showing the actual line-by-line differences. This is a quick way to see what files were affected.
  • --stat: Provides a summary of the changes, listing the files that were modified along with the number of lines added and removed from each.
  • --pretty=oneline: Formats the output to show a concise summary of the commit on a single line. This is useful for getting a quick overview without the detailed diff.
  • --summary: Shows a list of modified files, including whether they were created, deleted, or renamed.

Viewing Other Objects

While git show is most often used for commits, it can also display other Git objects.

  • git show <tag>: Displays the details of a tag, including the tag message and the commit that it points to. For annotated tags, this will show the tagger’s name and message.
    • Example: git show v1.0.0
  • git show <branch>: Displays the details of the latest commit on a specific branch. It’s an easy way to see the tip of a branch without checking it out.
    • Example: git show feature/new-feature
  • git show <object-hash>: Displays the contents of a specific object, such as a file’s blob or a tree’s directory structure.
    • Example: git show HEAD:README.md will show the contents of the README.md file in your last commit.

git rebase

git rebase is a command that moves or combines a sequence of commits to a new base commit. Its main purpose is to maintain a linear, clean project history by replaying commits from one branch onto another. This is an alternative to git merge for integrating changes and is often favored for keeping the commit history tidy.

Basic Usage

  1. Switch to your feature branch:
    • git checkout feature/your-feature
  2. Rebase onto the target branch:
    • git rebase <target-branch-name>
    • Example: git rebase main

How It Works

When you run git rebase main from your feature-branch, Git does the following:

  1. Finds the common ancestor: It identifies the last common commit shared by main and feature-branch.
  2. Saves your commits: It “saves” the commits from your feature-branch that are not on main.
  3. Rewinds: It resets your feature-branch pointer to the latest commit on main.
  4. Replays: It then reapplies, or “replays,” your saved commits one by one on top of the main branch.

The result is a new, linear history with your feature commits appearing as if they were created after the latest main commit.

Interactive Rebase

git rebase -i <commit-hash>

This is a powerful and popular way to use git rebase. The -i flag (for “interactive”) lets you edit the commits as they are being replayed. When you run this command, Git opens a text editor with a list of commits and instructions. You can use this to:

  • pick: Use the commit as is.
  • reword: Change the commit message.
  • edit: Pause the rebase to amend the commit.
  • squash: Combine the current commit with the one before it. This is great for turning multiple small commits into one logical commit.
  • fixup: Like squash, but it discards the commit’s log message.
  • reorder: Change the order of commits.
  • drop: Remove a commit completely.

git rebase vs. git merge

Featuregit rebasegit merge
HistoryCreates a clean, linear history.Creates a new merge commit, preserving a record of the merge.
CommitsRewrites commit history.Does not rewrite history.
Use CaseRecommended for personal branches or before merging to main.Recommended for shared branches to avoid rewriting history.
SafetyCan be dangerous if used on public/shared branches.Safe and non-destructive.

Important Safety Note

Do not rebase commits that have already been pushed to a shared remote repository. Rebasing rewrites history, and if you push a rebased branch, it will conflict with the history of anyone else who has pulled the original commits. The only way to fix this is with git push --force, which is a dangerous command and should be used with extreme caution and only with team consensus.

git config

git config is a command used to set and get configuration values for your Git installation. These settings control how Git looks and behaves, from your user information to repository-specific rules.

Levels of Configuration

Git has three main configuration levels, each with its own file. When Git looks for a setting, it checks these levels in order, and a more specific setting overrides a more general one.

  1. System: Applies to every user on the computer. This is usually for system-wide settings.
    • File: /etc/gitconfig
    • Command: git config --system
  2. Global: Applies to the current user’s profile and all their repositories. This is the most common level for personal settings.
    • File: ~/.gitconfig or ~/.config/git/config
    • Command: git config --global
  3. Local: Applies only to the current repository. This is used for project-specific configurations.
    • File: .git/config inside your repository.
    • Command: git config --local (this is the default)

Basic Usage

  • Set a value: git config --<level> <key> <value>
    • Example: git config --global user.name "John Doe"
    • Example: git config --global user.email "john.doe@example.com"
  • Get a value: git config --<level> <key>
    • Example: git config --global user.name
  • List all settings: git config --list
    • To see settings for a specific level, add --local, --global, or --system.
  • Edit the config file directly: git config --global -e
    • This opens the specified config file in your default text editor, allowing you to manually edit all settings at once.

Common Configuration Keys

KeyDescriptionExample Command
user.nameYour name for commit messages.git config --global user.name "John Doe"
user.emailYour email for commit messages.git config --global user.email "john.doe@example.com"
core.editorThe text editor used for commit messages.git config --global core.editor "vim"
core.autocrlfHandles line endings (Windows vs. Unix).git config --global core.autocrlf true
color.uiEnables colored output in the terminal.git config --global color.ui auto
alias.<alias-name>Creates a shortcut for a Git command.git config --global alias.co "checkout"

Practical Example: Setting up your Identity

The first thing you should do after installing Git is to set your user name and email. This information is included in every commit you make.

# Set your name (global level)
git config --global user.name "Your Name Here"

# Set your email (global level)
git config --global user.email "your.email@example.com"

# Verify the settings
git config --global --list

This will ensure that all your future commits are properly attributed to you.

git clean

git clean is a command used to remove untracked files from your working directory. Untracked files are new files that have not yet been added to the Git repository using git add. It is a powerful command for cleaning up your project’s workspace.

Basic Usage

git clean is a potentially destructive command, so it’s a good practice to first run it in “dry run” mode to see what files will be deleted.

  • git clean -n or --dry-run: This is the safest way to use the command. It will show you a list of the files and directories that would be removed without actually deleting them.
    • Example: git clean -n
  • git clean -f or --force: This command actually performs the cleanup and removes the untracked files. The -f or --force flag is required to run this command because of its destructive nature.
    • Example: git clean -f

Key Options & Flags

  • -d: This flag tells git clean to also remove untracked directories, in addition to untracked files.
    • Example: git clean -nd (dry run for files and directories)
    • Example: git clean -fd (force clean for files and directories)
  • -x: This flag tells git clean to also remove files that are ignored by your .gitignore file. This is useful for removing build artifacts or temporary files that you’ve told Git to ignore.
    • Example: git clean -nx (dry run for files and ignored files)
    • Example: git clean -fx (force clean for files and ignored files)
  • -X: This flag is similar to -x, but it only removes files that are ignored by your .gitignore file and leaves other untracked files alone. This is useful for a more targeted cleanup.

Common Workflows

  1. Remove new, untracked files:
    • First, preview the files that will be removed: git clean -n
    • If the list looks correct, perform the cleanup: git clean -f
  2. Remove new files and empty directories:
    • First, preview the files and directories that will be removed: git clean -n -d
    • If the list looks correct, perform the cleanup: git clean -f -d
  3. Clean up build artifacts:
    • Check what ignored files would be removed: git clean -n -x
    • Remove them: git clean -f -x

git clean is an excellent tool for tidying up your working directory before committing or switching branches. It ensures that only the files you intend to track are present in your workspace.

git reflog

git reflog is a command that records a log of all updates to the tips of branches and other references in your local repository. It is a powerful safety net because it keeps track of every time your HEAD pointer has changed, making it possible to recover lost commits that seem to have disappeared from your regular git log.

How It Works

git reflog is a local-only command and is not part of your repository’s history that you share with others. It’s a running record of your activities. Each time you run a command that modifies your HEAD—like git commit, git merge, git rebase, git reset, or git pull—a new entry is added to the reflog.

  • Output format: Each line of the reflog shows the commit hash, the action that was performed, and a timestamp.
    • Example:a2f98e7 HEAD@{0}: commit: Add new feature 9f1b2c4 HEAD@{1}: rebase (start): checkout main 82b8811 HEAD@{2}: checkout: moving from feature-A to main

Basic Usage

  • git reflog: Displays the entire log of HEAD updates. This is the most common way to use the command.
  • git reflog show <branch-name>: Displays the reflog for a specific branch, showing a history of all the commits that the branch has pointed to.

Practical Use Cases for Recovery

git reflog is your best tool for recovering from a mistake, especially after using a destructive command like git reset --hard.

  • Recovering from a Hard Reset: Imagine you accidentally deleted your last commit with git reset --hard HEAD~1. Your commit seems to be gone.
    1. Run git reflog. You will see an entry for the commit you just undid. For example, 82b8811 HEAD@{1}: reset: moving to HEAD~1. The commit you want to recover is the one before the reset.
    2. Use the reflog to find the hash of the commit you want to restore.
    3. Create a new branch at that point: git branch recovered-work <commit-hash>.
    4. Then, check out the new branch: git checkout recovered-work. Your lost commits are now safely back on a new branch.
  • Fixing a bad rebase: If you mess up a git rebase and want to go back to the state you were in before you started, you can use the reflog to find your previous HEAD position.
    1. git reflog
    2. Find the entry before the rebase started (e.g., HEAD@{2}: rebase: abort).
    3. git reset --hard HEAD@{2} to go back in time to that commit.

git log vs. git reflog

Featuregit loggit reflog
PurposeShows the commit history of a branch.Shows the history of where HEAD and other refs have pointed.
ScopeShows reachable commits from the current branch.Shows every action that changed a reference, even if they’re no longer reachable.
PersistencePart of the shared repository history.Local to your machine; not shared.
Example UseTo see who made changes and when.To recover a lost commit.

git blame

git blame is a command used to show who last modified each line of a file and in which commit. It is a powerful tool for understanding the history of a file and is often used for debugging, finding the source of a bug, or understanding why a certain piece of code exists.

Basic Usage

  • git blame <file-name>: Displays the content of the specified file, with each line prefixed by the commit hash, author, and date of the last change to that line.
    • Example: git blame index.js
  • Result: The output is a formatted list where each line of the file is preceded by its “blame” information.^9f1b2c4 (John Doe 2025-08-01 10:30:01 -0500 1) var express = require('express'); 82b8811 (Jane Smith 2025-09-02 14:15:30 -0500 2) var app = express(); ... This shows you the commit hash, the author, the date, and the line number, which helps you track down the change.

Key Options & Flags

  • -L <start>,<end>: Restricts the blame output to a specific range of lines. This is useful for focusing on a specific function or block of code.
    • Example: git blame -L 10,20 main.js will only show the blame for lines 10 through 20.
  • -e or --email: Shows the author’s email address instead of their name.
  • -w or --ignore-whitespace: Ignores any changes that only involve whitespace, which can make the output cleaner and more focused on meaningful changes.
  • -M or --find-copies: Detects lines that have been moved within the same file.
  • -C or --find-copies-harder: Detects lines that have been copied from other files in the same commit. This is useful for tracking a line of code’s origin across different files.

Practical Use Cases

  • Debugging: You find a bug and you’re not sure which commit introduced it. Using git blame, you can pinpoint the exact line of code and the commit where it was changed, giving you a starting point for your investigation.
  • Understanding code: You’re looking at a piece of code and don’t understand why it was written a certain way. By blaming the line, you can find the commit and read the commit message, which often provides context and rationale for the change.
  • Code Review: When reviewing a large file, you can quickly see which parts have been recently modified by a particular user, helping you to focus your review.

git blame vs. git log -p

While both commands can be used to view file history, they serve different purposes.

  • git blame shows the history of each individual line.
  • git log -p shows a chronological history of commits, including a patch (diff) for each commit, which is better for understanding the full context of a change set.

.gitignore

A .gitignore file is a plain text file that tells Git which files or directories to ignore in a project. It is used to prevent you from accidentally committing files that are not part of the codebase, such as temporary files, build artifacts, or personal configuration files.

Basic Syntax

Each line in a .gitignore file represents a pattern for files or directories to be ignored.

  • Blank lines or lines starting with # are ignored.
    • # This is a comment
  • Matches a specific file.
    • my-config.txt
  • Matches all files with a specific extension.
    • *.log (ignores all .log files)
  • Matches all files with a specific name in any directory.
    • config.yml (ignores src/config.yml and assets/config.yml)
  • Matches files in a specific directory.
    • /logs/ (ignores the logs directory and all its contents, but not a/logs/)
  • Matches a directory and all its contents, including subdirectories.
    • build/ (ignores the build directory and everything inside it)
  • Excluding a file that was previously matched. Add a ! at the beginning of the line.
    • # ignore all log files except production.log
    • *.log
    • !production.log
  • Ignoring a file only in a specific directory.
    • path/to/directory/*.tmp (ignores .tmp files only in path/to/directory)

Common Files to Ignore

It is a best practice to create a .gitignore file at the root of your project. Here are some common examples of files and directories to ignore:

CategoryExample .gitignore patterns
Operating System.DS_Store, Thumbs.db
Node.jsnode_modules/, npm-debug.log
Python__pycache__/, *.pyc, .env
Java*.class, *.jar, .gradle/, target/
C++*.o, *.out, a.exe
IDEs and Editors.idea/, .vscode/, .project, *.swp
Build Artifactsbuild/, dist/, bin/
Logs and Temp files*.log, temp/, *.tmp

How It Works

Git uses the .gitignore file to determine which files to track. When you run git status, Git will not list any files or directories that match a pattern in this file, even if they are present in your project.

If you accidentally committed a file that should be ignored, you can remove it from Git’s tracking while keeping it in your working directory using the command: git rm --cached <file-name>. After this, add the file to your .gitignore file to prevent it from being tracked again in the future.

gitattributes

A .gitattributes file is a plain text file that tells Git how to handle different types of files in a repository. It allows you to define per-path attributes, which can control various aspects of Git’s behavior, such as how line endings are handled, how diffs are generated, or how files are exported.

Basic Syntax

Each line in a .gitattributes file consists of a pattern followed by one or more attributes.

  • Pattern: A path or file glob (e.g., *.js, docs/, *.txt).
  • Attributes: A list of key-value pairs or simple flags separated by spaces.

Example:

*.txt text eol=crlf
*.jpg binary

In this example, all files ending in .txt are treated as text files with Windows-style line endings, and all .jpg files are treated as binary.

Common Attributes

AttributeDescriptionExample
textTells Git to treat a file as text. This enables automatic line-ending conversion.*.js text
binaryTells Git to treat a file as a binary file. Git will not try to perform line-ending conversions or show diffs.*.jpg binary
eol=<style>Sets the end-of-line style for a text file. Common values are crlf (Windows) and lf (Unix/macOS).*.txt text eol=crlf
diff=<driver>Specifies a custom driver for generating diffs for a specific file type. This is useful for non-standard text files or files with structured data.*.pdf diff=pdf
export-ignorePrevents files or directories from being included when a repository is archived with git archive. This is great for excluding generated files./build/ export-ignore
linguist-generatedA special attribute used by GitHub’s Linguist library to mark generated files, preventing them from being counted in the repository’s language statistics.app/dist/ linguist-generated
merge=<driver>Specifies a custom merge driver for a specific file type.*.xcf merge=image-merge

Practical Use Cases

  • Managing Line Endings: This is the most common use case for .gitattributes. It ensures that all developers on a project use a consistent line-ending style, regardless of their operating system.
    • Best practice: * text=auto eol=lf. This tells Git to handle all files as text and normalize line endings to lf (Unix style) in the repository.
  • Improving Diffs: For file types like .docx or .pdf, Git’s default diff is unreadable. You can configure a .gitattributes file to use an external tool to generate a meaningful diff. For example, for a .docx file, you could configure a diff driver that uses a tool to extract and compare the text content.
  • Cleaning Up Archives: When you create a zip file of your project using git archive, you often don’t want to include temporary files, logs, or build directories. Using export-ignore keeps your archives clean and small.

The .gitattributes file should be committed to your repository so that its rules are shared with all collaborators, ensuring consistency across the project.

Git Hooks

Git hooks are scripts that run automatically whenever a particular event occurs in a Git repository. They allow you to customize Git’s behavior and automate tasks at specific points in its workflow, such as before a commit or after a push.

How They Work

Hooks are simple shell or Perl scripts that reside in the .git/hooks directory of every Git repository. When you git init or git clone, Git populates this directory with sample scripts, but you must rename them to remove the .sample extension to activate them.

  • Location: .git/hooks/
  • Activation: Remove the .sample from the file name (e.g., pre-commit.sample becomes pre-commit).

Types of Hooks

Hooks are categorized by when they are executed. They are divided into two main groups: client-side hooks (run on the local developer’s machine) and server-side hooks (run on the remote repository server).

Client-Side Hooks

These hooks are most commonly used for automating developer-specific tasks, enforcing policies, or preventing mistakes.

Hook NameWhen It RunsCommon Use Cases
pre-commitBefore a commit is created.Run a linter, syntax checker, or unit tests to ensure no broken code is committed.
prepare-commit-msgAfter a commit message is generated but before the editor is launched.Automatically generate or format a commit message based on the branch name.
commit-msgAfter a commit message has been written.Validate the commit message format (e.g., to ensure it adheres to a company’s standard).
post-commitAfter a commit has been made.Notify an external service, or update a local developer’s build system.
pre-rebaseBefore git rebase begins.Prevent rebasing of the main or other shared branches.
post-checkoutAfter a git checkout is performed.Set up the working directory for a specific branch (e.g., install dependencies).
post-mergeAfter a successful git merge.Clean up temporary files, or run a new build.
Server-Side Hooks

These hooks are installed on the remote repository and are used to enforce repository-wide policies for all users.

Hook NameWhen It RunsCommon Use Cases
pre-receiveWhen a push is received but before the refs are updated.Check if the pushed changes adhere to a policy, like preventing force pushes (git push --force).
updateSimilar to pre-receive, but runs once per pushed branch.Refuse pushes to a protected branch like main.
post-receiveAfter a push has been successfully completed.Trigger a continuous integration (CI) server to run tests, or update a live server.

Practical Example: The pre-commit Hook

A common and useful pre-commit hook is to run a linter. This prevents commits from being created if they contain syntax errors or do not follow style conventions.

  1. Navigate to your .git/hooks directory.
  2. Create a file named pre-commit (no extension).
  3. Add the following shell script to the file:Bash#!/bin/sh # Run the linter on staged files lint_output=$(npx eslint --format compact --fix $(git diff --cached --name-only --diff-filter=ACM | grep '\.js$')) if [ $? -ne 0 ]; then echo "ESLint found errors. Please fix them before committing." echo "$lint_output" exit 1 fi
  4. Make the script executable: chmod +x .git/hooks/pre-commit

Now, every time you try to git commit, this script will run. If the linter finds errors, the commit will be aborted.

Leave a Comment