This article was written as a submission of CS UI’s software development course’s article task.
In tech, generally, there are more than a few approaches to solve a problem. Whether it be paradigms, frameworks, or languages, what is deemed “best practice” might vary significantly from team to team. However, pretty much everyone agrees that version control is a must when it comes to group projects. One of the most popular version control software out there is git, made by none other than Linus Torvalds, the man behind linux.
If you’re new to git, you can use this article as a cheatsheet of sorts. The very basics of git, compressed into one article, just enough to get you started. Without further ado, let’s go over the basic commands and features of git.
Assuming you’ve installed git (which is pretty straightforward, learn more about it here), there are a few commands that you’re constantly going to be using when you’re using git.
First, we need to set a working directory for your project files. You can do so by simply running this command.
After you’ve made a repository on something like gitlab or github, you would get a link that can be used to access your repository from your local git repository. To do so, you have to add that repository to your local “remote” variable. You can have more than one remote variables, but for this example, we’ll stick to having just one.
Similarly, if you want to add an already existing repository as your remote, you can simply add said repository’s link to your remote variable.
git remote add origin <link-to-repository>
Should you want to “pull” from an existing remote, you can now pull from the remote you set, by using the git pull command.
git pull origin <branch>
Fill “branch” with the specific branch of the repository that you want to pull from. Usually, you’d want to pull from “master” when you’re just getting started.
If you just want to get a working copy of the remote repository, then you don’t have to bother setting up a remote variable at all. You can simply utilize the git clone command to get a copy, and you’re set.
git clone <link-to-repository>
Getting to work
Now, we’re gonna talk about how you can actually work with git. After you’ve done the setup phase, your repository should now be connected to a remote repository that you can push your changes to (assuming you have permission) to save and share your work.
Before we start committing and pushing things, it’s important to get the gist of how the workflow of git works. First, your local repository (that you initialized with git init) is called the working directory. You then have to add your changes to the staging tree, and then commit that tree to point to the latest commit.
To make things simpler, let’s use a metaphor for each part of the process. First, you have to add the changes to the staging tree. You can do that by using the following commands.
#Adding a specific file to the staging tree
git add <name-of-file>#Adding all changes to the staging tree
git add *
You can think of using “git add” as putting things inside a box that you want to send. Should you want to take something out of the box, you can use “git rm” to remove that specific file out of the staging tree.
#removing a specific file from a staging tree
git rm <name-of-file>
You can also check all of the files that you’ve changed, and whether or not they have been put into the staging tree by using “git status”.
#Checking the status of files that you've made changes to
Next, you need to commit that staging tree. You can think of the act of committing as packaging the box that you’ve put things into, so that it’s ready to be shipped/mailed. The “commit message” that you put is akin to a post-it note that you stick on the box describing what’s inside.
#Committing your changes
git commit -m "<message of commit>"
Next, you can ̶m̶a̶i̶l̶ ̶y̶o̶u̶r̶ ̶p̶a̶c̶k̶a̶g̶e̶ push your commit into the remote repository! but first, just like mailing packages, you need to specify an address. “But I thought I specified an address already when I setup my remote?”, you ask? think of that as specifying which building you want to send your package to, but in this scenario, you also have to specify which floor is your recipient.
Now what do I mean by floors? Well, branches are sub-addresses in a remote repository that are independent from each other; kinda like how floors are in a building. However, while floors in a building have nothing to do with other floors, branches (while independent) always has a relationship with at least one other branch. Branches are derived from other branches, and (usually) will merge with the main branch of the repository to implement the changes that were made (in that specific branch) into the main branch.
You can create a new branch by using these commands.
# Creating a new branch
git branch <name-of-branch>#Switching to a different branch
git checkout <name-of-branch>#Shorthand of above commands (create new branch and move to it)
git checkout -b <name-of-branch>
When you use the above commands, a new branch will “split” from the branch that you’re currently on; meaning that the new branch is derived from your current branch. Another important thing to note is that when you switch branches, git will reset your working directory to the state it was in when you last made a commit in that branch. So don’t be surprised when your files change if you switch branches!
If you decide to merge your branch with another branch, you can do so with the command “git merge”. But, naturally, conflicts may occur when you’re trying to merge two different branches. To make this process as smooth as possible, I recommend you do these sequence of commands.
#Pull the latest commit from the target branch
git pull origin <target-branch>#If conflicts occur, find where they are
git diff <source-branch> <target-branch>#Resolve the conflicts. Then add them to the staging tree
git add .#Finally, you can merge.
git merge <target-branch>
There’s also an alternative to git merge, git rebase. While git merge merges a source branch to a target branch, the source branch of the operations does not change in any way, safe for a “merge commit” if necessary. git rebase, on the other hand, appends the source branch to the target branch; effectively making the commit history linear. To illustrate this better, here’s a diagram of git merge and git rebase, respectively.
As you can see, git merge will make a “merge commit” that combines all commits from the source branch, while git rebase will simply move all the source branch commits into the target branch.
Now that we know what remotes and branches are, we can finally push the commit that we made in the “getting to work” section. To do that, you can simply use the command:
git push origin <name-of-branch>
Your changes will then be pushed to remote repository’s branch of your source. One thing that’s important to note is that if your working directory is behind the latest commit in the target remote repository’s branch (likely to happen if other people are working and pushing to the same branch as you are), then you have to update your working directory first so that it corresponds to the latest commit. You can do so by using “git pull” before pushing (git will tell you if your working directory is behind the latest commit and prevent you from pushing).
And that’s it! You can now start working with git. Other commands that you are likely to use are:
#Stashing your changes
git stash#Applying stashed changes
git stash apply
“git stash” stashes your work, and can easily apply them again when you want to. Useful when you want to save your current working directory without making a new commit (for example, when you want to switch to another branch but want to save your work).
#Check commit history
git log#Undoing a commit
git reset --soft <commit-hash>#Undoing a commit and resetting all changes made after that point
git reset --hard <commit-hash>#Making a new commit that undoes all the changes of a commit
git revert <commit-hash>
These commands are useful when you want to undo a specific commit or revert to the latest stable commit. Note that “git reset- -hard” will delete all the commits that come after the chosen commit, while revert will make a new commit without touching the other commits.
Git Implementation in My Project
For my team’s project, we use git for version control and file managing. For every feature that we implement, a branch is made that corresponds to said feature.
If a feature is completed, than that feature’s corresponding branch will merge to staging. At any given time, the flow of our branches’ lifetimes look somewhat like this:
Obviously this is just a small piece of the entire graph, and at busy times like the days before a sprint review there are significantly more merging than usual, but that picture represents most of the graph well enough.
For every merge request, the team gets together to review the changes made in that branch and review the code that has been submitted.
This way, we can make sure that every branch that merges can be integrated easily into the main branch, and that code quality can be up to standards. This saves us tremendous time in debugging and making things compatible with each other, which we can now allocate to implementing more features or refactoring.
That’s it for this article. I hope you’ve found this useful and helpful in some way. Thank you for reading!