Some git commands for amending commits and showing short logs

I noticed a friend of mine tweet about git commit --amend yesterday, and it occurred to me that some people probably haven't used git very much and are still learning the ins and outs. I thought I'd share some commands I find really useful.

The first thing to mention is that you can set up your own command aliases by editing a file called .gitconfig in your home directory. This is where I keep all my custom aliases. (I use them so often that I'm often lost when using git on a different system where my aliases aren't set up.) Here's an extract from my .gitconfig with some explanation of the aliases:

[user]
  # sets up your details so that commits carry the right user info;
  # I use my primary github email address for mail, so that
  # all my github commits are associated with the right account
  mail = <you primary github email address>
  name = <your real name>
[smtp]
[sendemail]
[color]
  # turns on the default terminal colouring for git output
  ui = auto
[alias]
  # A good resource on git aliases is https://git.wiki.kernel.org/index.php/Aliases

  # these are just shortcuts to full git commands
  st = status
  ci = commit
  br = branch
  co = checkout
  cp = cherry-pick

  # I use this one when I am working locally, miss some changes, then want to
  # add them onto the last commit I made; it stages all the files which have
  # changed (NB NOT new files or deleted files), merges those changes to HEAD,
  # and retains any existing comment from HEAD
  cim = commit -a --amend -C HEAD --reset-author

  # this is similar to the cim command, but instead of automatically adding any
  # changed files, it only merges staged files into the HEAD commit; this is useful
  # where you just want to add one or two files you've changed to the existing
  # HEAD commit, before making a new commit with the other changes
  fix = commit --amend -C HEAD

  # sl: short log showing author and changed files; useful for checking
  # what I've patched in each commit
  sl = log --format=format:'%h %s%n%an, %ar (%ai)' --name-status

  # author: Show all the commits a specified author has done
  # Usage: git author <email_address|name>
  author = "!sh -c 'git log --tags --source --oneline --author=\"$1\"' -"

[merge]
  tool = meld
  keepBackup = false

[push]
  default = current

Note that I have others, but these are the ones I use most often.

Next, to give a flavour of how you might use them, here's an example session making use of these commands.

First I init a git repo and add a README file:

[ell@lp shiny]$ git init .
Initialized empty Git repository in /tmp/shiny/.git/
[ell@lp shiny]$ vim README
[ell@lp shiny]$ git st
# On branch master
#
# Initial commit
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#	README
nothing added to commit but untracked files present (use "git add" to track)
[ell@lp shiny]$ git add README
[ell@lp shiny]$ git ci -m "Add README"
[master (root-commit) a2584b9] Add README
 1 file changed, 1 insertion(+)
 create mode 100644 README

Now I edit the README, but want to merge those changes into the existing commit. So I use my cim command:

[ell@lp shiny]$ vim README 
[ell@lp shiny]$ git cim
[master f4be9e7] Add README
 1 file changed, 3 insertions(+)
 create mode 100644 README

This adds my changes to the existing commit, keeping the commit message I've already laboriously typed in.

Now I show a short log of what's happened so far. I prefer this log format as it shows just the changes files, a short form of the git commit idedntifier, the author, and the comment:

[ell@lp shiny]$ git sl
f4be9e7 Add README
Elliot Smith, 2 seconds ago (2013-07-18 10:35:12 +0100)
A       README

Now I add a new file, package.json, then make an edit to README:

[ell@lp shiny]$ vim package.json
[ell@lp shiny]$ vim README 
[ell@lp shiny]$ git st
# On branch master
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#	modified:   README
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#	package.json
no changes added to commit (use "git add" and/or "git commit -a")

I want to include my edit to README with the existing commit, then add a new commit for package.json. So I first stage the changes to README and use my fix command to merge them into the existing HEAD:

[ell@lp shiny]$ git add README
[ell@lp shiny]$ git fix
[master 71de8f9] Add README
 1 file changed, 5 insertions(+)
 create mode 100644 README
[ell@lp shiny]$ git sl
71de8f9 Add README
Elliot Smith, 32 seconds ago (2013-07-18 10:35:12 +0100)
A       README

Then I stage the changes to package.json and make a new commit for them:

[ell@lp shiny]$ git add package.json
[ell@lp shiny]$ git ci -m "Add package JSON"
[master b717cc8] Add package JSON
 1 file changed, 1 insertion(+)
 create mode 100644 package.json
[ell@lp shiny]$ git sl
b717cc8 Add package JSON
Elliot Smith, 2 seconds ago (2013-07-18 10:35:52 +0100)
A       package.json

71de8f9 Add README
Elliot Smith, 42 seconds ago (2013-07-18 10:35:12 +0100)
A       README
[ell@lp shiny]$ 

Notice that I almost automatically do git sl after each cim/fix/commit command, as it's so quick and easy to read the output.

Anyway, I might write some more if I feel so inclined another day. I make extensive use of interactive rebasing, for example, which is never really explained anywhere in simple terms, but which is massively useful (especially if you're making branches to turn into pull requests for other projects).

git can be a bit daunting at first, but after you've used it for a while I don't think you'd use any other version control system ever again, unless forced to.

Comments

interesting

I've never used git, simply because I haven't had any reason to, but thanks for the syntax. Maybe I'll research and write about it myself, try and frame it like my article on access to blocked sites, I think that will be cool.