General documentation / cheat sheets for various languages and services


git status
On branch master Your branch is ahead of 'origin/master' by 1 commit. (use "git push" to publish your local commits) Changes to be committed: (use "git reset HEAD <file>..." to unstage) modified: app.jsx modified: site.less Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: build/bundle.js
git status -s
git status --short
M app.jsx M build/bundle.js M site.less
git branch -d fix-app-loader
Delete the fix-app-loader local branch only if it has been merged.
git branch -D demo-app-loader-idea
Delete the demo-app-loader-idea local branch even if it hasn't been merged.
git push origin --delete pr-2042
git push origin :pr-2042
Delete the pr-2042 remote branch.
git ls-files --ignored --exclude-standard
List the files that are currently tracked, but are configured to be ignored by .gitignore or ~/.gitignore_global.ref
git show HEAD^ --color-words
Show word-level patch diff of second-to-last commit. Deletes are red, additions are green.
git log --oneline --graph --all --decorate --simplify-by-decoration
  • --oneline pretty prints the commit hash and message to fit on one line.
  • --graph draws a tree-stylized graph of the different branches
  • --all include all available refs, not just the ones headed to the current branch (I think that's what it does)
  • --decorate prints the branch(es) terminating at that commit.
  • --simplify-by-decoration omits commits that are not decorated (which are usually less significant commits)
git diff -- ':!build'
Compute the diff as usual, but exclude everything matching build.ref This also works for other commands, like status.

Templates (especially hooks/)

When you run git init, git creates a new .git/ directory with files like config and HEAD, and subdirectories objects and refs, which are all required by git for its basic functionality. It also recursively copies everything from a “template” directory into that newly-created .git/ directory.

The template directory can be specified by supplying the --template /path/to/template option to git init, or setting a $GIT_TEMPLATE_DIR environment variable, or having configured the init.templateDir in your git configuration.

Or, if none of those are set, it will use /usr/share/git-core/templates. For the Homebrew-installed git on macOS, git is built with the prefix /usr/local instead of /usr, so the actual default directory is /usr/local/share/git-core/templates. (That directory is symlinked to /usr/local/Cellar/git/*/share/git-core/templates – replace the * with your current version.)

That default template includes several sample “hooks”, which are all disabled by default (due to the .sample suffix). I rarely use git hooks, so all those (duplicate) samples serve to just clutter up my filesystem. (They’re tiny, but there’s nearly a dozen of them; they add up!)

To trim down the templates, create a new directory with just the files you want. I’ll use ~/.config/git/templates, since ~/.config/git is the default directory for many other git configuration files.

Then, to start using that as the templates directory for all new repositories, simply run:

git config --global --add init.templateDir ~/.config/git/templates


Rewriting history

Extract the history of a single file from a git repo:

The file in question is originally located at /sp-latex/sp.cls. By the end, it will be relocated to /sp.cls.

git clone git://remote dir
cd dir
# Select just the commits that involved files in the subdirectory 'sp-latex' (for all branches):
git filter-branch --prune-empty --subdirectory-filter sp-latex -- --all
# Remove all files at each commit that do not match the file we're looking for:
git filter-branch --force --prune-empty \
  --index-filter 'git rm --cached --ignore-unmatch $(git ls-files | grep -v "^sp.cls")'

git filter-branch --prune-empty --subdirectory-filter sp-latex -- --all
git filter-branch -f --prune-empty --index-filter 'git rm --cached --ignore-unmatch $(git ls-files | grep -v "^sp.cls")'
# git remote rm origin


Relevant git-filter-branch flags:

Flag Description
-f, --force git filter-branch refuses to start with an existing temporary directory or when there are already refs starting with refs/original/, unless forced.
--prune-empty Some filters will generate empty commits that leave the tree untouched. This option instructs git-filter-branch to remove such commits if they have exactly one or zero non-pruned parents; merge commits will therefore remain intact. This option cannot be used together with --commit-filter, though the same effect can be achieved by using the provided git_commit_non_empty_tree function in a commit filter.
--tree-filter <command> This is the filter for rewriting the tree and its contents. The argument is evaluated in shell with the working directory set to the root of the checked out tree. The new tree is then used as-is (new files are auto-added, disappeared files are auto-removed - neither .gitignore files nor any other ignore rules HAVE ANY EFFECT!).
--index-filter <command> This is the filter for rewriting the index. It is similar to the tree filter but does not check out the tree, which makes it much faster. Frequently used with git rm --cached --ignore-unmatch .... For hairy cases, see git-update-index.

Relevant git-rm flags:

Flag Description
--cached Use this option to unstage and remove paths only from the index. Working tree files, whether modified or not, will be left alone.
--ignore-unmatch Exit with a zero status even if no files matched.