Have you ever met one of these problems?
-
The code I did last night worked. I wish I could revert it back.
-
I have to copy the same file to maintain multiple versions, and now I don't know their differences and don't know which one to choose.
-
I want someone else to participate in my work, but I don't want him to overwrite my progress.
Git is a distributed version-control system, created by Linus Torvalds (who is also the creator of Linux kernel) in 2005, originally designed for efficiently handling large projects like Linux kernel.
People may get confused with git and github. Git is a command-line tool for version control. While github is a website that user can share and even collaborate on their git repositories.
I will categorize each page with a level of difficulty.
Basic commands that you should be familiar with
Learning these commands or knowledge will help you understand how git internally works
Advanced skills but still proved to be useful
A Repository is a location that you keep all the files related to your project.
We can either create a new repository (git init
), or get an existing repository from somewhere else (git clone
).
This will copy a remote repository (usually from the Internet) to your local filesystem.
git clone https://github.com/PropicSignifi/GitTutorial
This will convert your current directory into a git repository
mkdir MyProject
cd MyProject
git init
It shows the status of your current branch, the status of all the files in your repository, and the status of the differences between your local branch and your remote branch.
This is an example of a clean status. We will see more complicated status as the tutorial proceeds.
$ git status
On branch master
Your branch is up to date with 'origin/master'.
nothing to commit, working tree clean
Advice: always check your status before taking further actions.
git branch
shows the status of the branches.
$ git branch
* master
This shows me that I have only one branch named "master". By default, "master" is the main branch of a git repository.
We can create a new branch by type a new branch name after git branch
:
$ git branch myNewBranch
Now check your branches status again.
$ git branch
* master
myNewBranch
We have two branches now, but our current working branch is still "master".
We can switch to a different branch using the command git checkout
$ git checkout myNewBranch
$ git branch
master
* myNewBranch
git checkout
has many, many usages. We can use it to switch to a branch,
a commit, or a tag. We can also checkout a file or a directory. Even
more, we can combine the both. For example, checkout a file from a
specific branch. We will see some of these examples later.
Let's start from creating a new file, name it "hello.txt", and add some content to the file:
echo "Hello world" >> hello.txt
Now if we see our git status
, we can see "hello.txt" is recognized as
an untracked file.
$ git status
On branch myNewBranch
Untracked files:
(use "git add <file>..." to include in what will be committed)
hello.txt
nothing added to commit but untracked files present (use "git add" to track)
git add
will convert our untracked file to a staged status.
$ git add hello.txt
$ git status
On branch myNewBranch
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: hello.txt
We are not ready to commit our change. A new commit requires a commit message.
You may pass your commit message through the -m
option.
git commit -m "Add the line Hello world to the file hello.txt"
Now check our status again. Everything is clean.
$ git status
On branch myNewBranch
nothing to commit, working tree clean
$ git log
commit 4ce2556bc32186220054359bc275f8a6a90d4ca4 (HEAD -> myNewBranch)
Author: Henry Li <[email protected]>
Date: Fri Mar 6 11:20:14 2020 +1100
Add the line Hello world to the file hello.txt
Many times, we can use git log -p
instead, which will also show the
detailed changes.
$ git log -p
commit 4ce2556bc32186220054359bc275f8a6a90d4ca4 (HEAD -> myNewBranch)
Author: Henry Li <[email protected]>
Date: Fri Mar 6 11:20:14 2020 +1100
Add the line Hello world to the file hello.txt
diff --git a/hello.txt b/hello.txt
new file mode 100644
index 0000000..802992c
--- /dev/null
+++ b/hello.txt
@@ -0,0 +1 @@
+Hello world
Using git diff
can also check the changes. For example, git diff master
will show us the difference from the master branch to our current branch.
$ git diff master
diff --git a/hello.txt b/hello.txt
new file mode 100644
index 0000000..802992c
--- /dev/null
+++ b/hello.txt
@@ -0,0 +1 @@
+Hello world
Let's continue to make changes on the file "hello.txt".
echo "Hello again" >> hello.txt
Check the status. This time, the file "hello.txt" is in a modified status.
$ git st
On branch master
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: hello.txt
no changes added to commit (use "git add" and/or "git commit -a")
If there are files in a modified status, we can see the unstaged
changes using git diff
.
$ git diff
diff --git a/hello.txt b/hello.txt
index 802992c..06ae335 100644
--- a/hello.txt
+++ b/hello.txt
@@ -1 +1,2 @@
Hello world
+Hello again
So far, we've seen all four different status of a file. They are:
- Staged
- Modified (unstaged)
- Untracked (new)
- Unmodified (clean)
For different file status, commands for discarding the changes would be different.
The most common situation is to discard modified/unstaged changes: we
need to use git checkout <path>
.
git checkout hello.txt
For files in staged status, we can use git reset <path>
to convert it
to unstaged status, then use git checkout <path>
to discard the changes.
git reset hello.txt
git checkout hello.txt
For those untracked files, we may simply use rm <file>
to get rid of it,
since git doesn't care about the file.
Alternatively, we can use git clean -f <file>
.
touch randomNewFile
git clean -f randomNewFile
Git is a distributed version control system, which means there are also changes
made by other people from other places. We can get their update using the
git pull
command.
Usually we only care about the main branch (master) from our remote server. So the following one would be a frequently used command:
git pull origin master
When you think your changes are good enough, you'd probably want to push your changes to the remote server. Usually, you wouldn't want to push the changes to the main branch (master) directly, so we should do the push for our current branch.
git push origin myNewBranch
When the push is finished, your local branch "myNewBranch" will be copied to the remote repository.
More topics:
-
git stash
-
git merge
-
git rebase
-
git revert
-
git cherry-pick
-
git diff / git apply