Fundamental aspects
Username & Email
Here I want to define the username and email to my git repositories. First thing we do is the following:
git config --global user.name "NAME"
git config --global user.email "E-MAIL"
This defines, respectively, the username and email. We can change it anytime we want, but keep it consistent. We can check it with:
git config user.name
git config user.email
First Commands
Status
The first thing we need to understand is the command:
git status
It gives information on the current status of a git repository and its contents.
Init
The next command is:
git init
It makes the directory we are in a git repository. We run this command one time per project.
The init creates a directory .git
(it is hidden). If
we delete this folder, it destroys the git history, so the directory
is not a repository anymore. A common git mistake is the following:
Once we create a repository, git watches everything that happens in
the repository, even the creation of nested folders. For this reason,
we do not run the git init in a folder inside a repository, as it
avoids mistakes.
Committing
Add
Now we want to commit the modifications we do on our projects.
git add file1 file2 file3
Once we have modified our project, we can pack the modifications or part of them using the add command.
Also, we can add all modifications at once with:
git add .
Commit
Now we can commit the modifications we have done.
git commit
In this option, we will need to provide the message using vim. Or we can write the message as follows:
git commit -m "my message"
Log
This command gives a log of commits of a project.
git log
There are many options available (see documentation). One particularly useful option is the following:
git log --abbrev-commit
That gives a shorter commit name. Another useful option is:
git log --oneline
It gives a short version of the commit message.
Amend
Suppose we want to fix a mistake we make in a previous commit. Then we can do the following:
git commit -m 'some message'
git add forgotten_file
git commit --amend
Gitignore
Here I just add the file .gitignore
and list the files
and folders we do not want to track. There are several patterns to
follow. Some patterns are:
.DS_Store # it ignores files called .DS_Store
folderName/ # It ignores an entire directory
*.log # it ignores everything with the .log extension
Branching
This is one of the last fundamental tools we learn in git. Everything else is secondary. The idea here is that if we need to modify our project, or work simultaneously with other people, we can create other branches of the project and merge them afterwards.
The default branch when we create a repository — that is, when we
git init — is called master branch
. When we
type git log
, we see that the most
recent commit
is called HEAD
. As a matter of
fact, it is written something of the form HEAD ->
master
. It refers to the thing we are currently working on.
Git branch
Here we can start with our first command. It is:
git branch
That gives the existing branches in our repository. Moreover, the *
indicates our current branch.
Creating and switching branches
In order to create new branches, we use the same syntax, except that now we add the name of the branch, that is:
git branch <new_branch>
Observe that this command just creates another branch for us, but it does not change our work to the new branch. We can change the branch with:
git switch <branch_name>
It is important to notice that this command creates a new branch based on the current head.
There is another command to switch between branches, it is:
git checkout <branch_name>
This command does a zillion other things, so the switch
was introduced to be a simpler alternative.
Finally, we can create and switch to the new branch at once; we just need to introduce a flag -c
:
git switch -c <branch_name>
git checkout -b <branch_name>
Finally, there is something important we need to understand. If we switch to new branches without committing the modifications, these would be lost. So, we need to commit (or stash them), and just after that, we switch to new branches. Actually, sometimes, when the files do not exist in other branches — and there is no risk of conflicts — the files follow us to the new branch.
Deleting and renaming branches
We can delete the branch with the command:
git branch -d <branch_name>
It works if the branch is fully merged. Otherwise, instead
of -d
, we can use -D
, which denotes
force. We cannot delete inside the branch.
Moreover, we can rename the branch with:
git branch -m <new_branch_name>
In order to rename, we need to be inside the branch.
Merging branches
Finally, we have the last fundamental concept of git: Merging different branches. We need to keep in mind that the master branch should not be used for experiments; in other words, we must use the master branch just for “permanent” coding.
This discussion is somewhat straightforward. We use the following command:
git merge <name_modified_branch>
We need to be in the branch we want to update. Moreover, it is worth noticing that the merge is temporary, and it means that no branch is destroyed in the process.
On the other hand, there are at least three different situations we need to distinguish when we merge branches.
Fast-forward
The first case is very easy. It is basically the case where the older commit is kept as it was, and the new branch basically adds new information. In this case, the commit just brings the old commit to a new point, and the two branches are similar. Evidently, if we change any branch, they diverge again.
Merging without conflicts
The second type of merging is when two branches are modified, but no conflicts are found. It happens, for example, when the branches touch different files or add new files.
In this case, git creates a new commit unifying all modifications.
Merging with conflicts
The last case is when there are conflicts. In this case, git reports the conflicts, and we need to manually resolve them.