We are a non-profit association and hacking community
formed by students from Politecnico di Milano
We promote the use of Free and Open Source Software through courses, talks and workshops
We tinker with software and hardware and share knowledge with anyone who is curious about technology
...but also
Creative Cazzeggio Development
Politecnico di Milano (Leonardo campus), building 9A
Come visit us!
Make sure to check BITS to know if the headquarters are open!
git is a VCS (Version Control System)
VCSs support development, removing the risk of losing work
for both a single person, and groups of teams
And you want to make a change...
A VCS is an archive of every edit ever done to your files
This archive is called repository
git is not the only VCS out there!
...these slides too are versioned with git
And how does it do it?
With few commands, this repository allows you to do things like:
git is a
distributed version control system (DVCS)
git is a CLI program
However, many graphical tools, or IDE integrations exist
Today we will use exclusively the CLI
apt install git
pacman -S git
dnf install git
For the other systems there is the official guide
Generally, all operations are done calling git and a command
git <command> [<subcommand>]
To be able to make any write, you need to tell git some personal data:
This is done with the config command:
git config --global user.name <my_name>
git config --global user.email <my_email>
In practice, a repository is any folder
we told git to version control, with some of its content
From inside the folder we want to version control, just run:
git init
And we should get something like:
Initialized empty Git repository in /path/project/.git/
The init command makes the current directory a git repository
n.b. it is not required for the directory to be emptyWhat has changed?
ls -al
total 0
drwxr-xr-x 1 user users 60 31 ago 01.16 .
drwxr-xr-x 1 user users 460 31 ago 01.16 ..
drwxr-xr-x 1 user users 200 31 ago 01.16 .git
The .git folder contains all the necessary files
that git needs in order to work
(So, do not delete this folder)
git status
This command is extremely useful
It will tell you the current status of the repository, and also give you suggestions about how to do the most common actions
Displays files which have changed since the latest commit, files which are ready to be committed and files which are not tracked by git (and more in some cases)
A commit is how git saves a set of edits that have been written to files whose changes are saved by git
It can be also seen as a snapshot of the state of
the repository
A repository is thus an ordered set of commits
...and few additional stuff (we will get back to it later)First we need to tell git which files
we want to be included in the next commit, to do so we use the add command
git add [<path_to_file>...]
n.b. git will not include any file in a commit unless we tell it to do so
git add file1.txt file2.json
What has changed?
git status
On branch master
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: file1.txt
new file: file2.json
The status command returns some information about the current repository status
What has happened?
git takes a snapshot of the files and stores it in the staging area
The staging area is a file that stores information about what will go into your next commit
Now, the files are ready to be included in a commit
N.B. the files were taken as a snapshot to another place,Let's create the commit, using the commit command
git commit
A text file will open in our predefined text editor,
in which we have to write, in the first line,
a brief comment of the commit
We save the file and the commit will be ready
n.b. in Linux environments the default editor for git is usuallyvim
, nano
or vi
Changing it is
easy
What has happened?
git log
commit aa581d11d4caed7084cd8114d2454d9380acd869 (HEAD -> master)
Author: my_name <my_mail@poul.org>
Date: Sat Aug 31 01:56:49 2019 +0200
This is my first commit
The log command allows us to see all the commits in the history of the repository
git commit -m "This is my first commit"
With this syntax we will prevent the opening of
the text editor, providing the comment
through the command line
All these data will be used to create
the fingerprint (hash) of the commit
Each commit includes the fingerprint of the previous one
⇓
Edits of old commits are (generally) forbidden
and easily identifiable
We don't need it, we just search for the fingerprint of the commit
which we want to roll back
git reset <commit_hash>
The reset command restores the repo status to the specified old commit
Be careful: use this command with caution
n.b. it is not necessary to specify the whole fingerprint of the commit,A branch is an isolated set of commits
You can also see it as a separate copy of the repository
(just for the purpose of learning)
git branch <branch_name>
The branch command without any arguments lists the branches in the current repository
git branch
After you created a branch, you also need to switch to it,
so that your commits will be saved in the desired branch
git switch <branch_name>
When switching branch, git will change your files and restore the last commit on the branch (if any)
The old way is using the checkout command
git checkout <branch_name>
Whenever you find yourself with two branches
that you want to "unify",
you will need to do a merge
A merge between two branches is done with a third, unifying, commit
Switch to the branch you want to import the changes in
git switch <branch_merge_to>
Initiate the merge with the merge command,
specifying the branch to import
git merge <branch_merge_from>
But, is it that simple?
Auto-merging old_file
CONFLICT (content): Merge conflict in old_file
Automatic merge failed; fix conflicts and then commit the result.
Inside a file where there is a conflict:
<<<<<<< HEAD
--some text coming from the current branch here---
=======
--some text coming from the branch to merge--
>>>>>>> other_branch
To actually solve the conflict:
A tag is a way to mark a commit with a simple name
It can be seen as an alias to the commit hash
They are usually used to mark important commits, such as releases
Sometimes, they are important for some automated tools
git tag <tag_name> [<commit_hash>]
The tag command requires a name for the tag and optionally the hash of the commit which has to be tagged (If no hash is provided the "last" commit will be tagged)
tag names must be short and simple,-m
, followed by the message
git tag v1.2.0 be4f621
A pointer is added to the commit with the specified name
The command git tag
without arguments lists the repository's tags
Branches and tags both point to a commit
From git's point of view they are technically the same
Those "pointers to a commit" are called references, or refs
In a nutshell, history allows you to see a git repository like a collection of commits and references
The answer is "the commit pointed to by HEAD"
HEAD is a special reference, pointing to the last commit of the current working branch
in an ordinary situation
To do this we can use the checkout command with the hash of the commit we want move HEAD to
git checkout <commit_hash>
n.b. when HEAD points to a specific commit not pointed to by a branch, we call it detached HEAD
A remote is a repository in a different place (usually online)
Git provides the tools to keep
local and remote repositories synchronized with each other
Usually we rely on hosting platforms to be a common repository between local ones
Even if possible, the direct synchronization betweenBefore being able to synchronize a repository, we need to tell git were is the remote one
This can be done with the remote command
git remote add <ref_name> <url_to_repo>
The subcommand add allows to create a new reference to a remote repository
git supports https, ssh or pathgit remote add origin https://gitlab.org/path/repository.git
What has changed?
git remote -v
origin https://gitlab.org/path/repository.git (fetch)
origin https://gitlab.org/path/repository.git (push)
Two references to a remote repository (which I called "origin") were created:
Every ref on the remote is different from the local one
The remote refs will be called <remote_name>/ref_name
If the remote is called origin, the main branch will be:
git pull <remote_ref_name> <ref>
The pull command tries to retrive a ref (and associated commits) from a remote and merge them to the local history
git pull origin master
git tries to download the commits of branch master
from the remote repository called origin,
and then tries to merge them with the local history.
If there is any merge conflict it needs to be solved as usual
git push <remote_ref_name> <ref>
The push command takes a reference to a remote and a reference to a commit, then it sends the referenced commit to the remote, with all the commit it depends on
git push origin master
git sends the commits which the branch master depends on
to the remote repository called origin,
which then tries to merge them to its history.
If that merge would result in a conflict, the remote will refuse the commits
You will have to to first pull and solve the conflict locally
We can do it with the previous commands
mkdir <repo_name>
cd <repo_name>
git init
git remote add origin <repo_uri>
git pull
...or, we can also use the clone command
git clone <repo_uri>
git <command> -h
Will display a short help on the command line
git <command> --help
Will open the manual page for that command (almost like calling man
)
Those pages are available also at the official website
Online there is also the git book, which is open and free
The official documentation page also contains other resources