2021-10-01Simple Git
Git is a file history
version control tool. You can think of it as keeping a
backup of every change you make—no need to worry if you
mess something up. Git also supports simultaneous
collaboration among multiple people, making it ideal for
teams working on code together. You won’t lose your
unsaved work to someone else’s upload, and if a bug
appears, you can trace who introduced it. Open-source
projects can make their Git repositories public so
others can access the source code, and Git provides a
mechanism for others to contribute code to the
project.
1. Repository
A Git repository corresponds to a directory that
stores your project code. Changes made inside this
directory can be recorded and backed up. To create a new
local repository, use:
git init
This command turns your current directory into a Git
repository.
To download a remote Git repository (e.g., code from
an open-source project) to your local machine, use:
git clone <uri>
This creates a new directory named after the project,
containing the full contents of the remote
repository—including its complete history, so you can
view or revert to any previous version.
If you only want the latest code without the full
history, use the --depth parameter to limit
the number of commits downloaded:
git clone <uri> --depth 1
This creates a shallow clone with only the most
recent commit, reducing data transfer.
Git stores history in a hidden .git
folder inside the repository directory. This folder
contains all Git-related data, including history and
branches. Deleting .git erases all version
history and turns the directory back into a normal
folder.
2. Commit
If you only use Git to download code, the previous
section is enough. One of Git’s greatest strengths is
backing up change history, where each set of
modifications corresponds to a commit.
After editing files in your working directory, how do
you tell Git to save your changes?
2.1 Stage
First, you stage your changes to
mark which files will be included in the next commit.
You can stage files that are:
- Untracked: New files not yet in the
repository
- Modified: Existing files that have
been changed
- Deleted: Existing files that have
been removed
Check the status of your files with:
git status
For example, if you create README.md,
modify material/base.html, and delete
package-lock.json, the output will look
like:
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: material/base.html
deleted: package-lock.json
Untracked files:
(use "git add <file>..." to include in what will be committed)
README.md
Stage files using:
git add <file>
For deleted files, you can use either
git add or git rm.
git rm both stages the deletion and removes
the file from your working directory.
After staging, git status will show:
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: README.md
modified: material/base.html
deleted: package-lock.json
2.2 Commit
Once all desired changes are staged, commit them
with:
git commit -m <msg>
The msg is a short description of your
changes. If this is your first commit, Git will ask you
to identify yourself:
git config --global user.name <name>
git config --global user.email <email>
These details are attached to all future commits.
The full stage-commit workflow is shown below:
Stage-Commit
Workflow
If you need to fix the last commit (e.g., missing
files or a typo in the message), stage your corrections
and run:
git commit --amend
This overwrites the last commit instead of creating a
new one.
2.3 Restore
To unstage a file:
git restore --staged <file>
To revert a modified or deleted file back to its last
committed version:
git restore <file>
This permanently discards changes, so use it
carefully. Untracked new files can simply be deleted
manually.
The restore workflow is shown below:
Restore
Workflow
3. Branch
Here’s where it gets more advanced! Git supports a
non-linear workflow, which enables
powerful team collaboration. For example, you might be
building a new feature, then need to quickly fix a
critical bug on the main version, then return to your
feature while including the bug fix. Branches make this
possible.
A Git repository starts with a default branch called
master.
3.1 History
Git stores commits in a tree structure. Each commit
has a unique SHA-1 hash (a 40-character hexadecimal
string) that identifies it. Most commits point to their
parent commit.
Example commit history:
Commit
History
The HEAD pointer shows your current
position. New commits move HEAD and the
branch forward.
You can use a short prefix of the SHA-1 if it’s
unique, e.g., 6 characters.
View commit history:
git log
View a graphical graph of all branches:
git log --all --graph
3.2 Branch
Create a new branch:
git branch <branch_name>
The new branch starts at your current
HEAD.
New Branch
Switch branches:
git checkout <branch_name>
Now new commits belong to this branch.
Checkout
Branch
3.2 Merge
To combine changes from one branch into another
(e.g., merge dev into
master):
git checkout master
git merge <branch_name>
If the branches have not diverged, Git performs a
fast-forward merge with no new
commit.
If the branches have diverged (both have new
commits), Git creates a merge commit
with two parents.

If changes overlap, you get a merge
conflict:
Auto-merging main.c
CONFLICT (content): Merge conflict in main.c
Automatic merge failed; fix conflicts and then commit the result.
Git marks conflicts in the file:
<<<<<<< HEAD
content from master
=======
content from dev
>>>>>>> dev
Edit the file to resolve conflicts, then:
git add <file>
git commit
Delete a branch when you no longer need it:
git branch -d <branch_name>
3.3 Rebase
For a clean, linear history, use
rebase instead of merge. Rebase
reapplies your branch’s commits on top of another
branch.
On master:
git rebase <branch_name>
Example: git rebase dev reapplies
master commits onto dev.
Rebase
If conflicts occur:
- Fix the files
git add <file>git rebase --continue
Rebase rewrites commit hashes. Use rebase for clean
history; use merge for preserving actual development
steps.
3.4 Reset
restore and amend only
affect the latest commit. To view an older commit:
git checkout <commit_sha_1>
To roll back the current branch to an older
commit:
git reset [--soft|--hard] <commit_sha_1>
- Default: keep changes but unstage them
--soft: keep changes and stage
them--hard: permanently delete changes
You can also use HEAD~x to refer to the
x-th commit before HEAD.
Squash multiple commits into one:
git reset --soft HEAD~3
git commit
4. Remote
To collaborate online, connect your local repository
to a remote repository.
When you git clone <uri>, Git
automatically creates a remote named origin
pointing to the URL.
Add a remote manually:
git remote add <remote_name> <uri>
Remove a remote:
git remote rm <remote_name>
Download updates from the remote without merging:
git fetch <remote_name>
4.1 Track
Link a local branch to a remote branch
(tracking):
git branch -u <remote_name>/<branch_name>
-u = set upstream.
If the remote branch exists locally, you can simply
check it out:
git checkout <branch_name>
Git will automatically set up tracking.
4.2 Pull
To fetch and merge in one step:
git pull [--merge|--rebase]
git pull = git fetch +
git mergegit pull --rebase =
git fetch + git rebase
Resolve conflicts the same way as with local
branches.
4.3 Push
Upload local commits to the remote:
git push
Always pull before pushing to avoid overwriting
others’ work.
Force push (use carefully, e.g., to remove sensitive
data):
git push --force
Create a remote branch and set upstream:
git push -u <remote_name> <branch_name>
Delete a remote branch:
git push -d <remote_name> <branch_name>
You need write permission to push.
4.4 GitHub
GitHub is a popular Git hosting platform.
- Maintainers: People you invite with
write access.
- Contributors: The public can fork
your repo, make changes, and open a pull request
(PR) for you to review and merge.
Similar platforms: GitLab, Gitee.
5. Submodule
To include another Git repository inside yours (for
dependencies), use submodules:
git submodule add <uri>
This creates a .gitmodules file and
links the external repo.
Clone a repo with submodules:
git clone <uri> --recursive
Or initialize after cloning:
git submodule update --init [--recursive]
Submodules save storage by referencing external repos
instead of copying their code.
Summary
This tutorial covered:
- Repository:
git init,
git clone - Commit:
git add,
git commit, git restore,
git reset - Branch:
git branch,
git checkout, git merge,
git rebase - Remote:
git remote,
git fetch, git pull,
git push, GitHub workflow - Submodule: Managing
dependencies
To learn more about any command:
git <command> --help