Git is a really cool source control system that can do loads of things and works really well and stuff. But if you've never used it before and haven't really learned how to use it right it sucks and is shit and seems like a massive chore for very little benefit. This article should help to give you some tiny level of understanding of how to use basic git stuff in a way that doesn't suck and lets you reap some of the benefits of using it.
Stop using sucky tools and do things properly
There are a lot of applications that are designed to give you a shiny interface for working with Git, and they probably made you think "oh hay cool, pres butan ftw lol!!1" but they are BAD and WRONG! 1 If you want to have a proper understanding of what you're doing and you want access to all the tools it provides, you should run it from the command prompt because that's what it was made for. This is not as scary and difficult as it sounds. Plus you'll look really pro.
To get started, you will obviously need to download and install git and then you'll want to install ConEmu because it makes working on the command line not terrible. That's it for software setup.
Type words, make things happen
There are a few bash commands that it's worth being familiar with:
cd <path>- Change directory just like in a windows command prompt, so
cd c/development/my-dumb-project/would take you to c:\development\my-dumb-project
ls- lists the contents of a directory
rm <filename>- deletes a file, I only use this when I type something wrong and end up making an empty file called sqhel
Then you'll also need git commands for doing actual git things:
git status- tells you the current status of the repository (changes in your working copy, staged changes, other stuff) also tends to tell you what you can do next, so it's super handy if you get stuck
git init- creates a repository in the current folder (gosh that was easy)
git branch <branchname>- makes a new branch with the given name
git checkout <branchname>- switches branch to the one specified
git add -A- adds all your pending changes to staging
git add <file>- adds just the specified file's changes to staging
git commit -m "<message>"- makes a commit with all the changes in staging and gives it the specified message
git log- lists the commit history, most recent first (press
qto make it stop)
git merge <branchname>- merges the specified branch onto your current branch
git rebase <branchname>- rewrite history in your own image
That covers the basics for working with your local repository, but when you're working with other people you'll also need a remote repository somewhere to sync against. And that involves a few more commands:
git remote add origin <url>- Adds a remote called origin with the specified url (like that url that github gives you for your repository2)
git pull- pulls down any changes on the remote to your local copy
git push origin HEAD- pushes any new commits you have made on your current branch up to the remote origin (HEAD refers to the tip of your branch)
Don't panic if you end up in vim!
Vim is some fancy text editor thing that people who are way nerdier
than me think is awesome - the shell will possibly dump you there
when you do things with git and it needs you to type a message or
something. It looks weird and scary, but don't panic! It's built
around having a lot of flashy keyboard shortcuts, but if you press
insert key on your keyboard you'll go into regular
text editing mode (like how other editors are) and when you're done
making changes press
escape and then type
which means Write and Quit and you're outta there.
Git as you go
Knowing the commands is one thing (one very important thing, but still) but the really important part is using them well and fitting them into your workflow. So what is a good approach with all this stuff?
Always work on branches
Importantly, not the master branch. Branches are good because they keep all your work on a particular thing isolated - if you're half way through something and you find a bug in your main build that needs to be fixed now it's really good that you can just commit any changes to your branch, make a new bugfix branch from master and get that fix in, without having to undo any of your in-progress work.
It's also nice that your master branch can be a rock solid pillar of stability, until any code you're working on really is done and ready to join it. When you're starting a new line of development, either a feature or bugfix, you should start a new branch from master 3:
git checkout master
git branch my-awesome-new-branch
git checkout my-awesome-new-branch
First change to the master branch and pull any changes from origin to ensure that your local copy of master is up to date with any remote changes. Then create a new branch - here creatively titled my-awesome-new-branch but it's probably a good idea to go with a more descriptive name - and then check it out ready to be worked on.
Or if you're a super fast speedy person, you could just go:
git checkout master
git checkout -b my-awesome-new-branch
The -b switch on checkout will make a new branch if it doesn't already exist
Commit often, push less often
Make a lot of commits. Each commit should be the smallest change you could've made without breaking everything. If you add a line inside a method that doesn't change the outcome (so everything still builds and tests still pass) that's a commit. If you change the signature of a method, then you would also need to change all the callers before commiting.
If you make a commit, then realise you forgot to add something to it
(because sometimes you're silly like that) you can add that change with
git add <file> and then use
git commit --amend
to sneakily add it to the last commit, instead of cluttering things up
with 3 commits for the same thing.
Before you push your branch and share your commits with everyone else, it's a lot easier for you to change them (and it won't mess up anyone else's flow) - so don't push until you're happy with the state of a branch. If it's a particularly long lived branch, you might want to push periodically just to have it backed up, but generally try to avoid long lived branches anyways because they are a pain to work with.
Write good commit messages
Every commit in your history should have a descriptive, easy to understand message that says what it changes and in a lot of cases why it makes that change. It should be a note to a future developer (or just as likely future you) that explains the reasoning for changing the code in a clear, concise way so that you're not baffled by a change in 6 months with no one to turn to for answers.
It's a good rule of thumb to have all your commit messages finish this sentence:
If applied, this commit will...
All of this is explained much better than I can manage in this very good article.
If not now, then at least later
Sometimes you're in the middle of changing a bunch of things, got a
mad good flow going on and really don't wanna break it up by writing
beautiful, poetic commit messages. Fortunately, you can use a temporary
message for now and then fix it up later with the secret voodoo of
interactive rebasing (
git rebase -i)
An interactive rebase lets you go through all the commits after a starting point of your choosing and fuck around with them. You can split them apart into more commits, squash them together into fewer, even add and remove changes from each one or get rid of a commit entirely. But a very handy thing to do if you suck at writing commit messages first time, is that you can change the commit messages.
So code away, get your flow on real good and make nice small commits with temporary messages just for you. Then, when you're done rebase interactively from the commit before your changes and make all those messages beautiful:
git rebase -i <commit id>
Share with others
When you've finished a feature (or part of a feature depending on the size of it) it's time to make a pull request and get your work merged into the rest of the code. Making a good pull request helps other developers review your code and make sure you didn't do something dumb. Read this cool article for some pointers on how to make your pull request the best it can be, and help everyone out by making it easier to review.