Je suis en train de tout convertir en Git pour mon usage personnel et j'ai trouvé quelques anciennes versions d'un fichier déjà dans le référentiel. Comment puis-je le valider dans l'historique dans le bon ordre en fonction de la "date de modification" du fichier afin d'avoir un historique précis du fichier?
On m'a dit que quelque chose comme ça marcherait:
git filter-branch --env-filter="GIT_AUTHOR_DATE=... --index-filter "git commit path/to/file --date " --tag-name-filter cat -- --all
git
version-control
repository
git-commit
inconnue
la source
la source
git commit --date="xxx day ago" -m "yyy"
suffit à cet effet si quelqu'un se le demande.Réponses:
Les conseils que vous avez reçus sont viciés. La définition inconditionnelle de GIT_AUTHOR_DATE dans an
--env-filter
réécrirait la date de chaque validation. De plus, il serait inhabituel d'utiliser git commit à l' intérieur--index-filter
.Vous traitez ici de multiples problèmes 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 via 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 ci-dessous:
La seule commande qui écrit un nouveau commit pendant une utilisation normale est git commit . Il dispose également d'une
--date
option qui vous permet de spécifier directement la date de l'auteur. Votre utilisation prévue comprendgit filter-branch --env-filter
également les variables d'environnement mentionnées ci-dessus (elles font partie de «env» après lequel l'option est nommée; voir «Options» dans git-filter-branch (1) et la commande sous-jacente «plumbing» git-commit -arbre (1) .Insertion d'un fichier dans un historique de références unique
Si votre référentiel est très simple (c'est-à-dire que vous n'avez qu'une seule branche, pas de balises), vous pouvez probablement utiliser git rebase pour faire le travail.
Dans les commandes suivantes, utilisez le nom d'objet (hachage SHA-1) de la validation au lieu de «A». N'oubliez pas d'utiliser l'une des méthodes de «remplacement de date» lorsque vous exécutez git commit .
Si vous souhaitez mettre à jour A pour inclure le nouveau fichier (au lieu de créer un nouveau commit là où il a été ajouté), utilisez
git commit --amend
plutôt à la place degit commit
. Le résultat ressemblerait à ceci: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 réellement que votre nouveau fichier soit ajouté via un nouveau commit racine (pas de parents), alors vous avez besoin de quelque chose d'un peu différent:
git checkout --orphan
est relativement nouveau (Git 1.7.2), mais il existe d' autres façons de faire la même chose qui fonctionnent sur les anciennes versions de Git.Insertion d'un fichier dans un historique multi- références
Si votre référentiel est plus complexe (c'est-à-dire qu'il a plus d'une référence (branches, balises, etc.)), alors vous devrez probablement 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. Une simple archive tar de l'ensemble de votre arborescence de travail (y compris le répertoire .git) est suffisante. git filter-branch crée des références de sauvegarde, mais il est souvent plus facile de récupérer à partir d'un filtrage pas tout à fait correct en supprimant simplement votre
.git
répertoire et en le restaurant à partir de votre sauvegarde.Remarque: Les exemples ci-dessous utilisent la commande de niveau inférieur
git update-index --add
au lieu degit add
. Vous pouvez utiliser git add , mais vous devez d'abord copier le fichier d'un emplacement externe vers le chemin prévu (--index-filter
exécute sa commande dans un GIT_WORK_TREE temporaire qui est vide).Si vous souhaitez que votre nouveau fichier soit ajouté à chaque commit existant, vous pouvez le faire:
Je ne vois pas vraiment de raison de changer les dates des commits existants avec
--env-filter 'GIT_AUTHOR_DATE=…'
. Si vous l'utilisiez, vous l'auriez rendu conditionnel pour qu'il réécrive la date de chaque commit.Si vous souhaitez que votre nouveau fichier n'apparaisse que dans les validations après une validation existante («A»), vous pouvez le faire:
Si vous souhaitez que le fichier soit ajouté via un nouveau commit qui doit être inséré au milieu de votre historique, vous devrez générer le nouveau commit avant d'utiliser git filter-branch et l'ajouter
--parent-filter
à git filter-branch :Vous pouvez également prendre des dispositions pour que le fichier soit d' abord ajouté dans un commit racine: créer votre nouvelle racine engagement via la méthode « orphelin » de la rebasage git section (capture en
new_commit
), utiliser l'inconditionnel--index-filter
, et--parent-filter
comme"sed -e \"s/^$/-p $new_commit/\""
.la source
--index-filter
appliqué les validations renvoyées pargit rev-list
? Pour le moment, je vois un filtre d'index appliqué à un sous-ensemble de rev-list. Appréciez tout aperçu.-- --all
de traiter tous les commits accessibles depuis n'importe quelle ref. Le dernier exemple montre comment modifier uniquement certaines validations (testez simplement GIT_COMMIT pour ce que vous voulez). Pour modifier uniquement une liste spécifique de validations, vous pouvez enregistrer la liste avant de filtrer (par exemplegit rev-list … >/tmp/commits_to_rewrite
), puis tester l'appartenance à l'intérieur du filtre (par exempleif grep -qF "$GIT_COMMIT" /tmp/commits_to_rewrite; then git update-index …
). Qu'essayez-vous exactement d'accomplir? Vous voudrez peut-être commencer une nouvelle question si elle est trop à expliquer dans les commentaires.import-directories.perl
partir de Gitcontrib/
(ouimport-tars.perl
, ouimport-zips.py
…) pour créer un nouveau référentiel Git à partir de vos instantanés (même avec "Anciens" horodatages). Les techniquesrebase
/filter-branch
dans ma réponse ne sont nécessaires que si vous souhaitez insérer un fichier qui a été «laissé de côté» de l'historique d'un référentiel existant.Vous pouvez créer la validation comme d'habitude, mais lorsque vous la validez, définissez les variables d'environnement
GIT_AUTHOR_DATE
etGIT_COMMITTER_DATE
les horaires appropriés.Bien sûr, cela fera le commit à la pointe de votre branche (c'est-à-dire devant le commit HEAD actuel). Si vous voulez le repousser plus loin dans le repo, vous devez faire un peu de fantaisie. Disons que vous avez cette histoire:
Et vous voulez que votre nouveau commit (marqué comme "X") apparaisse en second :
Le moyen le plus simple serait de créer une branche à partir du premier commit, d'ajouter votre nouveau commit, puis de rebaser toutes les autres commits au-dessus du nouveau. Ainsi:
la source
GIT_AUTHOR_DATE='Fri Jul 26 19:32:10 2013 -0400' GIT_COMMITTER_DATE='Fri Jul 26 19:32:10 2013 -0400' git commit
2013-07-26T19:32:10
: kernel.org/pub/software/scm/git/docs/…THE_TIME='2019-03-30T8:20:00 -0500' GIT_AUTHOR_DATE=$THE_TIME GIT_COMMITTER_DATE=$THE_TIME git commit -m 'commit message here'
Je sais que cette question est assez ancienne, mais c'est ce qui a fonctionné pour moi:
la source
--date
format de date relative soit lisible par l'homme.git --date
ne modifiera que le $ GIT_AUTHOR_DATE ... donc selon les circonstances, vous verrez la date actuelle attachée au commit ($ GIT_COMMITTER_DATE)git show <commit-hash> --format=fuller
. Là, vous verrezAuthorDate
la date que vous avez spécifiée, mais laCommitDate
date réelle du commit.Dans mon cas, au fil du temps, j'avais enregistré un tas de versions de monfichier en tant que myfile_bak, myfile_old, myfile_2010, sauvegardes / myfile etc. Je voulais mettre l'historique de myfile en git en utilisant leurs dates de modification. Renommez donc le plus ancien en monfichier,
git add myfile
puisgit commit --date=(modification date from ls -l) myfile
, renommez le plus ancien en monfichier, un autre git commit avec --date, répétez ...Pour automatiser quelque peu cela, vous pouvez utiliser shell-foo pour obtenir l'heure de modification du fichier. J'ai commencé avec
ls -l
etcut
, mais stat (1) est plus directla source
--date
"Remplacez la date de l'auteur utilisée dans le commit."git log
La date de semble être la AuthorDate,git log --pretty=fuller
affiche à la fois AuthorDate et CommitDate.git commit
option--date
ne modifiera que leGIT_AUTHOR_DATE
, pasGIT_COMMITTER_DATE
. Comme l'explique le Pro Git Book : "L'auteur est la personne qui a écrit l'œuvre à l'origine, tandis que le committer est la dernière personne à avoir appliqué l'œuvre." Dans le contexte des dates,GIT_AUTHOR_DATE
c'est la date à laquelle le fichier a été modifié, tandis queGIT_COMMITTER_DATE
c'est la date à laquelle il a été validé. Il est important ici de noter que par défaut,git log
affiche les dates de l'auteur en tant que «Date» mais utilise ensuite les dates de validation pour le filtrage lorsqu'une--since
option est donnée .stat -c %y
dans macOS (et d'autres variantes BSD) eststat -f %m
.Ce qui suit est ce que j'utilise pour valider des modifications sur
foo
desN=1
jours dans le passé:Si vous voulez engager à une date encore plus ancienne, disons 3 jours en arrière, il suffit de changer l'
date
argument:date -v-3d
.C'est vraiment utile lorsque vous oubliez de commettre quelque chose hier, par exemple.
UPDATE :
--date
accepte également les expressions comme--date "3 days ago"
ou même--date "yesterday"
. Nous pouvons donc le réduire à une commande de ligne:la source
git --date
ne modifiera que le $ GIT_AUTHOR_DATE ... donc selon les circonstances, vous verrez la date actuelle attachée au commit ($ GIT_COMMITTER_DATE)git commit --amend --date="$(stat -c %y fileToCopyMTimeFrom)"
git commit --amend --date="$(date -R -d '2020-06-15 16:31')"
Dans mon cas, lors de l'utilisation de l'option --date, mon processus git s'est planté. Peut-être que j'ai fait quelque chose de terrible. Et en conséquence, un fichier index.lock est apparu. J'ai donc supprimé manuellement les fichiers .lock du dossier .git et exécuté, pour que tous les fichiers modifiés soient validés dans les dates passées et cela a fonctionné cette fois. Merci pour toutes les réponses ici.
la source
git commit --date
. De plus, votre exemple de message de validation devrait être modifié pour décourager les messages pauvres d'une seule ligne comme ceux-ci @JstRoRRgit --date
ne modifiera que le $ GIT_AUTHOR_DATE ... donc selon les circonstances, vous verrez la date actuelle attachée au commit ($ GIT_COMMITTER_DATE)Pour faire un commit qui semble avoir été fait dans le passé, vous devez définir les deux
GIT_AUTHOR_DATE
etGIT_COMMITTER_DATE
:où
date -d'...'
peut être la date exacte comme2019-01-01 12:00:00
ou relative comme5 months ago 24 days ago
.Pour voir les deux dates dans git log, utilisez:
Cela fonctionne également pour les validations de fusion:
la source
Vous pouvez toujours changer une date sur votre ordinateur, faire un commit, puis changer la date et pousser.
la source
Ou utilisez simplement un faux historique pour le générer pour une plage de données spécifique.
la source