1140 lines
32 KiB
Markdown
1140 lines
32 KiB
Markdown
## Commit sémantique
|
||
|
||
Divise les gros changements en petits commits significatifs avec des messages appropriés. Utilise uniquement des commandes git standard.
|
||
|
||
### Utilisation
|
||
|
||
```bash
|
||
/semantic-commit [options]
|
||
```
|
||
|
||
### Options
|
||
|
||
- `--dry-run` : Afficher les divisions de commits proposées sans réellement committer
|
||
- `--lang <langue>` : Forcer la langue pour les messages de commit (en, fr)
|
||
- `--max-commits <nombre>` : Spécifier le nombre maximum de commits (défaut : 10)
|
||
|
||
### Exemples de base
|
||
|
||
```bash
|
||
# Analyser les changements actuels et committer en unités logiques
|
||
/semantic-commit
|
||
|
||
# Vérifier uniquement la proposition de division (pas de commit réel)
|
||
/semantic-commit --dry-run
|
||
|
||
# Générer les messages de commit en anglais
|
||
/semantic-commit --lang en
|
||
|
||
# Générer les messages de commit en français
|
||
/semantic-commit --lang fr
|
||
|
||
# Diviser en maximum 5 commits
|
||
/semantic-commit --max-commits 5
|
||
```
|
||
|
||
### Comment ça fonctionne
|
||
|
||
1. **Analyser les changements** : Vérifier ce qui a changé avec `git diff HEAD`
|
||
2. **Grouper les fichiers** : Assembler les fichiers liés
|
||
3. **Créer les messages** : Écrire des messages de commit sémantiques pour chaque groupe
|
||
4. **Committer étape par étape** : Committer chaque groupe après votre approbation
|
||
|
||
### Quand diviser les changements
|
||
|
||
#### Ce qui rend un changement "important"
|
||
|
||
Nous divisons quand nous voyons :
|
||
|
||
1. **Nombreux fichiers** : 5+ fichiers modifiés
|
||
2. **Nombreuses lignes** : 100+ lignes modifiées
|
||
3. **Multiples fonctionnalités** : Changements dans 2+ zones
|
||
4. **Types mixtes** : feat + fix + docs ensemble
|
||
|
||
```bash
|
||
# Analyser l'échelle du changement
|
||
CHANGED_FILES=$(git diff HEAD --name-only | wc -l)
|
||
CHANGED_LINES=$(git diff HEAD --stat | tail -1 | grep -o '[0-9]\+ insertions\|[0-9]\+ deletions' | awk '{sum+=$1} END {print sum}')
|
||
|
||
if [ $CHANGED_FILES -ge 5 ] || [ $CHANGED_LINES -ge 100 ]; then
|
||
echo "Changement important détecté : division recommandée"
|
||
fi
|
||
```
|
||
|
||
#### Comment diviser en petits commits significatifs
|
||
|
||
##### 1. Division par limites fonctionnelles
|
||
|
||
```bash
|
||
# Identifier les unités fonctionnelles à partir de la structure des répertoires
|
||
git diff HEAD --name-only | cut -d'/' -f1-2 | sort | uniq
|
||
# → src/auth, src/api, components/ui, etc.
|
||
```
|
||
|
||
##### 2. Séparation par type de changement
|
||
|
||
```bash
|
||
# Nouveaux fichiers vs modifications de fichiers existants
|
||
git diff HEAD --name-status | grep '^A' # Nouveaux fichiers
|
||
git diff HEAD --name-status | grep '^M' # Fichiers modifiés
|
||
git diff HEAD --name-status | grep '^D' # Fichiers supprimés
|
||
```
|
||
|
||
##### 3. Analyse des dépendances
|
||
|
||
```bash
|
||
# Détecter les changements de relations d'import
|
||
git diff HEAD | grep -E '^[+-].*import|^[+-].*require' | \
|
||
cut -d' ' -f2- | sort | uniq
|
||
```
|
||
|
||
#### Analyse détaillée des fichiers
|
||
|
||
```bash
|
||
# Obtenir la liste des fichiers modifiés
|
||
git diff HEAD --name-only
|
||
|
||
# Analyser les changements de chaque fichier individuellement
|
||
git diff HEAD -- <fichier>
|
||
|
||
# Déterminer le type de changement pour les fichiers
|
||
git diff HEAD --name-status | while read status file; do
|
||
case $status in
|
||
A) echo "$file: Nouvelle création" ;;
|
||
M) echo "$file: Modification" ;;
|
||
D) echo "$file: Suppression" ;;
|
||
R*) echo "$file: Renommé" ;;
|
||
esac
|
||
done
|
||
```
|
||
|
||
#### Comment grouper les fichiers
|
||
|
||
1. **Par fonctionnalité** : Garder les fonctions liées ensemble
|
||
- Fichiers `src/auth/` → Authentification
|
||
- Fichiers `components/` → Composants UI
|
||
|
||
2. **Par type** : Même type de changements
|
||
- Tests uniquement → `test:`
|
||
- Documentation uniquement → `docs:`
|
||
- Configuration uniquement → `chore:`
|
||
|
||
3. **Par dépendances** : Fichiers qui ont besoin les uns des autres
|
||
- Modèle + Migration
|
||
- Composant + Style
|
||
|
||
4. **Par taille** : Garder les commits gérables
|
||
- Max 10 fichiers par commit
|
||
- Garder les fichiers liés ensemble
|
||
|
||
### Exemple de sortie
|
||
|
||
```bash
|
||
$ /semantic-commit
|
||
|
||
Analyse des changements...
|
||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||
|
||
Changements détectés :
|
||
• src/auth/login.ts (modifié)
|
||
• src/auth/register.ts (nouveau)
|
||
• src/auth/types.ts (modifié)
|
||
• tests/auth.test.ts (nouveau)
|
||
• docs/authentication.md (nouveau)
|
||
|
||
Divisions de commits proposées :
|
||
|
||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||
Commit 1/3
|
||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||
Message : feat: implémenter système d'enregistrement et connexion utilisateur
|
||
Fichiers inclus :
|
||
• src/auth/login.ts
|
||
• src/auth/register.ts
|
||
• src/auth/types.ts
|
||
|
||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||
Commit 2/3
|
||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||
Message : test: ajouter tests complets pour système d'authentification
|
||
Fichiers inclus :
|
||
• tests/auth.test.ts
|
||
|
||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||
Commit 3/3
|
||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||
Message : docs: ajouter documentation du système d'authentification
|
||
Fichiers inclus :
|
||
• docs/authentication.md
|
||
|
||
Exécuter le commit avec ce plan de division ? (y/n/edit):
|
||
```
|
||
|
||
### Vos options
|
||
|
||
- `y` : Procéder avec la division proposée
|
||
- `n` : Tout annuler
|
||
- `edit` : Changer les messages de commit
|
||
- `merge <numéro1> <numéro2>` : Combiner les commits
|
||
- `split <numéro>` : Diviser davantage un commit
|
||
|
||
### Mode Dry Run
|
||
|
||
```bash
|
||
$ /semantic-commit --dry-run
|
||
|
||
Analyse des changements... (DRY RUN)
|
||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||
|
||
[Affichage de la proposition de division de commit]
|
||
|
||
ℹ️ Mode DRY RUN : Aucun commit réel ne sera exécuté
|
||
💡 Pour exécuter, relancez sans l'option --dry-run
|
||
```
|
||
|
||
### Fonctionnalités intelligentes
|
||
|
||
#### 1. Comprend votre projet
|
||
|
||
- Détecte le type de projet à partir des fichiers de configuration
|
||
- Détermine les fonctionnalités à partir de la structure des dossiers
|
||
|
||
#### 2. Reconnaissance de patterns de changement
|
||
|
||
```bash
|
||
# Détecter les patterns de correction de bugs
|
||
- Mots-clés comme "fix", "bug", "error"
|
||
- Ajout de gestion d'exceptions
|
||
- Corrections de branches de conditions
|
||
|
||
# Détecter les patterns de nouvelles fonctionnalités
|
||
- Création de nouveaux fichiers
|
||
- Ajouts de nouvelles méthodes
|
||
- Ajouts de points de terminaison API
|
||
```
|
||
|
||
#### 3. Analyse des dépendances
|
||
|
||
- Changements dans les déclarations d'import
|
||
- Ajout/modification de définitions de types
|
||
- Relation avec les fichiers de configuration
|
||
|
||
### Comment c'est construit
|
||
|
||
#### Commits étape par étape avec Git
|
||
|
||
##### 1. Préprocessing : Sauvegarder l'état actuel
|
||
|
||
```bash
|
||
# Réinitialiser les changements non stagés s'il y en a
|
||
git reset HEAD
|
||
git status --porcelain > /tmp/original_state.txt
|
||
|
||
# Vérifier la branche de travail
|
||
CURRENT_BRANCH=$(git branch --show-current)
|
||
echo "Branche de travail : $CURRENT_BRANCH"
|
||
```
|
||
|
||
##### 2. Exécution séquentielle de commits par groupe
|
||
|
||
```bash
|
||
# Lire le plan de division
|
||
while IFS= read -r commit_plan; do
|
||
group_num=$(echo "$commit_plan" | cut -d':' -f1)
|
||
files=$(echo "$commit_plan" | cut -d':' -f2- | tr ' ' '\n')
|
||
|
||
echo "=== Exécution du commit $group_num ==="
|
||
|
||
# Stager uniquement les fichiers pertinents
|
||
echo "$files" | while read file; do
|
||
if [ -f "$file" ]; then
|
||
git add "$file"
|
||
echo "Stagé : $file"
|
||
fi
|
||
done
|
||
|
||
# Vérifier le statut de staging
|
||
staged_files=$(git diff --staged --name-only)
|
||
if [ -z "$staged_files" ]; then
|
||
echo "Attention : Aucun fichier stagé"
|
||
continue
|
||
fi
|
||
|
||
# Générer le message de commit (analyse LLM)
|
||
commit_msg=$(generate_commit_message_for_staged_files)
|
||
|
||
# Confirmation utilisateur
|
||
echo "Message de commit proposé : $commit_msg"
|
||
echo "Fichiers stagés :"
|
||
echo "$staged_files"
|
||
read -p "Exécuter ce commit ? (y/n) : " confirm
|
||
|
||
if [ "$confirm" = "y" ]; then
|
||
# Exécuter le commit
|
||
git commit -m "$commit_msg"
|
||
echo "✅ Commit $group_num terminé"
|
||
else
|
||
# Annuler le staging
|
||
git reset HEAD
|
||
echo "❌ Commit $group_num ignoré"
|
||
fi
|
||
|
||
done < /tmp/commit_plan.txt
|
||
```
|
||
|
||
##### 3. Gestion d'erreurs et rollback
|
||
|
||
```bash
|
||
# Gérer les échecs de hooks pre-commit
|
||
commit_with_retry() {
|
||
local commit_msg="$1"
|
||
local max_retries=2
|
||
local retry_count=0
|
||
|
||
while [ $retry_count -lt $max_retries ]; do
|
||
if git commit -m "$commit_msg"; then
|
||
echo "✅ Commit réussi"
|
||
return 0
|
||
else
|
||
echo "❌ Échec du commit (tentative $((retry_count + 1))/$max_retries)"
|
||
|
||
# Incorporer les corrections automatiques des hooks pre-commit
|
||
if git diff --staged --quiet; then
|
||
echo "Changements automatiquement corrigés par le hook pre-commit"
|
||
git add -u
|
||
fi
|
||
|
||
retry_count=$((retry_count + 1))
|
||
fi
|
||
done
|
||
|
||
echo "❌ Échec du commit. Veuillez vérifier manuellement."
|
||
return 1
|
||
}
|
||
|
||
# Récupérer des interruptions
|
||
resume_from_failure() {
|
||
echo "Processus de commit interrompu détecté"
|
||
echo "Statut de staging actuel :"
|
||
git status --porcelain
|
||
|
||
read -p "Continuer le traitement ? (y/n) : " resume
|
||
if [ "$resume" = "y" ]; then
|
||
# Reprendre depuis le dernier commit
|
||
last_commit=$(git log --oneline -1 --pretty=format:"%s")
|
||
echo "Dernier commit : $last_commit"
|
||
else
|
||
# Réinitialisation complète
|
||
git reset HEAD
|
||
echo "Processus réinitialisé"
|
||
fi
|
||
}
|
||
```
|
||
|
||
##### 4. Vérification post-complétion
|
||
|
||
```bash
|
||
# Vérifier que tous les changements ont été committés
|
||
remaining_changes=$(git status --porcelain | wc -l)
|
||
if [ $remaining_changes -eq 0 ]; then
|
||
echo "✅ Tous les changements committés"
|
||
else
|
||
echo "⚠️ Changements non committés restants :"
|
||
git status --short
|
||
fi
|
||
|
||
# Afficher l'historique des commits
|
||
echo "Commits créés :"
|
||
git log --oneline -n 10 --graph
|
||
```
|
||
|
||
##### 5. Supprimer le push automatique
|
||
|
||
```bash
|
||
# Note : Pas de push automatique
|
||
echo "📝 Note : Push automatique non effectué"
|
||
echo "Si nécessaire, pushez avec la commande suivante :"
|
||
echo " git push origin $CURRENT_BRANCH"
|
||
```
|
||
|
||
#### Détails de l'algorithme de division
|
||
|
||
##### Étape 1 : Analyse initiale
|
||
|
||
```bash
|
||
# Obtenir et classifier tous les fichiers modifiés
|
||
git diff HEAD --name-status | while read status file; do
|
||
echo "$status:$file"
|
||
done > /tmp/changes.txt
|
||
|
||
# Statistiques des changements par répertoire fonctionnel
|
||
git diff HEAD --name-only | cut -d'/' -f1-2 | sort | uniq -c
|
||
```
|
||
|
||
##### Étape 2 : Groupement initial par limites fonctionnelles
|
||
|
||
```bash
|
||
# Groupement basé sur les répertoires
|
||
GROUPS=$(git diff HEAD --name-only | cut -d'/' -f1-2 | sort | uniq)
|
||
for group in $GROUPS; do
|
||
echo "=== Groupe : $group ==="
|
||
git diff HEAD --name-only | grep "^$group" | head -10
|
||
done
|
||
```
|
||
|
||
##### Étape 3 : Analyser la similarité des changements
|
||
|
||
```bash
|
||
# Analyser le type de changement pour chaque fichier
|
||
git diff HEAD --name-only | while read file; do
|
||
# Détecter les ajouts de nouvelles fonctions/classes
|
||
NEW_FUNCTIONS=$(git diff HEAD -- "$file" | grep -c '^+.*function\|^+.*class\|^+.*def ')
|
||
|
||
# Détecter les patterns de correction de bugs
|
||
BUG_FIXES=$(git diff HEAD -- "$file" | grep -c '^+.*fix\|^+.*bug\|^-.*error')
|
||
|
||
# Déterminer si c'est un fichier de test
|
||
if [[ "$file" =~ test|spec ]]; then
|
||
echo "$file: TEST"
|
||
elif [ $NEW_FUNCTIONS -gt 0 ]; then
|
||
echo "$file: FEAT"
|
||
elif [ $BUG_FIXES -gt 0 ]; then
|
||
echo "$file: FIX"
|
||
else
|
||
echo "$file: REFACTOR"
|
||
fi
|
||
done
|
||
```
|
||
|
||
##### Étape 4 : Ajustements basés sur les dépendances
|
||
|
||
```bash
|
||
# Analyser les relations d'import
|
||
git diff HEAD | grep -E '^[+-].*import|^[+-].*from.*import' | \
|
||
while read line; do
|
||
echo "$line" | sed 's/^[+-]//' | awk '{print $2}'
|
||
done | sort | uniq > /tmp/imports.txt
|
||
|
||
# Grouper les fichiers liés
|
||
git diff HEAD --name-only | while read file; do
|
||
basename=$(basename "$file" .js .ts .py)
|
||
related=$(git diff HEAD --name-only | grep "$basename" | grep -v "^$file$")
|
||
if [ -n "$related" ]; then
|
||
echo "Fichiers liés : $file <-> $related"
|
||
fi
|
||
done
|
||
```
|
||
|
||
##### Étape 5 : Optimisation de la taille des commits
|
||
|
||
```bash
|
||
# Ajuster la taille des groupes
|
||
MAX_FILES_PER_COMMIT=8
|
||
current_group=1
|
||
file_count=0
|
||
|
||
git diff HEAD --name-only | while read file; do
|
||
if [ $file_count -ge $MAX_FILES_PER_COMMIT ]; then
|
||
current_group=$((current_group + 1))
|
||
file_count=0
|
||
fi
|
||
echo "Commit $current_group: $file"
|
||
file_count=$((file_count + 1))
|
||
done
|
||
```
|
||
|
||
##### Étape 6 : Déterminer les groupes finaux
|
||
|
||
```bash
|
||
# Vérifier les résultats de division
|
||
for group in $(seq 1 $current_group); do
|
||
files=$(grep "Commit $group:" /tmp/commit_plan.txt | cut -d':' -f2-)
|
||
lines=$(echo "$files" | xargs git diff HEAD -- | wc -l)
|
||
echo "Commit $group: $(echo "$files" | wc -w) fichiers, $lines lignes modifiées"
|
||
done
|
||
```
|
||
|
||
### Conformité Conventional Commits
|
||
|
||
#### Format de base
|
||
|
||
```text
|
||
<type>[scope optionnel]: <description>
|
||
|
||
[corps optionnel]
|
||
|
||
[pied(s) optionnel(s)]
|
||
```
|
||
|
||
#### Types standard
|
||
|
||
**Types requis** :
|
||
|
||
- `feat` : Nouvelle fonctionnalité (ajout de fonctionnalité visible par l'utilisateur)
|
||
- `fix` : Correction de bug
|
||
|
||
**Types optionnels** :
|
||
|
||
- `build` : Changements au système de build ou aux dépendances externes
|
||
- `chore` : Autres changements (sans impact sur la release)
|
||
- `ci` : Changements aux fichiers de configuration CI ou aux scripts
|
||
- `docs` : Changements de documentation uniquement
|
||
- `style` : Changements qui n'affectent pas la signification du code (espaces, formatage, points-virgules, etc.)
|
||
- `refactor` : Changements de code sans corrections de bugs ou ajouts de fonctionnalités
|
||
- `perf` : Améliorations de performance
|
||
- `test` : Ajout ou modification de tests
|
||
|
||
#### Scope (Optionnel)
|
||
|
||
Indique la zone affectée par le changement :
|
||
|
||
```text
|
||
feat(api): add user authentication endpoint
|
||
fix(ui): resolve button alignment issue
|
||
docs(readme): update installation instructions
|
||
```
|
||
|
||
#### Breaking Change
|
||
|
||
Quand il y a des changements d'API breaking :
|
||
|
||
```text
|
||
feat!: change user API response format
|
||
|
||
```
|
||
|
||
ou
|
||
|
||
```text
|
||
feat(api)!: change authentication flow
|
||
```
|
||
|
||
#### Détection automatique des conventions de projet
|
||
|
||
**Important** : Si des conventions spécifiques au projet existent, elles prennent la priorité.
|
||
|
||
##### 1. Vérifier la configuration CommitLint
|
||
|
||
Détection automatique de la configuration à partir des fichiers suivants :
|
||
|
||
- `commitlint.config.js`
|
||
- `commitlint.config.mjs`
|
||
- `commitlint.config.cjs`
|
||
- `commitlint.config.ts`
|
||
- `.commitlintrc.js`
|
||
- `.commitlintrc.json`
|
||
- `.commitlintrc.yml`
|
||
- `.commitlintrc.yaml`
|
||
- Section `commitlint` dans `package.json`
|
||
|
||
```bash
|
||
# Vérifier les fichiers de configuration exemple
|
||
cat commitlint.config.mjs
|
||
cat .commitlintrc.json
|
||
grep -A 10 '"commitlint"' package.json
|
||
```
|
||
|
||
##### 2. Détecter les types personnalisés
|
||
|
||
Exemple de types spécifiques au projet :
|
||
|
||
```javascript
|
||
// commitlint.config.mjs
|
||
export default {
|
||
extends: ["@commitlint/config-conventional"],
|
||
rules: {
|
||
"type-enum": [
|
||
2,
|
||
"always",
|
||
[
|
||
"feat",
|
||
"fix",
|
||
"docs",
|
||
"style",
|
||
"refactor",
|
||
"test",
|
||
"chore",
|
||
"wip", // Travail en cours
|
||
"hotfix", // Correction d'urgence
|
||
"release", // Release
|
||
"deps", // Mise à jour de dépendance
|
||
"config", // Changement de configuration
|
||
],
|
||
],
|
||
},
|
||
};
|
||
```
|
||
|
||
##### 3. Détecter les paramètres de langue
|
||
|
||
```javascript
|
||
// Quand le projet utilise des messages en français
|
||
export default {
|
||
rules: {
|
||
"subject-case": [0], // Désactiver pour le support français (accents)
|
||
"subject-max-length": [2, "always", 72], // Ajuster la limite de caractères pour le français
|
||
},
|
||
};
|
||
```
|
||
|
||
#### Flux d'analyse automatique
|
||
|
||
1. **Recherche de fichiers de configuration**
|
||
|
||
```bash
|
||
find . -name "commitlint.config.*" -o -name ".commitlintrc.*" | head -1
|
||
```
|
||
|
||
2. **Analyse des commits existants**
|
||
|
||
```bash
|
||
git log --oneline -50 --pretty=format:"%s"
|
||
```
|
||
|
||
3. **Statistiques d'usage des types**
|
||
|
||
```bash
|
||
git log --oneline -100 --pretty=format:"%s" | \
|
||
grep -oE '^[a-z]+(\([^)]+\))?' | \
|
||
sort | uniq -c | sort -nr
|
||
```
|
||
|
||
#### Exemples de conventions de projet
|
||
|
||
##### Style Angular
|
||
|
||
```text
|
||
feat(scope): add new feature
|
||
fix(scope): fix bug
|
||
docs(scope): update documentation
|
||
```
|
||
|
||
##### Style combiné Gitmoji
|
||
|
||
```text
|
||
✨ feat: add user registration
|
||
🐛 fix: resolve login issue
|
||
📚 docs: update API docs
|
||
```
|
||
|
||
##### Projets français
|
||
|
||
```text
|
||
feat: ajout de la fonctionnalité d'inscription utilisateur
|
||
fix: correction du bug du processus de connexion
|
||
docs: mise à jour de la documentation API
|
||
```
|
||
|
||
### Détection de langue
|
||
|
||
Comment nous déterminons votre langue :
|
||
|
||
1. **Option explicite** avec `--lang`
|
||
|
||
```bash
|
||
# Forcer en français
|
||
/semantic-commit --lang fr
|
||
|
||
# Forcer en anglais
|
||
/semantic-commit --lang en
|
||
```
|
||
|
||
2. **Analyse du git log** pour la détermination automatique
|
||
|
||
```bash
|
||
# Analyser la langue des 20 derniers commits
|
||
git log --oneline -20 --pretty=format:"%s" | \
|
||
grep -E '^[\x{00C0}-\x{017F}]' | wc -l
|
||
# Mode français si détection de caractères accentués
|
||
```
|
||
|
||
3. **Fichiers de projet** paramètres de langue
|
||
|
||
```bash
|
||
# Vérifier la langue du README.md
|
||
head -10 README.md | grep -E '^[\x{00C0}-\x{017F}]' | wc -l
|
||
|
||
# Vérifier la description de package.json
|
||
grep -E '"description".*[\x{00C0}-\x{017F}]' package.json
|
||
```
|
||
|
||
4. **Analyse des commentaires et chaînes** dans les fichiers modifiés
|
||
|
||
```bash
|
||
# Vérifier la langue des commentaires dans les fichiers modifiés
|
||
git diff HEAD | grep -E '^[+-].*//.*[\x{3040}-\x{30ff}]|[\x{4e00}-\x{9fff}]' | wc -l
|
||
```
|
||
|
||
#### Algorithme de détermination
|
||
|
||
```bash
|
||
# Calcul du score de langue française
|
||
FRENCH_SCORE=0
|
||
|
||
# 1. Configurations CommitLint (+3 points)
|
||
if grep -q '"subject-case".*\[0\]' commitlint.config.* 2>/dev/null; then
|
||
FRENCH_SCORE=$((FRENCH_SCORE + 3))
|
||
fi
|
||
|
||
# 2. Analyse de git log (max +2 points)
|
||
FRENCH_COMMITS=$(git log --oneline -20 --pretty=format:"%s" | \
|
||
grep -cE '[àâäçéèêëïîôùûüÿæœÀÂÄÇÉÈÊËÏÎÔÙÛÜŸÆŒ]' 2>/dev/null || echo 0)
|
||
if [ $FRENCH_COMMITS -gt 10 ]; then
|
||
FRENCH_SCORE=$((FRENCH_SCORE + 2))
|
||
elif [ $FRENCH_COMMITS -gt 5 ]; then
|
||
FRENCH_SCORE=$((FRENCH_SCORE + 1))
|
||
fi
|
||
|
||
# 3. Vérification README.md (+1 point)
|
||
if head -5 README.md 2>/dev/null | grep -qE '[àâäçéèêëïîôùûüÿæœÀÂÄÇÉÈÊËÏÎÔÙÛÜŸÆŒ]'; then
|
||
FRENCH_SCORE=$((FRENCH_SCORE + 1))
|
||
fi
|
||
|
||
# 4. Vérification du contenu des fichiers modifiés (+1 point)
|
||
if git diff HEAD 2>/dev/null | grep -qE '^[+-].*[àâäçéèêëïîôùûüÿæœÀÂÄÇÉÈÊËÏÎÔÙÛÜŸÆŒ]'; then
|
||
FRENCH_SCORE=$((FRENCH_SCORE + 1))
|
||
fi
|
||
|
||
# Déterminer : mode français si score >= 3
|
||
if [ $FRENCH_SCORE -ge 3 ]; then
|
||
LANGUAGE="fr"
|
||
else
|
||
LANGUAGE="en"
|
||
fi
|
||
```
|
||
|
||
### Chargement automatique de configuration
|
||
|
||
#### Ce qui se passe à l'exécution
|
||
|
||
Nous vérifions les fichiers de configuration dans cet ordre :
|
||
|
||
1. **Rechercher les fichiers de configuration CommitLint**
|
||
|
||
```bash
|
||
# Rechercher dans cet ordre, utiliser le premier fichier trouvé
|
||
commitlint.config.mjs
|
||
commitlint.config.js
|
||
commitlint.config.cjs
|
||
commitlint.config.ts
|
||
.commitlintrc.js
|
||
.commitlintrc.json
|
||
.commitlintrc.yml
|
||
.commitlintrc.yaml
|
||
package.json (section commitlint)
|
||
```
|
||
|
||
2. **Parser le contenu de configuration**
|
||
- Extraire la liste des types disponibles
|
||
- Vérifier les restrictions de scope
|
||
- Obtenir les limites de longueur de message
|
||
- Vérifier les paramètres de langue
|
||
|
||
3. **Analyser l'historique des commits existants**
|
||
|
||
```bash
|
||
# Apprendre les patterns d'usage à partir des commits récents
|
||
git log --oneline -100 --pretty=format:"%s" | \
|
||
head -20
|
||
```
|
||
|
||
#### Analyser les exemples de configuration
|
||
|
||
**commitlint.config.mjs standard** :
|
||
|
||
```javascript
|
||
export default {
|
||
extends: ["@commitlint/config-conventional"],
|
||
rules: {
|
||
"type-enum": [
|
||
2,
|
||
"always",
|
||
["feat", "fix", "docs", "style", "refactor", "perf", "test", "chore"],
|
||
],
|
||
"scope-enum": [2, "always", ["api", "ui", "core", "auth", "db"]],
|
||
},
|
||
};
|
||
```
|
||
|
||
**Configuration compatible japonais** :
|
||
|
||
```javascript
|
||
export default {
|
||
extends: ["@commitlint/config-conventional"],
|
||
rules: {
|
||
"subject-case": [0], // Désactiver pour le japonais
|
||
"subject-max-length": [2, "always", 72],
|
||
"type-enum": [
|
||
2,
|
||
"always",
|
||
["feat", "fix", "docs", "style", "refactor", "test", "chore"],
|
||
],
|
||
},
|
||
};
|
||
```
|
||
|
||
**Configuration avec types personnalisés** :
|
||
|
||
```javascript
|
||
export default {
|
||
extends: ["@commitlint/config-conventional"],
|
||
rules: {
|
||
"type-enum": [
|
||
2,
|
||
"always",
|
||
[
|
||
"feat",
|
||
"fix",
|
||
"docs",
|
||
"style",
|
||
"refactor",
|
||
"test",
|
||
"chore",
|
||
"wip", // Travail en cours
|
||
"hotfix", // Correction d'urgence
|
||
"release", // Préparation de release
|
||
"deps", // Mise à jour de dépendance
|
||
"config", // Changement de configuration
|
||
],
|
||
],
|
||
},
|
||
};
|
||
```
|
||
|
||
#### Comportement de fallback
|
||
|
||
Si aucun fichier de configuration n'est trouvé :
|
||
|
||
1. **Inférence automatique** par analyse du git log
|
||
|
||
```bash
|
||
# Extraire les types des 100 derniers commits
|
||
git log --oneline -100 --pretty=format:"%s" | \
|
||
grep -oE '^[a-z]+(\([^)]+\))?' | \
|
||
sort | uniq -c | sort -nr
|
||
```
|
||
|
||
2. **Par défaut au standard Conventional Commits**
|
||
|
||
```
|
||
feat, fix, docs, style, refactor, perf, test, chore, build, ci
|
||
```
|
||
|
||
3. **Détermination de langue**
|
||
- Mode français si détection de caractères accentués français
|
||
- Mode anglais par défaut
|
||
|
||
### Exigences
|
||
|
||
- Doit être dans un dépôt Git
|
||
- Besoin de changements non committés
|
||
- Les changements stagés sont temporairement réinitialisés
|
||
|
||
### Important
|
||
|
||
- **Ne pushera pas** : Vous devez `git push` vous-même
|
||
- **Même branche** : Les commits restent dans la branche actuelle
|
||
- **Sauvegardez d'abord** : Considérez `git stash` pour la sécurité
|
||
|
||
### Quelles règles gagnent
|
||
|
||
Lors de la création de messages de commit, nous suivons cet ordre :
|
||
|
||
1. **Paramètres CommitLint** (priorité la plus élevée)
|
||
- Paramètres dans les fichiers `commitlint.config.*`
|
||
- Types personnalisés et restrictions de scope
|
||
- Restrictions de longueur et de casse de message
|
||
|
||
2. **Historique des commits existants** (deuxième priorité)
|
||
- Statistiques des types réellement utilisés
|
||
- Langue des messages (français/anglais)
|
||
- Patterns d'usage des scopes
|
||
|
||
3. **Type de projet** (troisième priorité)
|
||
- `package.json` → Projet Node.js
|
||
- `Cargo.toml` → Projet Rust
|
||
- `pom.xml` → Projet Java
|
||
|
||
4. **Standard Conventional Commits** (fallback)
|
||
- Comportement standard quand aucun paramètre n'est trouvé
|
||
|
||
#### Exemples de détection de convention
|
||
|
||
**Détection automatique de scope dans Monorepo** :
|
||
|
||
```bash
|
||
# Inférer les scopes à partir du dossier packages/
|
||
ls packages/ | head -10
|
||
# → Proposer api, ui, core, auth, etc. comme scopes
|
||
```
|
||
|
||
**Conventions spécifiques au framework** :
|
||
|
||
```javascript
|
||
// Pour les projets Angular
|
||
{
|
||
'scope-enum': [2, 'always', [
|
||
'animations', 'common', 'core', 'forms', 'http', 'platform-browser',
|
||
'platform-server', 'router', 'service-worker', 'upgrade'
|
||
]]
|
||
}
|
||
|
||
// Pour les projets React
|
||
{
|
||
'scope-enum': [2, 'always', [
|
||
'components', 'hooks', 'utils', 'types', 'styles', 'api'
|
||
]]
|
||
}
|
||
```
|
||
|
||
**Conventions spécifiques à l'entreprise/équipe** :
|
||
|
||
```javascript
|
||
// Pattern courant dans les équipes françaises
|
||
{
|
||
'type-enum': [2, 'always', [
|
||
'feat', 'fix', 'docs', 'style', 'refactor', 'test', 'chore',
|
||
'wip', // Travail en cours (pour les pull requests)
|
||
'hotfix', // Correction d'urgence
|
||
'release' // Préparation de release
|
||
]],
|
||
'subject-case': [0], // Support japonais
|
||
'subject-max-length': [2, 'always', 72] // Limite plus longue pour le japonais
|
||
}
|
||
```
|
||
|
||
### Bonnes pratiques
|
||
|
||
1. **Suivre les règles** : Utiliser les patterns existants
|
||
2. **Garder petit** : Un changement logique par commit
|
||
3. **Être clair** : Dire ce qui a changé
|
||
4. **Grouper intelligemment** : Fichiers liés ensemble
|
||
5. **Tests séparés** : Commits de tests seuls
|
||
6. **Utiliser les configurations** : CommitLint aide les équipes à rester cohérentes
|
||
|
||
### Exemples de division du monde réel (Avant/Après)
|
||
|
||
#### Exemple 1 : Ajout de système d'authentification volumineux
|
||
|
||
**Avant (un commit massif)** :
|
||
|
||
```bash
|
||
# Fichiers modifiés (15 fichiers, 850 lignes modifiées)
|
||
src/auth/login.js # Nouveau
|
||
src/auth/register.js # Nouveau
|
||
src/auth/password.js # Nouveau
|
||
src/auth/types.js # Nouveau
|
||
src/api/auth-routes.js # Nouveau
|
||
src/middleware/auth.js # Nouveau
|
||
src/database/migrations/001_users.sql # Nouveau
|
||
src/database/models/user.js # Nouveau
|
||
tests/auth/login.test.js # Nouveau
|
||
tests/auth/register.test.js # Nouveau
|
||
tests/api/auth-routes.test.js # Nouveau
|
||
docs/authentication.md # Nouveau
|
||
package.json # Ajout de dépendance
|
||
README.md # Ajout d'usage
|
||
.env.example # Exemple de variable d'environnement
|
||
|
||
# Commit conventionnel problématique
|
||
feat: implement complete user authentication system with login, registration, password reset, API routes, database models, tests and documentation
|
||
```
|
||
|
||
**Après (divisé en 5 commits significatifs)** :
|
||
|
||
```bash
|
||
# Commit 1 : Fondation base de données
|
||
feat(db): add user model and authentication schema
|
||
|
||
Fichiers inclus :
|
||
- src/database/migrations/001_users.sql
|
||
- src/database/models/user.js
|
||
- src/auth/types.js
|
||
|
||
Raison : La structure de base de données est la fondation pour les autres fonctionnalités, committée en premier
|
||
|
||
# Commit 2 : Logique d'authentification
|
||
feat(auth): implement core authentication functionality
|
||
|
||
Fichiers inclus :
|
||
- src/auth/login.js
|
||
- src/auth/register.js
|
||
- src/auth/password.js
|
||
- src/middleware/auth.js
|
||
|
||
Raison : Logique métier d'authentification centrale committée ensemble
|
||
|
||
# Commit 3 : Points de terminaison API
|
||
feat(api): add authentication API routes
|
||
|
||
Fichiers inclus :
|
||
- src/api/auth-routes.js
|
||
|
||
Raison : La couche API dépend de la logique d'authentification, committée plus tard
|
||
|
||
# Commit 4 : Tests complets
|
||
test(auth): add comprehensive authentication tests
|
||
|
||
Fichiers inclus :
|
||
- tests/auth/login.test.js
|
||
- tests/auth/register.test.js
|
||
- tests/api/auth-routes.test.js
|
||
|
||
Raison : Tests ajoutés après que l'implémentation soit complète
|
||
|
||
# Commit 5 : Documentation et configuration
|
||
docs(auth): add authentication documentation and configuration
|
||
|
||
Fichiers inclus :
|
||
- docs/authentication.md
|
||
- package.json
|
||
- README.md
|
||
- .env.example
|
||
|
||
Raison : Documentation et configuration committées ensemble à la fin
|
||
```
|
||
|
||
#### Exemple 2 : Corrections de bugs et refactorisation mixtes
|
||
|
||
**Avant (commit mixte problématique)** :
|
||
|
||
```bash
|
||
# Fichiers modifiés (8 fichiers, 320 lignes modifiées)
|
||
src/user/service.js # Corrections de bugs + Refactorisation
|
||
src/user/validator.js # Nouveau (refactorisation)
|
||
src/auth/middleware.js # Correction de bug
|
||
src/api/user-routes.js # Correction de bug + Amélioration de gestion d'erreurs
|
||
tests/user.test.js # Ajout de test
|
||
tests/auth.test.js # Ajout de test de correction de bug
|
||
docs/user-api.md # Mise à jour de documentation
|
||
package.json # Mise à jour de dépendance
|
||
|
||
# Commit problématique
|
||
fix: resolve user validation bugs and refactor validation logic with improved error handling
|
||
```
|
||
|
||
**Après (divisé en 3 commits par type)** :
|
||
|
||
```bash
|
||
# Commit 1 : Corrections de bugs critiques
|
||
fix: resolve user validation and authentication bugs
|
||
|
||
Fichiers inclus :
|
||
- src/user/service.js (portion correction de bug uniquement)
|
||
- src/auth/middleware.js
|
||
- tests/auth.test.js (tests de correction de bugs uniquement)
|
||
|
||
Raison : Bugs affectant la production corrigés avec la priorité la plus élevée
|
||
|
||
# Commit 2 : Refactorisation de logique de validation
|
||
refactor: extract and improve user validation logic
|
||
|
||
Fichiers inclus :
|
||
- src/user/service.js (portion refactorisation)
|
||
- src/user/validator.js
|
||
- src/api/user-routes.js
|
||
- tests/user.test.js
|
||
|
||
Raison : Améliorations structurelles committées comme unités fonctionnelles
|
||
|
||
# Commit 3 : Documentation et mise à jour de dépendance
|
||
chore: update documentation and dependencies
|
||
|
||
Fichiers inclus :
|
||
- docs/user-api.md
|
||
- package.json
|
||
|
||
Raison : Améliorations de l'environnement de développement committées ensemble à la fin
|
||
```
|
||
|
||
#### Exemple 3 : Développement simultané de multiples fonctionnalités
|
||
|
||
**Avant (commit massif cross-fonctionnel)** :
|
||
|
||
```bash
|
||
# Fichiers modifiés (12 fichiers, 600 lignes modifiées)
|
||
src/user/profile.js # Nouvelle fonctionnalité A
|
||
src/user/avatar.js # Nouvelle fonctionnalité A
|
||
src/notification/email.js # Nouvelle fonctionnalité B
|
||
src/notification/sms.js # Nouvelle fonctionnalité B
|
||
src/api/profile-routes.js # API nouvelle fonctionnalité A
|
||
src/api/notification-routes.js # API nouvelle fonctionnalité B
|
||
src/dashboard/widgets.js # Nouvelle fonctionnalité C
|
||
src/dashboard/charts.js # Nouvelle fonctionnalité C
|
||
tests/profile.test.js # Tests nouvelle fonctionnalité A
|
||
tests/notification.test.js # Tests nouvelle fonctionnalité B
|
||
tests/dashboard.test.js # Tests nouvelle fonctionnalité C
|
||
package.json # Dépendances de toutes les fonctionnalités
|
||
|
||
# Commit problématique
|
||
feat: add user profile management, notification system and dashboard widgets
|
||
```
|
||
|
||
**Après (divisé en 4 commits par fonctionnalité)** :
|
||
|
||
```bash
|
||
# Commit 1 : Fonctionnalité profil utilisateur
|
||
feat(profile): add user profile management
|
||
|
||
Fichiers inclus :
|
||
- src/user/profile.js
|
||
- src/user/avatar.js
|
||
- src/api/profile-routes.js
|
||
- tests/profile.test.js
|
||
|
||
Raison : La fonctionnalité profil est une unité fonctionnelle indépendante
|
||
|
||
# Commit 2 : Système de notification
|
||
feat(notification): implement email and SMS notifications
|
||
|
||
Fichiers inclus :
|
||
- src/notification/email.js
|
||
- src/notification/sms.js
|
||
- src/api/notification-routes.js
|
||
- tests/notification.test.js
|
||
|
||
Raison : La fonctionnalité notification est une unité fonctionnelle indépendante
|
||
|
||
# Commit 3 : Widgets de tableau de bord
|
||
feat(dashboard): add interactive widgets and charts
|
||
|
||
Fichiers inclus :
|
||
- src/dashboard/widgets.js
|
||
- src/dashboard/charts.js
|
||
- tests/dashboard.test.js
|
||
|
||
Raison : La fonctionnalité tableau de bord est une unité fonctionnelle indépendante
|
||
|
||
# Commit 4 : Mise à jour des dépendances et infrastructure
|
||
chore: update dependencies for new features
|
||
|
||
Fichiers inclus :
|
||
- package.json
|
||
|
||
Raison : Mises à jour de dépendances communes committées ensemble à la fin
|
||
```
|
||
|
||
### Comparaison des effets de division
|
||
|
||
| Élément | Avant (Commit massif) | Après (Division appropriée) |
|
||
| --------------------------- | --------------------------------------------------- | -------------------------------------------------------------------- |
|
||
| **Reviewabilité** | ❌ Très difficile | ✅ Chaque commit est petit et reviewable |
|
||
| **Suivi de bugs** | ❌ Difficile d'identifier l'emplacement du problème | ✅ Les commits problématiques peuvent être immédiatement identifiés |
|
||
| **Revert** | ❌ Besoin de tout reverter | ✅ Peut identifier et reverter uniquement les parties problématiques |
|
||
| **Développement parallèle** | ❌ Sujet aux conflits | ✅ Fusion basée sur les fonctionnalités est facile |
|
||
| **Déploiement** | ❌ Toutes les fonctionnalités déployées en une fois | ✅ Déploiement par étapes possible |
|
||
|
||
### Dépannage
|
||
|
||
#### Quand le commit échoue
|
||
|
||
- Vérifier les hooks pre-commit
|
||
- Résoudre les dépendances
|
||
- Réessayer avec des fichiers individuels
|
||
|
||
#### Quand la division est inappropriée
|
||
|
||
- Ajuster avec l'option `--max-commits`
|
||
- Utiliser le mode manuel `edit`
|
||
- Relancer avec une granularité plus fine
|