/pick-git

Use fzf to turbocharge your Git workflow

Primary LanguagePythonMIT LicenseMIT

pick-git

License

pick-git is a set of command line tools for leveraging fzf to turbocharge your Git workflow.

Git can be a bit of a pain, especially when passing branches or commit hashes as args. Big projects have lots of branches and tons of commits. Finding and copying commit hashes to compare commits, for example, is awkward and slow.

fzf, however, was literally born for jobs like this. pick-git uses fzf to make working with branches, commits and files in your project's repo a breeze.

It's installable via pip and works with Python 2/3.

Installation

pip install pick-git

Dependencies

  • fzf
  • pyperclip (optional, and anyway it's automatically included if you install with pip)

Usage

Check out how pick-git removes the pain of finding and comparing commits.

pick-git -b commit git diff

I invoked ghp -b gd, but what just happened? Let's break it down.

I have ghp aliased to pick-git --function commit. The function argument is one of the public functions exposed by pick-git.

gd is a shortcut I have that resolves to git diff. The -b flag allows me to pick both commits and compare them, instead of just picking one and comparing it with HEAD.

At the end the final command that was invoked, gd 28faaf7 4750072, was printed to the console. I was able to find two commits and compare them very quickly and with very few keystrokes. Even if these commits had been in a much bigger project and were months old, fzf's fuzzy select would have found them in no time as long as my commit messages were descriptive.

Shortcuts to pick-git Public Functions

It's a good idea to create shortcut aliases to all of the functions exposed by pick-git. You can simply copy and paste the following into your startup script, e.g. .bash_profile.

alias gbp="pick-git --function branch"
alias gtp="pick-git --function tag"
alias ghp="pick-git --function commit"
alias grp="pick-git --function commit_reflog"
alias gfp="pick-git --function file"

alias gbpf="pick-git --function branch_file"
alias ghpf="pick-git --function commit_file"
alias grpf="pick-git --function commit_reflog_file"
alias gpf="pick-git --function file_commit"

alias gbc="pick-git --function branch_compare"

Here are descriptions of pick-git's public functions. Run pick-git -h to get help/information about optional arguments!

  • branch: Pick branch(es) and pass them to args, or copy branch names.
  • commit: Pick commit hash(es) and pass them to args, or copy commit hash names.
  • commit_reflog: Pick commit hash(es) from the reflog and pass them to args, or copy commit hash names.
  • file: Pick a modified file relative to last commit, pass it to args, or copy file name. Optionally pick from files that have been staged for commit.
  • branch_file: Pick branch(es), get list of files that are different in these branches, pick one of these files and diff or show it.
  • commit_file: Pick commit(s), get list of files that are different in these commits, pick one of these files and diff or show it.
  • commit_reflog_file: Pick commit(s) from the reflog, get list of files that are different in these commits, pick one of these files and diff or show it.
  • branch_compare: Find out how far ahead or behind this branch is compared with that. A detailed comparison shows all commits instead of just the commit count.
  • file_commit: Pick a file from index, and show all commits for this file. Pick a commit and diff file against HEAD or show it.

--shell and --rcfile

I actually lied above. I really have ghp aliased to pick-git --shell /bin/bash --rcfile ~/.git_aliases --function commit. What are these --shell and --rcfile args, and why are they useful?

When pick-git is invoked, it creates a child process to execute whichever public function you specify. The child process invokes your default shell and sources the corresponding rcfile. This is nice, but if your startup file is loaded with crap, like mine, you might experience lag every time you invoke pick-git and the rcfile is sourced.

To avoid this, I have a lightweight startup file called .git_aliases that defines a few Git shortcuts and nothing else. When I invoke pick-git, I used the --rcfile argument to make sure only this file is sourced.

~/.git_aliases

alias gb='git branch'
alias go='git checkout'
alias gc='git commit'
alias gm='git merge'
alias gd='git diff'
alias ga='git add'
alias gr='git reset'

Help

Run pick-git -h.

Contributing

The "primitives" for the package are defined in pick_git/core.py and are listed below. These are the functions that actually invoke fzf. If you think of other useful primitives please fork the repo and submit a pull request.

  • pick_branch
  • pick_commit
  • pick_commit_reflog
  • pick_modified_file
  • pick_file

The public methods whose names are passed to pick-git in the --function argument, for example branch or commit, are defined in a mixin class in pick_git/helpers.py. I'm sure there are use cases I haven't thought of that deserve public functions, and I would be grateful for contributors.

Development

See main.py in the root of the repo? This script is there for making it easy to test the package. It ensures the pick-git executable can be invoked from the command line, without going through the shim created by setuptools when the package is installed.

For example, from the root of the repo, just try running python main.py --function commit.

Tests

The package currently has no tests. This is because pick-git requires user keystrokes to return a value. Sending keystrokes isn't part of Python's standard library, and anyway Python doesn't seem like the best way to do this, although this seems promising.

If anyone has ideas I'd love to hear them.

License

This code is licensed under the MIT License.