Skip to content


baddass version control


git init

Create a git repository for the CWD

git init
echo "" >> .gitignore
echo "# Ignore other unneeded files.
.DS_Store" >> .gitignore

git clone

Clone a local repo

git clone /path/to/repo

Clone a remote git repo via ssh

git clone user@ssh_server:/opt/git/project

git filesystem operations

Add everything in the CWD to the git repo

git add .

Rename a file in the git repo

This also renames the filesystem file.

git mv README.rdoc

Delete a file from the repo

git rm filename

git status

Check the status of git

git status

git commit

Commit the current changes

git commit -m "Initial commit"

Commit all changes with commit -a

git commit -a -m "Improve the README file"

Skip git commit hooks

git commit --no-verify

git tag

Git supports two types of tags: lightweight and annotated.

Create an annotated tag

Annotated tags, are stored as full objects in the Git database.

git tag -m "Improve X and Y." v0.5.3

Create a light tag

This is basically DNS A records for git SHAs. The SHA is referenced by the tag, no other info is stored. Using them is generally frowned upon because tags tend to be used where context is important, so the annotations that go with an annotated tag are more suitable.

git tag v0.5.3

Delete a local tag

git tag -d v0.5.3

Delete a remote tag

git push --delete origin v0.5.3

git config

git config interacts with configs. There are three scopes: --local, --global, --system.

  • Local = per-repo settings. IE: stored in .git/config directory for the repo
  • Global = per-user settings. IE: stored in ~/.gitconfig
  • System = per-system settings, found in /etc/ or wherever git is looking for system settings.

Always use ssh for

git config --global url."".insteadOf ""

Git client setup

This creates and modifies ~/.gitconfig with some parameters:

git config --global "Daniel Hoherd"
git config --global
git config --global checkout
git config --global core.editor "vim"
git config --global merge.tool vimdiff
git config --global iso

Edit a .git/config file with some params

git config --replace-all svn-remote.svn.url
git config --replace-all svn-remote.svn.fetch ops:refs/remotes/trunk
git config --add svn-remote.svn.preserve-empty-dirs true
git config --unset svn-remote.svn.branches
git config --unset svn-remote.svn.tags
git config --add svn.authorsfile /srv-cluster/git-svn/git/author.txt

Show your configs in a dotted one-one-per-option format

git config --list

git diff

Show differences between objects and stuff.

diff between staged and committed

This is useful when you're adding files that were not previously in the repo alongside changes to existing files, since a bare git diff before adding the files will only show changes to files that were already in the repo.

git diff --staged

diff that shows per-word colored differences

git diff --color-words

Machine readable word diff

git diff --word-diff

Diff and ignore whitespace

This does not ignore line ending changes or blank line insertion and removals.

git diff -w

Show diffs between master and a given date

git diff $(git rev-list -n1 --before="1 month ago" master)

Show what has changed since a point in time

git whatchanged --since="18 hours ago" -p


git whatchanged --since="18 hours ago" --until="6 hours ago" -p

git blame

git blame shows information about the commit associated with each line of a file.

Simple usage

git blame <filename>

Show non-whitespace changes in blame

When somebody has reformatted code but didn't make any code changes, this will show the prior commits where something more than whitespace changed.

git blame -w <filename>

git log

Shows commit history.

View the commit history

git log

Show one log entry

git log -1

Show git commits that contain a given string

This searches the content of the diff, not the commit message.

git log -S search_string

Show commit messages that match a given regex

git log --grep='[Ww]hitespace'

Show logs for a given dir in the last 3 days

git log --since=3.days modules/profile_sensu

Show raw log history for 5 most recent commits

Useful for seeing TZ settings.

git log --format=raw -5

Really pretty logs

log --graph --oneline --decorate --all

git shortlog

Show number of commits by user, including e-mail

Using the -e flag includes e-mail address. The list is unique per entry, so if you use a different name along with the same e-mail address, that shows up as two entries in the list.

git shortlog -ens

Keep in mind this is commits, not lines within the current codebase. If the repo is old, this information may not be useful for finding people who are in-the-know about the current contents of the repo. This is useful for preparing a user list for a git filter-repo operation.

git show

Show the changes from a specific SHA

git show f73f9ec7c07e

Show a complete file as of a given SHA

This is an absolute path from the git root, not relative to CWD. This command will show the whole file as of the given SHA.

git show f73f9ec7c07e:dir/filename.yaml

git branches

Branches are an integral part of git. They allow you to work on distinct changes without mixing them all up together.

Create a branch

git checkout -b readme-fix

Check which branch you're in

git branch

Rename (move) a branch

git branch -m oldname newname

git merge

This lets you merge two branches.

Merge branch with master

git checkout master
git merge readme-fix-branch
git branch -d readme-fix-branch

disable fast-forward merges

You can control how the history is kept when merging. By default, fast-forward merges occur, which replays the commits on the branch that is being merged into. By disabling this you can see several commits being merged from one branch into another, making it easier to roll back that whole series of commits without digging through the history to see where each commit from the branch came from.

git config --global merge.ff false

git filter-repo

git filter-repo is not a standard tool with git, but can be installed separately. It is used for rewriting the history of the git repo, allowing move, rename, merging and trimming operations, rewriting commit IDs, and more. This is a destructive tool, so it should be performed on a fresh clone of the repo while you iterate on finding the right sequence of operations to perform to get to your desired state. The destructive nature is that it rewrites the entire history of the repo, so if your repo depends on specific SHAs or any other specific history, you probably need to take a harder look at how to solve your problem.

Extract one subdir into its own repo, renaming some files

This is great if you want to extract part of a repo for public release, or just for organizational purposes.

Extract the path scratch-work/scripts into bin, removing all other history in the repo.

git-filter-repo --path scratch-work/scripts --path-rename scratch-work/scripts:bin


Add a remote

git remote add upstream

Push to a specific remote

# push to the master branch of the remote named upstream
git push upstream master

Alter the source of origin

If you move your repo to another location, use this command to change the upstream URL:

git remote set-url origin https://user@newhost/newpath/reponame

git reset

git reset allows you to reset your state to what it was at a previous point.

Reset to a prior state based on what has been done locally

The reflog is a log of what steps have been performed locally. You can view the reflog, then reset to a prior state.

git reflog # show all HEAD changes
git reset --hard 45e0ae5 # reset all git tracked state to 45e0ae5

Alternately, you can use a date:

git reflog --date=iso # absolute date based reflog references
git reset "HEAD@{2015-03-25 14:45:30 -0700}" --hard

Reset feature branch to state when it was branched from master

Do this if you want to start your branch over with only the current changes. This is useful if you've been iterating through lots of bad changes that were committed and want to clean them all out. It basically lets you squash to a single commit on your branch.

git reset $(git merge-base master $(git rev-parse --abbrev-ref HEAD))

Hard reset of local changes

This will abandon all local changes and resolve merge conflicts

git fetch origin
git reset --hard origin/master

git clean

Remove all untracked files and directories

This is useful after your reset to a prior state. It deletes all files and directories that show up in the untracked section of git status

git clean -ffdx

Miscellaneous tricks

Refresh all Git repos in a path

find /var/www/html/mediawiki/ -name .git | while read -r X ; do
  pushd "$(dirname "${X}")" && \
  [ $(git remote -v | wc -l) -gt 0 ] && \
  git pull && \
  popd ;
done ;

Show a numbered list of remote branches sorted by last commit date

git branch -r | grep -v HEAD | xargs -r -n1 git log -1 \
--pretty=format:'%ad %h%d %an | %s %n' --date=iso -1 | sort | nl -ba

Branch cleanup

git gc --prune=now
git remote prune origin

git grep

Find a string in all branches

This finds the word "hunter2" in the tests directory of all branches.

git grep '\bhunter2\b' $(git branch -a --format='%(refname:short)') tests/