Skip to content

๐ŸŒฑ Install and Use Git

git-logo Git is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency. Git is easy to learn and has a tiny footprint with lightning fast performance.

This documentation details the following procedures:

  • basic introduction of git
  • installation of a git server on linux
  • creation of an empty git repository
  • installation/configuration of a git website using gitlist

๐Ÿงญ Basic Git usage

๐Ÿ“ Basic Git commands

The default branch of Git were commits are pushed is "master".

git-workflow

git status                              # see the current status of files for git
gitk                                    # see status graphicaly
git add files                           # add files to staging (waiting to be committed)
git add -A                              # add all files and folder to staging
git rm files                            # remove files to be committed
git restore files                       # removes the changes that weren't committed
git commit -m "message"                 # commit the files added 
git branch test                         # create a branch "test"
git branch -D test                      # remove a branch "test"
git checkout test                       # switch to the branch test

Tip

To remove permanently everything that is referenced only in the reflog execute the following commands:

git reflog expire --expire-unreachable=now --all && git gc --prune=now

๐Ÿ“š Basic Usage

The following section explains how to create a local repository.

# quick steps to initialize a local repository
cd source-directory
git init                                        # initialize an empty local git repository
git commit -m "initial release" --allow-empty   # push an empty commit to allow full-rebase afterward
git status                                      # display the status of files in the repos

# mask all object files and binaries for status command
touch .gitignore                                # create .gitignore file
nano .gitignore                                 # edit file
    .vs
    Debug
git add .gitignore                              # add files to be committed
git commit -m "add .gitignore file"             # commit the files
git status                                      # see status

๐Ÿง  Advanced Usage

๐Ÿงจ Rewrite History

It's possible to rewrite the history of the local repository using git rebase.

git rebase -i HEAD~3                            # edit history of git with the last 3 commits
git rebase -i commit^                           # edit history of git using the first 7 characters of the git hash
git rebase -i --root                            # edit history since the first commit
Usefull options
Field Description
edit or e rework the commit to allow split/add/remove files
squash or s merge the commit
reword or r reword the name of the commit

It's possible to add/remove/split files from a commit by resetting it's state to the previous commit:

git reset HEAD^                                 # reset state to the previous commit to allow add/remove/split files

๐Ÿงฉ Create and Apply Patches

# create a patch from a commit
git format-patch -1 <sha>

# create n commits (here: 1)
git format-patch -1 HEAD
# apply the patch to a file
git am < file.patch

๐Ÿ—‚๏ธ Git LFS

๐Ÿงฎ Introduction

Git LFS is an open-source project and is an extension to Git. The goal is to work more efficiently with large files and binary files into your repository.

๐Ÿ“– Description

git-lfs Git is a distributed version control system, meaning the entire history of the repository is transferred to the client during the cloning process. For projects containing large files, particularly large files that are modified regularly, this initial clone can take a huge amount of time, as every version of every file has to be downloaded by the client. Git LFS (Large File Storage) is a Git extension developed by Atlassian, GitHub, and a few other open source contributors, that reduces the impact of large files in your repository by downloading the relevant versions of them lazily. Specifically, large files are downloaded during the checkout process rather than during cloning or fetching.

Git LFS does this by replacing large files in your repository with tiny pointer files. During normal usage, you'll never see these pointer files as they are handled automatically by Git LFS. When a Git LFS file is pulled to your local repository, the file is sent through a filter which will replace the pointer with the actual file. The actual files are located on the remote server and the pulled actual files are located in a cache in your local repository. This means that your local repository will be limited in size, but the remote repository of course will contain all the actual files and differences.


๐Ÿ“ฆ Installation

The Git LFS extension should be automatically installed with Git.

sudo apt install git-lfs

๐Ÿท๏ธ Create a Git LFS repository

# initialize a git repository
mkdir <dir> && cd <dir>
git init
git commit --allow-empty -m "initial release"

# initialize git-lfs in this repository
git lfs install
# tracking binary files
git lfs track '*.exe'
git lfs track '*.dll'

# see a list of all patterns currently being tracked by git-lfs
git lfs track

# see the list of tracked binary files by git-lfs
git lfs ls-files

# push the .gitattributes
git add .gitattributes
git commit -m "activate git-lfs by tracking files and pushing .gitattributes"
# remove permanently everything in git lfs that is referenced only in the reflog
git lfs prune

Important

Don't forget to track files using git lfs track '*.xxx' after the git lfs install then commit the .gitattributes file.


๐Ÿ–ง Install Git server

This guide explains how to set up a Git server accessible over HTTPS for cloning and pushing to bare repositories.

For example: https://git.domain.fr/repo.git

On Debian systems, a common and lightweight setup relies on:

  • nginx โ€” handles HTTPS (TLS) and authentication
  • git-http-backend โ€” Gitโ€™s Smart HTTP backend providing repository access
  • fcgiwrap โ€” executes CGI programs for nginx

This combination allows secure Git operations over standard HTTPS without requiring SSH access.

# install required packages
sudo apt update
sudo apt install nginx fcgiwrap git git-core

# enable fcgiwrap
sudo systemctl enable --now fcgiwrap

โš ๏ธ Disable Git safety check

Git includes a security feature that prevents operations in repositories owned by a different user. This helps protect against executing Git commands in directories that may have been modified by another account.

On systems where repositories are intentionally shared between users, this protection may block normal Git operations. If the machine is fully under your control and repositories are trusted, you can disable this check globally:

git config --global --add safe.directory '*'

๐Ÿ“ Create empty Git repository

With Git Smart HTTP over HTTPS, repository operations are executed by the web server process (www-data when using nginx + fcgiwrap). As a result, objects created during pushes will be owned by www-data unless permissions are configured to allow shared access.

To allow collaborative access, we add www-data to the debian group and configure the repository directory so that new files inherit this group.

# allow the web server to share repository permissions
sudo usermod -aG debian www-data

# path where Git repositories will be stored
GIT_REPOS=/media/ssd/git

# check that git repository is set
[ -n "${GIT_REPOS}" ] && [ -d "${GIT_REPOS}" ] || { echo "Invalid git repository directory: ${GIT_REPOS}"; exit 1; }

# create the repository root and initialize a bare repository
mkdir -p "${GIT_REPOS}"
cd "${GIT_REPOS}"
git init --bare

# enable pushes over HTTP for each bare repo
sudo -u www-data git config core.sharedRepository group
sudo -u www-data git config http.receivepack true

# ensure proper ownership and shared permissions
sudo chown -R www-data:debian "${GIT_REPOS}"
sudo find "${GIT_REPOS}" -type d -exec chmod 2775 {} \;
sudo find "${GIT_REPOS}" -type f -exec chmod 0664 {} \;

Note: 2775 enables the setgid bit on directories so newly created files and directories automatically inherit the debian group. Then reload services later (nginx/fcgiwrap) so group membership is picked up.

Replace Fields

Replace the following fields:

Field Description
<GIT_REPOS> Directory where Git repositories will be stored

๐ŸŒ nginx Git HTTPS setup

Install NGINX

NGINX needs to be installed, follow the NGINX section.

Configure NGINX

NGINX needs to be configured using a file in /etc/nginx/sites-enabled directory.
This configuration file specify the documentation path:

server {
  server_name git.domain.fr;

  # setup 404 error_page
  error_page 404 /404.html;
  include snippets/error-404.conf;

  # --- Authentication ---
  auth_basic "Git";
  auth_basic_user_file /etc/nginx/.htpasswd;

  # where your bare repos live
  set $git_root /media/ssd/git;

  # for large pushes/clones
  client_max_body_size 0;
  client_body_timeout 300s;
  client_header_timeout 300s;
  send_timeout 300s;

  # only forward Git smart-HTTP endpoints to git-http-backend
  location ~ ^/.+\.git/(info/refs|git-(upload|receive)-pack)$ {
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME /usr/lib/git-core/git-http-backend;
    fastcgi_param GIT_PROJECT_ROOT $git_root;
    fastcgi_param GIT_HTTP_EXPORT_ALL "";
    fastcgi_param PATH_INFO $uri;
    fastcgi_param REMOTE_USER $remote_user;
    fastcgi_pass unix:/run/fcgiwrap.socket;

    fastcgi_read_timeout 300s;
    fastcgi_buffering off;
  }

  # everything else: 404
  location / { return 404; }
}
# restart NGINX
sudo nginx -t && sudo service nginx restart

Replace git.domain.fr by the name of your website.

Activate HTTPS

To activate HTTPS protocol, follow theย Let's Encrypt section.


๐Ÿ” Configure HTTPS Basic Auth

# install htpasswd utility (provided by apache2-utils)
sudo apt install apache2-utils

# create Basic Auth credentials for the 'git' user
# the command will prompt for the password
sudo htpasswd -c /etc/nginx/.htpasswd git

# set secure permissions for the credentials file
sudo chown root:www-data /etc/nginx/.htpasswd
sudo chmod 640 /etc/nginx/.htpasswd

# reload nginx to apply authentication configuration
sudo systemctl reload nginx

๐Ÿ“ค Pushing first commit

The git repository needs to be cloned before pushing the first commits.
Clone the server git repository on a client machine then push a commit to the *server.

# clone the git reposiroty located on the server
git clone https://git.domain.com/repository.git

# push first empty commit
git commit --allow-empty -m "initial release"
git push origin master

๐Ÿช Configure Git Hook

Git hooks are scripts triggered by Git events. When certain actions occur (such as a push), Git checks the repositoryโ€™s hooks directory and executes the corresponding script if it exists.

In this setup, a server-side post-update hook will run after a successful push to the bare repository.

๐Ÿ” Create Git hook

The post-update hook runs once after all references have been updated on the server.

# add your deployment or service command
docker compose restart <container>
# add the hook user www-data to Docker group
sudo usermod -aG docker www-data
sudo systemctl restart nginx fcgiwrap
# enable post-update hook
mv post-update.sample post-update
sudo chmod +x post-update

Tip

Git hooks are enabled by removing the .sample suffix and ensuring the script is executable.