Git Reference Guide - Part Two
Published Feb 1, 2019
Reading time 9 minutes
Getting started
In my examples, I’m using GitLab but if you’d rather use GitHub, go ahead as there won’t be much difference.
Before you can start using git, you need to set up a couple of things first. If you already have git locally on your computer and you’ve got up SSH keys with GitLab or GitHub you can skip the next two steps.
Getting git on your computer
If you want to use git, having git on your computer really helps. If you’re not sure if you already have git, open a terminal and run the following:
$ git
If you get an output saying “usage: git…."` you’ve got git! Well done and move ahead to the next section, if not, let’s get it downloaded and running.
For the most up to date install instructions, I recommend following this guide but go ahead and use your favorite resource if you have one.
Once installed, you should be able to run $ git
and see the output “usage: git…”. 🎉
Setting up SSH Keys
GitLab has a great tutorial on checking and generating keys and I recommend following these steps to generate new keys if you’ve never done this before or if you already have keys and need to add your SSH key.
gitlab.com/help/ssh/README#gitlab-and-ssh-keys
Now you have git and SSH keys, you’re ready to git like a pro.
To initialize a new git repository.
To start a new git repository (called repo for short) - this is the folder your project is saved under. If you have a website or project you want under source control, initialize the very top level on the folder - root level. Or if you’re starting a new project that will be under source control, everything will be within the folder.
You’ll first need to create the project on GitLab. This is the online version of your local .git file (See part one for more information on your .git file) It’s essentially all the same information as you have locally with git but with a lovely UI and some extra goodies sprinkled on top to help you manage your project.
When you create the new project, for the title (and branch name), it’s best practice to avoid capital letters, spaces or any special characters. This is so when you’re talking to GitLab from your computer the urls are easier to parse and you’ll be able to navigate easier. It also solves any cross-platform problems, like Windows not caring about capitals but Linux caring so you can end up with repo names or branches with different names even though it’s the same name… very annoying! It’s also handy if your local project folder has the same name as your git repo on GitLab.
Head over to GitLab and create your project.
Once you’ve created a new project on GitLab, all the instructions for what to do next are shown. But it’s super annoying when you navigate away from that page and can’t get back to it.
So here it is again:
Git global setup
git config --global user.name "<first-name>"
git config --global user.email "<email-address>"
Create a new repository
git clone git@gitlab.com:<username>/<name-of-project>.git
cd <name-of-project>
touch README.md
git add README.md
git commit -m "add README"
git push -u origin master
Existing folder
cd existing_folder
git init
git remote add origin git@gitlab.com:<username>/<name-of-project>.git
git add .
git commit -m "Initial commit"
git push -u origin master
Existing Git repository
cd existing_repo
git remote rename origin old-origin
git remote add origin git@gitlab.com:<username>/<name-of-project>.git
git push -u origin --all
git push -u origin --tags
If you already have a project you want to put into git, follow the “Existing Folder” steps above or for a new project that you don’t have any files for yet, follow “Create a new repository”.
And with that, you have your repo!
Adding a git ignore file
A .gitignore
file tells git to ignore certain files to save you committing them. It’s optional but recommended especially for folders like node_modules where they’re generated on your machine and you can get them locally when you need them rather than being an integral part of your project like your code.
I like to add a gitingore file straight away to new projects so all the generated files and binaries are ignored from the get-go and on GitLab it’s super easy to use a template so I don’t have to bother writing one from scratch each time.
In your new project on GitLab, click to add a ‘New File’. This gives you the option to use a gitignore template for whatever language/framework you might be using. Select the one you want from the drop-down list and then at the bottom of the screen, add a commit message “Add gitignore file” and commit it.
Great, you now have a gitignore file but it’s on the remote, not locally yet and it also means your local repo is out of sync so must be updated before you can proceed.
To get the gitignore file locally, on your master branch run:
$ git pull
This will pull the changes into your local copy and you’ll have the .gitignore file which will start working immediately. Check it’s there by running ls
to see all files listed. You can add to your gitignore at any point if you create a new file or directory you want ignored.
Working locally
Git saves everything in a local database in your project root - the .git
file. When you clone a repo, this is what contains all the information and history of the project. Pushing and pulling to the remote (GitLab) is effectively just keeping that git file up to date.
Once you’ve made changes and want to save those changes to the server, you first add them.
To add all the files listed by git status
, run:
$ git add .
To individually add files:
$ git add <file-name>
you can add multiple files or directories at once:
$ git add <file-name> <file-name> <file-name>
Once you’ve added them, they’re staged ready to commit to your local git directory. To commit, you also add a commit message. I highly recommend reading this blog post by Chris Beams about commit messages. A good commit message is a thing of beauty and will save you future pain and heartache.
In a nutshell, think about the changes you’ve made and why. You won’t remember when you need to look at it next time! Running the following command will open up vim to write your message in. See the Linux Beginners Guide to Vim for more info but for a quick reference to get your message in:
Hit Esc
to move into Normal mode, I
for Insert mode (you need to be in Insert mode to type text) and from normal mode, type :x
to save and exit or :q!
to quit without saving if you’ve had enough and want to abort and try again.
$ git commit
Or if you only want to add a line, pass in -m
to type the message directly into the terminal.
$ git commit -m "Quick one line commit message"
And that’s it! You’ve staged and committed to your local git directory!
The next step is to push your changes to your remote.
Working with remotes
Your remote is the remote server, GitLab or GitHub for example. To see what remotes you have set up, run:
$ git remote -v
You should see the URL of your GitLab repo, called your origin. For more information about the remote, run:
$ git remote show <remote-name>
If you’re working on a fork of a repo, there will be two remotes listed. One for your fork and one for the original repo you forked. The next section covers how to sync your local repo with the original repo.
Add an upstream remote
It’s usual practice in open source projects to follow a fork flow workflow. This means there’s one main project, known as the upstream and anybody contributing to that project has a fork of the project. They do their work on their fork and only when it’s ready, do they request to merge that into the main project.
To keep your repo up to date, you need to merge it into yours regularly. This helps minimize any potential big messy merge conflicts and makes sure you have all the newest features and functionality.
To add main repository you forked as your upstream:
$ git remote add upstream https://github.com/<original_owner>/<original_repository>.git
If you run git remote -v
again, the new remote should be listed as your upstream. You can now keep your fork up to date with the upstream.
Firstly, fetch any changes in the upstream to your local repository so you can see which files have changed, this is good if you’re nervous about merge conflicts and would like to change anything before merging anything in.
$ git fetch upstream
Then merge the upstream branch into your branch so the changes in the fork repo are pulled into your branch on top of your files.
$ git merge upstream/<branch-name>
If there’s any merge conflicts, they’ll be raised here so you can resolve them before making a merge commit.
This can be the master branch but there’s is typically a development branch that you will be raising your merge request into when your changes are ready. Reading the projects contributing guide will tell you how that works.
Typically, you’ll want the development upstream branch to stay up to date with your development branch and then you can branch off the development branch for your new feature branch and regularly merge the development branch into your feature branch if required so you can resolve any merge conflicts that arise there and then.
To track the upstream development branch in your local development branch:
$ git checkout -b <develop-branch> upstream/<develop-branch>
Pushing to a remote
Your changes are still only saved locally and need to be pushed up to your remote to be backed up properly and available for others to pull down and get your changes.
To push, you need to specify where you’re pushing to. Everything that’s been committed will be pushed. You can have multiple commits per one push or one commit per push - it’s up to you.
$ git push origin <feature-branch>
You can optionally set this branch as your upstream by adding the -u
in before the branch name. Then your local git knows it’s tracking the remote branch you give it, then you can run $ git pull
or $ git push
without needing to specify the branch name each time.
$ git push -u origin <feature-branch>
Remember there’s always help
Never forget your friend, -h
$ git checkout -h
There’s a huge git community and loads of helpful resources online. And you can always ask me if you need help 🤓