Skip to content

+++ title = "Git" date = 2020-02-22T16:26:07+01:00 weight = 1 +++

GIT LOG

$ git log -p -2 $ git log --stat $ git log --pretty=format:"%h - %an, %ar : %s" $ git log --pretty=oneline

synchro fetch upstream

git fetch upstream
git rebase upstream/master
git push origin master

Git - Checkout local d'une Merge-Requests


Lien vers la dog Gitlab


Méthode 1 - Configuration globale

Alias à mettre dans la conf locale

Fichier de conf ~/.gitconfig

[alias]
    mr = !sh -c 'git fetch $1 merge-requests/$2/head:mr-$1-$2 && git checkout mr-$1-$2' -

Utilisation

Exemple, remote origin et merge-requests 123

git mr origin 123

Cela la créer la branche locale mr-origin-123


Méthode 2 - Configuration d'un dépôt spécifique (avec fetch possible)

Exemple actuel de la conf du dépôt local (dans le fichier .git/config) :

[remote "origin"]
  url = https://gitlab.com/gitlab-org/gitlab-foss.git
  fetch = +refs/heads/*:refs/remotes/origin/*

Modifier le fichier de conf ou l'éditer avec la commande :

git config -e

Ajouter la configuration suivante :

fetch = +refs/merge-requests/*/head:refs/remotes/origin/merge-requests/*

Ce qui donne la configuration complète suivante :

[remote "origin"]
  url = https://gitlab.com/gitlab-org/gitlab-foss.git
  fetch = +refs/heads/*:refs/remotes/origin/*
  fetch = +refs/merge-requests/*/head:refs/remotes/origin/merge-requests/*

Maintenant avec un fetch nous avons la possibilité de voir les merge-requests :

git fetch origin

...
From https://gitlab.com/gitlab-org/gitlab-foss.git
 * [new ref]         refs/merge-requests/1/head -> origin/merge-requests/1
 * [new ref]         refs/merge-requests/2/head -> origin/merge-requests/2
...

Et pour faire un checkout :

git checkout origin/merge-requests/1

% Git diff, Git patch et Git email

Diff

  • Afficher les changements entre le dernier commit et les changements locaux

    git diff
    

  • Afficher les changements entre deux commit

    git diff tag1..tag2
    


Git Patch

Le but du présent tuto est de faire un patch d'un coté, puis de l'appliquer ailleur.

Exemple, un serveur possède des clés de déploiement, mais pas de push possible, alors que l'admin a les droit pour.

Création du patch

Sur le serveur, faire les modifications, add et commit, puis :

# Patch généré par rapport au dernier commit
git format-patch -o output HEAD^

# Patch généré entre plusieurs commit
# note, le patch est généré entre les deux ID, ce qui est dans ID_commit_debut n'est pas pris en compte
git format-patch <ID_commit_debut>..<ID_commit_fin>

-----

# Exemple - patch pour les commit 101 et 102
# Version n°3 du patch
# - commit 102 (intégré dans le patch)
# - commit 101 (intégré dans le patch)
# - commit 100 (non intégré dans le patch)
#
# Création des fichier suivants :
# - 0000-description
# - 0001-patch_commit_101
# - 0002-patch_commit_102
git format-patch --cover-letter -v3 -o output 100..102
  • -k, --keep-subject : Ne pas ajouter [PATCH] dans le sujet
  • --stdout : afficher la sortie dans la sortie standatd (stdout) au format mbox au lieu de créer un fichier de patch
  • --cover-letter : Ajouter un patch 0000 pour décrire les patch qui suivent (fichier à éditer ensuite)
  • -o <dir>, --output-directory <dir> : répertroire de sortie
  • -v<version> : spécifier la version du patch (dans le cadre d'une demande de modif après refus de fusion)

Application du patch

Sur la station de l'admin, pour importer le patch avant de faire le push

# Méthode 1 - Application simple du patch en intégrant le commit (dont son numéro de commit)
git am file.patch

# Méthode 2 - Application du patch sans prendre en compte le commit
git apply mypatch.patch
  • -k, --keep-subject : Ne pas prendre en compte [PATCH] dans le sujet
  • -3, --3way, --no-3way : En cas d'échec, application du patch en 3 étapes (voir git-config)

Git email

Envoyer le patch précédent créé via email

Paquet requis

  • git
  • git-email

Envoyer le mail

git send-email --from <expéditeur> --to <destinataire> --cc <copie> <patch_a_envoyer>
git send-email --from me@example.com --to dest@example.com --cc dest-cc@example.com output/000*

# Once your commits are ready to be sent to the mailing list, run the following commands:
# $ git format-patch --cover-letter -M origin/master -o outgoing/
# $ edit outgoing/0000-*
# $ git send-email outgoing/*

Man à voir

% GIT - Options de clone

Cloner juste une branche

git clone --single-branch --branch social_contract_french https://salsa.debian.org/albanvidal-guest/debian-flyers.git
  • --branch <branche> : indique la branche que l'on souhaite cloner
  • --single-branch : clone seulement la branche sélectionnée

Clone partiel (shallow clone)

# Cloner qu'un certain nombre de commit
git clone --depth 2 https://salsa.debian.org/debian/debian-flyers.git

# Cloner après une date
git clone --shallow-since=2019-02-01 https://salsa.debian.org/debian/debian-flyers.git
  • --depth <nombre> : spécifie le nombre de commit que l'on veut synchroniser (shallow clone)
  • --shallow-since=<date> : clone partiel après la date (format AAAA-MM-JJ)

% GIT et la synchro d'un fork via le dépot amont

Nous avons :

  • 1 dépot d'origine : https://git.example.com/projet/depot.git
  • 1 dépôt de fork : https://git.example.com/my_name/depot.git

  • On clone le dépôt de travail, le fork
    git clone https://git.example.com/my_name/depot.git
    
  • On a fait des modifications... ou non
  • On veut synchroniser le dépôt amont (upstream) dans notre fork
  • Étapes :

  • Ajouter le dépôt upstream

    git remote add upstream https://git.example.com/projet/depot.git
    

  • fetch

    git fetch upstream
    

  • Au cas ou, on retourne dans la branche master

    git checkout master
    

  • Deux solutions

  • On merge la branche master upstream avec notre branche master
    git merge upstream/master
    # ou
    git merge upstream/master master
    
  • On écrase la branche locale par la branche upstream

    git rebase upstream/master
    

  • Synchro du dépôt distant avec la branche master mise à jour

    git push origin master
    
    % Sauvegarde fichiers sensibles

Création du git local

mkdir /srv/.local-git
cd /srv/.local-git
git init
git config user.name "$HOSTNAME"
git config user.email "systemd-path@$HOSTNAME"

Commit initial

mkdir /srv/.local-git/etc
cp /etc/fstab /etc/hosts /srv/.local-git/etc
cd /srv/.local-git
git add .
git commit -m "Initial commit"

systemd.service git-crit-files.service

[Unit]
Description=Watch admin files alert
#Documentation=

[Service]
Type=oneshot
ExecStart=/usr/local/bin/git-crit-files

systemd.path git-crit-files.path

[Path]
PathChanged=/etc/fstab
PathChanged=/etc/hosts

[Install]
WantedBy=default.target

Script /usr/local/bin/git-crit-files

#!/bin/bash

# TODO :
# - vérifier si existe dans /etc
# - vérifier si existe sur le dépôt

local_git_dir="/srv/.local-git"

#list_files="
#/etc/fstab
#/etc/hosts
#"

list_files=$(awk -F'=' '/PathChanged/ {print $2}' /etc/systemd/system/git-crit-files.path)

cd $local_git_dir

for file in $list_files ; do
    if ! diff -q $file ${file#/} ; then
        # LOG
        logger -t system-file-alert -p warning "File '$file' was changed"
        # Copie dans le depot
        cp $file $local_git_dir/$file
        # Commit
        git add $local_git_dir/$file
        git commit -m "Update $file
Last 10 ssh logs:
$(journalctl --identifier=ssh-wrapper --no-pager --lines=10)
"
    else
        logger -t system-file-alert -p debug "File '$file' NOT changed"
    fi
done

sshrc (/etc/ssh/sshrc)

ip=`echo $SSH_CONNECTION | cut -d " " -f 1`

# Test if ip arealy present
if ! grep $ip /tmp/list_ip_ssh_$USER >/dev/null 2>&1
then
    #logger -t ssh-wrapper $USER login from $ip
    logger -t ssh-wrapper -p warning $USER login from unknown ip: $ip - $(host $ip|awk '{print $5}')
    #echo "User $USER just logged in from $ip - $(host $ip|awk '{print $5}')" |mail -s "New SSH Login to $USER in $(hostname)" admin-s3@zordhak.fr

    # add the ip in temporary list
    echo "$(date) - $ip" >> /tmp/list_ip_ssh_$USER
else
    logger -t ssh-wrapper -p info $USER login from known ip: $ip
fi

Activation systemd.path

systemctl enable --now git-crit-files.path

% Annuler des commit avec GIT


Commit locaux (pas encore pushé)

  • Annuler le dernier commit local
    git log
        commit 101: bad commit    # latest commit, this would be called 'HEAD'
        commit 100: good commit   # second to last commit, this is the one we want
    
    # To restore everything back to the way it was prior to the last commit,
    # we need to reset to the commit before HEAD:
    
    git reset --soft HEAD^     # use --soft if you want to keep your changes
    git reset --hard HEAD^     # use --hard if you don't care about keeping the changes you made
    
    # Now git log will show that our last commit has been removed.
    

Annuler plusieurs commit locaux

git log
commit 102 : HS
commit 103 : HS
commit 104 : OK

# On veut annuler les commits jusqu'au 104
git reset --soft 104    # Annule les commit jusqu'au 104 mais garde les modifications
git reset --hard 104    # Annule les commit jusqu'au 104 ET SUPPRIME LES MODIFICATIONS

Commit public

# If you have already made your commits public,
# you will want to create a new commit which will "revert"
# the changes you made in your previous commit (current HEAD).

git revert HEAD

# Your changes will now be reverted and ready for you to commit:

git commit -m 'restoring the file I removed by accident'
git log
    commit 102: restoring the file I removed by accident
    commit 101: removing a file we don't need
    commit 100: adding a file that we need

Plus d'info, voir :

Git-Basics-Undoing-Things

Suppression d'un sous module

git submodule deinit lib/custom_submodule
git rm lib/custom_submodule
rm -Rf .git/modules/lib/custom_submodule

Signer ses clés avec git

git config --global commit.gpgsign true
git config --global tag.gpgsign true
git config --global user.signingkey KEY