Whether you code or write documents, often you end up with multiple versions of the same file. You may want to archive one set of changes that are not needed at the moment, then send another set of changes to your colleagues for a review. At a certain point, keeping track of all these versions becomes unfeasible.
Tools like Dropbox or Google Drive, which you may know already, can help a bit. These tools allow you to share your files easily, or to restore their content to an earlier point in time. Here's an example:
Unfortunately, you can only see different versions of a single file. Also, it's hard to tell which version you might want to restore since there is no indication of how individual versions differ. A relatively large project wouldn't be manageable with this approach.
Therefore, programmers tend to use more powerful tools called version control system (VCS). Currently, the most popular one is Git, and we'll learn more about it in this lesson.
Real programs are rarely created by a single person. Two heads are better than one, so it's better to work on a project in a team.
Each team member needs to be able to share their progress with others. Git can be used exactly for that: you can set up a shared repository online that your team members will synchronize with.
We will rely on the command line. If you are not confident working with it yet, look at the introduction.
Remember: don't write the
$ at the start.
It is shown here to indicate the beginning of each command.
The process of installing Git is described here. If you have skipped the lesson before, you might want to get back to it now.
Each project that you want to version-control needs to be stored in its own directory.
Create a new directory now and navigate inside (use the command
Then, create a new Git repository using the command
$ git init Initialized empty Git repository in ./.git/
At first glance, it looks like nothing happened.
This command created a hidden directory with the name
.git and stored some
information about history in there.
You can see the file using
ls -a (Linux) or
dir /a (Windows).
.git is a hidden directory because it is managed only by Git
and you shouldn't be changing anything inside.
The repository is empty for now - it does not have any files or history.
You can see for yourself by invoking
git status, a command that shows information
about the state of the repository:
$ git status On branch main Initial commit nothing to commit (create/copy files and use "git add" to track)
“On branch main” refers to so-called branches, we'll get back to that later. “Initial commit” means that there is no commit stored yet. And “nothing to commit” says that there are no files to be saved and versioned in the directory.
We will now switch for a moment to a plain Text Editor (not Microsoft Word but for example Notepad) or optionally Code Editor (VS Code).
Now create a new text file there, write/copy a short poem text inside and save it in the folder where you originally did
git init in your command line. Name the file
poem.txt and do not forget to save it after you made the edits.
As a quick source of totally unbiased texts to work with, you can have a look here:
The file should span at least five lines so that we have enough to work with.
Then, try executing
git status again: Git reports that there is a new
file in the directory and that it isn't managed by Git yet.
$ git status On branch main Initial commit Untracked files: (use "git add <file>..." to include in what will be committed) poem.txt nothing added to commit but untracked files present (use "git add" to track)
If the state of folder is not looking the same for you
Double check that you have created the file in the same folder as where you did run the
You can check by listing the content of the folder (ls or dir) in the terminal.
We need to make Git track each new file explicitly. Let's do that for the file with your poem:
$ git add poem.txt
Then check the state of the repository again:
$ git status On branch main Initial commit Changes to be committed: (use "git rm --cached <file>..." to unstage) new file: poem.txt
The lines in green (“changes to be committed”)
will be included in the next batch of changes (a
commit) that you will create.
Let's create our first commit and add a commit message "First commit" via a "-m" suffix:
$ git commit -m "First commit" [main (root-commit) 1a009f4] First commit 1 file changed, 6 insertions(+) create mode 100644 poem.txt
Congratulations! Your first commit in the repository is finished!
What would happen if you did not add the -m "message" - read the text below. Otherwise you can skip the text block.
Working with editors
Without the -m "message" after entering this command, an editor would open where you can write a short description of this commit, briefly summarizing what changes have been made. In Windows, if you have set up your Git correctly, Notepad will be used as the editor; simply write something, save (Ctrl+S) and close (Alt+F4).
In Linux or macOS, an editor called Nano appears directly in the command line window. You can recognize it by the keyboard shortcut help on the bottom two lines. Write something, save using Ctrl+O, confirm the name of the file (Enter) and exit the editor using Ctrl+X.
If you haven't set up Git accordingly, Vim is invoked directly in the command line window
and will be used as the default editor.
It is a relatively complicated editor and learning to use it is beyond the scope
of this lesson. You can recognize it by one or two lines at the bottom that show a path
to a temporary file that you are currently editing.
In that case, first press
Esc, then type
:q! (colon, lower letter Q, exclamation mark)
and confirm by pressing Enter.
Then set up Git correctly and try
git commit again.
You can ignore the existing lines starting with
#, these are just for your information.
Git will ignore them as well. Finally, save the file and close the editor.
Try reporting on the repository again:
$ git status On branch main nothing to commit, working tree clean
This short report means that nothing has changed since the last commit. That is expected since we've just commited all our changes!
Now let's have a look at what has changed in the last commit.
$ git show commit 1a009f4267d5a6ab7ece87cb7514f5b803692e39 Author: Adéla Novotná <email@example.com> Date: Mon Mar 20 14:51:34 2017 +0100 First commit diff --git a/poem.txt b/poem.txt new file mode 100644 index 0000000..558d133 --- /dev/null +++ b/poem.txt @@ -0,0 +1,6 @@ +Holka modrooká, nesedávej u potoka +Holka modrooká, nesedávej tam + +V potoce je hastrmánek +Zatahá tě za copánek +Holka modrooká, nesedávej tam
Notice the unique Git commit ID that allows you to return to this state of your project at any point in the future. The author's name, the date of this commit's creation and the commit message are also listed, along with the summary of changes: a new file poem.txt containing the text in green has been added.
When the output of a command is too long, you can browse it using the keys (↓, ↑, PgUp, PgDn). In such case, exit the browsing mode by pressing q for Quit.
Text encoding in Windows
If you have trouble with displaying special characters like letters with diacritics,
enter the following command before
> set LC_ALL=C.UTF-8
This command will only configure the current command line window. It will have to be entered for any new window that you open.
Make a small change in your poem; replace one word, change punctuation, or add a new verse. Then check the status of the Git repository again.
$ git status On branch main 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: poem.txt no changes added to commit (use "git add" and/or "git commit -a")
The file is shown in red again. Something has changed inside!
To see the details, execute the command
$ git diff diff --git a/poem.txt b/poem.txt index 558d133..24e2384 100644 --- a/poem.txt +++ b/poem.txt @@ -1,6 +1,9 @@ -Holka modrooká, nesedávej u potoka -Holka modrooká, nesedávej tam +Holka modrooká +Nesedávej u potoka +Holka modrooká +Nesedávej tam V potoce je hastrmánek Zatahá tě za copánek -Holka modrooká, nesedávej tam +Holka modrooká +Nesedávej tam
The changes are shown on a per-line basis. The lines in red beginning with - indicate the original lines that have been removed; the lines in green starting with + show the newly added lines.
Even if just a single word or a letter has changed on any given line, the whole line will be listed as removed and added (including the small change). This interpretation can be customized if needed, but it's a good idea to get used to the default behavior.
It is easy to see what exactly has changed since the last commit.
If your program stops working, but the last commited version still worked,
git diff –
one of the changes listed must have introduced the error!
The line beginning with @@ indicates the location in the file where the changes occur. In the example above, the excerpt of the original file starts at line number 1 and it is 6 lines long; the matching block in the changed varsion starts at line 1 as well, but it is 9 lines long.
If you are satisfied with the changes, stage them for the next commit:
$ git add poem.txt
As usual, check the
status of the repository; the file in green will be included
within the next commit.
$ git status On branch main Changes to be committed: (use "git reset HEAD <file>..." to unstage) modified: poem.txt
Before we finalize the next commit, let's talk about the best practices
in formulating the commit messages.
There are common conventions that most programmers follow:
the first line summarizes the changes, the second line is left blank,
and the following lines list the reasons for the change or describe
the changes themselves in more detail.
Each line should have under 70 characters in length;
the lenth of the comments (lines starting with
#) can serve as a guide here.
It is not worth going into detail for changes that are trivial or obvious;
rather, focus on the broader context and reasons for the changes.
Anything that can help whomever will try to understand the changes in the commit;
this might include you few months later.
My commit message will be the following:
Split long lines Typically, each verse of a poem goes on its own line. I think that it's easier to read like this. (Although, the real reason was to demonstrate git diff.)
If you ever have trouble summarizing your changes using just 70 characters, you might be taking too many steps at once. E.g. "change string X and add loop Y" might be better to commit as two separate revisions.
git commit to create your second commit,
and then check it using
$ git show commit 81cbabb3bd3cd2f3896dd41b20012c44dbd69031 Author: Adéla Novotná <firstname.lastname@example.org> Date: Mon Mar 20 14:51:34 2017 +0100 Split long lines Typically, each verse of a poem goes on its own line. I think that it's easier to read like this. (Although, the real reason was to demonstrate git diff.) diff --git a/poem.txt b/poem.txt index 558d133..24e2384 100644 --- a/poem.txt +++ b/poem.txt @@ -1,6 +1,9 @@ -Holka modrooká, nesedávej u potoka -Holka modrooká, nesedávej tam +Holka modrooká +Nesedávej u potoka +Holka modrooká +Nesedávej tam V potoce je hastrmánek Zatahá tě za copánek -Holka modrooká, nesedávej tam +Holka modrooká +Nesedávej tam
These two diagrams below visualize what each command demonstrated thus far does exactly, and how the changes move from “not staged” to “commited” and back in case of need.
Diagram showing the process of viewing and committing changes:
Now that we have created our first few commits in the repository,
let's demonstrate more commands that will help us understand
the whole history of our Git repository.
The first command is
$ git log commit 81cbabb3bd3cd2f3896dd41b20012c44dbd69031 Author: Adéla Novotná <email@example.com> Date: Mon Mar 20 14:51:34 2017 +0100 Split long lines Typically, each verse of a poem goes on its own line. I think that it's easier to read like this. (Although, the real reason was to demonstrate git diff.) commit 1a009f4267d5a6ab7ece87cb7514f5b803692e39 Author: Adéla Novotná <firstname.lastname@example.org> Date: Mon Mar 20 14:51:34 2017 +0100 First commit
git log prints all commits starting from the newest one and going
all the way back to the initial commit at the origin of the repository.
When there are so many commits that they don't fit on a single screen of your command line window, you can browse back and forth using PgUp/PgDn. Finally, exit by pressing q.
There are many options that customize the output of
They are all described (at great length)
in the built-in documentation (command
git help log).
If the help is displayed in the command line window, press q
My personal favorite combination is
git log --oneline --graph --decorate --cherry-mark --boundary.
To see all details about any commit,
git show 5ff0b, replacing
with the first few characters of the Git commit ID.
These are the Git basics that we'll need in the following lessons.
Whenever you perform
git add file and
the current version of the file is saved and will be accessible even if you delete the file later.
You can always view any past version of any file in your repository,
and review all changes made since the last time the project was saved.
Maybe all this sounded unnecessarily too complicated for a beginner. Indeed, our projects will be relatively simple and easy to manage even without the use of Git. But it's a good idea to learn using it from the very beginning; when you get to participate in bigger projects, already being used to Git will come very handy.
So, from now on, whenever you make even a small but meaningful change to your program,
as long as the program works at least as well as it did before,
git add and
git commit to save the change in Git.