Git cheat sheet

Marc Deveaux
16 min readAug 14, 2021

Photo by David Clode on Unsplash

The following are my notes from the git and GitHub bootcamp online course by Colt Steele on Udemy

Intro

Differences between git and git hub

  • Git is the version control software that runs locally on your machine. You don’t need an account and you don’t need internet to use it. You can use git without ever touching GitHub
  • Github: service that hosts git repositories in the cloud and make it easier to collaborate with other people. You need an account and it is an online place to share work done using git
  • You don’t have to use git bash (command line style), you can use GUI like GitKraken

Configuring git

To check if git hub is installed / what version is it

git — version

To see the name associated with your work and configure it:

git config user.namegit config — global user.name “XXX XXXXX”

To configure the email address:

git config — global user.email blah@blah.com

To configure which editor you want to use (example below with notepad++)

https://git-scm.com/book/en/v2/Appendix-C%3A-Git-Commands-Setup-and-Config

git config --global core.editor "'C:\Program Files\Notepad\notepad.exe' -multiInst -notabbar -nosession -noPlugin"

The basics

Git command for adding and committing

git init: initialize a new repository

git status: git information on the current status of a git repository and its content. You can also use it to check if you are within a repo

git add: add one or multiple files to the staging area. i.e git add file1 file2 .

  • git add . will stage all changes at once
  • you can add a directory git add myDir/

git commit -m “my message”: can be think as a “check point”, we actually commit changes from the staging area.

  • documentation recommends to use present tense with imperative for comment: “make X do Y” instead of “I changed X to do Y”

git log: track the various past commits you did. at the top of each commit is a commit hash (a long suite of letters an numbers) which is used to revisit a commit, undo a commit or check out a commit

  • you can change the format with git log — pretty=oneline / git log — oneline to simplify the log
  • git log shows you only the past commits of your current branch

— amend: used if you forgot to include a file in a commit, or had a typo in the commit’s comment. Only for the previous commit.

# example:git commit -m "xxxxxxxx"git add file_new.txtgit commit --amend

The basic git workflow

Overview: work directory > git add > staging area > git commit > repository

  1. work on stuff: make new files, edit, delete, etc..
  2. add changes: group specific changes together, in preparation of committing
  3. commit: commit everything that was previously added

Atomic Commit: keep each commit focused on a single thing (instead of everything at once). So use git add once you know which modified files can be put together

Ignoring files to track

Using the .gitignore file, you can avoid git tracking. For example, for API keys, credentials, log files, dependencies and package, etc.

To do so, create a file called .gitignore in the root of a repository. Inside the file, we can write patters to tell Git which files/folders to ignore:

  • .DS_Store will ignore files named “.DS_Store”
  • *.log will ignore any files with .log extension
  • folderName/ will ignore an entire directory

Working with branches

Master branch

Branches are alternative timelines for a project. The default branch name is master (recently renamed “main” in 2020). Many people designate the master branch as the “official branch” for the codebase, the one that should always be working. However, from git point of view, the master branch is like any other branch — it doesn’t have to be the “master copy” of your project.

What is HEAD?

When you put git log, you can sometimes see in your past commit HEAD -> master.

HEAD is a pointer that refers to the current “location” in your repository. It points to a particular branch reference. So by default it will refer to the last commit on the master branch.

A good analogy is to think about a book with several bookmark. One bookmark indicates where I am in the book, another bookmark indicates where X is, etc. However, we can only be one to read the book at a given time and this is what HEAD indicates. So you can open the book at any bookmark place (or “checkpoint”) and this is where HEAD will be at.

Branches main commands

git branch: see the list of all existing branches. The current one is noted with “*”

git branch <branch-name>: create a new branch based upon the current HEAD. You are creating and not not moving to the <branch-name> branch

git switch <branch-name> : switch to the <branch-name>. git checkout is the old command to switch branches. It also do more things so to make it easier, git switch is used to switch branch

Note: if you have uncommitted work and that you want to change the branch, then you will lose your uncommitted work (if there is conflict between branch).

git branch — delete <branch-name>: delete a branch. You cannot be on the branch you want to delete

git branch -m <branch-name-new>: rename the branch. You have to be on the branch you want to rename

Merging Branches

Concept

  • we merges branches. not specific commits
  • we always merge to the current HEAD branch

Steps:

  1. switch to the branch you want to merge the changes into (the receiving branches)
  2. use the git merge command to merge changes from a specific branch into the current branch
git merge <branch-to-merge>

Fast forward merging

When you simply create a branch, commit few times and merge, we talk about a fast forward merging (i.e the pointer is just moved forward)

What if we add a commit on master? Merge Commit

If master had several commits while we worked on a separate branch, then we have what is called a merge commit. In this case when we will merge, there are 2 parents for the merging (your branch commit and the master branch commit)

Merging conflict

Steps:

  1. Open up the file(s) with merge conflicts. Note you have to stay on the same branch, you cannot go to the branch you want to be incorporated
  2. Edit the file(s) to remove the conflicts. decide which branch content you want to keep in each conflict. Or keep the content from both
  3. Remove the conflict “markers” in the document
  4. Add your changes and then make a commit (so no re-merge!)

Git diff

You use git diff to view changes between commits, branches, files, our working directory and more

git diff: By default, lists all the changes in our working directory that are NOT staged for the next commit

git diff HEAD: lists all changes in the working directory tree since your last commit

git diff — staged: list only the staged changes

git diff HEAD [filename] or git diff — staged [filename]: list changes on a specific files

git diff branch1 branch2: list the changes between two branches. The order of the branch does matter

git diff commit1_hash commit2_hash: list changes between two commits

Stashing with Git stash

What problem does git stash solve?

What if you have uncommitted changes on one branch and I switch on another branch? Example case: you have to fix a typo on another branch, etc…

Then two options:

  • my changes come with me to the destination branch (if there are no conflict)
  • git won’t let me switch if it detects potential conflicts (for example if master was changed in-between)

This is where git stash comes in. If I don’t want to bring the changes with me or if I am not ready to commit, I can use git stash to sort of pause to save my change without actually committing them. I can then return to them later.

Main Commands

git stash: take all uncommitted changes (staged and unstaged) and stash them, reverting the changes in your working copy. It is the same thing than git stash save

git stash pop: remove the most recently stashed changes in your stash and re-apply them to your working copy

git stash apply: apply whatever is stashed away, without removing it from the stash. This can be useful if you want to apply stashed changes to multiple branches

git stash list: you can add multiple stashes onto the stack of stashes. They will all be stashed in the order you added them. This command list them. You can then apply specific stash if you want with git stash apply stash@{2}

git stash drop <stash-id>: to delete a particular stash. for example git stash drop stash@{2}

git stash clear: clear out all stashes

Undoing changes and time traveling

Going to an old commit

git checkout <commit-hash>: going to a previous commit state. You are in a detached HEAD situation. Recall that HEAD points to a branch reference, and it points to the tip of the branch — not to a commit. So HEAD was changed from the last commit of a branch to a previous commit. if you need to re-attached the HEAD, simply switch back to whatever branch you were on before (git switch master for example)

git checkout HEAD~2: refers to 2 commits before HEAD. This is another way to go back to previous commit

git restore: another option.

Discarding changes

git checkout HEAD <filename>: discard any changes in that file, reverting back to HEAD. It means take the <filename> and bring it back to how HEAD is. So if you don’t have anything committed, you can bring back the file to the last commit status.

git restore <filename>: similar to above command, restore the file to the contents in the HEAD. Once done you cannot undo this action. if you want to restore to a specific commit, do git restore — source HEAD~1 home.html; it will restore the content of home.html to its state from the commit prior to HEAD

Unstaging files with restore

git restore — staged <filename>: the file will become unstaged

Undoing commits

git reset <commit-hash>: will reset the repo back to a specific commit. The commits are gone but the changes are still in the working directory. This is a simple “reset”. This is useful if the changes made were supposed to go on a new branch

git reset — hard <commit-hash>: hard reset up to the <commit-hash>. For instance, git reset — hard HEAD~1 will delete the last commit AND associated changes

Reverting commit with git revert

git revert and git reset are kind of similar in that they both “undo” changes, but they accomplish it in different ways

git reset actually moves the branch pointer backwards, eliminating commits

git revert <commit-hash> instead creates a brand new commit which reverses/undos the changes from a commit. Because it results in a new commit, you will be prompted to enter a commit message. This can be useful if you want to reverse some commits that other people already have on their machine. If you want to reverse commits that you haven’t shared with others, use reset and no one will ever know!

GitHub

Cloning

git clone <url>: clone a local repository hosted on GitHub by retrieving all files associated with the repo and initializes a new repo on your machine. Make sure you are not inside a repo when cloning!

SSH Keys

SSH keys are used to connect to GitHub without having to supply your username / password each time you do certain operations like pushing. You can find instruction steps on GitHub website

Creating a repo

Option 1: Existing repo

if you already have an existing repo locally that you want to get on GitHub…

  • create a new repo on GitHub
  • connect your local repo (add a remote)
  • push up your changes to GitHub

Steps

  1. create an empty repository on GitHub
  2. set up git remote to tell git about our remote repository on GitHub. A “remote” is simply the destination, i.e the URL where the hosted repository lives.
  • git remote add <name> <url>: add a new remote, using the <name>. Conventional name for the URL is origin
  • git remote or git remote -v : to check on which remote you are. -v is for verbose
  • git remote rename <old> <new>: if needed, rename the remote
  • git remote remove <name>: if needed, remove the remote

3. Then push up your changes

git push <remote> <branch>: specify the remote we want to push up AND the specific local branch we want to push up to that remote. For ex: git push origin master. If you push up branches, then you have the possibility on GitHub to switch from master to the other branches. Note that you can decide to push a local branch to a remote branch of a different name: git push <remote> <local-branch>:<remote-branch>

git push -u origin master: the -u option allows us to set the upstream of the branch we are pushing. You can think of this as a link connecting our local branch to a branch on GitHub. Running git push -u origin master sets the upstream of the local master branch so that it tracks the master branch on the origin repo. Basically, once done, we can use git push shorthand which will push our current branch to the upstream (so it creates a shortcut)

Option 2: start from scratch

If you haven’t begun work on your local repo, you can…

  • create a brand new repo on GitHub
  • clone it down to your machine
  • do some work locally
  • push up changes to GitHub

Steps

  1. create a brand new repo on GitHub
  2. clone it down to our machine: check that you are in a new local folder without any repo and do git clone <URL>
  3. do some work
  4. git push origin master

Fetching and pulling

Remote tracking branches

“At the time you last communicated with this remote repository, here is where x branch was pointing”

They follow the pattern <remote>/<branch>.

  • origin/master references the state of the master branch on the remote repo named origin
  • upstream/logoRedesign references the state of the logoRedesign branch on the remote named upstream (a common remote name)

Run git branch -r to view the remote branches our local repository knows about

You can do git checkout origin/master to check the remote branch pointer. HEAD will be detached

Working with remote branches

When you clone a repo, you only get the master branch, not all the branches that exist. However, if you do git branch -r, you will see them. So the repo knows about it but you don’t have the files. By default, git do a connection with origin/main, but it doesn’t do it with origin/<some-branch>.

In order to work on a remote branch, and have your own branch connected to it, you have to do git switch <remote-branch-name>; name has to be the same

Git fetch

Fetching allows us to download changes from a remote repository, BUT those changes will not be automatically integrated into our working files

It lets you see what others have been working on, without having to merge those changes into your local repo

  • from remote repo to local repo = git fetch
  • from git repo to workspace = git pull

git fetch <remote>: default remote is origin if not specified. This would fetch all changes from the origin remote repository

git fetch <remote><branch>: retrieve info from a specific branch

For example, if I do git fetch origin master then I will have a new branch origin/master that I can look at but my master branch didn’t change. I can do git checkout origin/master to go check what work those done by my colleague

Note: git is not constantly asking GitHub if they are aligned, so you can see written “your branch is up to date with origin/movies” while in fact it is not true. You will have to do git fetch origin and git status to see if that’s really the case

Git pull

git pull updates our HEAD branch with whatever changes are retrieved from the remote. so go and download data from GitHub AND immediately update my local repo with those changes

Not recommended if you have uncommitted changes

git pull = git fetch + git merge

git pull <remote> <branch-name>: like git pull origin master

Git pull and merge conflict

As a good practice, before you push up anything on GitHub, you should always start by a git pull

Resolving conflicts are done in a similar fashion as seen before

Git collaboration workflow

Centralized workflow

  • Everyone works on master/main
  • The weakest of all the workflows

Problems:

  • lot of time spent resolving conflicts and merging code
  • no one can work on anything without disturbing the codebase
  • The only way to collaborate on a feature together with another teammate is to push incomplete code to master. Other teammates now have broken code

Feature branches workflow

  • very common workflow
  • rather than work on master, all new development should be done on separate branches
  • treat master branch as the official project history
  • master branch won’t contain broken code
  • multiple teammates can collaborate on a single feature and share code back and forth without polluting the master branch

Merging in feature branches

We have a couple of options:

  • merge at will
  • send an email / chat message to discuss if the changes should be merge in
  • pull request

Note: there are conventions for branch name. For example feature/XXXX. See tips here

pull requests

Pull requests are built in to products like GitHub and are not native to git. They allow developers to alert team-members to new work that needs to be reviewed. They provide a mechanism to approve or reject the work on a given branch. You can open a pull request on GitHub when you are on a branch (“compare and pull request”)

Workflow looks like this:

  • do some work on a feature branch and push it up to GitHub
  • open a pull request using the feature branch you just pushed
  • wait for the push request to be approved and merged / or discussed

In case of conflicts, you can deal it with normally as for previous cases

Fork and clone: another workflow

Instead of just one centralized GitHub repository, every developer has their own GitHub repository in addition to the “main” repo. Developers make changes and push to their own forks before making pull requests. It is very common for large open-source projects.

Forking

Similar to pull requests, it is not a git feature and was implemented in GitHub. Forking allows us to create personal copies of other people’s repositories. Those copies are a “fork” of the original. So it allows you to push to origin because the origin is now under your name.

My fork becomes the “origin” while I need to set up a new pointer to the original project repo (not the fork) that we will call (by convention) upstream. It allows me to have one place where I can do my changes (the fork) while keeping track of the original repository to pull last changes, etc… So you would push your change to your origin fork and then make a pull request

Summary

  1. fork the project
  2. clone the fork
  3. add upstream remote (git remote add upstream <url>)
  4. do some work
  5. push to origin
  6. open pull request

Rebasing

There are two main ways to use the git rebase command:

  • as an alternative to merging
  • as a clean up tool

An alternative to merging

If you work on a feature branch and the rest of your team is very active on the master branch, you constantly need to merge your branch into master to be up to date. It will results in dozen of your merged commit being merge to follow master, which are “useless” commits or at least not very informative. The commit history becomes not so clean.

Rebasing fixes this problem by “rewriting history” to create new commits for each of the original feature branch commits. We rebase the feature branch onto the master branch. This moves the entire feature branch so that it BEGINS at the tip of the master branch.

git rebase master

When not rebase

Never rebase commits that have been shared with others. If you have already pushed commits up to GitHub… DO NOT rebase them unless you are positive no one one the team is using those commits

Interactive Rebase

You can use git rebase as a clean up tool to rewrite, delete, rename and even reorder commits (before sharing them)

git rebase -i HEAD~4: -i is for the interactive mode and ~4 means 4 commits ago. We need to specify how far back we want to rewrite commits and you have to rebase on the HEAD the commits are based on

Once used, you will enter in a text editor, seeing a list of commits alongside a list of commands that we can choose from. You can then decide what to do with your commits

  • pick: use the commit
  • reword: use the commit, but edit the commit message
  • edit: use commit but stop for amending
  • fixup: use commit contents but meld it into previous commit and discard the commit message
  • drop: remove commit

Combining commits with the fixup command

After doing git rebase -i HEAD~4, you can combine 2 commits together:

pick 000001 add project filespick 000002 add bootstrapfixup 000003 forget to add bootstrap js script

000003 will be merged to the upper commit 000002

Dropping commits

You can use “drop” to remove a commit entirely (all changes will be gone)

Git Tags

Tags are pointers that refer to particular points in git history. Tags are most often used to mark version releases in projects (v4.1.0, etc.)

Tags are like branch references that do NOT CHANGE. Once created it always refers to the same commit

2 types of tags:

  • lightweight tags: just a name/label that points a particular commit
  • annotated tags: store extra meta data including author’s name, email, date, tagging message

Versioning

The semantic versioning spec outlines a standardized versioning system for software releases.

Versions consists of three numbers separated by periods: for example, 2.4.1

  • 2: is the major release. Significant changes that is no longer backwards compatible. features may be removed or changed substantially. Minor release and patch release are reset to 0
  • 4: is the minor release. New features or functionality have been added, but the project is still backwards compatible. No breaking changes. The new functionality is optional and should not force users to rewrite their own code. Note that the patch number reset to 0 when minor releases increase.
  • 1: is the patch release. Patch releases do not contain new features or significant changes. They usually mean bug fixes and other changes that do not impact how the code is used

Typically, the first release is 1.0.0. Prerelease can have things words added like v4.5.1- Beta

Viewing tags

git tag: print the list of all tags in the current repo

We can search for tags that match a particular pattern by using git tag -l and then passing in wildcard pattern. For example: git tag -l “‘beta

To move to the state of a repo git checkout <tag_name>

To see the differences between 2 tags: git diff v17.0.0 v17.0.1

Creating lightweight tags

git tag <tag_name>: by default git will refer to the commit the HEAD is referencing

Creating annotated tag

git tag -a <tag_name>: it will open your default text editor and prompt you for additional information. Similar to git commit, you can use -m to pass a message directly

git show <tag_name>: to see the metadata information

Other

git tag -a <tag_name> <commit-hash>: tagging previous commits

git tag -f <tag-name>: we cannot reuse the same tag twice, except if you force our tag through with -f

git tag -d <tag-name>: to delete a tag

git push origin — tags: by default, git push doesn’t transfer tags to remote servers. If you need to push up all your tags, you can use the — tags option to git push. Use git push origin v1.5 to push a single tag

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Marc Deveaux
Marc Deveaux

No responses yet

Write a response