10. Version Control¶
We strongly recommend to at least read Chapter 1 and 2 of the official Git book and maybe the seven rules of a great Git commit message.
Setup for the First Time¶
$ git config --global user.name lyrahgames
$ git config --global user.email lyrahgames@mailbox.org
$ git config --global core.editor nano
New Project¶
$ pwd
/home/lyrahgames/projects/cpp-course
$ ls
01-hello 02-input 03-fibonacci 04-files 05-rational
06-graphics 07-build
$ mkdir 08-git
$ ls
01-hello 02-input 03-fibonacci 04-files 05-rational
06-graphics 07-build 08-git
$ cd 08-git
$ pwd
/home/lyrahgames/projects/cpp-course/08-git
Git Initialization¶
$ git init
Initialized empty Git repository in /home/lyrahgames/projects/cpp-course/08-git/.git/
Git created a new folder .git
inside the current directory. Because of the preceding dot, this folder is typically hidden. To print it to the screen, we use an additional flag for ls
.
$ ls -a
.git/
For now, the content of this folder is not interesting for us.
Status¶
$ git status
On branch master
No commits yet
nothing to commit (create/copy files and use "git add" to track)
Untracked Files¶
$ touch main.cpp
$ git status
On branch master
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
main.cpp
nothing added to commit but untracked files present (use "git add" to track)
Preparing for Commit¶
$ git add main.cpp
$ git status
On branch master
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: main.cpp
Commit¶
$ git commit -m "Initial commit"
[master (root-commit) 63588d9] Initial commit
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 main.cpp
Clean Repository and History¶
$ git status
On branch master
nothing to commit, working tree clean
$ git log
commit 63588d9bb330ba9edb2d6f7bf664a445ec53a457 (HEAD -> master)
Author: lyrahgames <lyrahgames@mailbox.org>
Date: Tue Oct 20 20:11:10 2020 +0200
Initial commit
Modified and Modified after Stage¶
// main.cpp
#include <iostream>
int main(){
std::cout << "Hello, World!\n";
}
$ g++ -o hello main.cpp
$ ./hello
Hello, World!
$ git status
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: main.cpp
Untracked files:
(use "git add <file>..." to include in what will be committed)
hello
no changes added to commit (use "git add" and/or "git commit -a")
$ git add main.cpp
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: main.cpp
Untracked files:
(use "git add <file>..." to include in what will be committed)
hello
Change main.cpp
again before committing.
// main.cpp
#include <iostream>
int main(){
using namespace std;
cout << "Hello, World!\n";
}
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: main.cpp
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: main.cpp
Untracked files:
(use "git add <file>..." to include in what will be committed)
hello
git add
adds a snapshot of the file at the time the command was called. If the file has changed after git add
, it has to be added again.
$ git add main.cpp
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: main.cpp
Untracked files:
(use "git add <file>..." to include in what will be committed)
hello
Now let us do another commit.
$ git commit
This one opens the nano
editor. Type in your commit message.
Printing the Log¶
$ git log
commit 37123eab509e177d2f7d7449b2dfde686bb8393a (HEAD -> master)
Author: lyrahgames <lyrahgames@mailbox.org>
Date: Tue Oct 20 20:35:27 2020 +0200
Add hello-world program
commit 63588d9bb330ba9edb2d6f7bf664a445ec53a457
Author: lyrahgames <lyrahgames@mailbox.org>
Date: Tue Oct 20 20:11:10 2020 +0200
Initial commit
Checkout Other Commits¶
$ git checkout 63588d
Return to the last commit.
$ git checkout master
Ignoring Specific Files: Black and White Listing¶
Let us now add a typical template buildfile
from the last project to be able to automatically compile the program by using build2.
$ touch buildfile
cxx.std = latest
using cxx
hxx{*}: extension = hpp
cxx{*}: extension = cpp
exe{hello}: {hxx cxx}{*}
cxx.poptions =+ "-I$src_base"
Test the compilation.
$ b
c++ cxx{main}
ld exe{hello}
$ ./hello
Hello, World!
$ git status
On branch master
Untracked files:
(use "git add <file>..." to include in what will be committed)
buildfile
hello
hello.d
main.o
main.o.d
nothing added to commit but untracked files present (use "git add" to track)
From these given files, only buildfile
should be tracked by Git. To not always manually decide which files to add to the commit or the history, we will use a .gitignore
file.
$ touch .gitignore
Black listing approach: List every file or file pattern you do not want to track.
# .gitignore
hello
hello.d
main.o
main.o.d
with patterns:
# .gitignore
hello
*.d
*.o
Both of these files gives us the following output when git status
is called.
$ git status
On branch master
Untracked files:
(use "git add <file>..." to include in what will be committed)
.gitignore
buildfile
nothing added to commit but untracked files present (use "git add" to track)
Black listing, in my opinion is not ideal. Therefore we will use white listing. We will first ignore every possible file by using *
and invert ignoring files by using !
.
#.gitignore
# Ignore everything.
*
# Allow any subfolder.
!*/
# Allow C++ header and source files.
!*.hpp
!*.cpp
# Allow build2 buildfiles.
!buildfile
# Allow .gitignore file.
!.gitignore
Now make the commit by adding everything that is not ignored.
$ git add .
$ git commit