Git: Modifier les étiquettes suite à une importation

Subversion ne gère pas les étiquettes de la même manière que Git. C’est pour cette raison que suite à une importation je me retrouve souvent à devoir faire des modifications à mon historique. Une étiquette créée lors d’une importation est composée d’une soumission sur laquelle une étiquette légère est ajoutée. Ce que je veux, c’est une étiquette annotée sans l’ajout d’une soumission inutile. Dans cet article, nous allons voir comment faire cela. Il est important de mentionner que les lignes de commandes mentionnées plus bas ont un impact sur votre historique. Faites attention de bien les comprendre avant de les utiliser.

Utilisez cette commande pour voir quelles étiquettes doivent être changées:

git for-each-ref --sort=-refname --format '%(refname:short) %(taggerdate:iso-local)' refs/tags

S’il n’y a pas de date à coté de la version, c’est que l’étiquette doit être modifiée. Par exemple, ici les versions 3.2.x à 3.4.x doivent être modifiées:

v3.7.0 2019-11-14 12:14:06 -0500
v3.6.1 2019-05-09 12:43:48 -0400
v3.6.0 2017-11-09 15:33:19 -0500
v3.5.0 2017-06-13 18:18:37 -0400
v3.4.0
v3.3.1
v3.3.0
v3.2.4
v3.2.3
v3.2.2
v3.2.1
v3.2.0

Dans l’image suivante on peut confirmer que c’est effectivement la vérité. Les dates affichées sont celles des étiquettes annotées uniquement, ce qui n’est pas le cas pour l’étiquette légère v3.4.0.

Une soumission a été créé pour l’étiquette légère v3.4.0

La nouvelle étiquette doit conserver la date de la soumission 72dce852, car c’est à cette date que la relâche a normalement eu lieu. Dans l’image précédente on peut voir que la dernière soumission pour la relâche a été effectuée au mois de mai. Par contre, l’étiquette a été créée au mois de juin. Utilisez la commande suivante pour récupérer la bonne date:

git log --tags --simplify-by-decoration --date=iso-local --pretty="format:%ad %d"

Voici un exemple de ce que j’obtiens:

2019-10-30 17:46:26 -0400  (tag: v3.7.0)
2019-04-25 19:54:37 -0400  (tag: v3.6.1)
2017-11-08 18:25:32 -0500  (tag: v3.6.0)
2017-06-13 17:31:05 -0400  (tag: v3.5.0)
2016-06-23 15:35:04 -0400  (tag: v3.4.0)
2015-02-18 17:04:22 -0500  (tag: v3.3.1)
2014-12-08 09:59:58 -0500  (tag: v3.3.0)
2012-07-03 10:26:33 -0400  (tag: v3.2.4)
2012-03-13 17:07:43 -0400  (tag: v3.2.3)
2011-12-20 15:12:39 -0500  (tag: v3.2.2)
2010-12-20 16:07:02 -0500  (tag: v3.2.1)
2010-09-10 16:55:17 -0400  (tag: v3.2.0)
2005-08-02 11:20:49 -0400

Cette commande donne la date de la dernière soumission effectuée avant l’étiquette et non la date de l’étiquette. C’est pourquoi cette commande nous sert pour les étiquettes non conformes. Maintenant, pour créer la nouvelle étiquette, on fait une commande similaire à celle-ci:

GIT_COMMITTER_DATE="2016-06-23 15:35:04 -0400" \
  git tag --annotate v3.4.0 \
    --message="Tag the 3.4.0 release" \
    d4ac586497b0642152fde2c682984bfbfe453113

À la première ligne, vous devez mettre la date de l’étiquette. La deuxième ligne sert à spécifier le nom de l’étiquette annotée. La troisième ligne est le message de l’étiquette. Finalement, la quatrième sert à désigner la dernière soumission sur laquelle l’étiquette est attachée. Lorsque que la commande est exécutée, il est possible d’avoir une erreur si vous tentez de créer une étiquette qui existe déjà. Alors, il suffit de supprimer l’étiquette existante et de réessayer la commande.

L’étiquette est corrigée

Comme on peut le voir dans l’image précédente, la soumission inutile a été supprimée et une étiquette annotée a été créée à la date de l’ancienne étiquette. Donc l’historique est complètement conservé.

Si une étiquette du même nom existe sur le serveur, vous devez d’abord la supprimer avec cette commande et ensuite vous pourrez pousser la nouvelle:

git push --delete origin v3.4.0

Il suffit maintenant de répéter ces étapes pour chaque étiquettes. J’espère pour vous qu’elles ne sont pas trop nombreuses. Sinon, il y a toujours moyen de vous simplifier la vie en générant toutes vos commandes avec une commande de la sorte:

git log --tags --simplify-by-decoration --date=iso-local \
  --pretty="format:GIT_COMMITTER_DATE=\"%ad\" GIT_COMMITTER_NAME=\"%an\" GIT_COMMITTER_EMAIL=\"%ae\" git tag --annotate v%S --message=\"Tag the %S release\" \$(git log --pretty=%%P -n 1 %H)"

Git: Renommer en bloc des fichiers avec expression régulière

Dans cet article, je vais expliquer comment renommer en bloc des fichiers sous Git à partir d’une expression régulière. Récemment j’ai eu besoin de changer plusieurs fichiers de la forme YYYYMMDD.pdf vers YYYY-MM-DD.pdf, donc ajouter des tirets pour séparer les éléments d’une date.

Mon premier réflexe a été d’utiliser PowerRename qui fait partie des utilitaires de Microsoft PowerToys. Pour ceux qui ne connaissent pas, c’est un des projets à code source ouvert de Microsoft qui est disponible sur GitHub.

PowerRename avec expressions régulières
PowerRename avec expressions régulières

Le renommage des fichiers a fonctionné parfaitement, malheureusement Git n’est pas capable de reconnaitre les nouveaux fichiers comme étant les anciens qui sont renommés. Cela veut donc dire que l’historique serait complètement perdu. Il fallait que je trouve une autre solution.

Ma chasse à la commande magique venait de commencer. Comme tout bon développeur, j’ai passé pas mal de temps sur Stack Overflow. Je n’ai pas réussi à trouver exactement ce que je cherchais. Par contre, j’ai trouvé assez d’informations pour créer mon propre script:

#!/bin/sh
in_regex='^([0-9]{4})([0-9]{2})([0-9]{2})\.pdf$'
out_match='\1-\2-\3.pdf'

for file in $(git ls-files | grep -E $in_regex); do
    newname=`echo "$file" | sed -E "s/$in_regex/$out_match/"`
    git mv --verbose $file $newname
done

Je me suis servi de regular expressions 101 pour tester mon expression régulière à la ligne 2. Il est a noter que je me sers de l’option -E pour grep et sed dans le but d’utiliser les expressions régulières étendues. Le renommage est effectué par la commande git mv. N’oubliez pas de soumettre vos changements une fois le renommage complété.

Git: Réécrire l’histoire

Encore une fois je vais traiter de la modification des informations d’une soumission. Dernièrement j’ai encore migré plusieurs projets qui étaient sous Subversion vers Git. Donc j’ai dû faire appel à git filter-branch.

Ma première erreur a été de faire des soumissions sans changer le nom du committer / author. Heureusement mon adresse de courriel était la bonne. J’ai donc ouvert une fenêtre de Git Bash pour y coller ce code:

#!/bin/sh

git filter-branch --env-filter '
EMAIL="crayon@server.com"
CORRECT_NAME="Crayon"
if [ "$GIT_COMMITTER_EMAIL" = "$EMAIL" ]
then
    export GIT_COMMITTER_NAME="$CORRECT_NAME"
fi
if [ "$GIT_AUTHOR_EMAIL" = "$EMAIL" ]
then
    export GIT_AUTHOR_NAME="$CORRECT_NAME"
fi
' --tag-name-filter cat -- --branches --tags

Si vous voulez l’utiliser il faut bien sûr changer les variables EMAIL et CORRECT_NAME pour y mettre vos informations. Si le CORRECT_NAME contient un guillemet simple, il faut le remplacer par '\'' pour pouvoir exécuter le code.

Mon deuxième problème est survenu suite à l’application de fichiers Patch. La date soumission était celle de l’application de la patch, mais je voulais que ce soit celle où l’auteur avait fait sa soumission. J’ai donc utilisé ce code:

#!/bin/sh

git filter-branch --env-filter '
if [ "$GIT_COMMITTER_DATE" != "$GIT_AUTHOR_DATE" ]
then
    export GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"
fi
' --tag-name-filter cat -- --branches --tags

Voici la liste de variables d’environnement mises à votre disposition pour effectuer d’autres tâches:

  • GIT_AUTHOR_NAME
  • GIT_AUTHOR_EMAIL
  • GIT_AUTHOR_DATE
  • GIT_COMMITTER_NAME
  • GIT_COMMITTER_EMAIL
  • GIT_COMMITTER_DATE

Il est important de savoir que si vous roulez ces scripts, l’historique de votre dépôt va être réécrit. Toutes les personnes qui ont un fork ou un clone devront prendre cette nouvelle version.

Git: Modifier un message d’une soumission

Suite à une migration de Subversion vers Git, je me suis retrouvé avec des messages qui contiennent un « git-svn-id ». Oui, je sais, il suffisait d’ajouter le paramètre ‘–-no-metadata‘ à la commande ‘git svn’.

Voici un exemple de message que j’obtiens:

libpng updated to 1.4.5

git-svn-id: https://wii-tac-toe.googlecode.com/svn/trunk@104 bba1cac1-252d-79fd-420d-80adb1f9fa09

Heureusement il existe un moyen de changer le message. C’est l’utilisation du paramètre ‘filter-branch‘ qui nous aidera à effectuer cette tâche. La commande suivante va effacer la ligne du message.

git filter-branch --msg-filter '
    sed -e "/^git-svn-id:/d"
'

L’application sed va servir à faire la modification. On utilise le paramètre -e pour lui spécifier une expression. Le ‘/^’ veut dire que la ligne débute par « git-svn-id: ». Le ‘/d’ à fin signifie que la ligne sera supprimée si elle correspond à l’expression.

La migration a aussi ajouté un saut de ligne avant d’insérer le « git-svn-id ». Si vous êtes dans la même situation que moi et que vous n’avez pas vous-mêmes ajouté des sauts de ligne dans vos messages, alors c’est facile de supprimer tous les sauts de lignes en plus des lignes qui contiennent le « git-svn-id ». Voici la commande que j’ai utilisée.

In the end exercise should be fun and make you feel cheapest price for cialis good. All these kinds of medicinal help are taken under strict vardenafil levitra online instruction of your physician. Eventually, he leaves his female partner sexual unsatiated, leading to disharmony in relationship. levitra 10 mg davidfraymusic.com This makes it to work actively in about 30 minutes in order to enrage the size and strength of an muscle when she (or he) presses on cialis generika 10mg particular cranials or sutures; this can be named as male impotence, erection disorder, ED poor erection etc.
git filter-branch --msg-filter '
    sed -e "/^$/d;/^git-svn-id:/d"
'

L’expression ‘/^$/d’ supprime toutes les lignes vides.

Pour transférer les tags sur les nouvelles soumissions qui ont été créée, on peux utiliser le paramètre ‘--tag-name-filter‘ de la manière suivante:

git filter-branch --tag-name-filter cat --msg-filter '
    sed -e "/^$/d;/^git-svn-id:/d"
'

Il est important de savoir que si des tags existent déjà sur le serveur avec les mêmes noms, ils vont devoir être supprimés en premier.

Lorsque que vous devrez pousser les changements, il va falloir utiliser l’option ‘--force‘ sinon ça ne fonctionnera pas.

Migration de Subversion vers Git

Bonjour, il est facile de faire la migration de Subversion vers Git, car l’outil git svn nous simplifie la vie grandement.

La première étape est de bâtir une liste de correspondance entre les noms utilisés dans Subversion et ceux qui seront utilisés dans Git. Pour cela il faut créer un fichier que je nomme habituellement users.txt et y insérer les auteurs comme suit:

Crayon = Crayon2000 <crayon@serveur.com>
(no author) = Crayon2000 <crayon@serveur.com>

À gauche du symbole « égal », on retrouve le nom utilisé dans Subversion et à droite, c’est celui utilisé dans Git. Si une soumission a été faite sans auteur, il faut utiliser (no author) comme à la dernière ligne. J’avais eu ce problème avec Google Code car la première soumission était faite par le système pour créer la structure standard de dossier.

Une structure standard est la plus facile à cloner, elle ressemble à ceci:
SVN Standard Layout
Donc, il s’agit d’une structure de dossier qui contient les dossiers trunk, tags et branches dans le dossier racine. Pour cloner ce genre de structure, on utilise le paramètre –stdlayout comme ceci:

$ git svn clone https://wii-tac-toe.googlecode.com/svn/ \
    --authors-file=users.txt --stdlayout Wii-Tac-Toe

Cette commande simplifie la syntaxe, car on aurait aussi pu utiliser celle-ci:

$ git svn clone https://wii-tac-toe.googlecode.com/svn/ \
    -Ausers.txt --trunk=trunk --tags=tags --branches=branches Wii-Tac-Toe

Si vous clonez un dépôt local sur votre PC, il est important d’enlever le : après le lettre du disque. Donc à la place de file:///C:/repo il faut utiliser file:///C/repo

Les messages créés lors du clonage devraient ressembler à celui-ci:

libpng updated to 1.4.5

git-svn-id: https://wii-tac-toe.googlecode.com/svn/trunk@104 bba1cac1-252d-79fd-420d-80adb1f9fa09

Si vous désirez ne pas avoir la dernière ligne, alors il faut ajouter le paramètre –no-metadata à la ligne de commande.

Maintenant, voyons un autre type de structure que beaucoup de gens utilisent sous Subversion, il s’agit d’une structure dans laquelle les dossiers standards ont étés omis. Donc les fichiers sont enregistrés directement dans le dossier principal. Elle ressemble à ceci:
SVN Bad Layout
Pour cloner cette structure, on doit faire ceci:

$ git svn clone https://wii-tac-toe.googlecode.com/svn/ \
    --authors-file=users.txt Wii-Tac-Toe

Il est possible aussi qu’un projet ait été démarré dans une branche, alors la structure ressemble à celle-ci:
SVN Sub Branch Layout
Pour cloner cette structure, on doit faire ceci:

$ git svn clone https://wii-tac-toe.googlecode.com/svn/ -Ausers.txt  \
    --trunk=branches/Sub Wii-Tac-Toe

La prochaine structure peut aussi exister si vous avez créé un projet avec la structure standard à l’intérieur d’une branche. Cette structure serait similaire à celle-ci:
SVN Sub Branch With Standard Layout
Pour cloner cette structure on doit faire ceci:

$ git svn clone https://wii-tac-toe.googlecode.com/svn/ -Ausers.txt  \
    --trunk=branches/Sub/trunk --tags=branches/Sub/tags --branches=branches/Sub/branches Wii-Tac-Toe

Je sais que cette structure n’a rien de standard, mais il m’est arrivé de la faire lorsque je voulais tester une petite application en lien avec celle dans le dossier racine. Par la suite seulement on se rend compte qu’elle devrait être dans son propre dépôt, mais par paresse on ne le fait pas. Il faut prendre cette opportunité lors de la migration vers Git.

Tous les types de clonage que l’on a vus sont assez simples comparativement à celui qui vient. C’est un cas de « j’ai changé d’idée en cours de route ». Il ne s’agit pas d’une structure mais bien de deux. Ceci peut arriver dans les cas où des personnes ont débuté un projet sans la structure standard et qui par la suite ont réalisé que cela n’avait pas de sens. Concrètement, cela veut dire que quelques soumissions ont été faites avec une structure et que par la suite les dossiers trunk, tags et branches ont été créés. Les soumissions fautes dans le dossier de base ont bien sûr été déplacées dans le trunk. Lorsque l’on migre vers Git on ne veut pas perdre l’historique des soumissions qui précèdent la création des dossiers. Donc on cherche à garder le travail dans la structure de gauche et celle de droite:
SVN Bad Plus Standard Layout
Pour faire cela, nous allons procéder en deux étapes. La première pour aller chercher les soumissions de la première structure et la seconde pour le reste. Il existe peut-être une façon simple de faire, alors si vous la connaissez n’hésitez pas à laisser un commentaire à cet article.

Pour la première étape, on doit connaitre la soumission qui précède la création de la structure standard. Dans cet exemple, il s’agit de la soumission 38:

$ git svn clone https://wii-tac-toe.googlecode.com/svn/ -Ausers.txt \
    --revision=BASE:38 Wii-Tac-Toe
$ cd Wii-Tac-Toe
$ mv .git/refs/remotes/git-svn .git/refs/remotes/trunk

Pour la deuxième étape, on doit changer la configuration pour utiliser les dossiers de la structure de base. Il faut exécuter ces commandes:

$ git config svn-remote.svn.fetch trunk:refs/remotes/trunk
$ git config --add svn-remote.svn.branches branches/*:refs/remotes/*
$ git config --add svn-remote.svn.tags tags/*:refs/remotes/tags/*

Le fichier .git\config devrait maintenant contenir ces lignes:

	fetch = trunk:refs/remotes/trunk
	branches = branches/*:refs/remotes/*
	tags = tags/*:refs/remotes/tags/*

On va chercher les soumissions dans la structure standard:

$ git svn fetch --revision=BASE:HEAD --authors-file=../users.txt

Au lieu d’utiliser BASE on aurait pu mettre le numéro de la soumission où la structure standard a été créée.
Maintenant on rassemble le tout en mettant le trunk dans le master:

$ git checkout
$ git reset --hard refs/remotes/trunk

Je crois que cela fait le tour des différents types de clones que j’ai effectués jusqu’à maintenant. La tâche n’est pas complétée car il faut faire un peu de ménage et envoyer les données sur le serveur. Voici maintenant les étapes qui s’appliquent à tout ce que l’on a vu précédemment.

Ces lignes servent à aller dans le dossier, si vous n’y êtes pas déjà, et y faire un peu de ménage.

$ cd Wii-Tac-Toe
$ cp -Rf .git/refs/remotes/tags/* .git/refs/tags/
$ rm -Rf .git/refs/remotes/tags
$ cp -Rf .git/refs/remotes/* .git/refs/heads/
$ rm -Rf .git/refs/remotes
$ rm -f .git/refs/heads/trunk

On assigne l’origine:

$ git remote add origin https://github.com/Crayon2000/Wii-Tac-Toe.git

On pousse sur le serveur:

$ git push origin --all
$ git push origin --tags

Si jamais on avait déjà des soumissions et que l’on veut tout effacer et recommencer on peut faire ceci:

$ git push --force --set-upstream origin master
$ git push --force origin --tags

Attention ces commandes vont détruire tout votre historique existant.

Voilà, maintenant je crois que j’ai exposé toutes mes connaissances actuelles sur Git dans cet article. Bonne chance!

Liens intéressants:

No doubt https://energyhealingforeveryone.com/levitra-7845.html on line cialis those erection problems can happen due to various reasons and for some patients the side effects of these drugs may seen: Antacids: Antacids containing Aluminum and Magnesium are given but contraindicated in documented hypersensitivity, it can’t be safely used in pregnancy as it decreases effect of allopurinol, amprenavir, chloroquine, corticosteroids, diflunisal, digoxin, ethambutol, iron salt, H2 antagonists, isoniazid, penicillamine, phenothiazines, tetracycline, thyroid hormones. Its intake recovers the blood movement in penile area, making male reproductive section stronger. ordine cialis on line check By focusing on what you want and take consistent actions towards it, you’ll be able to end this problem in no time and no longer be troubled by levitra order prescription the question on how to stop premature ejaculation naturally. Nandrolone Decanoate is ideal as a pre-contest anabolic steroid, commonly stacked with Winstrol and with non-aromatizing agents like Halotestin and purchase cialis Trenbolone.

Voir les soumissions depuis le dernier tag avec TortoiseGit

J’ai commencé à faire la transition de Apache Subversion vers Git dernièrement. Pour svn j’utilisais le client TortoiseSVN. Donc, il me fallait un client similaire pour ne pas avoir à tout réapprendre. Heureusement il existe TortoiseGit. Je me retrouve quand même souvent à devoir ouvrir une fenêtre d’invite de commandes pour faire certaines tâches. C’est sans doute dû a la facilité de trouver l’information avec la ligne de commande. Dans cet article, je discuterai d’un cas où il m’a fallu beaucoup plus de temps pour savoir comment faire avec l’interface Windows. C’est le genre de truc qui te fait dire « c’est pas compliqué, il faut juste le savoir ».

Ce que je cherchais à faire est simple. Voir le log des soumissions depuis mon dernier tag. Le but est de voir toutes modifications apportées au code pour mieux écrire ma liste de changement lors de ma relâche de logiciel.

Je travaille souvent sur des petits projets où il y a peu de programmeurs. Donc, il y a peu de branches et les tags apparaissent dans le temps au moment de la relâche.

Pour TortoiseSVN il fallait simplement ouvrir le Log et regarder toutes les soumissions qui suivent le tag. Dans cet exemple on peut voir qu’il y a un tag à la révision 114. Donc il est facile de savoir que tout ce qui suit sera dans la prochaine relâche.

TortoiseSVN Log Messages
Fenêtre Log Messages de TortoiseSVN

Avec Git c’est un peu différent. Les tags n’apparaissent pas dans la fenêtre de Log (sauf quand All Branches est coché). Alors ce qu’il faut faire c’est d’ouvrir le menu contextuel de TortoiseGit et de choisir Browse References.

TortoiseGit context menu: Browse References
Menu contextuel

Une fois que la fenêtre sera visible, il faut choisir refs dans arborescence à gauche. Ensuite on sélectionne les deux branches pour lesquelles on veut voir les différences. Ce qui nous intéresse c’est heads/master et le tags/0.8, 0.8 étant le dernier tag pour ce logiciel. L’ordre de sélection n’a pas d’importance car de toute façon les soumissions seront en ordre chronologique. Ensuite, on fait un clic droit et dans le menu on choisit la dernière option, Show log of x…y.

Browse References
Fenêtre Browse References de TortoiseGit

Voilà, maintenant la fenêtre dont nous avions besoin est affichée.