Thursday, June 12, 2014

Handy Git Aliases

git config --global alias.accept-remote-diffs 'merge origin/master'
git config --global alias.acp '!f() { git add-commit "$1" && git push; }; f'
git config --global alias.acpom '!f() { git add-commit "$1" && git push -u origin master; }; f'
git config --global alias.acpcb '!f() { git add-commit "$1" && git push origin `current-git-branch-name`; }; f'
git config --global alias.add-all '!git add-updated && git add-untracked'
git config --global alias.add-commit '!f() { git add-all && git commit -m "$1"; }; f'
git config --global alias.add-commit-pristine '!f() { git-add-commit-pristine }; f'
git config --global alias.add-untracked '!f() { git-add-untracked }; f'
git config --global alias.add-updated 'add --update :/'
git config --global alias.apply-gitignore-to '!f() { git rm --cached "$@"; }; f'
git config --global alias.clear-alias '!f() { git config --global --unset alias."$@"; }; f'
git config --global alias.clobber-this-branch '!f() { (CURRENT_BRANCH_NAME=`current-git-branch-name`; if [ $CURRENT_BRANCH_NAME = "master" ]; then echo "Cannot run this on master branch" && exit 1; fi; git delete-remote-branch $CURRENT_BRANCH_NAME; git checkout master; git delete-local-branch $CURRENT_BRANCH_NAME;); }; f'
git config --global alias.config-add-remote-origin '!f() { git remote rm origin 2>/dev/null; git remote add origin "$@"; }; f'
git config --global alias.config-make-pulls-merge 'config branch.master.rebase false'
git config --global alias.config-make-pulls-rebase 'config branch.master.rebase true'
git config --global alias.config-onetime-email '!f() { git config --global "$@"; }; f'
git config --global alias.config-onetime-username '!f() { git config --global "$@"; }; f'
git config --global alias.config-only-push-current-branch 'config --global push.default tracking'
git config --global alias.config-project-defaults '!f() { git config-add-remote-origin git@$REMOTE_GIT_ACCOUNT/$1.git; git config-only-push-current-branch; git config-make-pulls-rebase; }; f'
git config --global alias.config-remote-origin-push-head 'config remote.origin.push HEAD'
git config --global alias.create-and-switch-to-branch '!f() { create-git-branch "$@" 2>/dev/null; git config branch."$@".remote origin; git config branch."$@".merge refs/heads/"$@"; }; f'
git config --global alias.create-and-switch-to-new-empty-branch '!f() { git symbolic-ref HEAD refs/heads/$@;rm .git/index;git clean -fdx;echo "\nAdd files, then run: $ git add-commit \"YOUR_MSG\"; git push origin $@\n"; }; f'
git config --global alias.create-branch2 '!f() { create-git-branch2 "$@"; }; f'
git config --global alias.create-local-branch 'checkout -b'
git config --global alias.create-new-repo '!f() { mkdir "$@"; cd "$@"; touch; git init; git add; git commit -m "first commit"; git remote add origin git@"$REMOTE_GIT_ACCOUNT"/"$@".git; }; f'
git config --global alias.delete-alias '!f() { git config --unset alias."$@"; git config --global --unset alias."$@"; }; f'
git config --global alias.delete-local-branch 'branch -d'
git config --global alias.delete-remote-branch 'push origin --delete'
git config --global alias.delete-unstaged '!f() { (echo "";echo "THE FOLLOWING FILES WILL BE DELETED:";git diff --name-only; echo "";echo "ARE YOU SURE? (CTRL+C TO ABORT --OR-- ENTER TO CONTINUE...)";read x;set -x;`git diff --name-only`|xargs rm); }; f'
git config --global alias.delete-untracked '!f() { (echo "";echo "THE FOLLOWING FILES WILL BE DELETED:";git clean -f --dry-run; echo "";echo "ARE YOU SURE? (CTRL+C TO ABORT --OR-- ENTER TO CONTINUE...)";read x; echo "";echo "THE FOLLOWING DIRECTORIES WILL BE REMOVED:";git clean -f -d --dry-run; echo "";echo "ARE YOU SURE? (CTRL+C TO ABORT --OR-- ENTER TO CONTINUE...)";read x;set -x;git clean -f; git clean -f -d); }; f'
git config --global alias.diff-inline 'diff --word-diff'
git config --global alias.diff-remote-master '!f() { git difftool origin/master `current-git-branch-name` -Y; }; f'
git config --global alias.diff-stage-master '!f() { git difftool master `current-git-branch-name` -Y; }; f'
git config --global alias.discard-changes-to-unstaged-file '!f() { git checkout -- "$@"; }; f'
git config --global alias.discard-local-changes '!f() { git reset --hard origin/master && git pull origin master; }; f'
git config --global alias.fetch-and-show-diffs '!git fetch origin && git diff origin/master & echo "Manually merge conflicts. Then, run: $ git accept-remote-diffs"'
git config --global alias.go-to-new-repo '!f() { git link-to-new-repo "$@"; cd "$@"; }; f'
git config --global alias.init-gh-pages '!f() { git symbolic-ref HEAD refs/heads/gh-pages && rm .git/index && git clean -fdx && echo "hello, gh-pages" > index.html; git acpcb "initial gh-page";  }; f'
git config --global '!f() { echo "Git repo: $REMOTE_GIT_ACCOUNT/$@.git must already exist."; echo "CTRL+C TO ABORT --OR-- ENTER TO CONTINUE...";read x; mkdir "$@"; cd "$@"; touch; git init; git add; git commit -m "add empty readme file"; git config-project-defaults "$@"; git push -u origin master; echo "You just created a new local repo ($@) that is linked to $REMOTE_GIT_ACCOUNT/$@.git"; }; f'
git config --global alias.list-aliases '!f() { git config --get-regexp alias; }; f'
git config --global alias.list-configs '!f() { git config --list; echo ""; echo "Your git config file: $HOME/.gitconfig"; }; f'
git config --global alias.list-local-branches 'branch'
git config --global alias.list-remote-branches 'branch -r'
git config --global alias.list-unstaged-filenames '!f() { (git diff --name-only); }; f'
git config --global alias.merge-feature-branch-into-master '!f() { (CURRENT_BRANCH_NAME=`current-git-branch-name`; git checkout master; git merge $CURRENT_BRANCH_NAME; git status; echo ""; echo "If no problems, then run: $ git push" ); }; f'
git config --global alias.merge-feature-branch-to-remote-master '!f() { git push origin `current-git-branch-name`:master; }; f'
git config --global alias.merge-feature-branch-to-stage-master '!f() { git checkout -B master `current-git-branch-name`; }; f'
git config --global alias.pretty-log "log --graph --abbrev-commit --decorate --date=relative --format=format:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(bold yellow)%d%C(reset)' --all"
git config --global alias.push-current-branch-to-another '!f() { echo "Assumes you have already added and committed files to 'from-branch' (and your remote is named 'origin')."; echo "CTRL+C TO ABORT --OR-- ENTER TO CONTINUE...";read x; git push origin $1:$2; }; f'
git config --global alias.push-local-branch "push origin `current-git-branch-name`"
git config --global alias.rebase-onto-master 'rebase origin/master'
git config --global alias.rename-local-git-branch '!f() { git branch -m $1 $2; }; f'
git config --global 'cherry -v master'
git config --global 'branch'
git config --global 'log --oneline --decorate'
git config --global 'log --graph --decorate --pretty=oneline --abbrev-commit master origin/master master'
git config --global 'log --oneline --decorate'
git config --global "log --graph --decorate --pretty=oneline --abbrev-commit master origin/master `current-git-branch-name`"
git config --global '!f() { git branch -a --contains "$@"; }; f'
git config --global '!f() { git name-rev --name-only "$@"; }; f'
git config --global alias.switch-to-anothers-branch '!f() { git checkout -t "$@"; }; f'
git config --global alias.switch-to-branch '!f() { git checkout "$@"; }; f'
git config --global alias.switch-to-master-branch 'checkout master'
git config --global alias.undo-all-working-dir-changes-including-new-files '!f() { echo "ARE YOU SURE? (CTRL+C TO ABORT --OR-- ENTER TO CONTINUE...)";read x; git reset --hard; git clean -f -d; git clean -f -x -d; }; f'
git config --global alias.undo-last-git-commit-and-delete-local-changes-too '!f() { git reset --hard HEAD^; git push -f; }; f'
git config --global alias.undo-last-git-commit-but-keep-local-changes 'reset --soft HEAD^'
git config --global alias.untracked 'ls-files --other --exclude-standard'
git config --global alias.update-comment-for-unpushed '!f() { git commit --amend -m "$1"; }; f'
git config --global alias.wipe-local-master-replace-with-remote '!git clean -d -x -f && git fetch --all && git reset --hard origin/master'


Error on Linux

If you get an error mentioning a problem with ":/" when running git acp, likely when you are on a linux operating system, then replace the following git config:

git config --global alias.add-all '!git add -A'

Simple workflow

Create a local feature branch and switch your local workspace to point to it.

git create-local-branch new_feature

Make changes to your local source code.

Commit your changes to your local repo.

git commit -a

This will open your editor where you can see the files being committed and add your commit comment (to the first line).

Note that if you don't want to add every file you've been working on then add each file individually with git add <FILENAME> and then run git commit to commit add your commit comment.

Push your changes to your remote repo, e.g. github.

git push-local-branch

If you are using remote git repo features, like git workflow, now is the time to go to your remote repo and create a pull request.

Your pull request will hopefully pass peer code review. You may need to read comments from peers and perform fixes that you will subsequently push up to this branch and eventually all will be good and your merge master will merge your branch (and may also delete your remote branch to keep things clean on the server.)

View a list of all branches you're working on

git list-local-branches

Delete remote branch

git delete-remote-branch new_feature

Delete local branch

git delete-local-branch new_feature


After you create a git repository, e.g., on or, this should probably be the first command you run.

$ git link-to-new-repo golang-samples
Git repo: must already exist.

Initialized empty Git repository in /Users/lex/dev/go/golang-samples/.git/
[master (root-commit) 6fd5651] first commit
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644
error: Could not remove config section 'remote.origin'
You just created a new local repo (golang-samples) that is linked to

You can safely ignore the error: Could not remove config section 'remote.origin' message; There were no previous remote origins since this is the first time you initialized your local git repo.

You should make sure that your public key in ~/.ssh is properly configured.

This command assumes you have the environment variable (REMOTE_GIT_ACCOUNT) set to your repo:username.

You can run this command in its own shell and set REMOTE_GIT_ACCOUNT just before running the git command as follows:

(export && git link-to-new-repo reponame)

This command performs the same commands (and a few more goodies) as you might find in the Create a new repository on the command line help section at your remote git repo:

git init
git add
git commit -m "first commit"
git remote add origin
git push -u origin master


wipe-local-master-replace-with-remote has a long alias for a reason. It is destructive and you really need to understand that all local files will be removed (and replaced with the remote files) before running this one.


If you run $ git acp 'my commit message' without first setting the upstream origin, then you'll get an error like this:

 1 file changed, 1 insertion(+)
 create mode 100644 index.html
fatal: The current branch gh-pages has no upstream branch.
To push the current branch and set the remote as upstream, use

    git push --set-upstream origin gh-pages

Solution: Create/initialize your local repo using the $ git link-to-new-repo <PROJECT_NAME> command and it will set your git origin for you.

fatal: The current branch master has multiple upstream branches

If you run $ git push and get an error like this:

$ git push
fatal: The current branch master has multiple upstream branches, refusing to push.

Solution: Run the following command $ git config-remote-origin-push-head and try again.

Sometimes, when you push to the master branch, without passing any parameters to the git push command, you'll get that error.


When you need to pull another team member's branch into your workspace (to work on it) you need to create a local branch. This alias does that and sets up tracking so that you can run git push after making changes.


The name-rev command uses the tilde "~" character to indicate the position of a commit relative to tags in the project. If "5" comes after the "~" character, then that means that this commit is located 5 commits prior to the tag displayed. If you are working off a master branch it may look like this: "master~5". If you are creating release branches and tagging them as such, it may look like this: "tags/v1.2.0~5".


By default, git push will push all local branches that have matching remote branch names. Run this alias once (it sets a global config setting) to prevent this default behavior and cause git to only push the branch you are currently working on.


If you are working solo on the master branch or if you are working on a team that works off the same branch, e.g., "development" (and your team is not using github pull requests) and you don't want your git history polluted with merge bubbles, then run this alias once (it sets a global config setting).


If you are merging feature branches into a release branch (or have another scenario where you want to see exactly what happened with the merge), then run this alias once (it sets a global config setting).


If you go off the reservation and find yourself working on the master branch and you attempt to run git push without arguments and get an error like the following...

$ git push
fatal: The current branch master has multiple upstream branches, refusing to push.

... then, you should remove the following two lines from the [branch "master"] section in your ~/.gitconfig file

 remote = origin
 merge = refs/heads/master

and run git config-remote-origin-push-head


Unable to create git alias

If you get the following error message...

error: could not lock config file .git/config: No such file or directory

...when attempting to create a git alias, then run the following commands:

$ mkdir ~/.git
$ git config-add-global-email-account <YOUR_EMAIL@YOUR_HOST.COM>



# Filename: current-git-branch-name
#!/usr/bin/env ruby
# Filename: current-git-branch-name
puts `git branch`.split("\n").select{|i| i.include?('* ')}[0][2..-1]


# Filename:  git-add-untracked
(IFS=$'\n'; files=(`git untracked`); for file in "${files[@]}"; do git add $file;  if [ "$?" != "0" ]; then echo "<< run dos2unix  for this file. Then, git add ;git commit --amend --no-edit\n"; fi; done)
if [ "$?" != "0" ]; then
  echo "If you see something like:  fatal: CRLF would be replaced by LF in FILE_NAME."
  echo "Then run:  $ dos2unix on each FILE_NAME  ... and try again."


# Filename:  git-add-commit-pristine
MY_NAME=$(basename $0)
if [ "$MSG" == "" ]; then
    echo "Usage:  $MY_NAME "
    echo ""
    echo "Example:  $MY_NAME 'update readme'"
    exit 1
git add-commit "$MSG" && git fetch && git rebase-from-master && git merge-feature-branch-into-master && git push


# Filename: create-git-branch2
# Note:     This also replaces ' ' with '-' and lowercases the branch name
# Note:     This is named "create-git-branch2" b/c git-extras has a script named git-create-branch

if [ "$BRANCH_NAME" == "" ]; then
    BRANCH_NAME=$(date +%Y%b%d-%H%M)
   IFS=' '
   echo "ALL_ARGS: $ALL_ARGS"
   BRANCH_NAME=`echo $ALL_ARGS | tr '[:upper:]' '[:lower:]' | tr ' ' '-'`

if ( git show-ref --verify --quiet refs/heads/$1 ); then 
    echo "ERROR - Branch ($BRANCH_NAME) already exists." 
    exit 1
    if ( git show-ref --verify --quiet refs/remotes/origin/$BRANCH_NAME); then 
        echo "ERROR - Remote branch ($BRANCH_NAME) already exists." 
        exit 1
        echo "Switching to master..."
        git checkout master 

        echo "Fetching origin..."
        git fetch origin

        echo "Pulling master..."
        git pull

        echo "Creating new branch ($BRANCH_NAME)..."
        git checkout --track -b $BRANCH_NAME 

        echo "Done."



alias gcb='git create-and-switch-to-branch

gcb usage

$ gcb feature1
Switching to master...
Your branch is up-to-date with 'origin/master'.
Fetching origin...
Pulling master...
Current branch master is up to date.
Creating new branch (feature1)...
Branch feature1 set up to track local branch master.

That just created a branch named feature1 and setup the refs so that you can start using git push (without every any having to add -u origin feature1.

git config file after running gcb

feature1 ~/tmp/bogus $ cat .git/config
 repositoryformatversion = 0
 filemode = true
 bare = false
 logallrefupdates = true
 ignorecase = true
 precomposeunicode = true
[remote "origin"]
 url =
 fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
 remote = origin
 merge = refs/heads/master
[branch "feature1"]
 remote = origin
 merge = refs/heads/feature1

Global Git Config

Perform git clones using https rather than the git protocol.

git config --global url."https://".insteadOf git://


This work is licensed under the Creative Commons Attribution 3.0 Unported License.

No comments:

Post a Comment