In this series, I'll show you the basic workflow of how a team of developers use Git and Github / Gitlab to work and colab together.
If you aspire to be a developer but don't understand how all the Git, Github / Gitlab, development workflow stuff fit together and solving what problem, achieving what purpose, then this article is for you. I write this for the past me as a student years ago and for you to not have to go through all the struggle with Git I've been through.
More background on why I wrote this article
When I was in university, my professors / teachers taught me all kind of fancy theories and algorithm stuffs. From Assembly, C to OOP Java, to Database, to Network Theory,... they covered all and more. Memorize all of that? That's great, that's what a future software engineer should know.
But there was a rumor. Only when you start working at a company as an intern, that's when the real learning begin. People will pretend you know nothing, expect nothing from you and teach you every silly little stuffs.
One of that stuff is how to use Git.
If you search Google to try understanding what Git is and how to use Git, you're probably gonna be hit with a bunch of jargon and technical details that you not hope to understand. Hell one of my senior even send me an 8 hours course on Udemy on how to use Git. Damn how can you even begin to code if just understanding what tools you supposed to use would take a PhD?
Luckily that's not the case. Using a tool does not requires to know all technical details about it. It's more about knowing what problem does it solves.
So first, let's try to understand what problem we're facing. You don't want to use the wrong tool for the wrong situation.
What problem are we trying to solve?
Imagine you work on a group project to create a presentation. You create a new Google Slides in your Google Drive and share it to each other. To a team of developers, the Google Slides file is equivalent to the project, and the Google Drive is equivalent to Github / Gitlab. You can imagine Github / Gitlab is the Google Drive / Dropbox for developers.
But here come the next challenge. How to prevent someone in your group accidentally change your slides?
In the Google Slides world we have no way, but luckily in the development world we can achieve that with the combination Git and Pull Request (or in Gitlab is Merge Request).
Let me explain.
To solve the accidentally changed problem, imagine each time anyone want to the edit group's slide would have to do this:
- Create a copy of the group's Google Slides file
- Work on that copied file
- Ask the leader to review
- Only when the leader agree that the changes are merged into the group's file
This is wayyy complicated and messy in the Google Slides world, but luckily it's quite simple in the development world with the help of Git. You just need to know a few basic Git command.
But first, let's understand what Git is, what does it do and what problem does it solve. For now I can foreshadow a little bit:
- Download from Google Drive = git clone
- Make a copy of the file = create a new branch
- Upload to Google Drive = git push
- Ask the leader to review the changes = create new Pull Request (Merge Request)
- Download again to see the updated version = git pull
- 2 people change the same slide = conflict
What is Git?
Git is a software that you can install on your computer (like Chrome, VSCode, Team Viewer,...). You can go to https://git-scm.com/ to download and click a bunch of "Yes" to install it.
So what does Git do? From a simple viewpoint of me an ordinary developer, Git does 2 things:
- Versioning
- Branch
What is versioning?
Do you know that you can change back to an older version of a Google Docs file? Like if someone accidentally delete something important in a Google Docs, the whole team would frantically roll back to the last Friday version hoping to see that important thing is still there?
Git offers the same thing for developers. You can create a new version of your project or rollback to old version anytime you want!
Here's a simple diagram about Git versioning:
Create a new version
In the Git world, if you want to make a new version of your project, it called "commit". Each version has a message. Here's the command to tell git to create a new version:
git commit -m "Your message"
But before telling Git to create a new version, let's imagine you have to tell it which files has changed.
For example, let's say your project has one file index.js
. You change to content from console.log("hi there")
to console.log("hello there")
. First, you will have to tell Git the file index.js
has changed:
git add index.js
Then you create a new version with the message "change from hi to hello there":
git commit -m "change from hi to hello there"
To summary, there are 2 steps in order to create a new version of project:
git add
git commit -m
Why do we need to do the git add
? Can't Git automatically figure what files has changed to create new version with those files for us? Imagine this situation.
Let's say you have 2 files index.js
and main.js
. But you don't want to create a new version that include main.js
just yet. In that case you'd tell Git to just commit index.js
but ignore main.js
.
git add index.js
then
git commit -m "change to hello there"
The 2 steps git add
and then git commit -m
is for that flexibility.
This happens a lot in the "real world": you often have to change some config files in order to run the project on your local machine. You'd tell Git to only cares about the file that you actually coding on and ignore those config files.
Let's explains a little more about all the cool terminology people are saying: "staging" and "untracked files".
There are 3 kinds of files:
- The files you changed but not tell Git
- The files you changed and tell Git
- The files you already commit
When people talking about:
- Staging area: imagine that is "Files that Git knows is changed"
- Staging that file:
git add
that file - Untracked files: imagine that is "Files you don't tell Git that changed"
To show the all files are in the staging area and all untracked files, you can use git status
:
git status
Here's an example of mine:
On branch master
Your branch is up to date with 'origin/master'.
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: packages/solid-project/src/App.tsx
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: packages/solid-project/src/hooks/createWindowHeight.ts
This means that I have a createWindowHeight.ts
file that I've not yet tell Git about and an App.tsx
file that I already tell Git (git add
) but not commit yet.
From now, instead of saying "tell Git about what files has changed", I'll say "staging that file". What I said about git add
equals to "tell Git about what files has changed" is vastly simplify and definitely not technically correct. git add
is more like "I want you, Git, to care about the changes of this file". I told you that above because I think for "beginner", "imagine" it's equal is good enough. Now equip with basic idea and terminology you can read the Pro Git book at https://git-scm.com/book/en/v2 to really understand how Git works.
View all your project's versions
After understanding how to create a new version, next, let's talk about how to view all versions of your project. To see all versions your project has, use the command:
git log
Here's an example of my project:
commit 3f345bfcbbcbaf56f2b7a90a72fb6558a255d3df (HEAD -> master)
Author: Your Name <you@example.com>
Date: Thu Jan 30 00:53:33 2025
add examples
commit 67851c04de24214b25099cd5e3a128c06bd4551a
Author: Your Name <you@example.com>
Date: Mon Dec 9 13:44:31 2024
initial commit
Here's a diagram to explain it:
My project currently has 2 versions:
- Version 67851c04de24214b25099cd5e3a128c06bd4551a
- Version 3f345bfcbbcbaf56f2b7a90a72fb6558a255d3df
Currently I'm at the latest version 67851c04de24214b25099cd5e3a128c06bd4551a. That's what the HEAD means.
In previous diagrams, for the sake of easy-to-understand, I tell you "version 1", "version 2", "version 3", but Git uses unique string to label each version. Instead of saying "version 1", Git says "version 67851c04de24214b25099cd5e3a128c06bd4551a".
In fact, the string Git use to label each version is so unique that you can just take 5 - 10 characters of it for Git to know which version. For example, "version 67851c", "version 3f345bfc",...
From now I'll call those unique string "version hash".
Practice a little bit
Let's practice a little bit before going to the next section. We'll use the result of this section for the next section. If you don't want to type anything yet, it's fine. I'll draw a bunch of diagrams so that you can still understand this section without having to type anything.
First, let's create a new directory. I'll call mine simple-git-tutorial
.
Next, open a terminal in that directory and type:
git init
This command is to tell Git to start versioning all files inside this directory.
A little bit of extra information: when you git init
in a directory, git will create a folder named ".git" inside it to store all information needed to manage that directory.
Here's an example of mine:
If you're not seeing it on Windows, you might need to go to View and then turn on Hidden items to see it!
Next, let's add a file called index.js
with the following content:
console.log("hi there");
Now, let's create a new version of this project:
git add index.js
then:
git commit -m "add hi there"
To view all versions, type:
git log
Here's an example of mine:
commit e1c439a92efef55036a54250a8fa58d8db2e7981
Author: Your Name <you@example.com>
Date: Thu Jan 30 13:28:32 2025
add hi there
Let's practice again by changing the console.log
in index.js
file from "hi there" to "hello there":
console.log("hello there")
Now, let's create a new version of this project:
git add index.js
then:
git commit -m "change to hello there"
To view all versions, type:
git log
Here's an example of mine:
commit 56908bb558478bc61d7319b870beb459d9853ae1
Author: Your Name <you@example.com>
Date: Thu Jan 30 13:29:56 2025
change to hello there
commit e1c439a92efef55036a54250a8fa58d8db2e7981
Author: Your Name <you@example.com>
Date: Thu Jan 30 13:28:32 2025
add hi there
Here's a diagram showing what versions we have in our small project:
See a previous version
Now we can create a new version and view all version, let's talk about how we can see a previous version like in Google Docs.
In order to switch to any version, use git checkout
and then the version hash.
For example, if I want to see the version e1c439a92efef55036a54250a8fa58d8db2e7981, I'd use:
git checkout e1c439a92efef55036a54250a8fa58d8db2e7981
Since Git only need 5 - 10 characters of the version hash to recognize, I could have just use this:
git checkout e1c439a
If you open index.js
, you'll see the content change from:
console.log("hello there")
back into:
console.log("hi there")
That's great, if I want to return to the latest version, I can just plug in the latest version's hash with git checkout
like so:
git checkout 56908bb5
"But wait!", you said horrifyingly. In order to find the latest version hash, I have to use git log
. But my git log
does not print out the latest version anymore:
commit e1c439a92efef55036a54250a8fa58d8db2e7981 (HEAD -> master)
Author: Your Name <you@example.com>
Date: Thu Jan 30 13:28:32 2025
add hi there
Don't worry, just use git log --all
. Here's an example of mine:
commit 56908bb558478bc61d7319b870beb459d9853ae1 (master)
Author: Your Name <you@example.com>
Date: Thu Jan 30 13:29:56 2025
change to hello there
commit e1c439a92efef55036a54250a8fa58d8db2e7981 (HEAD)
Author: Your Name <you@example.com>
Date: Thu Jan 30 13:28:32 2025
add hi there
Tip: if git log
not showing all the results you needed, try to add --all
!
Now you can find the latest commit and switch back to latest version:
git checkout 56908bb5
Next, let's talk about a concept called "detached HEAD".
When you're using git checkout
to change to a version, the HEAD is point to that version. This is called "detached HEAD". You can imagine it's like the Git let us "preview" what the project looks like in that version.
Generally, you don't want to have a "detached HEAD" unless you really understand what you're doing. For now, to escape the "detached HEAD" mode, use:
git checkout master
master
here is the current branch we're in. I'll explain more in part 2 when we learn about branch.
Rollback to a previous version
If you want to rollback to a specific version, you can use git reset --hard
and then the version hash like so:
git reset --hard e1c439a9
But be really careful because this command will also delete all versions after that! git log --all
won't bring the newer versions back!
In fact, you should use git switch -c
and then the new branch name like so:
git switch -c new-branch-name
but again I'll explain in part 2 when we learn about branch.
.gitignore file
Next, let's talk about the famous git file: .gitignore
.
Have you ever seen this file?
What is the .gitignore
file and what does it do?
There are files and folders that you never want to include in any version of your project.
For example think about the node_modules
folder. As long as you have the package.json
and package-lock.json
file you can recreate the node_modules
folder exactly as needed anytime you want. Furthermore, let's imagine you use a Window machine and share your project with another guy using a Mac. Because he has a different OS, to run the project he'd have to delete the node_modules
and reinstall it again. But now if he git status
he'll see a bunch of changes in the node_modules
folder despite the fact that in reality he don't change a thing.
You'd only want to include things that absolutely necessary in your version.
To avoid accidentally git add
and git commit -m
that node_modules
folder, you can create a .gitignore
file with the following content to ignore the node_modules
folder:
/node_modules
Here are some of the usual .gitignore
stuffs in the wild:
.DS_Store
*.local
*.log*
node_modules
dist/
.vscode/*
!.vscode/extensions.json
.idea
Conclusion
Let's recap what we've learned so far:
-
git init
: tell git to versioning a folder -
git add
: stage file -
git commit -m
: create new version -
git status
: show all staged files and untracked files -
git log
,git log --all
: show all versions -
git checkout [version hash]
: see a previous version -
git reset --hard [version hash]
: roll back to previous version (careful when use this!)
That's the list of basic Git versioning commands that I use everyday.
In part 2 I'll talk about the next revolutionary feature of Git: branch, and in part 3 I'll talk about the full workflow.
Credits
If you like the cute fish that I'm using, check out: https://thenounproject.com/browse/collection-icon/stripe-emotions-106667/.
Top comments (0)