A Tutorial on Git and GitLab
As a (relatively new) software engineer at Ginkgo, I find myself intrigued and excited about everything there is to learn about software, working with a team of brilliant engineers, and the amazing problems Ginkgo solves on a daily basis. Amidst our COVID-19 efforts, I have learned it is imperative to understand the basics of version control systems, Git, GitLab, and processes specific to Ginkgo. My experience with Git and GitLab began about a year ago during my time in an immersive software engineering bootcamp. I thought I knew what I was doing. Fast forward to March, and I’m faced with the daunting task of rebasing. Through trial and error, I learned Git tips and tricks that I think would benefit a wide range of software engineers; whether you’re just starting out, a seasoned engineer, or someone who likes to have reassurance when working with sensitive code. Below, I will outline how Ginkgo uses Git and GitLab, as well as the common issues that a software developer might encounter when working with these systems!
First, you have to speak Git. Let’s start with basics, words you’ll hear in most team interactions.
What is Git?
Git is an open source, distributed version control system used for tracking changes in source code during software development. This basically means it manages changes to a project in a structured way, to coordinate changes made by different developers to the same code. Git uses repositories to store information. Repositories are storage spaces or directories in which your projects can live.
Why do we use Git?
Git simplifies the process of working with other developers on a team. After team members work on different features, they can merge their changes to a common branch, typically called the master branch.
What is a commit?
After you make any sort of change, a commit essentially takes a “snapshot” of the repository, with the changes you’ve added. The commit then stores the changes you’ve made since the last snapshot, and commits from different users can be seamlessly compiled as long as the two commits do not touch the same lines of code.
- Install Git. How to: https://git-scm.com/book/en/v2/Getting-Started-Installing-Git
- Obtain access to GitLab. We use GitLab CI to build our Python packages and Docker Images and to deploy them to our development and production environments. See: https://about.gitlab.com/
git clonerelevant repositories.
git clonecreates a copy of the specified repository which you intend to make changes to. For example, on your command line, make sure you are in the appropriate directory. For this example, I created a new directory called “testing” using the command
mkdir testingGo to your GitLab project and click on the “Clone” button, which should be on the upper right hand. From the dropdown, click on the “Copy URL” icon under “Clone with HTTPS”
- From your command line, run the command
git clone <url>, where the
<url>is the URL you just copied. That’s it!
For more information, visit this site.
Why do we use branches?
Branches represent a new, independent path of development. At Ginkgo, the “production’ version of code is also known as the “master branch.” It is important to use branches so that you don’t make inadvertent, untested changes to production. Other developers are also simultaneously branching, too. When you’re done, you “merge” your code into the master branch. Other developers do the same. More on that later.
git branch in the appropriate repository to view a list of existing branches, as well as the current branch you are on.
It is important to use a descriptive phrase with dashes between words when naming a new branch. For example, if you are working on adding a navigation bar to the UI of an existing project, you could name the branch something like “add-nav-bar”. This way, other developers on your team can understand the change you have made, and it helps with tracking in the future.
Note: Each team is different! Make sure you check in with your team about naming conventions, commit message conventions, etc.
Sometimes, you might find that you want to change the branch name to be more reflective of the code changes. In this case, you might want to rename your branch. To do this, run the following commands on the current branch:
git branch -m new-renamed-branch
Let’s say you want to check out a new branch, but you have uncommitted changes on the current branch you are on that you want to completely discard. If you want to ensure that those changes don’t get carried over to the new branch, run the following commands:
git reset --hard– This resets all of your local changes to the last commit.
git checkout master– This allows you to “check out” or navigate to another branch. In this case, it’s the master branch.
git pull --rebase– This essentially fetches upstream changes and rebases your branch.
git checkout -b new_branch– The
-bin this command creates a new branch off of the branch that you are on.
Submitting Merge Requests
What is merging?
Merging allows developers to integrate their individual changes to a single branch. In our case, this would be the master branch.
How do I submit a merge request?
To submit a merge request, ensure you have added all of your changes using the following commands:
git add -u– This command only adds changed files that are already tracked by git. It is usually recommended to add files individually, so you’re not faced with accidentally committing secrets or random files that you didn’t intend to.
git commit -m "your commit message"
git push origin your-branch-name
After pushing your changes, your terminal should provide a link to create a new merge request. Visit this link, and follow the steps below:
Keep every merge request specific to one change. Before pushing your branch and submitting an MR, run
git diff master to ensure that your branch only has the specific feature/change you intended
The GitLab CI/CD (Continuous Integration/Continuous Development) is a system that can be used for code deployment and development. GitLab uses pipelines to run jobs (instructions for a runner to execute and compile code) that get executed in stages. After pushing changes and creating a new merge request, make sure the pipeline succeeds before assigning a code reviewer.
What is rebasing?
Rebasing integrates changes from one branch into another. You typically do a rebase when the master branch is ahead of your branch, and you want to integrate those changes into your branch. Rebasing differs from merging by rewriting the commit history in order to produce a straight, linear succession of commits. Often, if you see a message in GitLab that says “There are merge conflicts”, it is likely that you need to rebase your branch.
Let’s say you’re working on adding a new feature to a project, and another developer on your team is simultaneously working on a different feature (in a different branch). It is important to note that your branch will not be up to date with the master branch if your teammate merges their changes before you. If this is the case, however, we use a setting in GitLab that ensures branches are up to date with master before merging, so we need to rebase when others have made changes to master.
How do I rebase?
To rebase your branch, follow the below commands in the appropriate repository:
git checkout master
- Switch to branch (i.e.
git checkout your-branch-name)
git rebase -r origin/master
The following lines are only necessary when there is a rebase conflict:
- Resolve changes in files that are highlighted.
git add -u
git rebase --continue
Continue following the above steps until rebase is successful. When pushing to Gitlab after rebasing, you’ll need to use
git push --force-with-lease origin your-branch-name. Don’t be alarmed, this is normal! This is important because otherwise it could overwrite someone else’s work.
Mess up? Here’s what to do
Oh no! You’ve accidentally committed changes that you didn’t want to! What should you do next?
One way to undo the last commit is to run the command
git reset HEAD~1. Additionally, if you’d like to undo a few commits, you may change the “1” in the above command to specify the number of commits you’d like to reset back to.
What if I want to undo everything I’ve done in my branch?
Use the command
git restore to undo everything. If you’ve staged something and want to unstage it, run
git restore --staged foo, where
foo is a file name.
What if I want to reset the whole branch to the last commit?
git reset --hard resets the whole branch to the last commit — be careful doing this! It will undo all of your changes.
Merging your branch should only occur after it has been reviewed and approved by another developer on your team. Different teams have slightly different conventions for approval, so make sure to check in with your team! When submitting a merge request, it is good practice to select “squash commits” and “delete branch after merge” on GitLab, as shown below:
Squashing commits results in a clean Git history which improves readability for your team. For example, say you have a commit history like so:
428239482hfs2... Added new UI feature, JIRA #321 1381ndj1o193... fixed error in failing test 32891njk189... small typo fix for other failing test 289b3kj723... made suggested changes 327823jfds89… hopefully this is the last! 382nvs328h... implemented small feature 923n9ds9824... last code iteration
Well, that simply gives me a headache to look at. Instead, after squashing your commits, the commit history will look something like this:
428239482hfs2... Added new UI feature, JIRA #321
When you are ready to merge, GitLab provides a “merge” button on the merge request. It is best practice to use this button!
After merging your branch, follow the steps below to update your local repository:
- Switch to master branch locally by running
git checkout master
- Delete branch locally using <code>git branch -d branch-name</code>
Things to Keep in Mind/Quick Checklist
- Always checkout a new branch from the master branch. To do this, follow the steps below in your terminal in the appropriate repository:
git checkout master
git checkout -b your-branch-name
- Forget a Git command? Run
git helpto view a list of the 21 most common Git commands.
- Git tips: https://about.gitlab.com/blog/2020/04/07/15-git-tips-improve-workflow/
- Git aliases: https://git-scm.com/book/en/v2/Git-Basics-Git-Aliases – Git aliases are useful because they allow you to do less typing — efficiency is key in development! i.e. using “git co” instead of “git checkout”.