git only

| 2 Comments | No TrackBacks
By now, everyone knows that Git is the best source control system since sliced RCS.  I don't have to tell you about that.

Sometimes, you want to see what commits you have on a branch, but you want to see *only* the commits on that branch, and aren't on any other.  If you happen to know which branch it came from, it's simple to do something like this:

git log starting_branch..new_branch

But if you don't know or care where it came from, this is more difficult.  In order to do this, you might craft a complicated command line that looks something like this:

git log $(git rev-parse --not --branches | grep -v $(git rev-parse <branch>)) <branch>

but this is impossible to remember, and annoying to type.  Fortunately, Git makes it trivial to add commands in several ways:

  1. Create a program and put it in your $PATH, and name it git-something, which then allows you to run "git something"
  2. Make an alias, which can simply add arguments to other git commands, or which can shell out to a system command

For this problem, I chose the second option.  However, since the convoluted command I wrote above requires you to pass the <branch> argument twice, an ordinary alias is not sufficient.  I decided to use a shell function to help.

First, we'll define the function.  You can put this in your .bashrc or .bash_profile, or somewhere similar:

git_only() {
    opts=$(git rev-parse --no-revs "$@" 2>/dev/null)
    rev=$(git rev-parse --revs-only "$@" 2>/dev/null)
    if [[ -z $rev ]]; then
        branch=$(git name-rev --name-only HEAD)
    git log $(git rev-parse --not --remotes --branches | grep -v $(git rev-parse $branch)) $branch $opts

Note that it uses git's rev-parse command to separate options from revisions, so that you'll be able to pass most arguments to this that you'd normally pass to "git log", including -- pathspecs

Then you need to export the function so that sub-shells can also see it

export -f git_only

Finally, you simply add it to git's config as an alias:

git config --global alias.only '!git_only'

And that's it!  Now you're ready to try it out:

$ git only origin/foobar

As written, this does have a couple of shortcomings:

  1. Any "revision arguments" will be eaten by rev-parse, so things like --no-merges wont work
  2. Since refs are parsed to SHA1s before grepping out the one that you want to inspect, if it's exactly identical to another branch, it will still be shown even though it's not actually unique
If I figure out workaround to those issues, I'll update the post with a new version of the function.

No TrackBacks

TrackBack URL:


Yay it works now! Thanks :D

Leave a comment

About this Entry

This page contains a single entry by cxreg published on June 17, 2010 8:04 PM.

Bash arrays, variable stashing, and cd aliasing = magic goodness is the next entry in this blog.

Find recent content on the main index or look in the archives to find all content.