The ultimate Git Cheat Sheet
TLDR; Get your Git Cheat Sheet as PDF or as an image. To follow this article, make sure you have Git installed. We start with an empty folder, save our first commit, and work with branches, merges and remote repositories. Every command uses the same small the-ultimate-git-cheat-sheet project, so you can follow along even if you have never used Git before. You will find the complete source code used in this article on GitHub. We intentionally did not delete the tutorial branches from this repository, so you can explore each one and follow the examples more easily.
Download The Ultimate Git Cheat Sheet
Please download your Git Cheat Sheet to follow along with this article. You are also welcome to share it with your colleagues and friends.
Do You Want More Resources Like This?
Join our community and sign up for our newsletter to stay up-to-date on the latest DevOps topics. Get access to our newest resources and insights directly in your inbox!
What Is Git?
Git is a distributed version control system. That sounds complicated, but the idea is simple: Git remembers changes to your files. You can see what changed, restore an earlier version and work on different ideas without copying your complete project into folders named final, final-2 and final-really-final.
Git is distributed because every developer normally has a complete copy of the project history. You can commit, inspect history and create branches without an internet connection. A shared server becomes important when you want to collaborate or back up your work.
Git is not the same as GitHub, GitLab or Bitbucket. Git is the version control tool on your machine. GitHub, GitLab and Bitbucket are hosting platforms that can store Git repositories and add features such as pull requests, issues and CI/CD pipelines.
How Does Git Work?
Git moves a change through four places:
- Working directory: The files that you can see and edit.
- Staging area: The changes you have selected for your next commit. Git also calls this the index.
- Local repository: The commits stored in the hidden
.gitdirectory on your machine. - Remote repository: A shared copy on another machine or a platform such as GitHub.
The most common flow is edit -> stage -> commit -> push. You edit a file, select the changes with git add, save a snapshot with git commit, and share the commits with git push.
working directory staging area local repository remote repository
edit -> git add -> git commit -> git push
Git stores snapshots, not a loose collection of unrelated file differences. If a file did not change, Git can refer to the existing content instead of storing it again.
How Do You Configure Git?
Before your first commit, tell Git who you are. The name and email become part of every commit that you create.
# show the installed Git version
$ git --version
## => output
### git version 2.51.0
# set your identity for every repository on this machine
$ git config --global user.name "Ada Lovelace"
$ git config --global user.email "ada@example.com"
# use main as the initial branch name for new repositories
$ git config --global init.defaultBranch main
# list the effective configuration and where every value comes from
$ git config --list --show-origin
## => output
### file:/Users/ada/.gitconfig user.name=Ada Lovelace
### file:/Users/ada/.gitconfig user.email=ada@example.com
### file:/Users/ada/.gitconfig init.defaultbranch=main
# open the documentation for a command
$ git help commit
Remove --global if a setting should apply only to the current repository. This is useful when you use a work email for company projects and a private email for open-source projects.
What Is A Git Repository?
A Git repository is a project folder in which Git records changes to your files over time. It contains your normal project files and a hidden .git directory. The .git directory stores commits, branches, tags and configuration. If you remove it, your files remain, but the directory is no longer a Git repository and its local history is gone.
A local repository is on your computer. A remote repository is a Git repository stored on another computer, such as a server, that your local repository accesses through a URL. It is usually hosted on a service such as GitHub, GitLab or Bitbucket. You can download changes from it with git fetch and upload your local commits to it with git push. You do not need a remote repository to use Git.
How Do You Create A New Repository?
We will create a small project called the-ultimate-git-cheat-sheet. We will use Git to build the cheat sheet itself, starting with its README and adding sections in feature branches.
# create and enter the project directory
$ mkdir the-ultimate-git-cheat-sheet
$ cd the-ultimate-git-cheat-sheet
# turn the current directory into a Git repository
$ git init
## => output
### Initialized empty Git repository in /Users/ada/the-ultimate-git-cheat-sheet/.git/
# inspect the current state
$ git status
## => output
### On branch main
###
### No commits yet
###
### nothing to commit (create/copy files and use "git add" to track)
How Do You Clone An Existing Repository?
If a repository already exists on a server, copy it with git clone instead. Cloning downloads the project files, history and remote configuration.
# create a new directory named the-ultimate-git-cheat-sheet from a remote repository
$ git clone https://github.com/aichbauer/the-ultimate-git-cheat-sheet.git
$ cd the-ultimate-git-cheat-sheet
# show the local repository and its configured remote
$ git status
## => output
### On branch main
### Your branch is up to date with 'origin/main'.
###
### nothing to commit, working tree clean
$ git remote -v
## => output
### origin https://github.com/aichbauer/the-ultimate-git-cheat-sheet.git (fetch)
### origin https://github.com/aichbauer/the-ultimate-git-cheat-sheet.git (push)
For this tutorial, continue with the repository created by git init.
What Is A Commit In Git?
A commit is a saved snapshot of your project. It contains the selected changes, a message, the author, the date and a reference to its parent commit. Git identifies every commit with a hash such as a1b2c3d.
You can think of a commit like a checkpoint in a game. It should represent one understandable step. A commit named Add branching command reference is easier to review and restore than one named changes that mixes five unrelated tasks.
Creating a commit is local. It does not automatically upload anything to GitHub or another server.
How Do You Track And Commit Changes?
The usual workflow is to create or edit files, inspect the changes, stage what belongs in the next snapshot and then commit it. You can also stage several files together and exclude files that Git should ignore.
How Do You Create Your First Commit?
Create the first file for our project and inspect how Git sees it.
# create a small project file
$ printf "# The Ultimate Git Cheat Sheet\n\nA practical reference for everyday Git commands.\n" > README.md
# README.md is untracked: Git sees it but does not save it yet
$ git status
## => output
### On branch main
###
### No commits yet
###
### Untracked files:
### (use "git add <file>..." to include in what will be committed)
### README.md
###
### nothing added to commit but untracked files present (use "git add" to track)
# inspect unstaged changes
$ git diff
# select the file for the next commit
$ git add README.md
# inspect staged changes
$ git diff --staged
## => output
### diff --git a/README.md b/README.md
### new file mode 100644
### index 0000000..56546aa
### --- /dev/null
### +++ b/README.md
### @@ -0,0 +1,3 @@
### +# The Ultimate Git Cheat Sheet
### +
### +A practical reference for everyday Git commands.
# save the staged snapshot
$ git commit -m "Add project introduction"
## => output
### [main (root-commit) a1b2c3d] Add project introduction
### 1 file changed, 3 insertions(+)
### create mode 100644 README.md
git add does not mean "track this file forever". It copies the current version of a change into the staging area. If you edit the file again after staging it, you need to stage the new change as well.
How Do You Stage Multiple Changes?
When several related changes belong in the same commit, you can stage specific files by naming each one. If you make more related changes afterward, git add . stages every changed or untracked file below your current directory.
# create a command reference and link to it from the README
$ printf "# Git Commands\n\nUseful Git commands for this project.\n" > commands.md
$ printf "\nSee commands.md for useful Git commands.\n" >> README.md
# stage several named files
$ git add README.md commands.md
# add a note and a simple workflow example
$ printf "Remember to review changes before committing.\n" > notes.md
$ mkdir examples
$ printf "git status\ngit add .\ngit commit\n" > examples/basic-workflow.txt
# stage changes below the current directory
$ git add .
# save all staged changes in one commit
$ git commit -m "Add Git command reference and examples"
## => output
### [main b2c3d4e] Add Git command reference and examples
### 4 files changed, 9 insertions(+)
### create mode 100644 commands.md
### create mode 100644 examples/basic-workflow.txt
### create mode 100644 notes.md
How Do You Ignore Files?
Use a .gitignore file for generated files, dependencies, secrets and editor files that should not enter the repository.
# create a local environment file with an example secret
$ printf "API_KEY=local-development-secret\n" > .env
# add ignore rules
$ printf ".env\nnode_modules/\n.DS_Store\n" > .gitignore
$ git add .gitignore
$ git commit -m "Ignore local and generated files"
## => output
### [main d4e5f6a] Ignore local and generated files
### 1 file changed, 3 insertions(+)
### create mode 100644 .gitignore
# check why a path is ignored
$ git check-ignore -v .env
## => output
### .gitignore:1:.env .env
Do not rely on .gitignore to protect a secret that was already committed. Ignoring a tracked file does not remove it from history. Rotate exposed credentials and clean the history with a dedicated tool when necessary.
What Is Git History?
Git history is the chain of commits in your repository. Most commits point to one parent; a merge commit can point to two or more parents.
HEAD is Git's name for your current position. Usually, HEAD points to the branch that you have checked out, and that branch points to its newest commit. HEAD~1 means the first parent of the current commit, while HEAD~2 means two generations back.
Branches and tags are readable names for commits. The commit hash remains the precise identifier.
How Do You Inspect And Compare Git History?
Use git log, git show and git blame to inspect commits and their origins. Use git diff to compare files, commits or branches.
How Do You Inspect Commits?
# show the full commit history
$ git log
## => output
### commit d4e5f6a (HEAD -> main)
### Author: Ada Lovelace <ada@example.com>
### Date: Wed Aug 5 10:15:00 2026 +0200
###
### Ignore local and generated files
###
### commit b2c3d4e
### Author: Ada Lovelace <ada@example.com>
### Date: Wed Aug 5 10:10:00 2026 +0200
###
### Add Git command reference and examples
###
### commit a1b2c3d
### Author: Ada Lovelace <ada@example.com>
### Date: Wed Aug 5 10:00:00 2026 +0200
###
### Add project introduction
# show one compact line per commit
$ git log --oneline
## => output
### d4e5f6a (HEAD -> main) Ignore local and generated files
### b2c3d4e Add Git command reference and examples
### a1b2c3d Add project introduction
# show branches and merges as a graph
$ git log --oneline --graph --decorate --all
## => output
### * d4e5f6a (HEAD -> main) Ignore local and generated files
### * b2c3d4e Add Git command reference and examples
### * a1b2c3d Add project introduction
# inspect the first commit and explicitly show its patch
$ git show --patch HEAD~2
## => output
### commit a1b2c3d
### Author: Ada Lovelace <ada@example.com>
### Date: Wed Aug 5 10:00:00 2026 +0200
###
### Add project introduction
###
### diff --git a/README.md b/README.md
### new file mode 100644
### index 0000000..56546aa
### --- /dev/null
### +++ b/README.md
### @@ -0,0 +1,3 @@
### +# The Ultimate Git Cheat Sheet
### +
### +A practical reference for everyday Git commands.
# see who last changed every line in a file
$ git blame README.md
## => output
### a1b2c3d (Ada Lovelace 2026-08-05 10:00:00 +0200 1) # The Ultimate Git Cheat Sheet
### a1b2c3d (Ada Lovelace 2026-08-05 10:00:00 +0200 2)
### a1b2c3d (Ada Lovelace 2026-08-05 10:00:00 +0200 3) A practical reference for everyday Git commands.
### b2c3d4e (Ada Lovelace 2026-08-05 10:10:00 +0200 4)
### b2c3d4e (Ada Lovelace 2026-08-05 10:10:00 +0200 5) See commands.md for useful Git commands.
How Do You Compare Changes?
Use git diff to compare your working directory, staging area and latest commit. In this example, you update README.md, move the change through each state and then restore the file so the project is clean for the next example. The displayed output is illustrative.
# add an unstaged line to the README
$ printf "\nExamples are available in the examples directory.\n" >> README.md
# unstaged changes: working directory versus staging area
$ git diff
## => output
### diff --git a/README.md b/README.md
### --- a/README.md
### +++ b/README.md
### @@ -1,5 +1,7 @@
### # The Ultimate Git Cheat Sheet
###
### A practical reference for everyday Git commands.
###
### See commands.md for useful Git commands.
### +
### +Examples are available in the examples directory.
# stage the README change
$ git add README.md
# inspect staged changes: staging area versus HEAD
$ git diff --staged
## => output
### diff --git a/README.md b/README.md
### --- a/README.md
### +++ b/README.md
### @@ -1,5 +1,7 @@
### # The Ultimate Git Cheat Sheet
###
### A practical reference for everyday Git commands.
###
### See commands.md for useful Git commands.
### +
### +Examples are available in the examples directory.
# add another unstaged line
$ printf "Review each command before running it.\n" >> README.md
# inspect staged and unstaged changes together
$ git diff HEAD
## => output
### diff --git a/README.md b/README.md
### --- a/README.md
### +++ b/README.md
### @@ -1,5 +1,8 @@
### # The Ultimate Git Cheat Sheet
###
### A practical reference for everyday Git commands.
###
### See commands.md for useful Git commands.
### +
### +Examples are available in the examples directory.
### +Review each command before running it.
# discard the example changes and return to the latest commit
$ git restore --staged README.md
$ git restore README.md
What Is A Branch In Git?
A branch is a movable name that points to a commit. When you create a commit, the current branch moves forward to the new commit. Creating a branch does not copy the entire project, which makes branches fast and small.
Teams normally keep a stable branch called main and create short-lived branches for features or fixes. This workflow is the foundation of trunk-based development. Two branches diverge when each contains commits that the other does not have.
How Do You Work With Git Branches?
A typical branch workflow consists of creating and switching to a branch, committing a focused change, switching back to main, merging the completed branch into main, and then deleting the merged branch when it is no longer needed.
How Do You Create And Switch Branches?
We will create a feature branch and add a branching guide without changing main yet.
# list local branches; the current branch has an asterisk
$ git branch
## => output
### * main
# create a branch and switch to it
$ git switch --create feature/branching-guide
## => output
### Switched to a new branch 'feature/branching-guide'
# add the feature
$ printf "# Branching Guide\n\nUse short-lived branches for focused changes.\n" > branches.md
$ git add branches.md
$ git commit -m "Add branching guide"
## => output
### [feature/branching-guide b7c8d9e] Add branching guide
### 1 file changed, 3 insertions(+)
### create mode 100644 branches.md
# switch back to main
$ git switch main
## => output
### Switched to branch 'main'
# switch quickly to the previous branch
$ git switch -
## => output
### Switched to branch 'feature/branching-guide'
How Do You Compare Branches?
Once both main and feature/branching-guide exist, use the two-dot form to compare the snapshots at their tips. You can also list commits that are reachable from the feature branch but not from main. The displayed output is illustrative.
# compare the files at the tips of both branches
$ git diff main..feature/branching-guide
## => output
### diff --git a/branches.md b/branches.md
### new file mode 100644
### --- /dev/null
### +++ b/branches.md
### @@ -0,0 +1,3 @@
### +# Branching Guide
### +
### +Use short-lived branches for focused changes.
# show commits reachable from the feature branch but not main
$ git log main..feature/branching-guide --oneline
## => output
### b7c8d9e (HEAD -> feature/branching-guide) Add branching guide
How Do You Rename And Delete Branches?
You can manage branch names without switching to them.
# create a branch without switching
$ git branch feature/commit-guide
# rename a branch
$ git branch --move feature/commit-guide feature/commit-basics
# safely delete a fully merged branch
$ git branch --delete feature/commit-basics
## => output
### Deleted branch feature/commit-basics (was b7c8d9e).
# force-delete an unmerged branch - check its commits first
$ git branch --delete --force feature/abandoned-experiment
What Is A Merge In Git?
A merge combines the histories of branches. If main has not changed since the feature branch was created, Git can perform a fast-forward merge by moving main to the feature commit.
# Before the merge, main has not advanced since feature branched
# and feature builds directly on the commit pointed to by main
A---B---C---D
^ ^
main feature
# After merging feature into main, both branches point to commit D
A---B---C---D
^
main, feature
No merge commit is created: Git only moves the main pointer from B to D.
If both branches contain new commits, Git normally creates a merge commit with two parents. This preserves the fact that two lines of work came together.
# Before the merge
C---D feature
/
A---B---E---F main
# After merging, Git creates commit M with D and F as its parents
C---D-------\
/ \
A---B---E---F-------M main
merge commit
The merge commit M has two parents: F, the previous tip of main, and D, the tip of feature.
How Do You Merge Git Branches?
Merge the branching guide into main.
# move to the branch that should receive the change
$ git switch main
## => output
### Switched to branch 'main'
# merge the feature into the current branch
$ git merge feature/branching-guide
## => output
### Updating d4e5f6a..b7c8d9e
### Fast-forward
### branches.md | 3 +++
### 1 file changed, 3 insertions(+)
### create mode 100644 branches.md
# inspect the result
$ git log --oneline --graph --decorate --all
## => output
### * b7c8d9e (HEAD -> main, feature/branching-guide) Add branching guide
### * d4e5f6a Ignore local and generated files
### * b2c3d4e Add Git command reference and examples
### * a1b2c3d Add project introduction
# remove the branch after the merge
$ git branch --delete feature/branching-guide
## => output
### Deleted branch feature/branching-guide (was b7c8d9e).
If you start a merge and realize that you are on the wrong branch, abort it before committing.
# return to the state before the unfinished merge
$ git merge --abort
What Is A Merge Conflict?
A merge conflict happens when Git cannot safely decide how to combine changes. This commonly occurs when multiple developers work in parallel on different branches and edit the same lines before their changes are merged. For example, main and a feature branch may contain different changes to the same line.
The following conflict is created deliberately for educational purposes. Try it only in this disposable example repository or another safe practice repository, not in work you need to preserve. It changes the final line of branches.md differently on a new feature branch and on main.
# create a feature branch from main
$ git switch --create feature/branch-tips
# change the advice on the feature branch
$ printf "# Branching Guide\n\nKeep branches for future reference.\n" > branches.md
$ git add branches.md
$ git commit -m "Recommend keeping branches"
## => output
### [feature/branch-tips c8d9e0f] Recommend keeping branches
### 1 file changed, 1 insertion(+), 1 deletion(-)
# return to main and change the same line differently
$ git switch main
$ printf "# Branching Guide\n\nDelete branches after merging them.\n" > branches.md
$ git add branches.md
$ git commit -m "Recommend deleting merged branches"
## => output
### [main e9f0a1b] Recommend deleting merged branches
### 1 file changed, 1 insertion(+), 1 deletion(-)
# merge the feature branch into main
$ git merge feature/branch-tips
## => output
### Auto-merging branches.md
### CONFLICT (content): Merge conflict in branches.md
### Automatic merge failed; fix conflicts and then commit the result.
Git pauses the merge and marks branches.md with both versions:
# Branching Guide
<<<<<<< HEAD
Delete branches after merging them.
=======
Keep branches for future reference.
>>>>>>> feature/branch-tips
The first part is from the current branch. The second part is from the branch being merged. The separator and markers are not valid project content; a person must choose or combine the result.
How Do You Resolve A Merge Conflict?
Choose the final wording, remove the conflict markers and stage the resolved file. Here, the resolution combines the useful intent of both versions.
# see every conflicted file
$ git status
## => output
### On branch main
### You have unmerged paths.
### (fix conflicts and run "git commit")
### (use "git merge --abort" to abort the merge)
###
### Unmerged paths:
### (use "git add <file>..." to mark resolution)
### both modified: branches.md
###
### no changes added to commit (use "git add" and/or "git commit -a")
Open branches.md in your editor. Remove the conflict markers and the versions you do not want, then edit the remaining text until the file looks like this:
# Branching Guide
Delete branches after merging them unless your team needs to retain them.
# mark the conflict as resolved
$ git add branches.md
# verify the staged resolution
$ git diff --staged
## => output
### diff --git a/branches.md b/branches.md
### index 7ac83a1..e49bf6c 100644
### --- a/branches.md
### +++ b/branches.md
### @@ -1,3 +1,3 @@
### # Branching Guide
###
### -Delete branches after merging them.
### +Delete branches after merging them unless your team needs to retain them.
# finish the merge
$ git commit -m "Merge branch retention guidance"
## => output
### [main f0a1b2c] Merge branch retention guidance
# remove the merged feature branch
$ git branch --delete feature/branch-tips
Run your tests before finishing the merge. A file without conflict markers can still contain the wrong behavior.
# cancel an unresolved merge instead of completing it
$ git merge --abort
What Is A Remote Git Repository?
A remote repository is another Git repository that your local repository knows by a short name. When you clone a repository, Git normally configures the repository you cloned from as a remote named origin, so you do not need to add it yourself.
A local repository can have multiple remotes, and each remote can have a different name. For example, a fork-based workflow often uses origin for your fork and upstream for the original repository. These names are conventions rather than special Git keywords.
A remote-tracking branch such as origin/main records the state of main that your local Git last received from origin. An upstream branch is the remote branch that a local branch uses by default for pull and push operations.
How Do You Work With Remote Repositories?
First connect the local repository to a remote and publish your commits. Later, fetch or pull remote changes to keep your local repository up to date.
How Do You Add And Push To A Remote?
Create a new empty repository in your GitHub account before running these commands. Do not initialize it with a README, .gitignore or license because this local project already has its own history. In the URL below, replace <your-account> with your GitHub account name and <your-repository> with the name of the repository you created.
# add a remote named origin
$ git remote add origin https://github.com/<your-account>/<your-repository>.git
# inspect remote names and URLs
$ git remote -v
## => output
### origin https://github.com/<your-account>/<your-repository>.git (fetch)
### origin https://github.com/<your-account>/<your-repository>.git (push)
$ git remote show origin
# publish main and remember origin/main as its upstream
$ git push --set-upstream origin main
# publish later commits
$ git push
How Do You Fetch And Pull Remote Changes?
git fetch downloads remote commits and updates remote-tracking branches without changing your current branch. git pull first fetches and then integrates the upstream branch into your current branch.
# download remote information without changing local files
$ git fetch origin
# compare the local and remote main branches
$ git log --oneline main..origin/main
$ git diff main..origin/main
# fetch and merge the upstream branch
$ git pull
# fetch and rebase local commits onto the upstream branch
$ git pull --rebase
Fetching first is easier to reason about because you can inspect incoming commits before integrating them.
Where Can You Find The Advanced Git Cheat Sheet?
This cheat sheet focuses on the Git commands used in a typical daily workflow. Continue with The Advanced Git Cheat Sheet to learn about stash, rebase, cherry-pick, tags, bisect, reflog, worktrees and submodules.
Conclusion
In this article, we started with an empty directory and built a practical mental model of Git. You can now create commits, inspect history, work with branches, resolve conflicts and collaborate through remote repositories.
The safest Git habit is simple: inspect before you change. Use git status, git diff and git log often, and create small commits with clear messages.
If you need help with your DevOps workflows, feel free to contact us, or join our community for further questions and discussions (free cookies for the first 42 arrivals and only 6 left 😱)!
Join Our CommunityYou liked this article? Share it with your colleagues and friends.
Sign up for our newsletter!
Do not miss out on our latest tips, guides, and updates – sign up for our newsletter now! We promise to only send you the most relevant and useful information. Be part of our journey in exploring the world of Git, DevOps and beyond.
By clicking subscribe, you agree to the privacy policy. You can unsubscribe at any time by clicking the link in the footer of our emails.

