Auto-Completion Within Complex Git Alias
UPDATE 2013-11-25: Prefixed commands in the Git aliases with !
DISCLAIMER: Bash only. I haven't explored other shells (like Fish or ZSH).
Git aliases are really helpful for saving you some typing. When the alias is simple, as in
[alias]
co = checkout
Git auto-completion looks up the valid completions for the checkout
command (e.g. branch names or refs) when you press the <TAB>
key. However, when your Git alias is more complex (using more than one command, using a custom function) auto-completion won't work.
To enable auto-completion for your complex Git aliases you need to define a function that Git can use to determine what should be completed. That function will follow this convention: _git_<the name of your alias>
.
Example
If we wanted to create an alias called rtrack
that will
- make sure we have all the latest code from the remote repository
- setup a remote tracking branch for us
- and then check out that new branch
... we'd create a function called _git_rtrack
in our Bash profile:
function _git_rtrack() {
_git_branch
}
In this example my alias will be working with branch names, so I simply delegate to _git_branch
.
Next, in our Git config (globally or in a project configuration file) we could define rtrack
in the alias
section as
[alias]
rtrack = "!git fetch origin;git branch --track $1 origin/$1;git checkout $1"
Note the !
in front of the command. This is necessary in order to execute anything other than a Git command directly.
More Examples
Here are a few examples translated from the grb
Ruby gem into Git aliases (including the rtrack
alias).
In your Git config, add:
# ~/.gitconfig
[alias]
# create a new branch off of a local branch and check it out locally, defaults to master
rcreate = "!git push origin ${2:-master}:refs/heads/$1;git fetch origin;git branch --track $1 origin/$1;git checkout $1"
# rename a branch ($1) to something else ($2)
rmove = "!git push origin $1:refs/heads/$2;git fetch origin;git branch --track $2 origin/$2;git checkout $2;git branch -d $1;git push origin :refs/heads/$1"
# push a local branch to the remote called origin and check it out locally
rpush = "!git push origin $1:refs/heads/$1;git fetch origin;git config branch.$1.remote origin;git config branch.$1.merge refs/heads/$1;git checkout $1"
# remove a branch
rrm = "!git push origin :refs/heads/$1;git branch -d $1"
# track a remote branch locally and check it out locally
rtrack = "!git fetch origin;git branch --track $1 origin/$1;git checkout $1"
Then in your Bash profile add:
# ~/.bash_functions, sourced from ~/.bash_profile
function _git_rcreate() {
_git_branch
}
function _git_rmove() {
_git_branch
}
function _git_rpush() {
_git_branch
}
function _git_rrm() {
_git_branch
}
function _git_rtrack() {
_git_branch
}
Enjoy!