Emerging technologies tend to be the catalyst for moving certain development paradigms and best practices into the mainstream. Call it the “Can’t Buy Me Love” phenomenon, named for the 80s movie in which a nerd boosts his popularity by hiring his high school crush to pose as his girlfriend. The latest example seems to be the emergence of Git, the open source version control system, greatly raising the profile of formalized source code management. I’ve used other solutions such as the CVS and Subversion version control systems for years, but Git makes source code management a much more natural part of my workflow — even almost fun.
But like many technologies, Git’s shallow learning curve encourages adoption, yet it offers so many features and options that it can easily overwhelm beginners. As I’ve become more experienced with the system, I’ve maintained a list of tips and tricks that have helped me better manage my Git projects. In this article, I’ll highlight the ones I think will be of most benefit to you newbies.
1. Simultaneously Add Files When Committing
Git requires you to explicitly confirm your request to add newly tracked files to the repository before committing the latest round of changes. Therefore the typical command sequence when committing changes goes like this:
%>git add . %>git commit -m "Latest commit message"
Save yourself the preliminary step and perform the task of both adding and committing files simultaneously using the -a
flag:
%>git commit -a -m "Latest commit message"
In many cases, however, you should not take this shortcut. Later in this article I’ll provide you with at least one example demonstrating why.
2. Save Keystrokes with Git Aliases
Like many popular command-line utilities, Git allows you to save user preferences within a configuration file named .gitconfig
. Within this file you’ll typically define your name and e-mail address as it relates to your repository interactions, but you can also define timesaving aliases here. For instance, my .gitconfig
file contains a few aliases to commonly used commands:
[alias] st = status co = checkout cm = commit pom = push origin master
If you happen to forget your defined aliases, you can quickly review your configuration file settings using the following command:
%>git config -l
3. Selectively Staging Files
Sometimes you might work on several files simultaneously but wish to add only a select few to the upcoming commit round. To do so you can use the interactive addition feature. For instance, suppose I’ve created two new files, ShopController.php
and ForumController.php
, but want to commit only the former. I can fire up the interactive adder by passing the -i
option to git add
:
%>git add -i
From there you’ll be greeted with a menu that provides you with several options:
*** Commands *** 1: [s]tatus 2: [u]pdate 3: [r]evert 4: [a]dd untracked
5: [p]atch 6: [d]iff 7: [q]uit 8: [h]elp
By selecting 4
, you can interactively choose which files you’d like to add:
What now> 4 1: application/controllers/ForumController.php
2: application/controllers/ShopController.php Add untracked>>
4. Ignoring Files and Directories with .gitignore
The very first thing I do after initializing a new Git repository is create a .gitignore
file. The .gitignore
file is used to filter out any files and directories that you don’t want to be tracked within your Git repository. For instance when working on a new Zend Framework project I typically omit the project documentation, the website images, and a file named notes.txt
from the repository, meaning my .gitignore
file looks like this:
docs public/images notes.txt
5. Removing Newly Added Files from the Commit List
In the heat of development you occasionally forget to add newly created files that you don’t want included in the repository to your .gitignore
file. You can remove these files from the list of changes to be committed (known as unstaging the file) using the rm
command:
%>git rm --cached schema-notes.txt
When unstaged, you can add the file to your .gitignore
file and begin the commit process anew.
6. Reviewing a Previously Committed File’s Contents
I often need to examine the contents of an earlier file revision after making some changes to the current version, without actually restoring the file. You can easily do so using the show
command accompanied by an argument that points to the file:
%>git show HEAD^:application/controllers/AboutController.php
The caret (^
)is representative of the number of revisions backwards you’d like to look. Therefore the above example will display the AboutController.php
file’s previous revision. If you’d like to look back three revisions you would use three carets, like this:
%>git show HEAD^^^:application/controllers/AboutController.php
Alternatively, you can use the commit’s hash to reference the file. For instance if you’d like to view the contents of the AboutConroller.php
file as it was committed five revisions ago, you could execute git log
to determine the commit hash, and then use the first five characters of that hash to retrieve the file contents:
%>git show 23aa985:application/controllers/AboutController.php
7. Editing Your Most Recently Committed Log Messages
I’m a stickler for spelling, but in my haste to commit the latest changes I occasionally will slip an unwanted letter or two into the message. You can easily edit the most recently committed message using the amend
command:
%>git commit --amend
Executing this command will load the latest commit message into a text editor, allowing to you edit and save the message.
8. Stashing Uncommitted Changes
Occasional interruption of your programming routine is inevitable, often putting you in a position of not being quite ready to commit changes, yet suddenly needing to fix and commit an issue unrelated to your current work. You can tuck away your current changes using the stash
command, thereby reverting your base to the previous commit point, allowing you to make and commit the new changes. When complete, you can return to your stashed state. For instance, suppose I was working on a new section to a project’s README
document, and suddenly noticed an egregious spelling mistake. I can tuck away my current changes like this:
%>git stash save
Opening README
anew, I would see that the new section has disappeared, because I returned to the previous commit point. I would then fix the spelling error and commit the changes. Then execute the following command to return to my original state:
%>git stash pop
9. Browsing Your Repository
Quite a few Web-based interfaces are available for browsing Git repositories, but did you know that one named instaweb
is integrated into the native distribution? To peruse your repository within the browser, execute the following command:
%>git instaweb --httpd apache2
Passing apache2
to the --httpd
switch will tell Git that Apache is the web server running on this machine. The default is lighthttpd, although several other servers are also supported.
10. Blaming Somebody Else
Occasionally a team member (but never you, of course) will introduce a bit of untested code into the repository and break your build. Naturally you’ll want to blame somebody for the problem, but who introduced the error? Use the blame
command to find out:
%>git blame application/controllers/AboutController.php
23aa9852 (Jason Gilmore 2010-06-03 12:34:04 -0400 11) public function indexAction()
23aa9852 (Jason Gilmore 2010-06-03 12:34:04 -0400 12) { 0e9e9f49 (Jason Gilmore 2010-06-03 13:32:47 -0400 13)
echo "Missing semicolon" 23aa9852 (Jason Gilmore 2010-06-03 12:34:04 -0400 14) }
Whoops!
Conclusion
Git is truly a treasure trove of fantastic features that make source code management a breeze. Which Git features, tips and tricks do you find useful? Tell us about them in the comments!
About the Author
Jason Gilmore is the founder of EasyPHPWebsites.com. He also is the author of several popular books, including “Easy PHP Websites with the Zend Framework“, “Easy PayPal with PHP“, and “Beginning PHP and MySQL, Third Edition“.