Le conseil qui vous a été donné est erroné. Le fait de définir inconditionnellement GIT_AUTHOR_DATE dans un fichier --env-filter
réécrirait la date de chaque livraison. De plus, il serait inhabituel d'utiliser git commit à l'intérieur de --index-filter
.
Vous avez affaire à des problèmes multiples et indépendants.
Spécification de dates autres que "maintenant".
Chaque commit a deux dates : la date de l'auteur et la date du committer. Vous pouvez les remplacer en fournissant des valeurs à travers les variables d'environnement GIT_AUTHOR_DATE et GIT_COMMITTER_DATE pour toute commande qui écrit un nouveau commit. Voir "Formats de date" dans git-commit(1) ou le ci-dessous :
Git internal format = <unix timestamp> <time zone offset>, e.g. 1112926393 +0200
RFC 2822 = e.g. Thu, 07 Apr 2005 22:13:13 +0200
ISO 8601 = e.g. 2005-04-07T22:13:13
La seule commande qui écrit un nouveau commit pendant une utilisation normale est git commit . Il dispose également d'un --date
qui vous permet de spécifier directement la date de l'auteur. Votre utilisation prévue comprend git filter-branch --env-filter
utilise également les variables d'environnement mentionnées ci-dessus (celles-ci font partie de la variable "env" dont l'option porte le nom ; cf. "Options" dans git-filter-branch(1) et la commande "plomberie" sous-jacente git-commit-tree(1) .
Insertion d'un fichier dans un seul réf. Histoire
Si votre dépôt est très simple (c'est-à-dire que vous n'avez qu'une seule branche, pas de tags), alors vous pouvez probablement utiliser git rebasement pour faire le travail.
Dans les commandes suivantes, utilisez le nom de l'objet (hachage SHA-1) du commit au lieu de "A". N'oubliez pas d'utiliser l'une des méthodes "date override" lorsque vous exécutez la commande git commit .
---A---B---C---o---o---o master
git checkout master
git checkout A~0
git add path/to/file
git commit --date='whenever'
git tag ,new-commit -m'delete me later'
git checkout -
git rebase --onto ,new-commit A
git tag -d ,new-commit
---A---N (was ",new-commit", but we delete the tag)
\
B'---C'---o---o---o master
Si vous voulez mettre à jour A pour inclure le nouveau fichier (au lieu de créer un nouveau commit où il a été ajouté), alors utilisez git commit --amend
au lieu de git commit
. Le résultat ressemblerait à ceci :
---A'---B'---C'---o---o---o master
Ce qui précède fonctionne tant que vous pouvez nommer le commit qui devrait être le parent de votre nouveau commit. Si vous voulez vraiment que votre nouveau fichier soit ajouté via un nouveau commit Root (sans parents), alors vous avez besoin de quelque chose d'un peu différent :
B---C---o---o---o master
git checkout master
git checkout --orphan new-root
git rm -rf .
git add path/to/file
GIT_AUTHOR_DATE='whenever' git commit
git checkout -
git rebase --root --onto new-root
git branch -d new-root
N (was new-root, but we deleted it)
\
B'---C'---o---o---o master
git checkout --orphan
est relativement récent (Git 1.7.2), mais il y a des d'autres façons de faire la même chose qui fonctionnent sur les anciennes versions de Git.
Insertion d'un fichier dans un système multi réf. Histoire
Si votre dépôt est plus complexe (c'est-à-dire qu'il a plus d'une référence (branches, tags, etc.)), alors vous aurez probablement besoin d'utiliser git filter-branch . Avant d'utiliser git filter-branch vous devez faire une copie de sauvegarde de l'ensemble de votre référentiel. Un simple tar de votre arbre de travail complet (y compris le répertoire .git) est suffisant. git filter-branch fait des références de sauvegarde, mais il est souvent plus facile de récupérer d'un filtrage incorrect en supprimant simplement le fichier .git
et le restaurer à partir de votre sauvegarde.
Remarque : Les exemples ci-dessous utilisent la commande de niveau inférieur git update-index --add
au lieu de git add
. Vous pouvez utiliser git add mais vous devez d'abord copier le fichier depuis un emplacement externe vers le chemin attendu ( --index-filter
exécute sa commande dans un GIT_WORK_TREE temporaire qui est vide).
Si vous voulez que votre nouveau fichier soit ajouté à chaque commit existant, alors vous pouvez faire ceci :
new_file=$(git hash-object -w path/to/file)
git filter-branch \
--index-filter \
'git update-index --add --cacheinfo 100644 '"$new_file"' path/to/file' \
--tag-name-filter cat \
-- --all
git reset --hard
Je ne vois pas vraiment de raison de changer les dates des commits existants avec --env-filter 'GIT_AUTHOR_DATE=…'
. Si vous l'avez utilisé, vous auriez dû le rendre conditionnel afin qu'il réécrive la date pour chaque livraison.
Si vous voulez que votre nouveau fichier apparaisse seulement dans les commits après un commit existant ("A"), alors vous pouvez faire ceci :
file_path=path/to/file
before_commit=$(git rev-parse --verify A)
file_blob=$(git hash-object -w "$file_path")
git filter-branch \
--index-filter '
if x=$(git rev-list -1 "$GIT_COMMIT" --not '"$before_commit"') &&
test -n "$x"; then
git update-index --add --cacheinfo 100644 '"$file_blob $file_path"'
fi
' \
--tag-name-filter cat \
-- --all
git reset --hard
Si vous voulez que le fichier soit ajouté via un nouveau commit qui doit être inséré au milieu de votre historique, alors vous devrez générer le nouveau commit avant d'utiliser la commande git filter-branch et ajouter --parent-filter
à git filter-branch :
file_path=path/to/file
before_commit=$(git rev-parse --verify A)
git checkout master
git checkout "$before_commit"
git add "$file_path"
git commit --date='whenever'
new_commit=$(git rev-parse --verify HEAD)
file_blob=$(git rev-parse --verify HEAD:"$file_path")
git checkout -
git filter-branch \
--parent-filter "sed -e s/$before_commit/$new_commit/g" \
--index-filter '
if x=$(git rev-list -1 "$GIT_COMMIT" --not '"$new_commit"') &&
test -n "$x"; then
git update-index --add --cacheinfo 100644 '"$file_blob $file_path"'
fi
' \
--tag-name-filter cat \
-- --all
git reset --hard
Vous pouvez également vous arranger pour que le fichier soit d'abord ajouté dans un nouveau commit racine : créez votre nouveau commit racine via la méthode "orphan" de l'application git rebasement (le capturer dans new_commit
), utilisez la méthode inconditionnelle --index-filter
et un --parent-filter
comme "sed -e \"s/^$/-p $new_commit/\""
.
1 votes
Réponses courtes et simples : stackoverflow.com/a/34639957/2708266
58 votes
Je me demande si les personnes qui cherchent la réponse à cette question veulent simplement maintenir leur "série de contributions" sur GitHub de cette façon.
10 votes
@ZitRo oui. Et il suffit de mettre
git commit --date="xxx day ago" -m "yyy"
est suffisant à cet effet si quelqu'un se pose la question.1 votes
alexpeattie.com/blog/working-with-dates-in-git : si vous cherchez une explication douce
6 votes
@ZitRo une meilleure utilisation de ceci est de faire en sorte que tous vos commits sur un projet personnel aient lieu le week-end. Juste au cas où un employeur voudrait réclamer votre travail, CYA.
0 votes
@VlasSokolov Je viens d'essayer ce que vous avez suggéré, et il définit la date et l'heure correctes localement, mais lorsque je pousse vers GitHub, il y a l'heure réelle de la livraison.
0 votes
@RichCourt intéressant, cela a fonctionné pour moi avant. Se pourrait-il qu'ils aient changé quelque chose de leur côté ?
0 votes
@VlasSokolov Oui, je suppose qu'ils ont dû le faire. Pour autant que je puisse dire, ils montrent maintenant l'heure à laquelle le commit wash a été poussé. C'est type de est logique, car c'est l'heure à laquelle il a été commité dans la branche master sur Origin. Du moins, je suppose que c'est leur logique. Cela n'aide pas les personnes qui veulent une heure spécifique affichée, et n'est pas non plus très utile si vous créez un tas de commits sans pousser pendant un certain temps, ou si vous essayez de faire correspondre les commits de la branche master avec ceux de la branche d'origine.
git log
avec ce que vous voyez sur GitHub.0 votes
@RichCourt vient de faire un test à ce sujet, s'engageant avec
--date="1 day ago"
a fonctionné comme je l'avais suggéré à l'origine pour les besoins de la vue "carrés verts" de GitHub. Donc, le conseil précédent est toujours valable, je suppose.