git filter-branch --env-filter '
export GIT_AUTHOR_EMAIL="[email protected]"
export GIT_AUTHOR_NAME="foo"' -- commita..commitb
Résultats en Which ref do you want to rewrite?
Donc, il semble que filter-branch
ne vous permet pas de utiliser la notation de distance utilisez une plage entre deux références arbitraires.
Quel est le moyen le plus simple d’exécuter un filtre sur une plage de validations consécutives (quelque part dans l’historique d’une branche) si cette approche n’est pas possible?.
La solution la plus propre que j'ai trouvée consistait à:
refb
.refa..temp
.c'est à dire.
git branch temp refb
git filter-branch --env-filter '
export GIT_AUTHOR_EMAIL="[email protected]"' refa..temp
git rebase temp
git branch --delete temp
Vous ne pouvez pas appliquer la branche de filtre au milieu de l'historique, comme le dit @kan. Vous devez postuler depuis votre engagement connu jusqu'à la fin de l'historique
git filter-branch --env-filter '...' SHA1..HEAD
Filter-branch peut vérifier l'auteur ou les autres informations du commit, choisir de modifier ou non le commit, il existe donc des moyens d'accomplir ce que vous voulez, voir http://git-scm.com/book/ch6-4 .html , recherchez "Modification des adresses électroniques dans le monde"
Rappelez-vous: si vous avez poussé les commits vers un référentiel public, vous ne devriez pas utiliser filter-branch
git filter-branch
accepte accepte la notation d'intervalle, mais la fin de l'intervalle doit être une référence et non l'ID d'un commit.
git checkout -b tofilter commitb
git filter-branch .... commita..tofilter
Si donné ne fait que valider, il ne saurait pas quelle référence mettre à jour avec la branche filtrée.
Vous pouvez filtrer les commandes dans une instruction if qui vérifie cette plage. Vous pouvez vérifier si un commit est dans une plage donnée avec cette commande:
git rev-list start..end | grep **fullsha**
Le commit en cours sera stocké dans $GIT_COMMIT
dans votre filtre. Donc, votre filtre devient:
git filter-branch --env-filter '
if git rev-list commita..commitb | grep $GIT_COMMIT; then
export GIT_AUTHOR_EMAIL="[email protected]"
export GIT_AUTHOR_NAME="foo"
fi' -- ^commita --all
Si vous souhaitez uniquement réécrire votre branche actuelle, remplacez --all
par HEAD
Je le fais de cette façon.
Supposons que vous souhaitiez filtrer le contenu d'une branche appelée branche-vous-êtes-filtre.
Supposons qu'il existe un ancêtre engagé dans cette branche, avec une référence appelée ref-for-commit-to-stop-at.
git filter-branch --commit-filter 'YOUR_FILTER_COMMANDS' branch-you-are-filtering...ref-for-commit-to-stop-at
Après exécution, la validation de ref-for-commit-to-stop-at ne sera pas modifiée. Tous les commits filtrés\modifiés dans la branche que vous filtrez seront basés sur ref-for-commit-to-stop-at.
Que vous utilisiez ou non --commit-filter ou quelque chose d'autre dépend de vous.
Vous ne pouvez pas simplement annuler des commits au milieu d'une histoire, car sha1 d'un commit dépend de celui d'un parent. Donc, le git ne sait pas où vous voulez pointer votre référence HEAD après la filtration. Donc, vous devriez tout réécrire à la tête.
Exemple:
A---B---C---D---E---F master
\
\--G---H branch
si vous voulez filtrer les commits B et C, vous devriez aussi filtrer tous les commits après: D, E, F, G, H . C'est pourquoi git vous dit d'utiliser un ref juste pas fini avec une tête détachée.
Après avoir modifié les commits B et C, l’arrêt aura l'aspect suivant:
A---B---C---D---E---F master
\ \
\ \--G---H branch
\-B'--C' (HEAD or a temporary TAG?..)
Ainsi, les variables master
et branch
ne seront pas modifiées. Je ne pense pas que c’est ce que vous voulez ... Cela signifie que vous devez annuler tous les commits. L'histoire sera alors:
A---B---C---D---E---F (loose end, will be garbage collected one day)
\ \
\ \--G---H (loose end, will be garbage collected one day)
\-B'--C'--D'--E'--F' master
\
\--G'--H' branch
Utilisez le paramètre --setup
de filter-branch et une alimentation Shell:
git filter-branch --setup '
for id in `git rev-list commitA..commitB`; do
eval filterfor_$id=rewrite
done
rewrite() {
GIT_AUTHOR_NAME="Frederick. O. Oosball"
[email protected]
}
' --env-filter 'eval \$filterfor_$GIT_COMMIT'
La solution de @Acron me semble fausse. Je suggérerais ensuite de changer entre refa et refb, y compris les deux hashs:
git tag master.bak
git reset --hard refa
git filter-branch --env-filter '
export GIT_AUTHOR_EMAIL="[email protected]"' refa^..master
git cherry-pick refb..master.bak
git tag -d master.bak