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
[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.