flowchart LR A[Version 1] --> B[Version 2] --> C[Version 3]--> D[...]
git
git
repositorygit
implements the main features of version controlVersion control is an approach to coding that allows you to keep track of the code evolution.
You may think of coding as a linear process, where a first version is followed by another more advanced version, which is again followed by a successive more refined version and so on.
flowchart LR A[Version 1] --> B[Version 2] --> C[Version 3]--> D[...]
This is not at all the case. In fact, as we develop our code we tyically try various ideas, similarly to what you would do if you were writing a novel, perform an experiment, or explore an uncharted territory.
flowchart LR A[Version 1] --> B B[Version 2] --> C[Version 3]--> D[...] A-->Aa[Variant 1.a]-->B A-->Ab[Variant 1.b]-->E[Alternative version 2]-->C
This is even more evident when collaboration is at play: different developers will try different approaches and require a system to keep track of their respective modifications and that helps them with bringing them together into a unified project. In fact, regularly, the various ideas need to come together and merge for the project to keep its unitary structure.
Version control tools serve precisely this purpose, and git
is the most popular of such tools.
It is powerful, but its usage can be subtle at times, as illustrated by the following cartoon:
Version control therefore solves two problems:
We are going to focus mostly on the first part, but it is important to realise that git
is an essential tool for code development in large projects.
Version control use repositories. These are a database of code versions, stored in an efficient manner, focusing on the changes between a version and another.
Each user of the repository has their own working copy of all the files (any kinds of files) of the project. This clone of the repository is typically stored on the local machine.
Changes to the local clone are not reflected in the repository unless the users explicitly require this to be the case.
In distribute version control each user has a complete copy of the repository, and they can perform their changes independently from other users, work locally and offline and eventually do collaborative work by merging their own versions with the one of others.
In principle, this can be done without a central server (e.g. peer to peer). In practice, one often uses some form of online repository, e.g. Github, Gitlab etc.
Branching in git
allow you to explore various ideas in parallel, developing in different directions and experimenting new features. Branching is a backbone ides in git
.
A repository typically has a main branch where the functional code is stored. When we want to develop our code we create new feature branches
%%{init: { 'logLevel': 'debug', 'theme': 'default' , 'themeVariables': { 'git0': '#ff0000', 'git1': '#00ff00', 'git2': '#0000ff', 'git3': '#ff00ff', 'git4': '#00ffff', 'git5': '#ffff00', 'git6': '#ff00ff', 'git7': '#00ffff' } } }%% gitGraph commit id: "main" branch feature commit id: "main work" checkout feature commit id: "feature work" checkout main commit id: "more main work" merge feature
On every branch, we can store out individual advancements as commits (see below). Eventually, when we are happy for our feature to be integrated with the main branche, we merge the feature branch with the main branch.
When you want a change to be registered in the repository’s database, your commit your changes to the repository. This means that a new entry in the database is added, keeping track of a timestamp associated with your changes and (often) an explanatory description of what the modification entails.
If you also have a remote repository (e.g. on GitHub), you can synchronise the changes between the local branch and the remote branch via the push operation.
Fetch allows you to retrieve the changes from a remote repository, see them and decide whether to merge such changes with your local repository (or not).
Pulling is simply fetching, followed by automatic merging.
An efficient way to produce a package out of a git
repository is to construct a bundle. This is a single file that contains a collection of commits, branches and logs allowing you to transfer or store the repository’s content without requiring access to a remote server.
git
works, adapted from https://homes.cs.washington.edu/~mernst/advice/version-control.html ↗️git
We start off working locally and creating a local project.
Previously, you should have created a project folder with a README.md
file. We now want to setup our local git repository.
Task 1: initialise the repository
Go to the project folder vicsek-cpp
and initialise the git
repository.
Use the information above or git --help
to find the correct command to use.
Task 2: create a .gitignore
file and add it to the staging area
We want to tell git
not to keep track of specifc files. For, example we want to ignore hidden files that are specific to MacOS. A hidden file/folder haas a name that starts with .
.
To provide git
with a list of files to ignore, we create a (hidden) configuration file inside vicsek-cpp
called .gitignore
.
Create such file and enter the following string
.DS_Store
Then add the .gitignore
file to the staging area.
Check git status
to see if your .gitignore
is ready to be committed and then commit it with a suitable comment.
You should also get a message concerning your README.md
file. What os the best course of action here?
Task 3: ignoring files and directly committing the changes
Suppose now that we also want to ignore all files that end with .txt
. The .gitignore
file accepts the wildcard *
.
Modify the .gitignore
to ignore all .txt
files. With a suitable option to the git commit
command, stage and commit the changes in a single go.
Then create two new files:
notes.txt
filenotes.md
fileAdd all new files in the current folder with git add .
, commit your changes to the repository and then check the files added to the repository with git ls-files
.
Is notes.txt
in your list?
Task 4: branching
We want to now start developing our code. For this purpose, we create a new branch called develop
. To do so we use the command
To check which branches now exist in your repository just type
A *
should appear on the branch you are on (which should be main
). You leave the view using theQ
key on your keyboard.
To switch to the develop
branch use
Check that you are on the right branch now (see above).
Once you are on your develop branch, create a new folder src
where we will put the C++ code (do not remember how to create a folder? go back to Using the shell).
Inside src
, create our C++ main file main.cpp
, e.g. using a suitable editor (e.g. nano
, pico
or vim
).
The minimal content should be the following
Now, add the src folder with its content to the git repository and commit the changes.
Switch back to the main
branch: what happened to the src
folder?
Task 4: merging
Now that you have your develop
branch set up, attempt to merge it back with the main
branch using the git merge
command. If you are not sure about how to use it, check the documentation with git merge --help
.
Task 5: bundling
Use now the command
to create a single bundle file conatining all of the repository. Move it to another folder (or even another machine with git, e.g. your Noteable account) and unpack it with
Can you check the branch structure? and the status?