Git Basics
Using Git for version control and collaborating with your teammates is a fundamental part of this course. Git enables you to manage your code efficiently and share it professionally.
Key Benefits of Git
- Version Control: Track code changes and revert to previous versions when needed
- Team Collaboration: Share code and conduct peer reviews seamlessly
- Easy Submission: Submit assignments via repository links instead of large zip files
- Professional Portfolio: Add your Git repositories to your resume to showcase your work
- Open Source Experience: Gain practical experience in open source development
- Cloud Backup: Maintain a secure backup of your code (GitHub offers unlimited storage for public repositories)
Core Git Concepts
In this section, you'll learn essential Git operations including:
- Basic Operations:
- Adding files to staging
- Committing changes
- Pushing code to GitHub
- Branch Management:
- Creating feature branches
- Working with pull requests
- Merging and rebasing code to the main branch
Make Your First Commit
TipIf you are on
macOS
, the Git client is already installed. You can check by runninggit --version
in your terminal.
OnWindows
, you can download Git from the official website: Git for Windows
We are going to use Fork
, a GUI client for Git, to manage our repositories. You can download Fork from the official website: Fork
However, you can still use the command line to interact with Git if you prefer. But Fork provides a more user-friendly interface for beginners.
Download the Fork client from the official website and install it on your machine.
Open your terminal (or git bash on Windows) and run git --version
to check if Git is installed.
Go to GitHub.
Click on your Avatar
and click the Settings
menu.
Click on the Developer settings
menu.
Click on the Personal access tokens
> Tokens (Classic)
or go to this
link
Click the top right corner Generate new token
button, and then click on the Generate new token (classic)
button.
You must select the repo
scope to access your repositories. Otherwise, you won't be able to push your code to
GitHub.
You are advised to select the workflow
scope as well to enable GitHub Actions and set expiration
to 90 days
or less
to keep your account secure.
Copy your GitHub
token on the screen. Note, you won't be able to see it again.
Open your terminal/git bash and run
git config --global credential.helper store
To store your credentials in the cache.
Run
git config --global user.name "Your Name"
git config --global user.email "YOUR EMAIL"
Keep in mind, use your GitHub assigned email, not your real email!
You can go to this link and copy the email from Email section. It should end
with @users.noreply.github.com
.
Create a new repository on GitHub, let's name it git-tutorial
.
Clone the repository to your local machine by running
git clone [repository-url]
Replace the [repository-url]
with the URL of your repository.
Create a readme.md
file in the repository and add some content.
Open the repository in Fork
You will find the readme.md
file is in the Unstaged
section. Click on the file or cmd+a
to select all files
and click on the Stage
button.
Add a commit message and click on the Commit
button.
And now you can see your commit in the Commits
section. Click on the Push
button to push your code to GitHub.
WarningYou may be ask to enter your
personal access token
you generated earlier.
And lastly, click the Push
button to push your code to GitHub.
And now you can find your repository on GitHub with the readme.md
file you created. If you have any question on Authentication Failed
error, you can check this link
for more information.
Git Commit History
Git repositories are structured like trees, where each commit represents a node connected to its parent commit(s). This creates a branching history that tracks how your codebase evolves over time. We will guide you step by step to visualize the main concepts of Git.
Branches and Main Branch
Just like a tree, a Git repository consists of branches that represent different versions of your codebase.
Usually, it represents different features or bug fixes that you are working on.
Some open source project may also have some release
branches to keep track of the stable versions.
For example, release/1.0
, release/2.0
.
The main branch (historically called "master", now commonly "main") serves as the primary branch
Each branch is a pointer to a specific commit
Multiple branches can diverge from main to develop different features independently
Every commit stores:
- A snapshot of all tracked files
- Author information
- Timestamp
- Commit message
- Reference to parent commit(s)
Since it stores the reference to the parent commit(s), it means
We have the ability to (hard) reset to any previous commit.
WarningHard reset: This operation is irreversible and will remove all the commits after the selected commit.
Use this operation with caution.
Or check out to any previous commit to see the code at that time.
Branches are essential in Git to manage different versions of your codebase. It enables us to:
- Create feature branches for new development
- Merge completed features back to main
- Delete obsolete branches to maintain cleanliness
- Use tags to mark important versions/releases
But managing branches can be tricky and lead to conflicts if not done correctly.
Merge and Rebase
Merge and rebase are two essential operations in Git. They help you combine changes from different branches and maintain a clean commit history. Below are some best practices to follow:
Rebase is a powerful operation that allows you to integrate changes from one branch to another by moving, or rebasing, the commits to the target branch.
It will produce a linear commit history, making it easier to understand.
NoteMain branch is in purple color and feature branch is in rose color.
And just like the name suggests, it will rebase your commits on top of the main branch.
You can see from the diagram, the commit C
is originally on the same level as D
,
but after the rebase, it is the child of D
.
Squash and rebase is a very popular operation in open source projects.
Unlike regular rebase, squash and rebase will combine all the commits in your feature branch into a single commit.
Usually, the squashed commit message will be a summary of all the changes in the feature branch. And links to the original pull request.
This operation is very useful when you have a lot of small commits in your feature branch. And you want to keep the main branch clean.
Merge is another operation that combines changes from different branches.
It will create a new commit that combines the changes from the source branch to the target branch.
For example, suppose we have commits A
, B
, and C
in the main branch.
And we have commits A'
, B'
, and C'
in the feature branch.
After merging the feature branch into the main branch, we will have a new commit M
that combines the changes from both branches.
The benefit of merge is that it preserves the history of both branches.
Which also means users can see the complete history of the changes. And it is easier to track down the changes.
However, in a large project, the commit history can be very messy.
It is almost impossible to track down the changes in the commit history.
And that's why rebase is preferred in most open source projects.
In GitHub, you can also add branch protection rules
to require a linear commit history.
Which will prevent users from merging the feature branch if it has a messy commit history.
Best Practices
-
Work on a Feature Branch: Always work on a feature branch and create a pull request to merge your changes. Avoid pushing directly to the
main
branch. -
Limit Pull Request Size: Each pull request should not exceed 500 lines of changes. If it does, consider splitting it into smaller, more manageable pull requests.
-
Commit and Merge Frequently: Commit your changes often and merge frequently to minimize the risk of conflicts.
-
Use Conventional Commits: Write meaningful commit messages following the Conventional Commits standard, such as:
feat: add new feature
fix: resolve bug
- Prefer Rebase Over Merge:
Rebase helps maintain a clean and linear commit history. Use it whenever possible, especially for integrating changes from
main
into your feature branch.