Git Cheat Sheet

Terminology

HEAD - pointer to the last commit in the currently check-out branch (pointing to tip of branch)
origin - points to repository that was cloned (when forking, points to your fork on Github)
upstream - generally refers to original repo that was forked. See git remote for adding remotes
untracked files - are files that git doesn't know about or isn't tracking and can be added with git add <file>
origin - pointer to remote repository URL that was cloned (when forking, points to your fork repo on Github)
work-tree - is the working directory of the user where local changes to files can be made
staging area (index) - where commits are prepared
~ - tilde is used to denote a commit object that is nth generation ancestor eg. (master~2 = grandparent of HEAD).

Common Commands

Adding

$ git add -A Stage all changes
$ git commit -m "" Commit all files
$ git commit -amend Amend commit (replace with new commit)

Undo

$ git reset <file> Unstage a file (remove file from staging)
$ git checkout -- <file> Discard changes to a file in work-tree
$ git reset --soft HEAD~1 Uncommit previous commit (moves HEAD to parent commit)
$ git reset --hard HEAD Reset everything use with caution
$ git revert HEAD~1 Revert all changes in HEAD~1 with new commit

Branching

$ git branch -a List local & remote branches
$ git branch <new-branch> Create new branch
$ git branch -d <branch> Delete a local branch
$ git checkout -b <branch> --track <remote>/<branch> Create & Track & checkout new branch
$ git rebase master Merge master changes with current checked-out branch
$ git stash Stashes work-tree & staging
$ git stash apply Apply a stash without removing from stash list

History

$ git log List all commits of checked-out branch, starting with HEAD
$ git blame <file> List changes made by who & when in a file
$ git bisect Use binary search to find the commit that introduced a bug

General Index

Git Add

Add files to staging area (index) from work-tree

$ git add -A // stages all changes
$ git add .  // stages new files and modifications, without deletions
$ git add -u // stages **tracked changes only** (modifications and deletions, without new files)

Undo adding files to staging by using git reset

$ git reset <file> // remove specific file from staging area (index)
$ git reset // remove all files from staging area (index)

Git Reset

Reset current HEAD to the specified state indicated by the commit & flag. The default flag is --mixed and the default commit is HEAD.

$ git reset --soft <commit> Only resets HEAD to commit, keeps staging area & work-tree unmodified
$ git reset --mixed <commit> Resets commit history & staging area, pending staged changes are moved to work-tree
$ git reset --hard <commit> Resets commit history & staging area & work-tree to match specified commit

Specific files can be reset using

$ git reset <file> // unstage file
$ git reset // unstage all files

Git Revert

Makes a new commit that reverts the changes made by other commits.

Example 1: Removing a single commit

git revert HEAD~3 //revert changes specified by 4th last commit in HEAD

Example 2: Removing a range of commits

git revert -n master~5..master~2 //revert changes done by commits 5th last - 3rd last (inclusive)

Git Fetch

Download objects and refs from another repository.

$ git fetch origin // default fetchs the origin, unless theres a matching upstream branch

Git Merge

Join two or more development histories commits together into a single merge commit.

Example of merging new master changes into feature branch
$ git checkout feature
$ git merge origin/master

Abort a merge

$ git merge --abort

Continue a merge (used after resolving conflicts)

$ git merge --continue

Git Pull

Fetch from and integrate with another repository or a local branch. If no branch is explicitly specified, changes are pulled in from the tracked branch as set by git branch --track.

Format
$ git pull <remote>

Equivalencies
git pull = git fetch + git merge
git pull --rebase = git fetch + git rebase

$ git pull // fetchs and merges tracking branch with current checked-out branch
$ git pull --rebase // fetchs and rebases current checked-out branch with changes from tracked branch
$ git pull --force // force the pull, use cautiously

To configure git pull to run a git pull --rebase every time, run the following

$ git config --global pull.rebase true

Git Push

Update remote refs along with associated objects. Pushes commit to remote repository.

Format
$ git push <remote> <branch>

Git Commit

Create a new commit containing the current content of staging with message describing changes.

Create new commit from staging, updating HEAD.
$ git commit -m ""

Replaces previous commit that with new commit.
$ git commit -amend

Add all tracked modified files to staging & commit them use with caution
$ git commit -am ""

Git Rebase

A form of merging that re-writes the project history by creating new commits for each commit in the origin branch. The major benefit of rebasing is a cleaner linear project history, removing unnecessary merge commits. The trade-offs are safety and traceability (content of merge commit - can't see when upstream changes were incorporated into the feature).

Normal Rebasing

Moves entire feature branch to begin on tip of master branch, creating brand new commits for each commit in the original branch.

Never use git rebase on public branches (shared feature branches). Upstream Rebase can cause additional complications for developers dependent on the public branch that was rebased.

$ git checkout feature
$ git rebase master

Abort a rebase

$ git rebase --abort

Continue a rebase (used after resolving conflicts)

$ git rebase --continue

Interactive Rebasing

Allows for the alteration of commits as they are moved to the new branch. Allowing for complete control over the branch's commit history. Most commonly used to clean up messy history before merging a feature branch into master (before PRs).

$ git checkout feature
$ git rebase -i <commit>

An editor will appear with all the commits in your branch (ignoring merge commits), which come after the provided commit. Here commits can be reorderd, edited, removed, and squashed together. This is done by replacing pick with the desired operation edit, drop, squash. For squash replace "pick" for the second and subsequent commits, that will be squashed into the first commit above squash.

Git Checkout

Switch branches or restore working tree files by updating HEAD.

Switching Branches

$ git checkout -b <branch> // create & checkout local branch
$ git checkout -b <branch> --track <remote>/<branch> //create & checkout & add tracking informaiton to branch

Restoring working tree (discarding local changes in specific file)

$ git chechout HEAD <file>

Git Branch

List, create, delete or update tracking info of branches

$ git branch -a List local & remote branches
$ git branch <new-branch> Create new branch
$ git branch -d <branch> Delete a local branch
$ git branch -u origin/branch update tracking info of current branch to track origin/branch (set upstream tracking)

Git Stash

Stash the changes in a work-tree and staging

$ git stash equivalent to $ git stash push Stashes work-tree & staging
$ git stash apply Apply a stash without removing from stash list

Git Remote

Manage set of tracked repositories

To view all tracked repositories
$ git remote -v

To add a remote repository
$ git remote add <nameOfPointer> git://github.com/<aUser>/<aRepo.git>

Git Log

$ git log show commit logs
$ git log --all display all commits (regardless of the current checked-out branch)
$ git log --stat view summary of changes made in each commit
$ git log --graph view ascii art graphical representation
$ git log --pretty=format:"Commit Hash: %H, Author: %aN, Date: %aD" modify format of output

Git Bisect

Use binary search to find the commit that introduced a bug

Example: Find the commit that broke the feature.

$ git bisect start
$ git bisect bad // current commit still has the bug
$ git bisect good <commit> // informing bisect that this commit does not have the bug

Git bisect will select a commit in the middle, check it out and you must test and inform it whether its a good or bad commit with git bisect bad or git bisect good.

After a bisect session, clean up the bisection state & return to original HEAD with the following command.

$ git bisect reset // returning you to the state before running git bisect start

Git Cherry Pick

Apply the changes introduced by some existing commit and append them to current working HEAD.

This requires your working tree to be clean (no modifications to HEAD).

$ git cherry-pick <commit> will append the commit to the tip of the current checked-out branch

Advanced

Untracked File

Removes file from repository but keeps it in working directory

$ git rm --cached <file>

Detached HEAD

A state which occurs when HEAD refers to a specific commit, as opposed to referring to a named branch.

Example

$ git checkout master^^

   HEAD (refers to commit 'b')
    |
    v
a---b---c---d  branch 'master' (refers to commit 'd')

If we make a commit here

$ edit; git add; git commit

     HEAD (refers to commit 'e')
      |
      v
      e
     /
a---b---c---d  branch 'master' (refers to commit 'd')

Then move to master, nothing will refer to commit e at which point it is considered an Orphaned Commit.

$ git checkout master

               HEAD (refers to branch 'master')
      e         |
     /          v
a---b---c---d  branch 'master' (refers to commit 'd')

Commit e will eventually get deleted by Git garbage collection and be deleted. If still checked-out to e, we can
use the following command to create a reference.

$ git checkout -b foo This creates new branch foo, which refers to commit f & updated HEAD to point to branch foo.

If we have moved away from commit f, we must first recover its object name, used the following command to do so.
$ git reflog -2 HEAD

Then we can use the object name to create a reference as seen above.

Orphaned Commits

Are commits that have no direct path from a ref to access them, usually caused by improper use of git reset.
They can be usually found and restored using

$ git reflog

Note: Git will permanently delete any orphaned commits when runnning internal garbage collector which is run every 30 days.

Adding shortcuts

$ git config --global alias.<NAME_OF_COMMAND> '<actual command>'

Local Hooks

Local hooks only affect the local repository in which they reside. They can be run in any scripting language, so long
as they are prefaced with the shebang line #! eg. for python (#!/usr/bin/env python).

Atlassian has a good article breaking down common git hooks.

Remove commits with sensitive data

If sensitive information is accidentally commited git filter-branch can be used to remove the file(s) from your git history.

Note: The sensitive data may still be accessible in any clones or forks of your repo via their SHA-1 hashes in cached views on GitHub, and through any pull requests that reference them.

Additional Note: Before using the git filter-branch command, make sure you don't have any important stashes as you won't be able to retrieve your changes with other stash commands.

Run the following command, replacing PATH-TO-YOUR-FILE-WITH-SENSITIVE-DATA with the path to the file you want to remove. Note: If the file with sensitive data used to exist at any other paths (because it was moved or renamed), you must run this command on those paths, as well.

$ git filter-branch --force --index-filter "git rm --cached --ignore-unmatch PATH-TO-YOUR-FILE-WITH-SENSITIVE-DATA" --prune-empty --tag-name-filter cat -- --all

Add the file to your .gitignore and force push your local changes to overwrite your GitHub repo.

$ git push origin --force --all

For more info see article