Table of Contents
- What is Git?
- Git features
- The statuses of your files
- The 3 Git directories
- Introduction to common Git commands
- Coffee Analogy: Steve and Wired Brain Coffee
- Git and the command line
- Install Git
- Create a new Git repository
- Set Git Configurations
- Set a default text editor
- Add Git to an existing project
- Add and track new files
- Make changes to files
- Create new branch
- Show different file statuses
- Merge one branch into another
- Show commit history
- Git on the network
- Configure a remote repository on GitHub
- Send local commits to network
- Clone a Git repository from the network
- Fetch and pull commits from network
- Introduction to merge strategies
- Fix a commit error with git amend
- Rewrite history with git reset
- Recover deleted history with git reflog
1. Course Overview
Welcome to this Git Fundamentals training presented by Aaron Stewart. This is an introduction to the foundations of Git, the hugely popular version control system that is used to manage code projects by the largest software companies around the world, all the way down to small startups.
This training is primarily aimed at developers, but is also suitable for technical project and program managers, content writers, or anyone who needs to review, contribute, or simply better understand a project maintained and monitored by Git.
What you will learn
- Thinking in Git: understand its fundamental characteristics and the main steps to manage and track changes within a project.
- Install and configure Git locally on your own computer on Mac, Windows and Linux, and start using Git to track and manage changes in new and existing projects.
- Working with Others in a Shared Git Environment: Host your Git project on a network server for others to view and contribute to, and use best practices for working effectively with team members while maintaining different environments.
- Edit and reset changes, resolve merge conflicts that may arise when working on conflicting changes, and discover common development workflows.
At the end of this training, you will know the fundamentals of Git, which will allow you to better understand and apply your knowledge in your next Git project.
2. Thinking in Git
What is Git?
Git is, by far, the most widely used version control system in the world today. Developers use it, non-developers use it, and pretty much anyone who contributes to, manages, or monitors projects that require versioning is most likely using it.
It is a fundamental tool for any technology company, and these days every company has to be a technology company to innovate or simply stay relevant.
Formal definition of Git
Git is a version control system, also known by the acronym VCS (Version Control System). Version control refers to the process of saving files or versions throughout the life stages of a project, allowing you to retrieve past versions at any time.
The best metaphor for understanding version control is that of a time machine. Git gives you the ability to go back to the past at any point during your development.
What Git is not
The goal of this course is not to be a comprehensive guide to everything Git. There is a lot of information beyond the scope of this course. The goal is to give you a solid understanding of the fundamentals that will provide you with a solid foundation and help you learn more.
The characteristics of Git
Git has a reputation for being confusing or having a steep learning curve, not to mention the fear of running a Git command that one doesn’t fully understand, with unintended consequences.
Understanding the features of Git and how it tracks and manages versions of your project early in your learning helps reduce that steep learning curve.
Git is distributed
Git is a distributed version control system (DVCS — Distributed Version Control System). Unlike centralized version control systems (like SVN or CVS), each developer has a complete copy of the entire project history on their own local machine. This means you don’t need a network connection to perform most Git operations.
Git uses snapshots, not deltas
Git does not track version changes as a simple list of file-based changes between one version and another, representing only changes from a base version of a file. These version differences are commonly called deltas or diffs.
Instead, Git stores each saved version of your project as a complete snapshot of the entire project file system at that precise point in time, not just the changed files and their deltas.
This snapshot captures everything in the project, including its history and all its metadata. You can reference old snapshots at any time, and new snapshots are created when your project changes.
Example:
- For Git, the version 2 snapshot captures:
- The modification made to file A
- A full file reference for file B from a previous snapshot (since file B was not changed in version 2, it still includes a full reference to the entire file and all its contents in the version 2 snapshot)
- Change to C file
Git is local
Everything in Git happens locally on your machine. Even if you’re working in a network-shared Git repository, all basic operations — viewing history, creating branches, making commits — don’t require a network connection.
Git is explicit
Git doesn’t do anything automatically without you telling it to do so. When you add a new file to an existing Git project, Git will not automatically start tracking that file — you must explicitly tell it to do so. This gives you more control over how and when you make your Git commands.
Git is healthy
Git uses checksums (SHA-1 checksums) for everything it tracks. Each commit, each file, each directory is identified by a unique hash. This ensures that you cannot modify the contents of a file or directory without Git knowing.
The statuses of your files
It is important to understand the different states of your files and the different states those files will move into as you make and save changes.
The two main states of a file
With a Git project, a file can be in one of the following two states:
-
Tracked: These are files that were in the last Git snapshot of the project. Once you tell Git to track a file, Git will continue to track that file until you tell it to stop. Warning: Telling Git to stop tracking files is a destructive command, as you will lose metadata and Git tracking for that file.
-
Untracked: These are files that exist in your project, but that you have not yet explicitly told Git to track.
The three statuses of a tracked file
Once a file is tracked, it can reside in one of three different statuses:
-
Unmodified: You are tracking the file, but there are no unsaved changes since the last time it was saved in this Git snapshot.
-
Modified: A file will enter this status when you have made changes but have not yet saved them in a Git commit. The modified files reside in the working directory.
-
Staged: A file will move to this status when you have told Git that you want to include this file in your next commit. Indexed files reside in the staging area.
The typical workflow
[Fichier non suivi]
|
git add
|
v
[Staged / Indexé] -----> git commit -----> [Unmodified / Non modifié dans l'historique]
^ |
| (modification)
git add |
| v
[Modified / Modifié dans le working directory] <----
The 3 Git directories
Git uses three directories to store and manage your Git project data. The different statuses mentioned above are stored in one of these three directories.
1. The .git directory (local history)
When you initialize Git for the first time in a project, it creates a hidden directory called .git stored in the root of your project. It is in this .git directory that all Git metadata and tracking is stored for each saved snapshot of your project.
This directory is called the local history, and it is where the unmodified status of your files lives. It’s basically a folder that contains all your saved snapshots of your Git project that you can view at any time.
Important: Never manually modify the contents of the
.gitdirectory. This could corrupt your deposit.
2. The Working Directory
As the name suggests, this is the directory where you do work in your project when you make changes to tracked files in your Git project. This is where the modified status of your files lives.
The working directory is one of two directories that will always remain local on your machine. This is considered a work in progress area, and changes that remain in this area will always be considered still work in progress.
3. The staging area (Staging Area / Index / Cache)
This is where files are moved when you want to commit or save your changes to a Git snapshot. This directory is often called the staging area, but it is also often called index or cache. This is where files in staged status live, waiting for you to save them in a commit.
The staging area is also local to your machine, but it serves as a buffer between your current work and your commit history.
Summary of the 3 directories
| Directory | Location | File Status |
|---|---|---|
.git (local history) | Hidden in the project root | Unmodified (committees) |
| Working Directory | Your working directory | Modified |
| Staging Area (Index/Cache) | Local buffer zone | Staged |
Introduction to common Git commands
Git is explicit: we have to tell it what to do before it does it. We use specific commands and sometimes options with those commands to be even more specific about how we want Git to do something.
In all, there are over 150 different Git commands, and most, if not all, can take options that further extend their capabilities. About 20 to 30 of these commands are considered fundamental or common.
From this point on, we’ll call our Git project a repository. This is the term Git uses to describe the project.
Git Command Categories
Basic commands are grouped into the following categories:
Git Basics
| Order | Description |
|---|---|
git init | Initializes a new Git repository in the current directory |
git status | Displays the current status of the repository (modified, indexed, untracked files) |
git add | Adds files to the staging area |
git commit | Save indexed changes to a new commit |
git diff | Shows differences between edited files and their previous versions |
git log | Show commit history |
Git Branches
| Order | Description |
|---|---|
git branch | List, create or delete branches |
git checkout | Switch between branches or restore files |
git merge | Merge a branch into the current branch |
Git Repositories
| Order | Description |
|---|---|
git clone | Clone a repository into a new directory |
git remote | Manages connections to remote repositories |
git push | Send local commits to a remote repository |
git fetch | Get changes from a remote repository without merging them |
git pull | Retrieves and merges changes from a remote repository |
Undoing Changes
| Order | Description |
|---|---|
git amend | Edit last commit |
git reset | Resets repository state to a previous commit |
git revert | Creates a new commit that reverts changes from a previous commit |
git reflog | Shows a log of all HEAD positions |
git cherry-pick | Apply changes from a specific commit to the current branch |
Coffee Analogy: Steve and Wired Brain Coffee
To illustrate Git concepts throughout this training, we use a coffee shop analogy to make these concepts more concrete.
Steve’s Story
Steve is the sole owner of a well-known downtown coffee shop called Wired Brain Coffee. Steve manages all operations and even developed most of the cafe’s recipes himself. To maintain the popularity of his coffee, he constantly tries new ideas by modifying existing recipes and changing some techniques and ingredients.
He wants to keep the existing recipes, but also follow all his changes in case he decides to modify the dish of the month.
Steve’s problems without Git
Currently, Steve stores all of these recipe files on his computer, and when he wants to make a change, he edits the actual file and then saves it again with a different recipe name. Its approach to backing up files is common and simple, but as we’ve learned, it’s incredibly error-prone:
- Steve made several mistakes and even accidentally backed up over files he didn’t intend to change.
- Steve sometimes works on his home computer as well as other devices. This made it difficult to maintain an up-to-date sync of the changes he made across these multiple devices.
- Steve also wants other people to contribute and have access to his recipes from any location. Eventually, he would like to have people contribute ideas and ingredients to his new recipes and perhaps even experiment with new methods of making drinks.
Git solves all of these problems! That’s why we’re going to use it in this training to manage Steve’s coffee recipe project.
3. Configure your local environment to start using Git
Git and the command line
Now that we have a good understanding of what Git is and how it manages our files between different statuses and directories, we need to make sure Git is installed before we can start using it.
Options depending on the operating system
On Mac:
- Open Terminal (Mac’s default command line application)
- Popular alternative: iTerm2 (
iterm2.com) which offers features like split panes, auto-completion and better in-page search
On Windows:
- Use the CMD window (Windows Command Prompt)
- Or use Git BASH, which tends to be the more popular choice of the two options
On Linux:
- You need a shell terminal
Check if Git is already installed
To check if Git is already installed, type in your command line:
git version
If Git is installed, you will get something like:
git version 2.37.1
Note for Mac users: You will probably see in parentheses after the Git version
Apple Gitfollowed by a number. If you see this, Apple has Git preinstalled on your computer with most likely an outdated version. With Git, there aren’t many major feature changes, so it’s generally acceptable.
Install Git
Regardless of what system you’re using, the best place to download Git is to navigate to git-scm.com. This is the official open source documentation for Git, and right on the home page you can see a prompt to download the latest version of Git.
This site detects the operating system you are using and will display the default download option for the system you are on.
Installing on Mac
The most common way is to use Homebrew, a free and open source software package management system that makes it easy to install software on Mac and Linux.
brew install git
Another option is to use MacPorts, another open source system used to install and upgrade software on your Mac.
Installation on Windows
Download the latest Git for Windows installer from git-scm.com, then go through the installation steps. The installation process will require some configuration, and Git BASH will be included in the installation.
Installing on Linux
On Debian/Ubuntu systems:
sudo apt-get install git
On Fedora/RHEL/CentOS systems:
sudo yum install git
Create a new Git repository
Now that Git is installed, let’s create a new Git repository. The repository represents your entire project. When you initialize Git for the first time in a project, you create a new Git repository inside that project called .git.
You can create a new empty project and initialize Git, or you can initialize Git with an existing project that already has a lot of content. Remember that wherever you initialize Git in a project, it will begin version control from that point in time.
Create a new project and initialize it with Git
# Créer un nouveau répertoire
mkdir demo
# Se déplacer dans ce répertoire
cd demo
# Initialiser un dépôt Git dans ce répertoire
git init
Git will return a message like:
Initialized empty Git repository in /Users/aarons/pluralsight/demo/.git/
Note on default branch
In newer versions of Git, you may see messages indicating that Git is looking to change from the default name master for the initial branch to the name main. Git will provide a git config command that you can run to make it a global setting:
git config --global init.defaultBranch main
Set Git configurations
Git has a config file in the .git directory. We can create Git configurations that will allow us to set certain settings when using Git.
There are two required Git configurations that you must set before you can make commits to the Git repository.
The three levels of Git configuration
Git configurations are done at three different levels:
-
System: Configurations defined at the system level and applied to all users of a machine. Useful if several users share the same computer.
-
Global: User-level settings that will apply to all Git repositories created under this user. These are the most common settings. Global configurations are stored in the
~/.gitconfigfile. -
Local: Settings specific to a single Git repository that will only apply to that repository. Local configurations override global configurations. They are stored in the
.git/configfile of the repository.
Essential Configuration Commands
Show all global configurations:
git config --global --list
Show all configurations (system + global + local):
git config --list
Both system requirements
Before you can make commits, you must set your username and email address:
# Définir le nom d'utilisateur global
git config --global user.name "Votre Nom"
# Définir l'adresse email globale
git config --global user.email "votre.email@exemple.com"
This information will be attached to each commit you create, so others can see who made each change.
Set default branch
git config --global init.defaultBranch main
Show specific configuration
git config user.name
git config user.email
Set a default text editor
With Git installed and the requirements set, we are now ready to start using Git.
Common text editors
Here are some common text editors compatible with Git:
- Visual Studio Code (recommended, cross-platform)
- Sublime Text (recommended, cross-platform)
- TextMate (Mac)
- Espresso (Mac)
- Notepad++ (Windows)
- Vim (universal, available in most terminals)
Open VS Code from terminal
A useful feature is to use your terminal to open VS Code in exactly the directory you are in. To enable this feature:
- Open Visual Studio Code
- Open the Command palette (View menu → Command Palette, or
Cmd+Shift+Pon Mac /Ctrl+Shift+Pon Windows/Linux) - Search for “shell” and select Shell Command: Install ‘code’ command in PATH
Now from your terminal you can simply type:
code .
And Visual Studio Code will open directly in the current directory.
Set VS Code as default editor for Git
git config --global core.editor "code --wait"
4. Work in a local repository
Add Git to an existing project
Now that we’ve covered the main concepts of Git, the next best thing is to see these Git concepts and commands in action using Git in a project.
In Steve’s story, his Wired Brain Coffee Shop project is located in a directory called coffee-shop-recipes with three folders: hot-beverages, iced-beverages, and syrups.
Terminal navigation
# Afficher le contenu du répertoire courant
ls
# Se déplacer dans le projet de Steve
cd wired-brain-coffee
# Afficher le chemin complet du répertoire courant
pwd
# Afficher tous les fichiers, y compris les fichiers cachés
ls -a
Initialize Git in an existing project
git init
After initialization, check the repository status:
git status
Git will return:
- There are no commits yet
- There are untracked files (existing files in the project)
- There is nothing added to the staging area to be committed
Add and track new files
After running git init on an existing project, Git tells us that there are untracked files. We need to tell Git to start tracking these files by adding them to the staging area to be committed.
Methods for adding files
When working in Git, there are often multiple ways to accomplish the same task. Here are the different ways to use git add:
# Ajouter un fichier spécifique
git add nom-du-fichier.md
# Ajouter un dossier entier
git add nom-du-dossier/
# Ajouter tous les fichiers non suivis/modifiés dans le répertoire courant
git add .
# Ajouter tous les fichiers non suivis/modifiés (alternative)
git add --all
git add -A
Check status after adding
git status
Files added to the staging area will now appear under the “Changes to be committed” section.
Make first commit
git commit -m "Initial commit - Add coffee shop recipe files"
After commit, git status will return that the working tree is clean (nothing to commit, working tree clean).
Make changes to files
Now that we have a Git repository and have made our first commit, let’s see how we can make changes to an already tracked file.
Scenario: Correct a file in Steve’s project
Steve wants to fix the caramel.md file in the syrups folder. The H1 title incorrectly says “Cinnamon Dolce Syrup” when it should say “Caramel Syrup”.
After making the modification in the editor and saving the file:
# Vérifier l'état - le fichier apparaîtra comme modifié dans le working directory
git status
# Ajouter le fichier modifié à la staging area
git add syrups/caramel.md
# Vérifier l'état - le fichier est maintenant dans la staging area
git status
# Commiter le changement
git commit -m "Fixed caramel file header"
Show differences between versions
The git diff command allows you to see exactly what changes have been made:
# Voir les modifications dans le working directory (non indexées)
git diff
# Voir les modifications dans la staging area (indexées, prêtes pour le commit)
git diff --staged
Create a new branch
So far everything has been done on the main branch, but since branches are an essential concept in Git, we should use multiple branches when committing changes to our project.
It is not recommended to make changes directly to the main branch. Of course, with Git you can always revert these changes, but branches allow you to work on new ideas and try new things without affecting your main branch.
Create and switch to a new branch
# Créer une nouvelle branche appelée "feature"
git branch feature
# Vérifier que nous sommes toujours sur main
git status
# Afficher toutes les branches locales (l'étoile * indique la branche courante)
git branch -a
# Basculer vers la branche feature
git checkout feature
# Alternative moderne (créer ET basculer en une seule commande)
git checkout -b feature
After running git checkout feature, Git will confirm:
Switched to branch 'feature'
Show different file statuses
Now that we are on the feature branch, Steve wants to make several changes. This illustrates Git’s flexibility to handle multiple changes in different states simultaneously.
Scenario with multiple files in different states
Steve makes two modifications:
- File 1 (café-latte.md): Change “1 cup of whole milk” to “1 cup of almond milk” → added to the staging area
- File 2 (frozen-mocha.md): Add a new step → remains in the working directory
# Après les modifications, vérifier l'état
git status
# Résultat :
# Changes to be committed: cafe-latte.md (staged)
# Changes not staged for commit: frozen-mocha.md (modified)
View change details
# Voir les modifications non indexées (working directory)
git diff
# Voir les modifications indexées (staging area)
git diff --staged
Note: The fact that Steve leaves for the weekend with one change in the staging area and one in the working directory perfectly illustrates the freedom that Git offers: you don’t have to commit everything at the same time. You can have work in progress at different stages and choose what you want to include in each commit.
The —patch option for partial commits
Git even allows you to add specific changes in the same file (specific lines):
git add -p nom-du-fichier
The -p (patch) option allows you to iterate through the changes in a file and select the specific line changes you want to add to the staging area while leaving the others behind in the working directory.
Merge one branch into another
After making several commits to different branches, it’s time to merge these changes.
Go back to the main branch and make a commit
# Retourner sur main
git checkout main
# Faire une modification et un commit sur main
# (pour créer une vraie histoire divergente)
git add .
git commit -m "Update recipe on main branch"
Merge feature branch into main
# S'assurer d'être sur la branche de destination (main)
git checkout main
# Fusionner la branche feature
git merge feature
If the merge succeeds without conflicts, Git will create a merge commit and display the files that have changed.
Show commit history
As you make more and more commits, it’s useful to see a history of your commits.
The git log command
Git provides a log command that will list the commit history of the Git repository. It includes all branches, and there are many options to define exactly what information you want to see (over 100 options available!).
git logis a display command, so all options are only for displaying information — they cannot be used to modify anything in your Git repository.
# Afficher l'historique complet
git log
Each commit shows:
- The full commit ID (40 character SHA-1 hash)
- The author of the commit
- The date and timestamp of the commit
- The commit message
- Branch pointers (where
main,feature,HEADare located)
To exit the log, press Q.
Common git log options
# Afficher chaque commit sur une seule ligne (ID abrégé + message)
git log --oneline
# Afficher le graphe des branches
git log --oneline --graph
# Afficher le graphe de toutes les branches
git log --oneline --graph --all
# Afficher les N derniers commits
git log -5
# Afficher les modifications de chaque commit
git log -p
# Afficher un résumé des fichiers modifiés
git log --stat
# Afficher les commits depuis une date
git log --since="2023-01-01"
# Afficher les commits par un auteur spécifique
git log --author="Aaron Stewart"
# Rechercher dans les messages de commit
git log --grep="fix"
5. Work with others in a shared repository
Git on the network
This part is about working with Git on the network. The majority of people working with Git do so in a shared network environment.
A network Git repository is a centralized location where you and others can collaborate to share changes to the project in the form of Git commits.
The basic principle
Remember that one of the characteristics of Git is that it is local. This means that everything you do in Git is done locally on your computer. Even when you’re working in a shared Git repository on the network, but wait a minute — if we’re working in a shared repository, are we making changes directly on the server?
The answer is no. Everything in Git is done locally, then shared with the repository on the network for others to see and retrieve.
This centralized Git repository is just a copy of the same repository that you and others copy to work on on your own local machine. Essentially, you can think of this centralized Git repository on the network as a branch that you want to exchange commits with:
git push: Send your commits to the centralized repositorygit fetch/git pull: Retrieve commits that others have pushed
Popular hosting platforms
The most popular options for hosting a Git repository on the network are:
- GitHub: The most popular code hosting platform in the world
- GitLab: Open source alternative to GitHub, can be self-hosted
- Bitbucket: Atlassian solution, well integrated with Jira
These platforms are cloud hosting platforms that you can use as a central repository to collaborate with others on your Git projects.
Configure a remote repository on GitHub
Steve wants to put his project on the network so others can see it, collaborate and contribute to his project.
Create a new repository on GitHub
- Log in to your user profile on GitHub
- Navigate to the Repositories tab
- Click New to create a new repository
- Give it a unique name (ex:
coffee-shop-recipes) - Add a description (e.g.: “A place to store, create, and explore new coffee shop recipes”)
- Choose Public so others can see it
- Click Create repository
Link local repository to remote repository
After creating the repository on GitHub, you will have a few options for linking your local repository. For an existing project with a commit history, use the following commands:
# Ajouter une connexion remote (lien vers le dépôt distant)
git remote add origin https://github.com/username/coffee-shop-recipes.git
# Vérifier les connexions remote configurées
git remote -v
You will see two connections to the same URL:
origin https://github.com/username/coffee-shop-recipes.git (fetch)
origin https://github.com/username/coffee-shop-recipes.git (push)
Why two connections? This concerns the two basic operations when working with remote repositories:
git push(send changes) andgit fetch/git pull(fetch changes).
Send local commits to the network
Now that we have linked our local repository to a repository on the network, let’s use the git push command.
Parse git push command
The complete command for the first push is:
git push -u origin main
Let’s break this command down:
git push: The Git command to send or push commits that we have locally and which are not yet represented in the remote Git repository on the network-u(upstream): Configure an upstream — define where we send our commits to the remote repository. The-uoption is needed the first time we want to push commits to a branch that we created locally but not yet to the remote repository. It tells the remote Git repository to create a remote tracking branch on the network that will link to our local branch.origin: The name of the remote (shortcut for the URL of the remote repository)main: The name of the branch we want to push
Once the upstream is configured, for the following pushes, you can simply use:
git push
Push a feature branch
# Première fois pour une nouvelle branche
git push -u origin feature
# Ensuite
git push
Clone a Git repository from the network
Now that we have our Git repository on the network, we can invite other team members to collaborate. But before they can collaborate, they need a copy of the project on their own computer.
By having this centralized Git repository on the network, each collaborator can simply clone Steve’s project from the network and then work on it locally.
How to clone a repository
- Navigate to the repository on GitHub
- Select the Code tab
- Copy the provided GitHub URL
- In the terminal, navigate to the location where you want the project to be copied
- Run the command:
git clone https://github.com/username/coffee-shop-recipes.git
Git will tell you that it is cloning the Git repository in the current directory, then return data telling you that the clone was successful.
Important: When cloning a project from GitHub, the remote connection to the origin is automatically configured, so any member who copies this project will automatically have this remote connection created.
# Après le clonage, vérifier la connexion remote
git remote -v
Retrieve and pull commits from the network
Now that we’ve seen how a team member can clone the repository from the network, make a change to a file in its local copy, and push that change to the Git repository on the network, it’s time for Steve to pull in the latest changes.
git pull — The most common command
The git pull command automatically pulls commits from the network that your local Git repository doesn’t have, then integrates them into the local versions of your branches.
git pull
git pull is essentially running two Git commands in one:
git fetch: Fetch changes from the networkgit merge: Merges these changes into your local repository
git fetch — Fetch without merging
What if you wanted to see the changes first before Git automatically merges them into your local repository? This is where git fetch comes in.
# Récupérer les changements du réseau sans fusionner
git fetch
# Vérifier l'état après le fetch
git status
# Résultat : "Your branch is behind 'origin/main' by 1 commit, and can be fast-forwarded."
# Git vous dit que vous pouvez exécuter 'git pull' pour fusionner ce commit
# Voir les changements récupérés avant de les fusionner
git log origin/main
# Fusionner les changements récupérés
git pull
Introduction to merge strategies
When working with different branches, you may need to merge them together to bring commits from one branch into another.
There are different types of merge strategies that you can use with Git, and depending on how you want your commit history to appear, it may depend on the type of merge you are asking to perform.
Type 1: Fast-Forward Merge
This is the most basic and simple type of merge, and it can only be done if you have a linear commit path between the two branches.
Visualization:
Avant la fusion :
main: A---B
\
feature: C---D
Après fast-forward merge de feature dans main :
main: A---B---C---D
In this example, the feature branch is two commits ahead of main, but no other commits have been made to main to create a true divergent story. The commit history between these two branches is linear. So when we merge feature into main, Git can simply advance the main pointer to the last commit of feature.
git checkout main
git merge feature
# Git effectuera automatiquement un fast-forward merge
Type 2: Three-Way Merge
When the two branches have diverged (that is, commits have been made to both branches since the point of divergence), Git cannot do a fast-forward merge. Instead, it performs a three-way merge which creates a new merge commit.
Visualization:
Avant la fusion :
main: A---B---E
\
feature: C---D
Après three-way merge de feature dans main :
main: A---B---E---M (merge commit)
\ /
feature: C---D
git checkout main
git merge feature
# Git crée automatiquement un merge commit
Type 3: Rebase (advanced)
An advanced strategy that rewrites history to create a linear history:
git checkout feature
git rebase main
Warning: The rebase rewrites the commit history. It should not be used on shared branches or commits already pushed to a centralized repository. This can create problems for other employees.
6. Merge conflicts: what are they and how to resolve them?
Understanding merge conflicts
Unless you are working on a personal project alone, you will be working with others in a Git repository shared with dozens, hundreds, or even thousands of other people contributing to the same project.
Even following best practices, you can and probably experience a merge conflict.
What is a merge conflict?
A merge conflict occurs when there are conflicting changes introduced to the same content of the same file. This means:
- Someone made changes to a file and pushed them to the centralized Git repository on the network
- Then you make a different change to the same file contents
- When you try to push your change, Git doesn’t know which change to accept
The 3 most common merge conflict situations
-
Same line changed: More than one person changes the same line in a file and both try to merge the changes to the same branch.
-
Deletion vs. modification: Someone deletes content in a file, but another person edits the same content.
-
File deletion vs modification: Someone deletes a file entirely, but someone else has made changes to that same file.
Create merge conflict
To illustrate, here is how a conflict is created in Steve’s project:
Team member side
The team member makes changes to the white-mocha.md file:
- Change “1 cup of 2% whole milk” to “1 cup of whole milk”
- Update “2% milk” to “whole milk” in step 4
- Add “And pairs perfectly with an almond croissant” to description
git status
git add hot-beverages/white-mocha.md
git commit -m "Update white mocha recipe"
git push
Steve’s side (at the same time, without having done git pull)
Steve also makes changes to the same white-mocha.md file:
- It changes the same description line differently
git add hot-beverages/white-mocha.md
git commit -m "Update white mocha description"
Conflict occurs during git pull or git merge
When Steve tries to merge the team member’s changes:
git merge update-mocha
# CONFLICT (content): Merge conflict in hot-beverages/white-mocha.md
# Automatic merge failed; fix conflicts and then commit the result.
Resolve merge conflict
Git is telling us that there is a conflict with the content we are trying to merge into the main branch, and Git cannot complete the merge until we resolve this conflict.
Steps to resolve a conflict
# Voir plus d'informations sur le conflit
git status
Git gives us two options:
- Fix conflicts and then run
git committo confirm the changes - Abort merge with
git merge --abort
Git also pointed out the exact file(s) that had a conflict and moved them back into our working directory.
Conflict markers
When opening the conflicting file in the text editor, you will see merge conflict markers:
<<<<<<< HEAD
Contenu de la branche courante (HEAD / main)
=======
Contenu de la branche entrante (update-mocha)
>>>>>>> update-mocha
- The top section (between
<<<<<<< HEADand=======) is called current change — this is the content in conflict on the current branch (main in our case) - The bottom section (between
=======and>>>>>>> update-mocha) is called incoming change — this is the conflicting content on the branch we are trying to merge
How to solve
- Decide what you want to keep: the current change, the incoming change, both, or a combination
- Remove conflict markers (
<<<<<<<,=======,>>>>>>>) and any content you don’t want - Save the file
In VS Code, you have practical buttons:
- Accept Current Change: Keep only the contents of HEAD
- Accept Incoming Change: Keep only incoming content
- Accept Both Changes: Keep both contents
- Compare Changes: See the differences side by side
Finalize resolution
# Après avoir résolu tous les conflits dans le fichier
git add hot-beverages/white-mocha.md
# Commiter pour finaliser la résolution du conflit
git commit -m "Resolve merge conflict in white mocha recipe"
Git automatically creates a merge commit message, but you can customize it.
Prevent merge conflicts
Knowing how to resolve merge conflicts is great, but there are best practices to follow that will help reduce the number of merge conflicts you and your team experience.
1. Standardize your formatting
Many conflicts arise simply because of formatting mismatches — extra spaces, different coding styles. You can apply code formatters and linting rules to ensure your team is aware of these issues and to reduce the number of these types of merge conflicts.
2. Make small and frequent commits
Taking weeks to make changes to a branch and adding lots of changes to lots of files is almost like asking for merge conflicts. It’s generally best to make small and direct changes and then merge them into your main branch frequently. Don’t wait long periods of time to merge changes if you can avoid it.
3. Communicate and pay attention
Talk to each other and know who is working on what. If multiple people are making changes to the same files, work together and communicate often. This is a great way to help reduce the number of merge conflicts within your team.
7. How to modify and correct your commits
Fix commit error with git amend
So far we have made a lot of commits. These commit IDs are really important and are what Git uses to track and manage each commit snapshot.
What makes up a commit ID
Git uses the following to create each commit ID:
- The author
- The timestamp
- The commit message
- The actual changes made
- Even commits that precede this commit
All of these and more are used when Git creates the commit ID. So, as you can imagine, editing an existing commit will change this ID.
The general rule for modifying history
If your commits exist only locally and you haven’t pushed them to a centralized Git repository that others use, you are free to modify these commits as much as you want.
If you have already pushed commits that others base their work on, changing the history will create a broken history.
Using git amend
The git commit --amend command allows you to modify the latest commit (only).
Common use cases:
- Fix a commit message:
git commit --amend -m "Nouveau message de commit corrigé"
- Add forgotten files to last commit:
# Ajouter le fichier oublié à la staging area
git add fichier-oublie.md
# Amender le dernier commit (inclure les nouveaux fichiers indexés)
git commit --amend --no-edit
# --no-edit conserve le même message de commit
- Edit message AND add files:
git add fichier-oublie.md
git commit --amend -m "Nouveau message incluant le fichier oublié"
Note:
git amendcreates a completely new commit replacing the last one. The old commit is removed from visible history, although it is still accessible viagit reflog.
Rewrite history with git reset
Sometimes we need something more robust — something we can use to reset some or even all of our files to look like they did at a different time in history.
The three git reset options
Git provides three options available with git reset:
Option 1: git reset —soft
This type of reset will take a commit from our history and put it back in our staging area. This is useful if you need to group commits or alter something in the changes indexed for the commit.
# Réinitialiser les 2 derniers commits vers la staging area
git reset --soft HEAD~2
After this command, git status will show the changes in the staging area, ready to be recommitted.
Option 2: git reset (—mixed, the default option)
This is the default option for reset. It will take a commit from history and place it in your working directory. This is if you want to take these changes back to the drawing board and make modifications before indexing them again.
# Réinitialiser les 2 derniers commits vers le working directory (option par défaut)
git reset HEAD~2
# Équivalent à :
git reset --mixed HEAD~2
After this command, git status will show the files in the working directory (not staged for commit).
Option 3: git reset —hard
⚠️ Warning: This is a destructive command! This type of reset will take a commit from history and throw it in the trash — almost as if it never happened. Double-check your work before using this type of reset.
# Supprimer définitivement les 2 derniers commits
git reset --hard HEAD~2
After this command, the commits and their changes disappear — they are neither in the staging area nor in the working directory.
Syntaxes for specifying the reset point
# Réinitialiser jusqu'à N commits en arrière
git reset HEAD~1 # Réinitialiser le dernier commit
git reset HEAD~3 # Réinitialiser les 3 derniers commits
# Réinitialiser jusqu'à un commit spécifique par son ID
git reset abc1234
# Réinitialiser jusqu'au commit parent du commit actuel
git reset HEAD^
Summary table of git reset options
| Options | Staging Area | Working Directory | History |
|---|---|---|---|
--soft | Keep changes ✓ | Unchanged | Commit deleted |
--mixed (default) | Empty | Keep changes ✓ | Commit deleted |
--hard | Empty | Remove changes ✗ | Commit deleted |
Recover deleted history with git reflog
After using git reset --hard to delete commits containing files 5, 6 and 7, Steve realizes he made a big mistake. He doesn’t want files 6 or 7, but he really wants file 5 back.
Git provides a way to recover commits, even if you deleted them with a git reset.
git reflog — The log of all HEAD positions
Similar to git log which tracks our commits, Git has a log which tracks wherever HEAD has been, and it is called the git reflog.
Reflog limitations
- Local only: The reflog is not pushed to the remote Git repository and only includes your local history. You can’t see the reflog of someone else’s commits.
- Limited duration: By default, these commits are only displayed in the reflog for 90 days. After 90 days, these commits are completely lost.
Using reflog to retrieve a commit
# Afficher le reflog
git reflog
The reflog shows output similar to git log --oneline. This is a history of where HEAD is, so we can find where we added file5 and then copy that commit ID.
Revert a commit with git cherry-pick
# Copier l'ID de commit du fichier que vous voulez restaurer depuis le reflog
# Exemple : abc1234
# Restaurer ce commit directement dans l'historique des commits
git cherry-pick abc1234
git cherry-pick allows you to take a commit from the reflog and place it directly in the commit history — not in the working directory or the staging area, but directly in the history.
Git will return output similar to when you make a normal commit, with the abbreviated commit ID and commit message.
8. Popular Team Workflows
Introduction to Git workflows
At this point, we have covered the main concepts and fundamentals of Git. These concepts and fundamentals will hold true in any Git project you work on.
It doesn’t matter if you’re working on a personal project alone, just on your local machine, or if you’re contributing to a centralized Git repository on the network with thousands of other contributors. The process of adding files from the working directory to the staging area and then committing those changes is a fundamental concept of how Git works.
What may change is the workflows and how you integrate your changes into the Git repository. Depending on the needs of the project, these workflows can be simple or a little more involved.
Pull requests in the workflow
Depending on the code hosting platform you use, there are collaboration features like pull requests (or merge requests on GitLab) that you can integrate into your Git workflow that will improve the way you review, discuss, and secure your Git projects.
Basic Workflow
The easiest way to use Git is to use a Basic Workflow.
Description
This workflow uses the default main branch as the only branch that contributors use to make their changes.
[Dépôt centralisé sur le réseau]
| ^
clone/pull |push
| |
[Copie locale 1] [Copie locale 2] [Copie locale 3]
Each contributor can:
- Clone the repository
- Work locally on the project
- Push their commits to the central repository — all on the main branch
Advantages
- Extremely simple to understand and use
- Perfect for personal projects or projects with very few contributors
Disadvantages and limitations
- Can quickly become problematic if more than one contributor wants to work on different features within the project
- Having everyone contribute to the
mainbranch is a great way to run into a lot of merge conflicts - Does not provide much flexibility to build features without affecting the production-ready project on the
mainbranch
This workflow works well for simple personal projects where you are the only contributor. This was the case for Steve at first, but with the addition of more contributors, it’s best to move to a workflow that better supports divergent history.
Feature Branch Workflow
The Feature Branch Workflow takes the basic workflow, but instead of committing directly to the main branch, contributors create feature branches from main when they want to work on new features or try new ideas.
Description
main: A---B-----------M (merge commit)
\ /
feature-login: C---D---E
With this workflow:
- Everything in the
mainbranch is deployable - When you want to work on a new feature, you create a new feature branch from
main - You can also create feature branches from other feature branches
Advantages
- Offers feature branching, but not too complex
- Workflow adapted to continuous integration and continuous delivery (CI/CD)
- Good option if you only need to maintain a single version in production
- Allows team members to better review code changes in feature branches before they are merged into the main branch
Disadvantages
- With these feature branches merging into
main, the only production version of the project, it is easy for errors to end up in production - Not a good option if you need release branches or multiple versions of the project in a production environment
If you want feature branches and only need one version of the project deployable to production, this workflow could be a good option. But if you need these features, but also need to better secure the main branch with release and develop branches, you will probably want the next workflow: the Git Flow.
Git Flow
The Git Flow takes the Feature Branch Workflow and adds some elements to it. This is the most common workflow you’ll encounter when working with Git repositories in larger teams.
Branch structure in Git Flow
main: ●-----------●-----------● (versions en production)
| | |
release: ●---●---● ●---●---●
| |
develop: ●---●---●---●---●---●---● (pré-production)
| | |
feature-A: ●---● | |
| | |
feature-B: ●---● |
|
hotfix: ●---●
Main branches
| Branch | Role |
|---|---|
main | Production version of the project — still stable and deployable |
develop | Pre-production branch — changes from feature branches are merged here |
feature/* | Branches to work on new features |
release/* | Branches of preparing a release |
hotfix/* | Branches for urgent fixes in production |
Description
The main difference with the Feature Branch Workflow is that contributors branch from develop and not from main.
The develop branch is a pre-production environment, so changes merged from the feature branches can be reviewed and tested in this pre-production state before being merged into the main branch, which is the production version of the project.
This adds that extra level of review and testing that helps eliminate errors and buggy code from the main branch.
Advantages
- Very popular, especially in the open source community
- Project maintainers can better review and approve code going into release or develop branches before being merged into main
- Works well with established products and multiple versions of the project
- Adds that extra layer of review, significantly reducing the amount of errors going into production
Disadvantages
- Sometimes this workflow can slow things down — it can take time to review and push to production
- Going through all these different branches can also be confusing for new team members contributing to a workflow and knowing all the different steps to merge their code
- With all these extra layers of branch merging, you may encounter merge conflicts more often
How these workflows are documented and communicated across the team makes all the difference when working in a large project environment.
9. Summary and next steps
Summary
Understanding the fundamentals of Git is a great start to working and contributing to a Git repository. And if you don’t consider yourself a developer, most companies these days are turning to Git repositories to better manage, secure, and innovate their projects and products.
What you learned in this training
-
Thinking in Git: Understand the characteristics of Git, the stages of a file, and the three main directories of Git.
-
Set up your Git environment: Install Git using the command line, basic command line navigation, and configure some Git configurations and your text editor.
-
Working in a local project (Steve’s Wired Brain Coffee Shop project):
- Add new files to a Git project
- Make changes and commit these changes to history
- Show these changes using the commit log
- Show changes in different file states using
git diffcommand - Merge these changes into the
mainbranch
- Working with a centralized repository on the network:
- Set up a centralized Git repository on the network so other team members can contribute
- Remote branches and how to interact with remote Git repositories with commands like
git push,git clone,git fetch, andgit pull
-
Merge strategies: Fast-forward merges and three-way merges, and a brief introduction to rebasing.
-
Merge conflicts: How they arise, how to resolve them with conflict markers, and best practices to prevent them.
-
Edit commit history:
git amendto modify the last commitgit resetwith its three options (soft, mixed, hard)git reflogto recover deleted commitsgit cherry-pickto restore a specific commit
- Popular team workflows: Basic Workflow, Feature Branch Workflow, and Git Flow.
Next steps
Now that you have a solid understanding of these fundamentals, expanding your knowledge with a deeper dive into Git is a great next step.
Suggested further developments
-
Understanding Git’s internal storage: How Git stores and manages your commits in depth — the objects, the blobs, the trees, the refs, and exactly what goes into each commit ID.
-
Advanced Git Commands: There are so many other commands you can use. They are separated into two categories:
- Porcelain commands: High-level commands (those we saw in this training)
- Plumbing commands: Low level commands that do what porcelain commands do, but at a lower level
-
Git Aliases: There’s a lot more you can do with Git configurations by creating aliases that you can use for those long Git commands:
# Exemple d'alias Git git config --global alias.st status git config --global alias.co checkout git config --global alias.br branch git config --global alias.cm "commit -m" git config --global alias.lg "log --oneline --graph --all" -
Customize the command prompt: Learn how to customize your command prompt to display the current Git branch and other useful information.
-
Visual tools for Git: Tools like GitKraken, Sourcetree, or VS Code extensions like GitLens can make viewing your Git history much more intuitive.
-
The official Git documentation: Navigate to
git-scm.com/docsfor complete documentation of all Git commands.
Resources mentioned in the training
- git-scm.com: Official Git documentation
- iterm2.com: Enhanced Terminal for Mac
- Homebrew: Package manager for Mac/Linux
- The GitHub repository used in training for Steve’s Wired Brain Coffee Shop project, which also includes a bash script to create the files used when learning
git reset
10. Appendix: Git Commands Quick Reference
Basic commands
# Initialiser un nouveau dépôt
git init
# Vérifier l'état du dépôt
git status
# Ajouter des fichiers à la staging area
git add <fichier> # Un fichier spécifique
git add . # Tout dans le répertoire courant
git add -A # Tous les fichiers (équivalent à git add --all)
git add -p <fichier> # Mode interactif (patch) pour ajouter des lignes spécifiques
# Commiter les changements
git commit -m "Message de commit"
git commit --amend -m "Corriger le message du dernier commit"
git commit --amend --no-edit # Amender sans changer le message
# Afficher les différences
git diff # Différences dans le working directory
git diff --staged # Différences dans la staging area
# Afficher l'historique
git log # Historique complet
git log --oneline # Historique simplifié
git log --oneline --graph --all # Graphe de toutes les branches
git log -5 # Les 5 derniers commits
Branch commands
# Lister les branches
git branch # Branches locales
git branch -a # Toutes les branches (locales + distantes)
# Créer une branche
git branch <nom> # Créer sans basculer
git checkout -b <nom> # Créer ET basculer
# Basculer de branche
git checkout <nom>
# Fusionner une branche
git merge <nom-branche>
# Supprimer une branche
git branch -d <nom> # Suppression sécurisée (refuse si non fusionnée)
git branch -D <nom> # Forcer la suppression
Network commands (remote)
# Gérer les remotes
git remote -v # Lister les remotes
git remote add origin <url> # Ajouter un remote
# Cloner un dépôt
git clone <url>
# Envoyer des commits
git push -u origin main # Premier push (configure l'upstream)
git push # Pushes suivants
# Récupérer des commits
git fetch # Récupérer sans fusionner
git pull # Récupérer ET fusionner (fetch + merge)
Cancel commands
# Modifier le dernier commit
git commit --amend -m "Nouveau message"
# Réinitialiser des commits
git reset --soft HEAD~N # N commits vers la staging area
git reset HEAD~N # N commits vers le working directory (défaut --mixed)
git reset --hard HEAD~N # Supprimer définitivement N commits
# Voir l'historique de HEAD
git reflog
# Restaurer un commit supprimé
git cherry-pick <commit-id>
# Créer un commit d'annulation (sûr pour les dépôts partagés)
git revert <commit-id>
Configuration commands
# Voir la configuration
git config --list
git config --global --list
# Configurer l'identité (requis)
git config --global user.name "Votre Nom"
git config --global user.email "email@exemple.com"
# Configurer la branche par défaut
git config --global init.defaultBranch main
# Configurer l'éditeur
git config --global core.editor "code --wait"
# Créer des alias
git config --global alias.st status
git config --global alias.lg "log --oneline --graph --all"
Search Terms
git · fundamentals · ci/cd · devops · merge · branch · commands · repository · commit · conflict · reset · local · command · commits · default · history · network · pull · steve · configuration · option · options · reflog · set