Adam's "Blog"

That's all, really.

Making Git Nice to Use

I’ve made a number of tweaks to my Git setup, but they never seemed that significant until I tried to work on a machine without them.

Probably the most important is to use a good command prompt. I use ConEmu, a tabbed Windows console app with many cool features.

  • I use its “Quake style slide down” along with a global hotkey to have a command prompt always quickly available.
  • If you create a ConEmu task (“tasks” are predefined apps/shells which you can launch in a new tab) which runs cmd.exe /k "%ConEmuBaseDir%\CmdInit.cmd" -git, you’ll see the current branch and status in every command prompt. It can slow things down slightly, since it’s running a git command every time you hit enter, but it’s worth it.
1
2
C:\Source\github\shrimpit [master +0 ~3 -0]
>
  • You can also make a copy of CmdInit.cmd to customize it; I wanted the > in the command prompt on a new line, so I made a customized version.

Clink provides command-line editing and tab completion in your command prompt (whether it’s cmd.exe or ConEmu). I forked and customized sweiss3’s code to create my own autocompletion script, so I can tab-complete branch names.

A GUI is often helpful too. I like TortoiseGit (along with P4Merge for resolving conflicts), so I created a batch file to quickly launch TortoiseGit commands. (I then realized that “tgit” is too much to type, and used ConEmu’s doskey aliases— under Startup, Environment in Settings— to define a shorter one: alias tg=c:\tools\tgit.cmd $*)

Speaking of aliases, I use a few in my Git config as well. You can put just about any Git command or shell command into an alias. To make git pr equivalent to git pull --rebase, for example, you would run:

1
git config --global alias.pr "pull --rebase"

And to make git hi run a shell command to say hi to you, by using !:

1
git config --global alias.hi "!echo Hi there"

(Leave out the --global if you only want it in the current repository.)

The aliases I use the most are just abbreviations: co for checkout, and ci for commit. I also use prom for pull --rebase origin master, to rebase a new branch on master in order to get it up to date before pushing it for the first time. And when I am ready to push it for the first time, I use pushup to set the upstream branch as shown below.

Here’s the full alias section from my .gitconfig. You can run git config --global --edit and paste in parts that you like.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
[alias]
  # pull down the latest changes to the current branch, rebasing your changes after them
  pr = pull --rebase

  # show a pretty log with a graph of changes
  gl = log --graph --pretty=format:\"%Cred%h%Creset . %an: %s %Cgreen(%cr)%Creset\" --abbrev-commit --date=relative

  co = checkout
  ci = commit

  # pull the latest changes from master on the "origin" remote, and rebase your branch on it
  prom = pull --rebase origin master

  # when a rebase has stopped so you can resolve conflicts:
  rc = rebase --continue
  ra = rebase --abort

  # show a list of branches sorted by last commit, with details including hash and upstream
  br = branch -vv --sort=-committerdate

  # push a branch for the first time, setting its upstream to the same name as the branch (so you don't have to type --set-upstream and the name)
  pushup = ![[ $(git config "branch.$(git symbolic-ref --short HEAD).merge") = '' ]] && git push -u origin $(git symbolic-ref --short HEAD) || echo Upstream already set.

  # add all current changes (except new untracked files) to the previous commit, without prompting to edit the commit message
  amend = commit -a --amend --no-edit

  # push the current changes without running pre-push hooks, overwriting known commits on the server -- only for work-in-progress branches!
  pushwip = push --no-verify --force-with-lease

Now I can git co mybranc[TAB][ENTER], make my changes, and tg ci to review in TortoiseGit and commit.