Philomatics Git Cheatsheet

Welcome! This is a cookbook for Git, with animated recipes for the most common tasks.

Getting started

Download (clone) an existing codebase (repository)

Obtain the URL for the codebase/repository
To download an existing codebase (also called a repository), you first need to find its URL. On GitHub, you can find it by clicking the green "Code" button. On other git hosters (for example GitLab, BitBucket, etc.) these steps are very similar.

For most repositories, you'll find two URL formats: HTTPS and SSH. If this is your first time ever downloading a repository, and you're unsure which one to choose, read this section first: Setting up Permissions

Make sure that either HTTPS or SSH is selected (depending on which method you set up previously), then copy the URL below to your clipboard
Run git clone URL to download the repo to the current directory
This will download a full copy of the repo, including its entire history.

If you're prompted for a username/password, get a Repository not found error, or permission denied, see this section: Setting up Permissions

Creating a new repository on your computer

Use git init to create an empty repository
The git init command will create an empty repository in the current directory. The newly created repo will not yet have any commits, and no files will be added yet. This command will create the hidden .git folder, in which git stores all the files needed to manage the repository.
Adding the first files to git
Create or copy files into your directory. Then you also have to tell git that it should start managing these files, which you can do by running git add PATH_TO_FILE.
Making your first commit
After adding your files, you can permanently save them to git. To do this, you need to create a so-called commit. A commit is a snapshot of all the files as they are at the current moment.
To do this, run git commit -m "Initial commit".
Connecting your repo with GitHub
If you also want to share your work with others (for example, upload it to GitHub) you need to connect it first with the following steps:
  • Create the repo on GitHub first here. While creating it, make sure not to add a README, .gitignore or license. If you don't want your code to be visible to everyone on the internet, make sure to select Private.
  • After creation, you can get the URL for the repository. For most repositories, you'll find two URL formats: HTTPS and SSH. If this is your first time ever creating a repository, and you're unsure which one to choose, read this section first: Setting up Permissions
  • Make sure that either HTTPS or SSH is selected (depending on which method you set up previously)
  • Then run the three commands shown below in the "…or push an existing repository from the command line" section:
  • Run git remote add origin URL. This will create the link between GitHub and the code stored on your computer.
  • Run git branch -M main. In earlier versions of git, the default branch name was master, which was later renamed to main. With this command, it's ensured that the default branch's name is main.
  • Run git push -u origin main. This will upload your code to GitHub for the first time.

Making code changes and sharing them with others

Write your code
  • Modify the files in your working copy as you like
  • Run git status to see all modified files
Add the changed files to git
  • Before you can commit your changes and store them permanently in your git repository, you need to add them to git
  • Run git status to see all modified files
  • Run git add PATH_TO_FILE for each modified file
  • Alternatively, run git add -A to add all uncommitted changes
  • After adding the files, you can run git status again to see which files are currently staged
  • To unstage a file again without deleting the changes, run git reset PATH_TO_FILE
  • All the files that you add like this will be added to the so-called staging area.
Commit your changes
  • Once you've staged all your changes, you can commit them. Committing will create a snapshot at the current point in time.
  • Run git status to verify which changes you've currently staged
  • Run git commit -m "COMMIT_MESSAGE". If this is your first commit, run git log first to see what commit message style your team is following. Alternatively just write a short description of what you did since your last commit.
Push your changes to the server (e.g. GitHub)
  • Run git branch to figure out which branch you're on
  • To push your changes to the server, run git push -u origin BRANCH_NAME
  • On subsequent pushes, you can just run git push

Branches

What are branches? Why are they useful?

Why should I use branches?
On bigger projects, different team members often work on different features. For example, for a web application, you might be working on a login feature, while your colleague is working on the shopping cart feature. In such cases, it can make sense to split your work into separate versions, until you're done, and then merging them together. This is one of the most common scenarios where branches are useful. To learn more about how this works in practice, see the following topics.
How do branches work under the hood?
  • By default, all commits you make are on the main branch
  • On a technical level, a branch is really just a name that is given to a specific commit. So, for example, when you create a new branch named feature/login, git will internally store this name and associate it with the current commit that you're on
  • When you then switch to a branch, the files in your working copy are modified so that they match the state of the branch
  • When you make commits while having checked out a branch, the branch pointer is moved to the newly created commit
  • If we switch back to the main branch, and continue to make commits to it, the two branches will diverge. This means that they are now different versions that have to be merged to bring all these changes together again.

Listing branches

List local branches
A local branch is a branch stored on your computer. You can then sync it with a remote server (usually GitHub) by pushing and pulling. To list all local branches, run git branch without any other arguments. This will also show you which branch you've currently checked out
List all (local & remote) branches
A remote branch (which usually starts with origin/) is a cached copy of a branch that has been pushed to the remote server, for example to GitHub. When you first clone your repo, it will also download all the remote branches, and cache them locally. To list all branches, including remote branches, run git branch -a. The branches that start with origin are locally cached copies of the branches that have been pushed to your server (most likely to GitHub).

Creating and switching branches

To create a branch, run git branch BRANCH_NAME
This will create the branch, but not switch to it yet.
Switch to your new branch with one of these two commands:
  • git checkout BRANCH_NAME
  • or, in newer versions of git: git switch BRANCH_NAME
There's also a faster way to create a new branch and switch to it in a single command:
  • git checkout -b BRANCH_NAME
  • or, in newer versions of git: git switch -c BRANCH_NAME
Note that you generally don't want to switch to remote branches (so branches that start with origin/).
  • git checkout -b BRANCH_NAME
  • or, in newer versions of git: git switch -c BRANCH_NAME

Merge two branches

Switch to the branch you want to merge into
For example, if you want to merge main into feature/example, run:
git switch feature/example
This will make the latest commit on the feature branch the new HEAD.
Run git merge BRANCH_TO_MERGE
For example, if you want to merge main into feature/example, run:
git merge main
If your branches had diverged before the merge, a merge commit will be created. In this case, you will be prompted to enter a commit message. Otherwise, your branch will be fast-forwarded, and no merge commit will be created.

If prompted, enter the commit message for the merge commit. Running this command may open a text editor, which by default is the terminal-based text editor Vim. If you're not familiar with Vim, I highly recommend configuring your text editor to something you're already comfortable with. To get out of Vim, press Escape, then type :q! and press return.

Fix merge conflicts, if there are any
Fixing merge conflicts is a hard to explain without visuals, so I made a full video for this here.

Deleting branches

Deleting a local branch
Run git branch -d BRANCH_NAME. This will fail if the branch hasn't already been fully merged, because then deleting it might lose you some work. If you're sure you want to delete it anyways, run git branch -D BRANCH_NAME (notice the capital -D).
Deleting a remote branch
Run git push -d origin BRANCH_NAME. This will delete the branch on the server. Note that there's no check if the branch has been merged fully, so be careful!

General tips

Changing the default text editor for Git

Why change the default text editor?
Various actions in git, such as editing commit messages, merging branches, or opening the config file will open the default text editor, which is a terminal-based editor called Vim. Vim is pretty notorious for being hard to use, so it's often a good idea to change the default text editor to something you're already comfortable with.

If you just want to get out of Vim, press Escape, then type :q! and press return.

The video to the right is timestamped and will take you to the exact point where I start talking about changing the default text editor.
How do I change the default text editor?
To change your editor to Visual Studio Code, run:
git config --global core.editor "code --wait"
If you use a different editor, you gotta figure out how to run it from the command line. To do this, just search the web for "run [your editor] from the command line". For example, for IntelliJ IDEA, you could run "idea --wait". For some editors, you might have to install a command line tool first.

Once you've found the command, you can set it as the default text editor by running:
git config --global core.editor "[your command]"
The video to the right is timestamped and will take you to the exact point where I show you how to change the default text editor.

Setting up permissions

HTTPS vs SSH
For most repositories, you'll find two URL formats: HTTPS and SSH. These are different ways to download the data, and, more importantly, log in to GitHub as you're downloading the code. This is necessary when you're downloading/cloning private (closed-source, company-owned) code, since of course not just anyone should be able to download it. Instead you need to configure your local git installation to use a username & password. How this is done exactly differs when using HTTPS and SSH (see below).

Some companies may restrict access to one or the other based on their security policies - in that case you have no choice, and the disabled option will not show up on GitHub.

If both are available, I recommend HTTPS, since it's easier to set up and works in more situations, and it's the way GitHub recommends accessing the repositories.

You can read up more about the differences between HTTPS and SSH in GitHub's official guide.
Setting up HTTPS access
  • When git prompts you for a username, enter your GitHub username
  • When prompted for a password, do not enter your regular GitHub password. Instead, you need to create a Personal Access Token (essentially a more secure password) on GitHub.
    • Go here, and log in with your GitHub account
    • For the Note, I recommend putting in your computer's name (especially if you have multiple computers)
    • Set the expiration date. You'll have to redo these steps after the token expires.
    • Check the repo checkmark
    • Scroll all the way down and click Generate token
  • Save the generated token in a secure place (for example, your browser's password manager)
  • Use the generated token when git prompts you for a password
  • If you don't want to copy/paste the token every time you can follow this guide to set up Git Credential Manager
Setting up SSH access
If you need to use SSH, GitHub has an excellent guide. Alternatively, you can watch the video to the right.

Setting up useful shortcuts/aliases

How to set up shortcuts/aliases?
To set up a single shortcut, use this command:
git config --global alias.SHORTCUT "FULL_COMMAND"
For example, to map git status -s to git st, run:
git config --global alias.st "git status -s"
From now on, you can always use git st instead of git status -s.

Alternatively, you can also modify the global git config, which is just a text file where git stores all configuration, including aliases. To open the global .gitconfig, run:
git config --global --edit
Make sure to configure your text editor to something you're already comfortable with before running this command.
My most used shortcuts/aliases
You can add the following aliases to your global git config. Check out the video to the side to see what all these do.
[alias]
    st = status -s
    sta = status
    conf = config --global --edit
    cge = config --global --edit
    ci = commit
    co = checkout
    cod = checkout .
    rh = reset HEAD
    aa = add -A
    cdf = clean -df
    br = branch
    bra = branch -a
    pr = pull --rebase
    amend = commit -a --amend --no-edit
    ciam = commit -a --amend --no-edit

Intermediate and Advanced Workflows

Saving code changes for later with git stash

Why use git stash?
Sometimes you want to switch branches or perform other actions that require a clean working copy, but you're not quite ready to commit your changes yet. Git stash is a way to temporarily store your changes, do whatever you need to do, and then retrieve them later.
Use git stash to store all uncommitted changes for later
This will remove all uncommitted changes from the working copy and put them in a temporary storage. You can also use this longer form to give your stash a message:
git stash push -m "MESSAGE"
This makes it easier to see which changes are contained in the stash, similar to a commit message.
You can see all stashes with the git stash list command
Your stashes will be listed with their messages if available. If you want to see the changes in the stash, it's probably easiest to do with a GUI client, like SourceTree.
Use git stash pop to retrieve the last stash you stored
This will re-apply the latest stash to your working copy and also remove the it from the temporary storage If you want to only apply it, but not remove it from the stash, run:
git stash apply
Both of these commands can also be used with a specific stash that you retrieved with git stash list, for example:
git stash pop stash@{1}
git stash apply stash@{1}

Undoing a commit (git revert, git reset)

How to undo a git commit?
Before undoing a commit, you need to determine if you've already pushed the commit to a remote repository or not:
  • If you haven't pushed the commit yet (it only exists on your local machine), you can use git reset to remove it
  • If you have already pushed the commit, you should use git revert to create a new commit that undoes the changes
This distinction is important because git reset rewrites history, which can cause problems for other developers if the commit was already shared. git revert is safer because it adds a new commit instead of removing existing ones. If you're not sure if you've already pushed the commit, you can always check with this command:
git log --oneline --branches --not --remotes
Any commits listed here have not yet been pushed and are safe to reset. However, if this command returns nothing or your commit is not listed, you definitely should not reset it and use revert instead.
Use git reset to undo commits that haven't been pushed yet
To undo the last N commits, run:
git reset HEAD~N
This will remove the commits from the current branch, but leave the changes in the working copy.

Be aware that any commits you reset this way are not deleted entirely. So you can't use this to remove sensitive data that you've accidentally committed. Instead, you need to use another tool, check out this guide.

Note that you can only use git reset to undo the latest commits, you can't delete commits earlier in the history while leaving your latest commit intact. To do this, you'd need to use interactive rebase.
Use git revert to undo commits that have already been pushed
To undo a commit that has already been pushed, run:
git revert --no-edit COMMIT_HASH
This will create a new commit that undoes all the changes from the specified commit. You can find the commit hash by running git log --oneline.

The main difference to git reset is that git revert doesn't remove any commits from the history. Instead, it adds a new commit that undoes the changes. This is much safer when working with shared repositories, since it won't cause any problems for other developers who have already pulled your changes.

Be careful when reverting merge commits - they require special handling. Check out this Stack Overflow post for details on how to properly revert merge commits.

Stop using git pull

Why should I not use git pull?
When you use git pull, git will fetch (download) all the changes of your currently checked out branch. However, if you already made a commit before pulling, this will create an extra merge commit, which is unnecessary. This merge commit pollutes the git commit history, making it more difficult to find the exact commit that you're looking for. If that's something you care about, you should avoid using git pull.
What to do instead?
Use git pull --rebase instead. This will temporarily put your not-yet-pushed commit on the current branch aside, fetch and apply the changes from the remote, and then re-apply your commit on top. This even works for multiple commits.
What about merge conflicts?
Of course you can still get conflicts when you use git pull --rebase. You can either fix them as you usually would fix a merge conflict, and then run git rebase --continue. Keep repeating this process until all conflicts are resolved.

Alternatively, you can also run git rebase --abort to return your repo to the state it was in before you ran git pull --rebase. Then you can just run git pull and do a regular merge as usual.
I heard that you shouldn't use rebase since it can mess up the history for the other team members?
These problems with rebasing can only happen if you rebase commits that have already been pushed. In this case, this can not happen, since by definition the commits that are being rebased have not yet been pushed.

Also, if you run into issues, you can always abort the rebase using git rebase --abort.

Using Git Rebase

Why use git rebase?
Rebasing helps you keep the commit history more linear, since it avoids unnecessary merge conflicts. This makes it easier to find old commits where a particular bug was fixed or feature introduced. If you don't care about a linear commit history, you don't ever have to rebase at all.
How to use git rebase?
Check out the branch that you want to rebase (i.e. the branch that has the commits you want to put on top of another branch). For example, when you want to rebase a branch called example on top of main, run git checkout example. Then run git rebase main to rebase on top of main.

Be careful though: Never rebase commits you've already pushed! If you're unsure if you've already pushed your feature branch, run git branch -a, and if the branch is listed there, under the remote branches, you really shouldn't rebase. Check the video to the side for a full explanation why this is the case.
Dealing with conflicts
Fixing conflicts during rebase is quite similar to fixing conflicts during merge. You remove the conflict markers, put the file in the desired end state, and then you run git add FILE on all conflicted files, and then run git rebase --continue. Keep repeating this process until no more conflicts appear. Watch the video to the side for a full overview of this process.
Aborting a rebase
Before the rebase is finished (while you're still resolving conflicts), you can always abort a rebase by using git rebase --abort. Careful though: Once the rebase is completed, undoing it is quite difficult. I recommend creating a local copy of your repo before you attempt a complex rebase.

Interactive Rebase (Edit, Delete, Squash, Reorder Previous Commits)

What's an interactive rebase?
Interactive rebase is a very powerful command, letting you edit, delete, squash and reorder older commits. Be careful though, you should only use this on commits you haven't pushed yet. See the video for a detailed explanation why.
How to do an interactive rebase?
To start an interactive rebase, run:
git rebase -i HEAD~N
where N is the number of commits you want to edit. For example: git rebase -i HEAD~4 will let you edit the last 4 commits. This will open your text editor with a list of commits. For each commit, you can:
  • Change pick to drop to delete the commit
  • Change pick to squash or s to combine it with the previous commit
  • Change pick to edit or e to modify the commit
  • Reorder the lines to reorder the commits
Save and close the editor to start the rebase. Git will stop at each commit you marked for editing.

Make sure to configure your text editor before attempting an interactive rebase.
Dealing with conflicts
Fixing conflicts during rebase is quite similar to fixing conflicts during merge. You remove the conflict markers, put the file in the desired end state, and then you run git add FILE on all conflicted files, and then run git rebase --continue. Keep repeating this process until no more conflicts appear. Watch the video to the side for a full overview of this process.
Aborting a rebase
Before the rebase is finished (while you're still resolving conflicts), you can always abort a rebase by using git rebase --abort. Careful though: Once the rebase is completed, undoing it is quite difficult. I recommend creating a local copy of your repo before you attempt a complex rebase.