• Stars
    star
    1,175
  • Rank 39,793 (Top 0.8 %)
  • Language
    Shell
  • License
    BSD 3-Clause "New...
  • Created about 11 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A suite of useful Git commands that aid with scripting or every day command line usage
git-toolbelt logo

Installation instructions

$ brew tap nvie/tap
$ brew install nvie/tap/git-toolbelt

If not using Homebrew, you will need to have GNU coreutils installed, for the realpath utility. Git for Windows users see #29.

git-toolbelt

Helper tools to make everyday life with Git much easier. Commands marked with ⭐️ are my personal favorites and are commands I use almost every day.

Everyday helpful commands:

Statistics:

Commands to help novices out:

Commands that simplify scripting. These commands typically only return exit codes and have no output.

Advanced usage:

git current-branch

Returns the name of the current branch, if any. Why doesn't this come with git?

$ git current-branch
master

Alias to git rev-parse --abbrev-ref HEAD.

git main-branch

Returns the name of the default main branch for this repository. Historically master, but could also be main if you've changed the default branch name. Since there's no way of reliably telling what the default branch name is for a repo, this script will probe for the existence of local branches named either main or master. The first one found is used.

$ git main-branch
master

git sha

Returns the SHA value for the specified object, or the current branch head, if nothing is provided.

$ git sha <some-object>

Typical example:

$ git sha HEAD
f688d7543c5d52f5f78b3db1b0dd1616059299a4
$ git sha -s HEAD
f688d75

Shows the commit SHA for the latest commit.

git modified

Returns a list of locally modified files. In contrast to git status, it does not include any detailed file status, and never includes non-existing files.

This makes it ideal for the following use-case:

$ vim (git modified)

If you want to locally modified files that are already staged, too, use:

$ vim (git modified -i)

git modified-since

Like git-modified, but for printing a list of files that have been modified since master (or whatever commit specified). In contrast to git status, it does not include any detailed file status, and never includes non-existing files.

Opens all files modified on your branch (since you branched off master).

$ vim (git modified-since)

git separator

Adds a commit with a message of only ---'s, so that it visually separates commits in the history. This is incredibly useful when doing more complex rebase operations. (They should be used as a temporary measure, and ideally taken out of the history again when done rebasing.)

git spinoff

Inspired by Magit's spinoff command. Creates and checks out a new branch starting at and tracking the current branch. That branch in turn is reset to the last commit it shares with its upstream. If the current branch has no upstream or no unpushed commits, then the new branch is created anyway and the previously current branch is not touched.

This is useful to create a feature branch after work has already began on the old branch (likely but not necessarily "master").

git push-current

Pushed the current branch out to origin, and makes sure to setup tracking of the remote branch. Shorthand for git push -u origin <current-branch>.

Accepts options, too, so you can use

$ git push-current -f

to force-push.

git is-headless

Tests if HEAD is pointing to a branch head, or is detached.

git diff-since

Shows the differences made on the current branch, compared to the main branch (or the given branch).

git local-branches / git remote-branches / git active-branches

Returns a list of local or remote branches, but contrary to Git's default commands for this, returns them machine-processable. In the case of remote branches, can be asked to return only the branches in a specific remote.

For git active-branches, a branch is deemed "active" if its head points to a commit authored in the last 3 weeks, by default. An arbitrary date can be specified using either git active-branches -s <date> or -a <date> (mnemonic: "since" or "after"), using any date format supported by git log.

git local-branch-exists / git remote-branch-exists / git tag-exists

Tests if the given local branch, remote branch, or tag exists.

git recent-branches

Returns a list of local branches, ordered by recency:

$ git recent-branches
foo
master
bar
qux

git remote-tracking-branch

Print the name of the remote tracking branch of the current or given local branch name, if one exists. Errors otherwise.

git local-commits / git has-local-commits

Returns a list of commits that are still in your local repo, but haven't been pushed to origin. git has-local-commits is the scriptable equivalent that only returns an exit code if such commits exist.

git contains / git is-ancestor

Tests if X is merged into Y:

$ git contains X Y  # does X contain Y?
$ git is-ancestor X Y  # is X an ancestor of Y?

CAVEAT: Even though they might look like opposites, X contains Y does not mean not (X is-ancestor Y), since (1) X and Y can point to the same commit, or the branches may have no common history and thus be unrelated completely.

git stage-all

Mimics the index / staging area to match the working tree exactly. Adds files, removes files, etc.

Alias to git add --all.

git unstage-all

Unstages everything. Leaves the working tree intact.

Alias to git reset HEAD.

git undo-merge

Ever created a merge accidentally, or decided that you didn't want to merge after all? You can undo the last merge using git undo-merge.

git undo-commit

Ever committed too soon, or by accident? Or on the wrong branch? You can now undo your last commit and you won't lose any data. All the changes in the commit will be staged (like right before the commit) and the commit itself is gone.

git cleanup

Deletes all branches that have already been merged into the main branch. Keeps other branches lying around. Removes branches both locally and in the origin remote. Will be most conservative with deletions.

git fixup

Amend all local staged changes into the last commit. Ideal for fixing typo's, when you don't want to re-edit the commit message.

$ git commit -m "Something cool."
$ vim somefile.txt  # fix typo
$ git add somefile.txt
$ git fixup  # merge this little change back into the last commit

git fixup-with

Interactively lets you pick a commit to fixup with. (Uses fzf for the interactive picking. Use brew install fzf to install this tool separately.) Use -r to trigger an interactive rebase right afterwards.

git workon

Convenience command for quickly switching to a branch <name>. If such local branch does not exist, but there is a remote branch named origin/<name>, then a local branch is created and the remote is tracked.

git delouse

Say you want to rebuild your last commit, but want to keep the commit message. git delouse empties the last commit on the current branch and places all changes back into the working tree.

Since the commit remains in history, you can now rebuild the commit by "git amend"'ing or "git fixup"'ing, instead of making new commits.

git shatter-by-file

Splits the last commit into N+1 commits, where N is the number of files in the last commit. The first commit is an empty commit with the original commit message and author details, and the following commits add (or delete) one file each, keeping the subject line of the original commit message.

After running git shatter-by-file, you'll typically want to run git rebase --interactive to start fixing up changes to files, etc. For that purpose, the original commit message is kept in there (in the empty first commit), so make sure to use it.

git cleave

Splits the last commit into 2 or more commits. Takes one or more regex values (which are fed to grep -Ee), and will split the last commit by file paths matching each of the regexes.

For example:

$ git cleave client/ server/

Will split the last commit into 2 (or 3) commits. The first one will contain all the files containing client/, the second will contain all the files matching server/. If there are files that don't match either of those, then a 3rd commit will be made with the "remainder".

Another example:

$ git cleave '.*\.js$'

This will split off all Javascript files from a commit.

git commit-to

Ever been on a branch and really wanted to quickly commit a change to a different branch? Given that this is possible without merge conflicts, git commit-to will allow you to do so, without checking out the branch necessarily.

$ git branch
  master
* mybranch
$ git status
M foo.txt
M bar.txt
$ git add foo.txt
$ git commit-to master -m "Add foo to master."
$ git add bar.txt
$ git commit -m "Add bar to mybranch."

git cherry-pick-to

Every been on a branch, just made a commit, but really want that commit available on other branches as well? You can now cherry-pick this commit to any branch, staying on the current branch. (Given the change won't lead to a merge conflict.)

$ git branch
  master
* mybranch
$ git add foo.txt
$ git commit -m "Really useful thing."
$ git cherry-pick-to master HEAD
$ git branch  # did not switch branches
  master
* mybranch

git is-repo

Helper function that determines whether the current directory has a Git repo associated to it. Scriptable equivalent of git repo.

git root / git repo

git root prints the root location of the working tree.

$ cd /path/to/worktree
$ cd some/dir/in/worktree
$ pwd
/path/to/worktree/some/project/dir
$ git root
/path/to/worktree

git repo prints the location of the Git directory, typically .git, but could differ based on your setup. Will return with a non-zero exit code if not in a repo.

$ cd /path/to/my/worktree
$ git repo
.git
$ cd /tmp
$ git repo
fatal: Not a git repository (or any of the parent directories): .git

git initial-commit

git initial-commit prints the initial commit for the repo.

$ git initial-commit
48c94a6a29e9e52ab63ce0fab578101ddc56a04f

git has-local-changes / git is-clean / git is-dirty

Helper function that determines whether there are local changes in the working tree, by returning a 0 (local changes) or 1 (no local changes) exit code.

git drop-local-changes

Don't care about your local working copy's state and really want to revert back to whatever is recorded in the history? git drop-local-changes lets you do this.

This covers aborting rebases, undoing partial merges, resetting the index and removing any unknown local files from the work tree. Anything that is already committed remains safe.

??? issue a git pull, too? Typical beginners will want this.

git stash-everything

The stash behaviour you (probably) always wanted. This actually stashes everything what's in your index, in your working tree, and even stashes away your untracked files, leaving a totally clean working tree.

Using "git stash pop" will recover all changes, including index state, locally modified files, and untracked files.

git update-all

Updates all local branch heads to the remote's equivalent. This is the same as checking out all local branches one-by-one and pulling the latest upstream changes. Will only update if a pull succeeds cleanly (i.e. is a fast-forward pull).

git-merged / git-unmerged / git-merge-status

This trio of subcommands makes it easy to inspect merge status of local branches. Use them to check whether any local branches have or haven't been merged into the target branch (defaults to master).

git-merge-status is a useful command that presents both lists in a single overview (not for machine processing).

git-branches-containing

This command, "git branches-containing []" returns a list of branches which contain the specified '' (defaults to 'HEAD').

git-branches-containing is useful to see if a branch has been merged, and, if so, which releases contain the feature/fix (if you use release branches).

git-committer-info

Shows contribution stats for the given committer, like "most productive day", "most productive hour", "average commit size", etc.

TODO: git force-checkout

Don't care about your local working copy's state and really want to switch to another branch? git force-checkout lets you do this.

Switching branches can be prevented by git. For good reasons, mostly. Git is designed to prevent you from losing data potentially. Examples are there are local unmerged files, or some files that would be overwritten by doing the checkout.

By using force-checkout you basically give git the finger, and check out a branch anyway. You do agree to lose data when using this command.

$ git checkout master
error: Your local changes to the following files would be overwritten by checkout:
    foo/bar.txt
Please, commit your changes or stash them before you can switch branches.
Aborting
$ git force-checkout master
Switched to branch 'master'

git conflicts

Generates a summary for all local branches that will merge uncleanly—i.e. will lead to merge conflicts later on.

$ git branch
  develop
* mybranch
  master
  other-branch
$ git conflicts
develop... merges cleanly
master...  merges cleanly
other-branch... CONFLICTS AHEAD

git-skip / git-unskip / git-show-skipped

Git supports marking files "skip worktree", meaning any change in the file locally will not be shown in status reports, or be added when you stage all files. This feature can be useful to toggle some switches locally, or experiment with different settings, without running the risk of accidentally committing this local data (that should remain untouched in the repo).

Notice that status reports won't show these files anymore, so it's also easily to lose track of these marked assumptions, and you probably run into weird issues if you don't remember this. (This is the reason why I put these scripts in the "advanced" category.)

Basic usage:

$ git status
 M foo.txt
 M bar.txt
 M qux.txt
$ git skip foo.txt
$ git status
 M bar.txt
 M qux.txt
$ git show-skipped
foo.txt
$ git commit -am 'Commit everything.'
$ git status
nothing to commit, working directory clean
$ git is-clean && echo "clean" || echo "not clean"
not clean
$ git unskip -a
$ git status
 M foo.txt

As you can see, git-is-clean is aware of any lurking "skipped" files, and won't report a clean working tree, as these assumed unchanged files often block the ability to check out different branches.

git wip

Commits all local changes under a commit message of "WIP". Great for quickly creating "savepoint" commits. If there is a mix of staged changes, and unstaged changes, and new files, will commit each of these as a separate commit, all titled "WIP". Effectively, running git-wip once will potentially lead to anywhere between 0 and 3 "WIP" commits being created.

More Repositories

1

gitflow

Git extensions to provide high-level repository operations for Vincent Driessen's branching model.
Shell
26,364
star
2

vim-flake8

Flake8 plugin for Vim
Vim Script
1,053
star
3

vimrc

My personal Neovim configuration, with a lot of love put into it.
Vim Script
548
star
4

times

Times and time zones in Python with a focus on best practices.
Python
394
star
5

decoders

Elegant validation library for type-safe input data (for TypeScript and Flow)
JavaScript
351
star
6

cookiecutter-python-cli

Python
186
star
7

itertools

TypeScript port of Python's awesome itertools stdlib.
TypeScript
139
star
8

vim-rst-tables

Easily create and reformat your RST (reStructuredText) tables as you change cell content.
Python
121
star
9

dotfiles

Shell
94
star
10

shFlags

Git mirror of the shFlags project by Kate Ward
Shell
89
star
11

vim-pyunit

Plugin enabling advanced unit test support inside your favorite editor.
Python
74
star
12

lemons.js

🍋 Common algebraïc data types for JS
JavaScript
59
star
13

SimpleAES

AES-256 encryption and decryption in Python for mere mortals.
Python
55
star
14

vim-togglemouse

Toggles the mouse focus between Vim and your terminal emulator, allowing terminal emulator mouse commands, like copy/paste.
Vim Script
52
star
15

python-fu

Python command line tools, for increased fu.
Python
46
star
16

vim-pep8

This project is superseded by vim-flake8!
Vim Script
38
star
17

sr

A simple mass search & replace tool
Rust
30
star
18

osx-install

Personal OSX install scripts / notes
Shell
26
star
19

vim_bridge

A Python-to-Vim bridge decorator that allows transparent calls to Python functions in native Vim scripts.
Python
23
star
20

pluck

General-purpose function to pluck fields from an iterable's values.
Python
21
star
21

dictmerge

Merge dicts without mutating them.
Python
16
star
22

git-it

Git issue tracker
Python
14
star
23

python-drainers

Event-based draining of process output
Python
13
star
24

new_workers

Python
13
star
25

vim-pyflakes

This project is superseded by vim-flake8!
Vim Script
11
star
26

rule-of-law

A sanity checker to verify assumptions about data consistency
JavaScript
8
star
27

debrief.js

Object serialization and annotation, for use in human-friendly error messages
JavaScript
8
star
28

even-more-itertools

Even more itertools than the stdlib and the more-itertools project provide.
Python
8
star
29

BKrypt

Thin wrapper around the bcrypt library.
Python
6
star
30

scripts

A collection of simple and small but useful UNIX shell scripts.
Shell
6
star
31

nox-ideas

Ideas for a new kind of programming language
6
star
32

vim-ini

Syntax highlighting for INI files in Vim.
Vim Script
6
star
33

Convenience

Convenience Cocoa classes, extending default functionality for a bunch of Cocoa objects.
Objective-C
5
star
34

VDOrderedEntityMigrationPolicy

Custom migration policy class for migrating Core Data entities with ordered relationships (i.e. entities that inherit from BWOrderedManagedObject).
Objective-C
4
star
35

ast-generator

TypeScript
3
star
36

syncfrom

Super-duper easy rsync wrappers for your home setup
Shell
3
star
37

Xcode-Extensions

Custom made Xcode extensions
Objective-C
3
star
38

homebrew-tap

Personal taps for Homebrew
Ruby
2
star
39

vim-nox

Nox syntax highlighting for Vim
Vim Script
1
star
40

nvie

1
star
41

clean-project

Repo to demonstrate a bug in Bun
TypeScript
1
star