Understand Version Control (2) — Manage a Local Change

Domi Yan
5 min readSep 4, 2020

In the previous article of this serials, we introduced the basics concepts in a version control system (VCS) — repository, commit and branch. We know code change is recorded as a commit. The next thing is to make a commit.

That sounds like an easy job — modify the file and update the repository, right? Well, it is, but in practice, there are places you can easily shoot yourself in the foot.

Problem

So, where is the pitfall? To put it simply, not every change on your local files is expected to be committed. You may generate temporary files during your compile/execution processes which you don’t want to record. It’s also possible that you have multiple changes in one file and only wish to submit part of them (others are for debugging/experimenting purposes).

A simple solution to this is to copy files to a different directory, do the dirty development/debugging work and copy back what’s to be recorded. This works if you are careful enough, but manually copying multiple files back-and-forth is usually a prone-to-error operation. Can we do better than this?

Turns out version control systems have provided mechanisms to help developers organize local changes. Let’s take a look at how this is done in git.

The first thing to sort out is what files should be recorded in the repository.

Track vs Untrack Files

In git, local files in the work directory are classified into two categories: tracked and untracked. Git only record tracked files and ignore untracked ones.

All files in the latest snapshot of the repository are tracked. New files by default are not tracked. You need to type git add <file name> to track them. Here is an example of adding a new file NEW_FILE.txt to be recorded. After creating the file, we can run git status to find NEW_FILE.txt is untracked.

$ git status
On branch master
Your branch is up to date with ‘origin/master’.
Untracked files:(use “git add <file>…” to include in what will be committed)NEW_FILE.txtnothing added to commit but untracked files present (use “git add” to track)

Now run git add <file name> to make it tracked and check git status:

$ git add NEW_FILE.txt
$ git status
On branch master
Your branch is up to date with ‘origin/master’.Changes to be committed:(use “git reset HEAD <file>…” to unstage)new file: NEW_FILE.txt

The new file is tracked now. If you run git commit -m <commit message>next, your git repository will know about this file and track it in future development.

We just learned how to deal with new files, how about modifying an existing one?

In the above example, before the change was committed, the file NEW_FILE.txtis in a status called “staged” which means ready for commit. When we modify a tracked file, the change does not immediately become “staged” for commit, it’s in an “unstaged” status.

Staged vs Unstaged Changes

In git, “staged” is a status indicating the change will be committed if you type git commit. “Unstage” status represents a changed file where the change is not to be committed. By default, changed files will be in “unstaged” status. You can use git add <file name> to update its status to staged. Check the following example. We added a new line (new line 1)in a tracked file README.md and run git status:

$ git status
On branch master
Your branch is up to date with ‘origin/master’.Changes not staged for commit:(use “git add <file>…” to update what will be committed)
(use “git checkout — <file>…” to discard changes in working directory)
modified: README.mdno changes added to commit (use “git add” and/or “git commit -a”)

README.md change is “unstaged” for commit. Now use git add to make it “staged”:

$ git add README.md
$ git status
On branch masterYour branch is up to date with ‘origin/master’.Changes to be committed:(use “git reset HEAD <file>…” to unstage)modified: README.md

One thing that may confuse you is one file can have staged and unstaged change at the same time. Let’s add one more line (new line 2) in README.md.

$ git status
On branch master
Your branch is up to date with ‘origin/master’.Changes to be committed:(use “git reset HEAD <file>…” to unstage)modified: README.mdChanges not staged for commit:(use “git add <file>…” to update what will be committed)
(use “git checkout — <file>…” to discard changes in working directory)
modified: README.md

At this moment, the first change (added new line 1) is staged and second (added new line 2) is not. We can run git diff --staged to check the staged change and git diff to check the unstaged change:

$ git diff --stageddiff — git a/README.md b/README.md
index 99920be..1c622f0 100644
--— a/README.md
+++ b/README.md
@@ -1,1 +1,2 @@
# This is a readme file
+new line 1
$ git diff
diff — git a/README.md b/README.md
index 1c622f0..1ec53cf 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,3 @@
# This is a readme file
new line 1
+new line 2

The status of the file README.txt can be illustrated as:

README.txt has both staged and unstaged change

At this point, you need to be very careful about what change will be checked in. The two git diff commands above are your friends.

Summary

Version control tools like git provide mechanisms to manage local changes. The two questions to ask yourself to avoid mistakes are:

1. Is this file tracked or untracked?

2. Is this change staged or unstaged?

This following graph recaps what we learned today:

Manage Local Changes: Statue Transfer Graph

Hope you have a clear picture of your local change now.

--

--