After just a little over a week’s time from the first part of this series – Getting started with Git (Part I), I’ve managed to put together a basic, yet hopefully comprehensive list of git commands that should get you right on track with your workflow. Before anything, you must understand that initially, this post was over 30 printable pages long, which made me seriously doubt my mental capacity and then split it into multiple posts, one for each major section of it.
Now, just to make sure we’re on the same page, know that Git doesn’t quite exactly track your files, but rather the changes you make to them. While this might seem useless in the event of a filesystem catastrophe (i.e. your files get lost / deleted / abducted by aliens and / or Pedobear), you best believe that it is more than enough to restore everything back to its previous state, provided that your project directory is still a git repository – which you can easily tell by the presence of a hidden .git folder in the root of your project.
Furthermore, with Git, you can actually restore the project to any state at any point in its development history, for which there is a commit entry. And even in case your whole directory is gone, you can still hope someone else has a copy of your repository and / or you can just clone the entire project from a remote… (you did use one, right?) Great, let’s get to it – this section will get you started with some basic commands for managing your git repository and making changes to it.
The first command you might want to take a look at before anything if you’re just starting out, is
git help. On its own, without any arguments, it will give you some general usage tips and a list of the most commonly used git commands, which is far less intimidating than the initial length of this post.
But the true power of this command lies in its ability to be used with other git commands to display their specific help page. Go ahead, give it a try for the next command we’re going to talk about:
git help clone
Sharp little young grasshoppa’ you are, aren’t you? You already know that git clone does wonders for your sheep then… Well, another thing it does is clone a repository into a newly created directory, creates remote-tracking branches for each branch in the cloned repository and checks out an initial branch that is forked from the cloned repository’s currently active branch.
You can actually clone from local repositories too, but this command is more commonly used when working with remotes. Just as in the case with most of the commands described in these posts, this one has a bunch of interesting options that are thoroughly described in the man pages, which you should check out whenever in doubt, or ask questions in the comments section below. Up to some level, I’m somewhat of a guru and might even find myself posting questions and answering them later – which might be sad and funny at the same time, but all in all normal.
There are multiple variations on Git URLs and they can all be used with this command. Some of the most common forms would be:
I’ve already posted a quick guide on how to make a git server that gives you those ssh:// URLs, and there’s another one on the way for a more elegant and secure solution that gives you the git:// URLs which are simply just prettier.
Then, a regular clone command would look something like:
git clone git://git.server.net/git/repo.git
That command will create a repo directory in your CWD, but you can override its default name by adding it as an extra argument:
git clone git://git.server.net/git/repo.git CustomName
git status displays paths that have differences between the… wait. Did I tell you about the 3 Tree Architecture? Yeah, well Git uses it, as opposed to most other version control systems that are stuck at 2 Tree. Simply put, that only means Git consists of 3 areas or places to store things. Oh, f*ck it – too much talk – here’s a picture:
So, as I was saying,
git status displays paths that:
- have differences between the Staging Area and the Repository (can be committed)
- have differences between the Working Copy and the Staging Area (can be added, then committed)
- are simply not being tracked by Git and can be added (and are not ignored, more on that later…)
This is already too long of a post, so I might as well talk a little bit about some of these terms:
Working copy would be your actual working directory on your local machine where you make your changes.
Staging Area is that magical place where pending changes (files that were added using
git add) wait to be committed – think of it as an intermediate step that allows you to build custom commits, organize your changes into commit batches.
Repository is the final destination of your changes, the place that stores your commits and their specific messages.
Committing is the process of moving the changes from the Staging Area to the Repository.
Adding would be the process of telling Git to start tracking a file or group of files and adding it to the Staging Area.
At this point, I sure as hell hope that all this typing will somehow offload the task of having to explain every minor little thing that will come into context… It’s all nice and interesting but not of utmost importance for someone who’s only going to be typing these commands and move on before it all becomes routine.
On a second bipolar thought, I’m glad I know about these things and if I ever stop knowing, at least I could get a good idea on what to want to know. My logic is impervious… and this, having been a long day is no good excuse. This post will either amuse me later on when I’ll review it or cause some serious self-pity as I go all emo.
At long last… wait. Did I tell you about the SHA checksums? Kidding… for now. But really, if you’re afraid of commitment, this is where you should stop reading ’cause we about to commit. Git it? We’ve already covered what the commit does, moving stuff from the Staging Area to the Repo, you only need to know that any commit needs to have a message associated with it (I keep hearing there will be an awesome post on writing good commit messages soon):
git commit -m "Your significant and concise commit message"
Note: You cannot commit files that Git is not currently tracking.
To start tracking files, you need to
git add them:
git add /path/to/file.ext
You can add multiple files simultaneously and even use wildcards, or you can just simply add all the files in your project:
git add .
Another useful thing to know would be the shorthand for adding all files and committing at the same time:
git commit -am "Yet another fascinating commit message"
Yeah, and then there’s the
--amend option – you can use it to squeeze in another commit within the last commit in case of a minor f*ckup (i.e. you forgot to add a file or change a title somewhere):
git commit --amend
That command will open the core editor allowing you to change the commit message of the most recent commit. Additionally you can set the commit message directly from the command line:
git commit --amend -m "The new and improved commit message"
Yes, the amend option comes in handy even when there aren’t really any changes and you only want to just maybe correct a typo in the previous commit message or something.
The command that lets you view all of the commits with their messages and other associated data – a command with many many options and a man page that’s really really worth going through. Soon as you start loving it, you’ll realize how important good commit messages are… Here are just a few tips:
git log # To view all the commits ever made
git log -n # To limit the number of commits
git log --oneline # Compact view, for large projects
git log --graph # To visualize branch merges
git log --author="John" # View only commits made by John
Also, you can filter commits by date:
git log --since=2014-09-03 # Commits since 2014-09-03
git log --until="two weeks ago" # Commits until 2 weeks ago
Oh, it gets better – with regular expression filters:
git log --grep="[bugfix]" # Look for bug fixes
git log --grep="[css]" # Look for CSS
Yes, the first line of commit messages could include tags, so that you can later on use
git log to filter them…
Yeah… I’m not going in depth with this one – it’s not really much to it, but for my diff-ing needs I usually rely on third party apps / plugins since I’m not even that much of a fan of Unix’s diff command either.
git diff is quite similar to it but works with different types of arguments like git trees or tree-ishes, blob objects, actual files on disk and all kind of combinations of all of the above. The official man page does a way better job describing it all than I ever even would be willing to.
But I don’t wanna be the bad guy here, so here are a couple of tips:
git diff # Working vs. Staging for all files
git diff <file> # Working vs. Staging for <file>
git diff --staged # Staging vs. Repository
The command can also be used to compare two or more branches:
git diff <branch-1>..<branch-n>
--color-words option can be used to suppress duplicate lines in the output and highlight only the changed parts.
git rm / git mv
There’s nothing really special about these two except the fact that they handle file moving, renaming or deleting inside a git repository the right way.
Their Unix-specific counterpart commands have their ways of affecting Git’s staging area by messing up the tracked and untracked files (that’s a pretty long and boring story) but I don’t mind a few extra steps cleaning after them so, yeah…
Committing stuff regularly is generally a good thing, think of it like the save / autosave feature in well, really any respectable game out there. Besides that, you have full control over when and what to save, and even then, sometimes things can go horribly wrong. In the next post we’ll go over a bunch of ways that we can Undo changes in Git (Part III).