Git 101
Git, created by Linus Torvalds, the Linux Operating System creator, is a distributed version-control to track changes in the source code during the software development process. Its goal is to coordinate everyone’s work in a single repository.
Basic Commands
Before we dive deeper, let’s first understand the basic commands for git. First, we must install git. Refer to this website to learn more. When the installation is completed, we can now proceed to use the commands.
- git init, used to turn an existing directory to a git repository
- git clone, download an existing repository including all of the files, branches, and commits
- git pull, to update your current local repository with all new commits from the corresponding git repository
- git push, upload all local commits into the git repository
- git merge, combines two branches into one
- git rebase, combine a sequence of commits to a new base commit. Usually when we change our working branch, any changes that has been made won’t be available on that branch. Therefore, I used it when I want to checkout the branch while still bringing all changes from the other branch.
- git revert, used to undo all of the changes made in a commit
- git statsh, to reset all changes in the local repository
- git remote, allows you to connect with remote repository
- git checkout, switch to the specified branch and updates the local directory
- git reset, undo all changes
git rebase illustration
Supposed that I currently have two branches: master and dev-Surya (current branch: master) and supposed I make some changes in the master branch and pushed it to my remote repository.
We decided to change the working branch to dev-Surya (we want to make the master branch cleaner).
As we can see, the title changed because the dev-Surya branch didn’t have any changes applied from the master branch. Therefore, to ‘bring’ the changes from the master branch, we can use git rebase.
After we execute git rebase, the dev-Surya branch now have the same title.
Further inspection conducted, git merge will actually create an additional commit that ‘combines’ all commits behind that branch. Previous commit history will be preserved .
While git rebase will move the commit from one branch to other without creating additional commit. For example, here I want to merge the branch master with dev-Surya
After I execute git rebase then push to dev-Surya branch, it doesn’t add any new commit. Instead it moves the commit from the master to dev-Surya branch.
Here I provide an illustration to help you understand the difference between git rebase and git merge:
In my opinion, git rebase is very useful when you’re working on a small project or a project where it consists only few people (one or two). It’s easier to keep track the commit and also to keep the branch clean from the ‘merge’ commit. But if you’re working on a big project, I don’t recommend you using git rebase since it doesn’t preserve previous commits and people tend to forget what they did. Therefore, it’s easier for many people to keep track the commits via the history with git merge.
git revert vs. git reset
From my personal experience,
git revert is used when I mistakenly commit and push something I didn’t meant to. It will undo (or delete) all changes that has been made before. Gitlab provides us a simple button to revert a commit. Simply head to the commit that you want to revert, click the options button on the top right corner, then choose ‘Revert’.
git reset is used when I want to undo all changes locally (to make the working tree clean) and also when I want to undo a commit (but not yet pushed). There are two options for reset:
- --soft, used when we want to undo a commit but still want to keep the changes that has been made.
- --hard, used when we want to undo all changes and undo a commit where we don’t want to keep the changes.
Git Flow
A pattern that helps the team to track changes that happen in their code easily. This makes the master branch cleaner (for deployment purpose) and sets a better release version.
Branches
Master branch or the main branch
Stores the source code that is ready to be released or deployed into the production environment and ready to be used by the user. It’s a protected branch that only Git master can make changes (push, merge, merge approval).
Staging branch or the development branch
Stores the source code from every member of the team (also used for the sprint review).
User story branch
Stores the source code of a user story’s implementation (there will be several user story branches).
- Name Convention: <your_first_name>-<user_story_number>-<user_story_title>
- Example: Surya-1-user_registration
Hotfix branch
A branch from the master branch, for bug fixing or error fixing in the master branch. After it’s resolved, it will be merged into the master branch.
Coldfix branch
Made for rollback or delete all changes from all user story branches. This can happen if the product owner rejects the user story developed (the development team must revert the rejected user story in the staging branch, after revert, make sure that all tests still passed).
- Name Convention: coldfix-sprint-<sprint_number>
- Example: coldfix-sprint-7
Flow
Step a, initialize master and staging branch in the repository
Make sure that the repository has a master branch already. After having approval from the product owner, the Git master can merge from the staging branch into the master branch.
Step b, initialize user story branch to do the implementation
Every user story in every sprint is our objective. The development process of a single user story will be done in one branch only.
Step x, TDD discipline during the implementation
We are required to conduct the TDD discipline. Few things to consider during the TDD process:
- Make sure that there’s a commit represents that you’ve created a new file (the file can have content inside it)
- At least one commit after implementing the unit test of a function (usually marked with [RED] tag).
- At least one commit after implementing the function to pass the unit test (usually marked with [GREEN] tag).
- At least one commit after refactor implementation (usually marked with [REFACTOR] tag). Make sure that refactoring doesn’t affect any function and make the test to be failed.
- Use [CHORES] for every implementation not related to the functionality (adding some assets, etc.).
Step e,f,g,h, adjustment of the staging branch to be merged with the master branch
During the sprint review, we will demonstrate all of our implementation from every user story given in one sprint. It will be easier if an automatic deployment script equips in the staging branch.
In-Depth Flow
Repository initialization
- Create a new repository (git clone)
- Use an existing directory to be a repository (git remote add origin)
- Connect with a new repository (git rename origin old-origin then git remote add origin)
Create a staging branch
- View branch (git branch -v)
- Make sure to checkout to master first (git checkout master)
- Create branch (git checkout -b staging)
Create a new user story branch through the staging branch
- Make sure to checkout to staging first (git checkout staging)
- Create branch then checkout (git checkout -b Surya-1-user_registration)
Merge the user story branch with the staging branch
- Create a new merge request with the user story branch as the source branch and the staging branch as the target branch.
- Make sure you already pull from staging branch before developing a user story, then resolve all conflicts.
- Make sure the Gitlab pipeline is green (all tests have passed).
- Uncheck the “Remove source branch” checkbox to prevent deleting the user story branch after merge.
- Perform “Squash Commit” when merging, to simplify the revert process on the coldfix branch.
- At least two team members must review the code before it can be approved.
Revert technique for committing merge results
Supposed that UserStory-1 is rejected by the product owner in the sprint review, then you must revert the commit in the staging branch into the coldfix branch. To do that:
- Checkout to new coldfix branch (git checkout -b coldfix-sprint-7)
- Revert the commit in staging branch (git revert -m <parent_number> <merge_commit_id>)
Deliver the app release
Do a merge request from the staging branch into the master branch, give a tag by the number of the sprint with the command git tag -a sprint<sprint_number> master.
References:
- IT Project 2020 Git Guideline
- Git Cheatsheet by Atlassian and training.github.com