Current Articles | RSS Feed
You only need a basic command of Git to make the source code management utility incredibly useful. But Git offers a range of commands and options that can make your workflow run even more smoothly. Here are a few Git tips and tricks to make this tool even greater than you already thought it was.
There are undoubtedly a few Git commands that you use regularly – git checkout, git commit, and git status, for example. You can reduce the number of keystrokes you type to invoke them by using Git aliases. Git stores its aliases (and some other config options; see below) in the file ~/.gitconfig. You can edit this file to add alias lines:
git checkout
git commit
git status
[alias] st = status co = checkout cm = commit
Or you can add them with a command like this:
git config --global alias.st "status"
To see what aliases and other config options you have set, run the command git config -l. Aliases are particularly handy for some longer commands, such as some of the commands discussed below. One useful alias is ds = diff --stages, which shows you a diff of the changes you're about to commit to the repository – once they're added, but before you commit. It's good practice to cast a quick eye over those before you commit.
git config -l
ds = diff --stages
If you have lots of branches, it can be useful to see a graphical representation of your Git history. One option for this is gitx, either in its standard version (which should be included in your Git install by default) or using this improved fork. However, if you just want to see a graphical representation of your history on the command line, try
gitx
git log --graph --simplify-by-decoration --pretty=format:'%d' --all
simplify-by-decoration shows only commits referred to by a branch or tag, and the only output here is a ref name (%d; see the PRETTY FORMATS section of the git log manpage for more format info). A more verbose version shows all commits, with their subject lines, author, date, and abbreviated commit hash, in pretty colors:
simplify-by-decoration
%d
git log --graph --pretty=format':%s %Cblue%an, %ar %Cgreen(%h)%Creset'
Add --simplify-by-decoration to that last version to get a cross between the two – simplified, with only certain commits, but with more commit info.
--simplify-by-decoration
Once you've had a look at a tree, you may notice that you have a lot of branches that seem to have already been merged. This is especially true if your workflow makes a lot of use of Git branches. To find out which branches have been merged into other branches, try git branch --merged, or use git branch --no-merged to show the unmerged branches. You can then manually delete merged branches with git -d. (Thanks to Chris Kelly for this tip.)
git branch --merged
git branch --no-merged
git -d
git log is useful for reviewing your commit history, but it's quite basic. It shows only commit ID, author, date, and commit message. I often want to also know which file was changed. You have a few options for doing this:
git log
git log --stat
git log --name-status
git log --name-only
Using these you should be able to get the information you want.
You can also use the git whatchanged command, which shows the commit logs and diff output for each commit. The default diff output is Git's internal format; for a textual diff, which is more useful to a human reader, try git whatchanged -p, though this is usually overkill if all you want is to check which files were changed.
git whatchanged
git whatchanged -p
To ignore files globally across all your git repositories; edit ~/.gitignore:
git config --global core.excludesfile '~/.gitignore'
If you accidentally add a file you'd rather have ignored, you can unstage it from the commit with git rm:
git rm
git rm --cached unwantedfile.txt
You can then add it to the local or the global .gitignore file to ignore it in future.
.gitignore
You may sometimes commit something you didn't want to, or commit too early. Try running git rebase -i if you wind up making multiple commits that should have been all in one, or if you wish to consolidate a bunch of commits for code review. Make sure your changes are up-to-date and that you're on the branch you've been working on, then type git rebase -i master to squash the commits you've made on that branch into one commit on the master branch. You'll see a screen that looks a bit like this:
git rebase -i
git rebase -i master
pick afa7532 Array handling methods pick b860afa Reading from notebook file into array pick df1af7b Setting up notebook file methods # Rebase cb44197..df1af7b onto cb44197 # # Commands: # p, pick = use commit # r, reword = use commit, but edit the commit message # e, edit = use commit, but stop for amending # s, squash = use commit, but meld into previous commit # f, fixup = like "squash", but discard this commit's log message # x, exec = run command (the rest of the line) using shell # # These lines can be re-ordered; they are executed from top to bottom. # # If you remove a line here THAT COMMIT WILL BE LOST. # However, if you remove everything, the rebase will be aborted.
You can reorder the lines if you like, so for example you could edit the above file like so:
pick afa7532 Array handling methods squash df1af7b Setting up notebook file methods pick b860afa Reading from notebook file into array
This leaves you with two commits (array handling and notebook file methods, and reading from file into array). Or edit it like this:
pick afa7532 Array handling methods squash b860afa Reading from notebook file into array squash df1af7b Setting up notebook file methods
to squash all three into a single commit. Once you save the file and exit the editor, the changes are committed to the master. If you change your mind before that, delete all the lines and nothing will happen. You can also of course rebase against another (non-master) branch.
You can amend a commit with git commit --amend. Make changes in the local copy of the codebase that you would like to commit (for example, maybe you forgot to add foo.rb, so type git add foo.rb), then type git commit --amend. foo.rb will then be included in the last commit (along with everything that was already there), and you'll have a chance to edit the commit message. If you make no local changes and just type git commit --amend, you get a chance to amend the commit message. Alternatively, if you want to keep your commit message and just amend the commit, use git commit --amend -C HEAD.
git commit --amend
git add foo.rb
git commit --amend -C HEAD
To undo a commit altogether, use git reset --soft HEAD^. This undoes the last commit but leaves the changes staged. git reset --hard HEAD^ undoes the commit and deletes all your changes locally; use this with caution!
git reset --soft HEAD^
git reset --hard HEAD^
A slightly different way to approach an individual commit is git cherry-pick. This command enables you to pick a specific commit and add it to your branch, without also taking all the other commits with it. This can also be useful if the branch you're cherry-picking from is so out of date that it would be hard to merge it all in with your own branch. Check out the branch you wish to add the commits to, find the commit ID from the other branch, and use:
git cherry-pick
git cherry-pick COMMIT_ID
If you run into conflicts, you need to fix them in the normal way.
Sometimes you might be working on several unrelated changes, and wish to commit them separately. You can do this on a per-file basis either by using git add this.file and working through the list, or git add -i to go into the interactive version of git add, which allows you to pick changes and stage untracked files.
git add this.file
git add -i
git add
You can also use the patch functionality to commit individual chunks of changes to a file. Type git add -p myfile.rb to be walked through the various chunks of changes that you've made to myfile.rb, and be given the option to add each to the commit. ? gives you help on the command options once you're in there. (Again, thanks to Chris Kelly for this one.)
git add -p myfile.rb
?
Check out the Git man pages for yet more options and tricks!
Allowed tags: <a> link, <b> bold, <i> italics