Git Notes

These are quick reference notes; most of my Git notes are part of tutorials on Java Hot Chocolate.


Git configuration

I do this stuff:

$ git config --global user.email "russ@windofkeltia.com"
$ git config --global user.name  "Russell Bateman"
$ git config color.ui true
$ git config --global user.email "russ@windofkeltia.com" ; git config --global user.name  "Russell Bateman" ; git config color.ui true

How to prime the pump of a new respository

This is what I do for GitHub and Bitbucket. I started out by managing my own git server using gitolite for about a year, but it's been many years now since switching to GitHub for work and Bitbucket for home (free even for private repositories) and managing a team git server is way more trouble than it's worth although there might be compelling reasons for a company to continue to do it.

But, if anyone asked me, I'd strongly encourage paying for GitHub or Bitbucket because it's not that much and you get automatic fire insurance plus secure access outside the walls without VPN. So, I don't remember how different this was for gitolite, but it shouldn't be too different, just replace bitbucket.org with your own server name/IP address.

I do this fairly often, but not quite often enough ever to remember all the commands. It starts out WAY from scratch (so it's all here). For the first one, the subdirectory might already exist and it might (or not) already have stuff in it. No matter which, both cases are fine, just skip creating it.

$ mkdir /path/to/your/project
$ cd /path/to/your/project
$ git init
$ git remote add origin git@bitbucket.org:russellbateman/project.git

I don't ever do this, I usually add a README.md...

$ echo "russellbateman" && contributors.txt
$ git add contributors.txt

This is also optional, but I do it 'cause I like color and blame...

$ git config --global user.email "russ@windofkeltia.com"
$ git config --global user.name  "Russell Bateman"
$ git config color.ui true

I do this, obviously...

$ git commit -m "Initial commit with contributors"
$ git push origin master

How to remember what Git branch I'm working in...

To remember what Git branch you're working in, you can add it to your prompt. Yeah, I know: yet a longer prompt--just what I wanted too. The Git branch name is in purple. The one below was dug up originally somewhere on the web, but I got it from a friend. (To narrow the width reproducing it in this illustration takes up, I'm splitting it without adding spaces, backslash to escape the next line, etc. So, where there is a space, such as at the beginning of the line, it's completely intentional.)

Also, I'm trying to split it on syntactic elements, i.e.:

username@hostname: current working directory {branch} $

This will make it easier for someone reading this to divvy up where elements begin and end, and modify it more easily.

export PS1="\[\e[0;32m\]\u\[\e[m\]\[\e[1;33m\]@
\[\e[m\]\[\e[1;32m\]\h\[\e[m\]\[\e[0;33m\]:
\[\e[m\]\[\e[1;37m\]\w\[\e[m\]
 \[\e[0;35m\]\$(git branch 2> /dev/null | grep -e '\* ' | sed 's/^..\(.*\)/{\1} /')$
 \[\e[m\]"

It looks approximately like this:

    bozo@clown-country:~/dev/myapp {russ} $

The subdirectory path is nigh invisible against a white-ish (light) background. It's for those who reject the (Apple Macintosh) notion that a computer console's purpose is to mimic the use of paper in the brick-, wood- and meat space.

Here's a better one for a white-ish console background. I also reserve the dollar sign for generic prompts preferring a right-facing caret.

export PS1="\[\e[0;32m\]\u@
\[\e[m\]\[\e[1;32m\]\h\[\e[m\]\[\e[0;33m\]:
\[\e[m\]\[\e[1;34m\]\w\[\e[m\]
 \[\e[0;35m\]\$(git branch 2> /dev/null | grep -e '\* ' | sed 's/^..\(.*\)/{\1}/')>
 \[\e[m\]"

It looks approximately like this:


    russ@tuonela:~/dev/myapp {russ}>

Incidentally, if you're not in a subdirectory with files tracked by Git, then the branchname will not even appear.


    russ@tuonela:~/dev/downloads >

If you don't switch users, care about your hostname, etc., you can shorten the prompt dramatically. It has occurred to me that for years, I've maintained an informative prompt, much of which only reminds me who I am and what computer I'm on. I could see the utility of that if I came in via ssh, but otherwise, really, what do I care? And I even have a minimum of two Linux machines running in my den at home. It's just not that hard for me to guess which keyboard I'm typing at.

export PS1="\[\e[m\]\[\e[1;34m\]\w\[\e[m\]
 \[\e[0;35m\]\$(git branch 2> /dev/null | grep -e '\* ' | sed 's/^..\(.*\)/{\1}/')>
 \[\e[m\]"

To look like this:

    ~/dev/myapp {master}> git checkout russ
    Switched to branch 'russ'
    ~/dev/myapp {russ}>

.bashrc entry for me

Here's an excerpt from my personal .bashrc on Ubuntu:

	if [ "$color_prompt" = yes ]; then
	  if [ "$using_git" = yes ]; then
	    export PS1="\[\e[m\]\[\e[1;34m\]\w\[\e[m\] \[\e[0;35m\]\$(git branch 2> /dev/null | grep -e '\* ' | sed 's/^..\(.*\)/{\1}/')> \[\e[m\]"
	  else
	    PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]> '
	  fi
	else
	  PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w> '
	fi
	unset color_prompt force_color_prompt

See some stuff on console window color here.


How to remember what Git branch I'm working in (2)

Jo Liss published a marvelous addition to .basrc for this problem and I replaced what I'd been using (above) with it. I commented out one line because it erased displaying "master" and I want to see that ('cause that's the branch I usually forget and do work in when I don't mean to).

One this this does, though, is erase the title of the GNOME terminal window. I believe this is because the prompt (PS1) become a bash function invocation and gnome-terminal can't endure that anomaly for its title bar.

What may screw up later on... If Git is changed to return different English strings, this script will have to be modified.

# -------------------------------------------------------------------------
function _git_prompt()
{
  local git_status="`git status -unormal 2>&1`"
  if ! [[ "$git_status" =~ Not\ a\ git\ repo ]]; then
      if [[ "$git_status" =~ nothing\ to\ commit ]]; then
        local git_state_color=42
      elif [[ "$git_status" =~ nothing\ added\ to\ commit\ but\ untracked\ files\ present ]]; then
        local git_state_color=43
      else
        local git_state_color=45
      fi
      if [[ "$git_status" =~ On\ branch\ ([^[:space:]]+) ]]; then
        branch_name=${BASH_REMATCH[1]}
#       test "$branch_name" != master || branch_name=' '
      else
        # Detached HEAD.  (branch_name=HEAD is a faster alternative.)
        branch_name="(`git describe --all --contains --abbrev=4 HEAD 2> /dev/null ||
          echo HEAD`)"
      fi

      # Insert color and branchname into prompt here:
      echo -n '\[\e[0;37;'"$git_state_color"';1m\]'"$branch_name"'\[\e[0m\] '
  fi
}

function _prompt_command()
{
  PS1="`_git_prompt`"'\[\e[1;34m\]\w \$\[\e[0m\] '
}

PROMPT_COMMAND=_prompt_command
# -------------------------------------------------------------------------

Git and binaries

Git has a heuristic for detecting binary files.

You can force file types to be binary by adding a .gitattributes file to the repository (just as you would add a .gitignore file.)

This file contains a list of glob patterns followed by attributes to be applied to files matching those patterns. Subsequent clones of the repository will pick this up as well.

For example, if you want all files extended by .foo to be treated as binary files you can have this line in .gitattributes:

*.foo -crlf -diff -merge

This will mean all .foo files will

  • not have carriage return/line feed translations done
  • not be diff'd
  • merges will result in conflicts leaving the original file untouched

Git aliases

At some point in Git's history, the ability to specify aliases arose.

$ git config --global alias.please 'push --force-with-lease'
$ git config --global alias.shorty 'status --short --branch'

...and, of course, these are used thus:

$ git please
$ git shorty