A Tutorial of Git and Source Code Management

version control

Why version control?

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 and its history

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.

Level of difficulty

I will categorize each page with a level of difficulty.

basic Basic commands that you should be familiar with

intermediate Learning these commands or knowledge will help you understand how git internally works

advanced Advanced skills but still proved to be useful

Getting a repository basic

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).

Getting a repository basic

git clone

This will copy a remote repository (usually from the Internet) to your local filesystem.

git clone https://github.com/PropicSignifi/GitTutorial

Getting a repository basic

git init

This will convert your current directory into a git repository

mkdir MyProject
cd MyProject
git init

Checking your status basic

git status

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.

Branch basic

git branch

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.

Branch basic

git branch

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".

Branch basic

git checkout <branch>

We can switch to a different branch using the command git checkout

$ git checkout myNewBranch
$ git branch
  master
* myNewBranch

intermediate
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.

Making changes basic

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)

Making changes basic

git add <path>

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

Making changes basic

git commit

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

Checking the history basic

git log

$ git log
commit 4ce2556bc32186220054359bc275f8a6a90d4ca4 (HEAD -> myNewBranch)
Author: Henry Li <henry@clicktocloud.com>
Date:   Fri Mar 6 11:20:14 2020 +1100

    Add the line Hello world to the file hello.txt

Checking the history basic

git log

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 <henry@clicktocloud.com>
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

Checking the changes basic

git diff

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

Making changes basic

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")

Checking the changes basic

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

File status basic

So far, we've seen all four different status of a file. They are:

  • Staged
  • Modified (unstaged)
  • Untracked (new)
  • Unmodified (clean)

status

File status basic

status-cycle

Discarding the changes basic

For different file status, commands for discarding the changes would be
different.

git checkout <path>

The most common situation is to discard modified/unstaged changes: we
need to use git checkout <path>.

git checkout hello.txt

Discarding the changes basic

git reset <path>

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

Discarding the changes basic

git clean -f <file>

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

Pulling the changes basic

git pull

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

Pushing the changes basic

git push

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.

To be continued...

More topics:

  • git stash

  • git merge

  • git rebase

  • git revert

  • git cherry-pick

  • git diff / git apply

References

Pro Git, Scott Chacon and Ben Straub