Git — The Art of Working Together Alone
Git. As a computer science student, surely you have used, known, or even heard about it. But for those who are living under a rock, this will be a quick start guide for you.
Git(s)? Like a standalone complex or something?
Git is a distributed version control system. Version control is the practice of keeping track of changes of something, in our case, codes for our works. Git doesn’t only keep track of changes, it also records old version for backup and rollback, so a mistake is easily mendable, hence the name “version control”.
Git also helps us work with other developers, and in parallel at that. Let’s say we have an application stored in a folder on your computer, git calls this folder a repository. Git then can help you upload this local repository to a central hub that host that repository online, this is called a push. Other developers that have access to that hub can then download the online repository to make their own local repository, this is called a pull. They then can make changes to their local repository and save their work when they’re done, this is called a commit. After that, they may also do another push to help deliver the update to everyone so that they too can download it. The cycle would repeat.
So with Git, you get two levels worth of repositories. You may ask why, well let’s say you worked really late at night and did a commit. Next morning you wake up to see what horrible abomination you just wrote last night, you can take that commit back before you embarrass yourself in front of other people, isn’t that great?
From 0 to 1
So, how do you exactly use this Git thing? Well I assume you have an online repository platform ready and git installed on your computer first. If not, you probably should go read up about Github. To start a local repository, pick a folder first, preferably empty, then you can do:
git init
This will create a .git folder inside that folder. You may not see because it’s hidden by default, but it’s there.
After that, you can freely add files or change files inside folder. Let’s try adding a text file. So how do you actually see the version control in action? You can use:
git status
So the file is on our working area, but not yet permanently in our repository, you can tell because it’s red. To add it, you have to use:
git add ghostinthe.txt
# Or alternatively
git add . #This command adds ALL updated files
Then we can see our status again
This new file is now in what’s called a staging area. In this staging area, the file is ready to be committed into our repository, but not yet there. This serves as a doubly safety pin. We can then fully commit to adding the file with:
git commit -m "Message here"
So what is the “message here”? This is where you summarize what changes you have made to the repository. Why must you do this? It’s so that you don’t forget what you have done and where, so if you ever want to roll back, you know exactly where. We can see our commit history with:
git log
With this, you have committed a file into the local repository and it’s written in history. This of it as a history in a tab of your browser, every click is a commit, but you can always click back to get back.
Now, how do we upload this to an online repository? Well, first you have to set one up, I’m not going to cover it in this post, but I use GitHub in this example. First, let’s connect our local with it with:
git remote add "name" "link"
What is a remote though? A remote is just a location where we can push our local repository to. So wait, you can have multiple remotes? Yes, of course!
Success, we are linked! But now how do we push our local? Well, it’s in the name, we do:
git push "remote_name" "branch_name"
Wait, what is a branch name? Well, a repository can actually have multiple different versions too! Wow! Different versions can be separated into different branches. When we create a git repository, we always create a branch called master. So for the meantime, we’ll push to that!
Success! We have pushed our local repository to the online repository. It tells us how many commit we have done, and when we did it too! But now, what if another person wants to get what we have worked on?
From 1 to even greater
Imagine we’re on someone else’s computer, we want to have access to ghostinthe.txt, how? Well, there’s a couple ways to do it. The first one involves using:
git clone "repository_link"
Repository link being the same link you used to connect us the the online repo. Here’s an example!
Now we got a mirror of our first repository on a folder, superb! The second way is to do repeat the steps of starting from 0, but instead of add, committing, or pushing something, we do a pull with this code:
git pull "remote_name" "branch_name"
Voila! This also ties in to pulling as a way to get changes. You see, if a developer push to the online repository and you want to get it, just simply do a pull!
Work Together Alone
Say you have two development team, a frontend and a backend one. Both of them works on the same repository, but the frontend team doesn’t want to keep pulling the backend team’s work, cause frankly, it’s annoying. Git has a solution for this, branches!
We said before that when you create a repository, you’ll automatically create a master branch, but then, you can add more branches to separate each online repositories. To create a new branch, you simply have to:
git branch "branch_name"
Then, to move to that branch, you have to:
git checkout "branch_name"
To see all the branches in a repository, you have simply can use:
git branch
Sometimes, a branch might not show up if you start from 0. If so, you may do:
git fetch
Let’s see all of these commands in action
You can also use another command to bundle a branch + checkout:
git checkout -b "branch_name"
With this the front end guys don’t have to see the backend guys’ stuff. But wait, what if we want to combine the works done? Well, you use:
git merge "branch_name"
This combines the what exists inside a branch name into your current branch. Note, the flow must be correct if you want to do it correctly!
Phew, now all those backend and frontend guys can finally relax in their own little locked room. Sometimes, there’ll be conflict over a file during a merge, you can solve this by picking which version of a file you’ll pick, or even combine both! Git is smart enough to combine simple ones, but for advanced ones, unfortunately machine hasn’t come that far.
Now, there is another way, a weird one, to combine two branches. It is called rebasing. Rebasing is a way to move the start of one branch and plant it on the end of another. This is done by making the other branch like an extension of the former.
To do this, you may do:
git rebase "branch_name"
What this will do is the same thing as merge, rebasing the branch you supply the name of to the current branch. Let’s look at an example.
Looks the same right? Because it mostly is, The only difference again is how it looks as a tree when you have visualized it. As seen in a few pictures above. So when should you use rebase? According to Atlassian, you should only rebase on private branches, then do merge on public branches. What about my opinion? Then you should just stick to merge instead of rebase!
Saving and Loading
Well, as I’ve talked about in this article, you can take back a commit, but how do you do that exactly? This is where you get your git log and start sniffing!
I see that you have made 3 mistakes in the commits, and you want to rectify them, go back to the good old days of added newfile. Well don’t worry, we can undo a commit with:
git revert "commit_hash"
Wait, you lied to me! Why does this add more commits! Well, git revert pushes an inverse of what a commit is. Say if you add a file, you will delete that file in the inverse. Basically a reverse of what you did.
What if you want to delete multiple commits though? Well, to do that you can:
git reset "commit_hash"
This will actually remove the commits from your logs! Hurray!
Now no one can see what horrible mistake you did! Great job! But this happened because you committed that change anyway! What if you’re working on something but don’t exactly want to commit it just yet, but you also have to switch branches? Well, you use git stash! Stashing is yet another redundancy git has to lessen mistakes. How to stash you ask? Well, you simply have to:
git stash
This stores your updates in a secure location until you get back to it, you can see the list of all stashes with
git stash list
Now how to get the file back? Simply do:
git stash pop
Excellent! Now we have a quick save and a way to load our previous saves!
Feel The Flow
Now if you’re already familiar with git and just scrolled down to see what this article is about, this is the section that you need to read. Every project that uses git has their own style of working, but to help serve as a blueprint for all future project, there’s something called “Gitflow”.
Gitflow is a series of stuff you may apply to your project to have benefits that have been proven at least empirically by some. Gitflow is also what my team use for our current PPL 2021 project. The basic gist of a Gitflow is to separate branches according to their use.
According to atlassian, Gitflow needs:
- A branch sourced from master called develop
- A branch sourced from develop called release
- Branches of separate features you may add sourced from develop called Feature-x
- Whenever a feature is completed, it’s branch gets merged into develop
- Whenever the release branch is done, it gets merged into develop and master
- Whenever an issue is detected in master, a hotfix branch is created to fix the issue and gets merged after it’s done to both develop and master
Of course, these are just blueprints. There’s no set convention of what steps must be done in a Gitflow. For our project, we call the develop branch “staging” and call each feature branch “PBI-X”. We don’t have a release branch and we merge some features together that are dependent. We even have some small branches from some features. Quite different from original, no?
Now what does this achieve in our project? This enables us to do a few things. First, in increases our effectivity and efficiency. Now I know that sounds cheesy, but our team is very unique, we code together on discord. We find that it’s best to code together, so we code a lot on the same time. Introducing Gitflow to the mix means we no longer have to worry about each others code interfering with one another!
Second, it also enables us to test various stuff in our code separately. We use continuous integration (which I will explain in another article), meaning once we push, the machine would automatically test and deploy our codes. Using gitflow, we can make sure that we deliver the best code as only we are responsible for the current branch. This also means that I don’t have to wait for the other person’s code to be tested before mine and can fully focus on my own!
Third of all, it’s neat to look at and identify things… at least in theory. You see, even in a small project, hundreds of commits can be created in a single sprint. Once you get enough commits, especially with TDD’s red green refactor method, it gets confusing. But fear not, git has an extra feature! It’s squash commits! Squashing combines every commit on a merge into one, leaving it extra tidy!
And those are among few of the many advantages of Gitflow! With this article, I hope you learned something and got inspired to finally use git. I know it can be hard to swallow sometimes, but you have to lose your gag reflex one day, right? Happy coding.
References:
https://www.atlassian.com/git/tutorials/